1mod composition;
7mod context;
8mod enhanced_context;
9mod error;
10mod hoc;
11mod lifecycle;
12mod node;
13mod performance;
14pub mod props;
15mod state_tracking;
16mod tree;
17mod update_scheduler;
18
19#[cfg(test)]
20mod tests;
21
22pub use composition::{
24 CompositionBuilder, CompoundComponent, FlexibleCompoundComponent, FlexibleCompoundProps,
25 RenderProp, RenderPropComponent, RenderPropProps, Slot, Slotted, SlottedComponent,
26 SlottedProps,
27};
28pub use context::{callback, Callback, ContextProvider};
29pub use enhanced_context::Context as EnhancedContext;
30pub use error::ComponentError;
31pub use hoc::{
32 HOCWrapper, HigherOrderComponent, LoggedComponent, MonitoredComponent, WithLogging,
33 WithPerformanceMonitoring,
34};
35pub use lifecycle::LifecycleManager;
36pub use node::Node;
38pub use performance::{
39 LazyComponent, LoadTrigger, MemoCache, MemoComponent, Memoizable, PerformanceMonitor,
40 PerformanceRegistry, RenderStatistics, RenderTimer, UpdateBatcher,
41};
42pub use state_tracking::{
43 ChangePriority, StateChange, StateChanges, StateSnapshot, StateTracker, StateTrackingConfig,
44 StateValue,
45};
46pub use tree::{ComponentTree, TreeError, TreeResult};
47pub use update_scheduler::{UpdatePriority, UpdateScheduler as ModuleUpdateScheduler};
48
49use std::{
50 any::TypeId,
51 collections::HashMap,
52 sync::{
53 atomic::{AtomicU64, Ordering},
54 Arc, Mutex,
55 },
56};
57
58use crate::{
59 events::EventEmitter,
60 layout::{LayoutNode, LayoutStyle},
61 state::{State, StateContainer},
62};
63
64static COMPONENT_ID_COUNTER: AtomicU64 = AtomicU64::new(1);
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69pub struct ComponentId(u64);
70
71impl ComponentId {
72 pub fn new() -> Self {
74 Self(COMPONENT_ID_COUNTER.fetch_add(1, Ordering::SeqCst))
75 }
76
77 pub fn id(&self) -> u64 {
79 self.0
80 }
81}
82
83impl Default for ComponentId {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl std::fmt::Display for ComponentId {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 write!(f, "Component#{}", self.0)
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
97pub enum LifecyclePhase {
98 Created,
100 Mounting,
102 Mounted,
104 BeforeUpdate,
106 Updating,
108 BeforeUnmount,
110 Unmounting,
112 Unmounted,
114}
115
116pub type LifecycleCallback = Box<dyn FnMut(&mut dyn AnyComponent) + Send + Sync>;
118
119#[derive(Default)]
121pub struct LifecycleHooks {
122 on_mount: Vec<LifecycleCallback>,
124 on_before_update: Vec<LifecycleCallback>,
126 on_update: Vec<LifecycleCallback>,
128 on_before_unmount: Vec<LifecycleCallback>,
130 on_unmount: Vec<LifecycleCallback>,
132}
133
134impl std::fmt::Debug for LifecycleHooks {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 f.debug_struct("LifecycleHooks")
137 .field("on_mount", &format!("[{} callbacks]", self.on_mount.len()))
138 .field(
139 "on_before_update",
140 &format!("[{} callbacks]", self.on_before_update.len()),
141 )
142 .field(
143 "on_update",
144 &format!("[{} callbacks]", self.on_update.len()),
145 )
146 .field(
147 "on_before_unmount",
148 &format!("[{} callbacks]", self.on_before_unmount.len()),
149 )
150 .field(
151 "on_unmount",
152 &format!("[{} callbacks]", self.on_unmount.len()),
153 )
154 .finish()
155 }
156}
157
158impl LifecycleHooks {
159 pub fn new() -> Self {
161 Self::default()
162 }
163
164 pub fn on_mount<F>(&mut self, callback: F)
166 where
167 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
168 {
169 self.on_mount.push(Box::new(callback));
170 }
171
172 pub fn on_before_update<F>(&mut self, callback: F)
174 where
175 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
176 {
177 self.on_before_update.push(Box::new(callback));
178 }
179
180 pub fn on_update<F>(&mut self, callback: F)
182 where
183 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
184 {
185 self.on_update.push(Box::new(callback));
186 }
187
188 pub fn on_before_unmount<F>(&mut self, callback: F)
190 where
191 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
192 {
193 self.on_before_unmount.push(Box::new(callback));
194 }
195
196 pub fn on_unmount<F>(&mut self, callback: F)
198 where
199 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
200 {
201 self.on_unmount.push(Box::new(callback));
202 }
203
204 pub(crate) fn execute_mount(&mut self, component: &mut dyn AnyComponent) {
206 for callback in &mut self.on_mount {
207 callback(component);
208 }
209 }
210
211 pub(crate) fn execute_before_update(&mut self, component: &mut dyn AnyComponent) {
213 for callback in &mut self.on_before_update {
214 callback(component);
215 }
216 }
217
218 pub(crate) fn execute_update(&mut self, component: &mut dyn AnyComponent) {
220 for callback in &mut self.on_update {
221 callback(component);
222 }
223 }
224
225 pub(crate) fn execute_before_unmount(&mut self, component: &mut dyn AnyComponent) {
227 for callback in &mut self.on_before_unmount {
228 callback(component);
229 }
230 }
231
232 pub(crate) fn execute_unmount(&mut self, component: &mut dyn AnyComponent) {
234 for callback in &mut self.on_unmount {
235 callback(component);
236 }
237 }
238}
239
240pub trait Props: 'static + Send + Sync + std::any::Any {
242 fn type_name(&self) -> &'static str;
244
245 fn box_clone(&self) -> Box<dyn Props>;
247
248 fn as_any(&self) -> &dyn std::any::Any;
250
251 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
253}
254
255impl<T: 'static + Clone + Send + Sync> Props for T {
256 fn type_name(&self) -> &'static str {
257 std::any::type_name::<T>()
258 }
259
260 fn box_clone(&self) -> Box<dyn Props> {
261 Box::new(self.clone())
262 }
263
264 fn as_any(&self) -> &dyn std::any::Any {
265 self
266 }
267
268 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
269 self
270 }
271}
272
273pub trait SizedProps: Props + Sized {}
275
276pub struct ComponentInstance {
278 pub instance: Arc<Mutex<Box<dyn AnyComponent>>>,
280 pub props: Box<dyn Props>,
282 pub type_id: TypeId,
284}
285
286impl std::fmt::Debug for ComponentInstance {
287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288 f.debug_struct("ComponentInstance")
289 .field("type_id", &self.type_id)
290 .field("instance", &"<AnyComponent>")
291 .field("props", &"<Props>")
292 .finish()
293 }
294}
295
296impl Clone for ComponentInstance {
297 fn clone(&self) -> Self {
298 Self {
299 instance: Arc::clone(&self.instance),
300 props: self.props.box_clone(),
301 type_id: self.type_id,
302 }
303 }
304}
305
306impl ComponentInstance {
307 pub fn new<C: Component + 'static>(instance: C, props: C::Props) -> Self {
309 Self {
310 instance: Arc::new(Mutex::new(Box::new(instance) as Box<dyn AnyComponent>)),
311 props: Box::new(props),
312 type_id: TypeId::of::<C>(),
313 }
314 }
315
316 pub fn id(&self) -> ComponentId {
318 if let Ok(component) = self.instance.lock() {
319 component.component_id()
320 } else {
321 ComponentId::new()
323 }
324 }
325
326 pub fn update<P: Props>(&mut self, props: P) -> Result<(), ComponentError> {
328 let prop_type_id = TypeId::of::<P>();
329
330 if self.type_id != TypeId::of::<P>() {
332 return Err(ComponentError::PropsMismatch {
333 expected: self.type_id,
334 got: prop_type_id,
335 });
336 }
337
338 self.props = Box::new(props);
340
341 let mut _instance = self.instance.lock().map_err(|_| {
343 ComponentError::LockError("Failed to lock component for update".to_string())
344 })?;
345
346 Ok(())
348 }
349
350 pub fn type_id(&self) -> TypeId {
352 self.type_id
353 }
354}
355
356#[derive(Debug, Clone)]
358pub struct MountContext {
359 pub component_id: ComponentId,
361 pub parent_id: Option<ComponentId>,
363 pub timestamp: std::time::Instant,
365 pub options: MountOptions,
367}
368
369#[derive(Debug, Clone, Default)]
371pub struct MountOptions {
372 pub enable_state_tracking: bool,
374 pub register_hooks: bool,
376 pub custom_data: HashMap<String, String>,
378}
379
380#[derive(Debug, Clone)]
382pub struct UnmountContext {
383 pub component_id: ComponentId,
385 pub parent_id: Option<ComponentId>,
387 pub timestamp: std::time::Instant,
389 pub reason: UnmountReason,
391 pub force_cleanup: bool,
393}
394
395#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397pub enum UnmountReason {
398 Removed,
400 ParentUnmounted,
402 Replaced,
404 Shutdown,
406 Error,
408}
409
410impl MountContext {
411 pub fn new(component_id: ComponentId) -> Self {
413 Self {
414 component_id,
415 parent_id: None,
416 timestamp: std::time::Instant::now(),
417 options: MountOptions::default(),
418 }
419 }
420
421 pub fn with_parent(component_id: ComponentId, parent_id: ComponentId) -> Self {
423 Self {
424 component_id,
425 parent_id: Some(parent_id),
426 timestamp: std::time::Instant::now(),
427 options: MountOptions::default(),
428 }
429 }
430
431 pub fn with_options(mut self, options: MountOptions) -> Self {
433 self.options = options;
434 self
435 }
436}
437
438impl UnmountContext {
439 pub fn new(component_id: ComponentId, reason: UnmountReason) -> Self {
441 Self {
442 component_id,
443 parent_id: None,
444 timestamp: std::time::Instant::now(),
445 reason,
446 force_cleanup: false,
447 }
448 }
449
450 pub fn with_parent(
452 component_id: ComponentId,
453 parent_id: ComponentId,
454 reason: UnmountReason,
455 ) -> Self {
456 Self {
457 component_id,
458 parent_id: Some(parent_id),
459 timestamp: std::time::Instant::now(),
460 reason,
461 force_cleanup: false,
462 }
463 }
464
465 pub fn with_force_cleanup(mut self, force: bool) -> Self {
467 self.force_cleanup = force;
468 self
469 }
470}
471
472pub trait AnyComponent: Send + Sync + std::any::Any {
476 fn component_id(&self) -> ComponentId;
478
479 fn lifecycle_phase(&self) -> LifecyclePhase;
481
482 fn set_lifecycle_phase(&mut self, phase: LifecyclePhase);
484
485 fn request_update(&mut self) -> Result<(), ComponentError>;
487
488 fn as_any(&self) -> &dyn std::any::Any;
490
491 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
493
494 fn type_name(&self) -> &'static str;
496
497 fn any_initialize(&mut self) -> Result<(), ComponentError>;
500
501 fn any_mount(&mut self) -> Result<(), ComponentError>;
503
504 fn any_before_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError>;
506
507 fn any_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError>;
509
510 fn any_after_update(&mut self) -> Result<(), ComponentError>;
512 fn any_before_unmount(&mut self) -> Result<(), ComponentError>;
514
515 fn any_unmount(&mut self) -> Result<(), ComponentError>;
517
518 fn any_on_mount(&mut self, context: &MountContext) -> Result<(), ComponentError>;
521
522 fn any_before_mount(&mut self) -> Result<(), ComponentError>;
524
525 fn any_after_mount(&mut self) -> Result<(), ComponentError>;
527
528 fn any_on_update(&mut self, changes: &StateChanges) -> Result<(), ComponentError>;
530
531 fn any_on_unmount(&mut self, context: &UnmountContext) -> Result<(), ComponentError>;
533
534 fn any_after_unmount(&mut self) -> Result<(), ComponentError>;
536}
537
538pub trait Component: AnyComponent + Send + Sync + std::any::Any {
540 type Props: Props + Clone;
542
543 fn component_id(&self) -> ComponentId;
545
546 fn create(props: Self::Props, context: Context) -> Self
548 where
549 Self: Sized;
550
551 fn initialize(&mut self) -> Result<(), ComponentError> {
554 Ok(())
555 }
556 fn mount(&mut self) -> Result<(), ComponentError> {
559 Ok(())
560 }
561
562 fn on_mount(&mut self, _context: &MountContext) -> Result<(), ComponentError> {
564 self.mount()
566 }
567
568 fn before_mount(&mut self) -> Result<(), ComponentError> {
570 Ok(())
571 }
572
573 fn after_mount(&mut self) -> Result<(), ComponentError> {
575 Ok(())
576 }
577
578 fn state_changed(&mut self, _state_key: &str) -> Result<(), ComponentError> {
580 Component::request_update(self)
582 }
583
584 fn on_update(&mut self, _changes: &StateChanges) -> Result<(), ComponentError> {
586 Ok(())
587 }
588
589 fn request_update(&mut self) -> Result<(), ComponentError> {
591 Ok(())
594 }
595
596 fn should_update(&self, _new_props: &Self::Props) -> bool {
599 true
602 }
603
604 fn before_update(&mut self, _new_props: &Self::Props) -> Result<(), ComponentError> {
606 Ok(())
607 }
608
609 fn update(&mut self, props: Self::Props) -> Result<(), ComponentError>;
611
612 fn after_update(&mut self) -> Result<(), ComponentError> {
614 Ok(())
615 }
616 fn before_unmount(&mut self) -> Result<(), ComponentError> {
619 Ok(())
620 }
621
622 fn on_unmount(&mut self, _context: &UnmountContext) -> Result<(), ComponentError> {
624 self.unmount()
626 }
627
628 fn after_unmount(&mut self) -> Result<(), ComponentError> {
630 Ok(())
631 }
632
633 fn unmount(&mut self) -> Result<(), ComponentError> {
635 Ok(())
636 }
637
638 fn cleanup(&mut self) -> Result<(), ComponentError> {
640 Ok(())
645 }
646
647 fn render(&self) -> Result<Vec<Node>, ComponentError>;
649
650 fn lifecycle_phase(&self) -> LifecyclePhase {
652 LifecyclePhase::Created }
654
655 fn as_any(&self) -> &dyn std::any::Any;
657
658 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
660}
661
662#[derive(Debug)]
664pub struct ComponentBase {
665 id: ComponentId,
667 lifecycle_phase: LifecyclePhase,
669 context: Context,
671 layout_style: LayoutStyle,
673}
674
675impl ComponentBase {
676 pub fn new(context: Context) -> Self {
678 Self {
679 id: ComponentId::new(),
680 lifecycle_phase: LifecyclePhase::Created,
681 context,
682 layout_style: LayoutStyle::default(),
683 }
684 }
685
686 pub fn new_with_layout(context: Context, layout_style: LayoutStyle) -> Self {
688 Self {
689 id: ComponentId::new(),
690 lifecycle_phase: LifecyclePhase::Created,
691 context,
692 layout_style,
693 }
694 }
695
696 pub fn id(&self) -> ComponentId {
698 self.id
699 }
700
701 pub fn lifecycle_phase(&self) -> LifecyclePhase {
703 self.lifecycle_phase
704 }
705
706 pub fn set_lifecycle_phase(&mut self, phase: LifecyclePhase) {
708 self.lifecycle_phase = phase;
709 self.context.set_lifecycle_phase(phase);
710 }
711
712 pub fn layout_style(&self) -> &LayoutStyle {
714 &self.layout_style
715 }
716
717 pub fn layout_style_mut(&mut self) -> &mut LayoutStyle {
719 &mut self.layout_style
720 }
721
722 pub fn set_layout_style(&mut self, layout_style: LayoutStyle) {
724 self.layout_style = layout_style;
725 }
726
727 pub fn create_layout_node(&self) -> LayoutNode {
729 LayoutNode::new(self.id, self.layout_style.clone())
730 }
731
732 pub fn context(&self) -> &Context {
734 &self.context
735 }
736
737 pub fn context_mut(&mut self) -> &mut Context {
739 &mut self.context
740 }
741}
742
743impl Component for ComponentBase {
745 type Props = (); fn component_id(&self) -> ComponentId {
748 self.id
749 }
750
751 fn create(_props: Self::Props, context: Context) -> Self {
752 Self::new(context)
753 }
754
755 fn update(&mut self, _props: Self::Props) -> Result<(), ComponentError> {
756 Ok(())
758 }
759
760 fn render(&self) -> Result<Vec<Node>, ComponentError> {
761 Ok(vec![])
763 }
764
765 fn as_any(&self) -> &dyn std::any::Any {
766 self
767 }
768
769 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
770 self
771 }
772 fn lifecycle_phase(&self) -> LifecyclePhase {
773 self.lifecycle_phase
774 }
775}
776
777impl<T: Component> AnyComponent for T {
779 fn component_id(&self) -> ComponentId {
780 Component::component_id(self)
781 }
782
783 fn lifecycle_phase(&self) -> LifecyclePhase {
784 Component::lifecycle_phase(self)
785 }
786
787 fn set_lifecycle_phase(&mut self, _phase: LifecyclePhase) {
788 }
791
792 fn request_update(&mut self) -> Result<(), ComponentError> {
793 Component::request_update(self)
794 }
795
796 fn as_any(&self) -> &dyn std::any::Any {
797 Component::as_any(self)
798 }
799
800 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
801 Component::as_any_mut(self)
802 }
803
804 fn type_name(&self) -> &'static str {
805 std::any::type_name::<T>()
806 }
807
808 fn any_initialize(&mut self) -> Result<(), ComponentError> {
810 Component::initialize(self)
811 }
812
813 fn any_mount(&mut self) -> Result<(), ComponentError> {
814 Component::mount(self)
815 }
816
817 fn any_before_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError> {
818 if let Some(typed_props) = props.as_any().downcast_ref::<T::Props>() {
820 Component::before_update(self, typed_props)
821 } else {
822 Err(ComponentError::PropsMismatch {
823 expected: TypeId::of::<T::Props>(),
824 got: props.as_any().type_id(),
825 })
826 }
827 }
828
829 fn any_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError> {
830 if let Some(typed_props) = props.as_any().downcast_ref::<T::Props>() {
832 Component::update(self, typed_props.clone())
833 } else {
834 Err(ComponentError::PropsMismatch {
835 expected: TypeId::of::<T::Props>(),
836 got: props.as_any().type_id(),
837 })
838 }
839 }
840
841 fn any_after_update(&mut self) -> Result<(), ComponentError> {
842 Component::after_update(self)
843 }
844 fn any_before_unmount(&mut self) -> Result<(), ComponentError> {
845 Component::before_unmount(self)
846 }
847
848 fn any_unmount(&mut self) -> Result<(), ComponentError> {
849 Component::unmount(self)
850 }
851
852 fn any_on_mount(&mut self, context: &MountContext) -> Result<(), ComponentError> {
854 Component::on_mount(self, context)
855 }
856
857 fn any_before_mount(&mut self) -> Result<(), ComponentError> {
858 Component::before_mount(self)
859 }
860
861 fn any_after_mount(&mut self) -> Result<(), ComponentError> {
862 Component::after_mount(self)
863 }
864
865 fn any_on_update(&mut self, changes: &StateChanges) -> Result<(), ComponentError> {
866 Component::on_update(self, changes)
867 }
868
869 fn any_on_unmount(&mut self, context: &UnmountContext) -> Result<(), ComponentError> {
870 Component::on_unmount(self, context)
871 }
872
873 fn any_after_unmount(&mut self) -> Result<(), ComponentError> {
874 Component::after_unmount(self)
875 }
876}
877
878#[derive(Clone)]
880pub struct Context {
881 id: ComponentId,
883
884 state: StateContainer,
886
887 events: EventEmitter,
889
890 lifecycle_hooks: Arc<Mutex<LifecycleHooks>>,
892
893 lifecycle_phase: LifecyclePhase,
895
896 context_provider: ContextProvider,
898
899 update_scheduler: Arc<Mutex<UpdateScheduler>>,
901}
902
903#[derive(Debug, Default)]
905pub struct UpdateScheduler {
906 pending_updates: HashMap<ComponentId, bool>,
908 batch_scheduled: bool,
910}
911
912impl UpdateScheduler {
913 pub fn schedule_update(&mut self, component_id: ComponentId) {
915 self.pending_updates.insert(component_id, true);
916 if !self.batch_scheduled {
917 self.batch_scheduled = true;
918 }
921 }
922
923 pub fn has_pending_update(&self, component_id: ComponentId) -> bool {
925 self.pending_updates.contains_key(&component_id)
926 }
927
928 pub fn clear_pending(&mut self, component_id: ComponentId) {
930 self.pending_updates.remove(&component_id);
931 }
932
933 pub fn get_pending_components(&self) -> Vec<ComponentId> {
935 self.pending_updates.keys().copied().collect()
936 }
937}
938
939impl std::fmt::Debug for Context {
940 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
941 f.debug_struct("Context")
942 .field("state", &self.state)
943 .field("events", &self.events)
944 .field("lifecycle_hooks", &"[LifecycleHooks]")
945 .field("lifecycle_phase", &self.lifecycle_phase)
946 .field("context_provider", &self.context_provider)
947 .finish()
948 }
949}
950
951impl Default for Context {
952 fn default() -> Self {
953 Self::new()
954 }
955}
956
957impl Context {
958 pub fn new() -> Self {
960 Self {
961 id: ComponentId::new(),
962 state: StateContainer::new(),
963 events: EventEmitter::new(),
964 lifecycle_hooks: Arc::new(Mutex::new(LifecycleHooks::new())),
965 lifecycle_phase: LifecyclePhase::Created,
966 context_provider: ContextProvider::new(),
967 update_scheduler: Arc::new(Mutex::new(UpdateScheduler::default())),
968 }
969 }
970
971 pub fn id(&self) -> ComponentId {
973 self.id
974 }
975
976 pub fn state(&self) -> &StateContainer {
978 &self.state
979 }
980
981 pub fn events(&self) -> &EventEmitter {
983 &self.events
984 }
985
986 pub fn lifecycle_phase(&self) -> LifecyclePhase {
988 self.lifecycle_phase
989 }
990
991 pub(crate) fn set_lifecycle_phase(&mut self, phase: LifecyclePhase) {
993 self.lifecycle_phase = phase;
994 }
995
996 pub fn schedule_update(&self, component_id: ComponentId) {
998 if let Ok(mut scheduler) = self.update_scheduler.lock() {
999 scheduler.schedule_update(component_id);
1000 }
1001 }
1002
1003 pub fn has_pending_update(&self, component_id: ComponentId) -> bool {
1005 if let Ok(scheduler) = self.update_scheduler.lock() {
1006 scheduler.has_pending_update(component_id)
1007 } else {
1008 false
1009 }
1010 }
1011
1012 pub fn create_reactive_state<T>(&self, initial_value: T, component_id: ComponentId) -> State<T>
1014 where
1015 T: Clone + Send + Sync + 'static,
1016 {
1017 let state = self.state.create(initial_value);
1018
1019 let scheduler = Arc::clone(&self.update_scheduler);
1021 state.on_change(move |_| {
1022 if let Ok(mut s) = scheduler.lock() {
1023 s.schedule_update(component_id);
1024 }
1025 });
1026
1027 state
1028 }
1029
1030 pub fn register_lifecycle_hooks<F>(&self, setup: F)
1032 where
1033 F: FnOnce(&mut LifecycleHooks),
1034 {
1035 if let Ok(mut hooks) = self.lifecycle_hooks.lock() {
1036 setup(&mut hooks);
1037 }
1038 }
1039
1040 pub fn execute_lifecycle_hooks(&self, phase: LifecyclePhase, component: &mut dyn AnyComponent) {
1042 if let Ok(mut hooks) = self.lifecycle_hooks.lock() {
1043 match phase {
1044 LifecyclePhase::Mounted => hooks.execute_mount(component),
1045 LifecyclePhase::BeforeUpdate => hooks.execute_before_update(component),
1046 LifecyclePhase::Updating => hooks.execute_update(component),
1047 LifecyclePhase::BeforeUnmount => hooks.execute_before_unmount(component),
1048 LifecyclePhase::Unmounted => hooks.execute_unmount(component),
1049 _ => {} }
1051 }
1052 }
1053
1054 pub fn context_provider(&self) -> &ContextProvider {
1056 &self.context_provider
1057 }
1058}