orbit/component/
mod.rs

1//! Component model for Orbit UI framework
2//!
3//! This module contains all the types and traits related to the component model,
4//! including lifecycle management, state, props, and rendering.
5
6mod 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
22// Re-export component module contents
23pub 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;
36// Import Node from our own node module instead of component_single
37pub 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
64/// Global component ID counter for unique component identification
65static COMPONENT_ID_COUNTER: AtomicU64 = AtomicU64::new(1);
66
67/// Unique identifier for component instances
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69pub struct ComponentId(u64);
70
71impl ComponentId {
72    /// Generate a new unique component ID
73    pub fn new() -> Self {
74        Self(COMPONENT_ID_COUNTER.fetch_add(1, Ordering::SeqCst))
75    }
76
77    /// Get the raw ID value
78    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/// Lifecycle phase of a component
96#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
97pub enum LifecyclePhase {
98    /// Component is created but not yet mounted
99    Created,
100    /// Component is being mounted
101    Mounting,
102    /// Component is fully mounted and operational
103    Mounted,
104    /// Component is about to be updated
105    BeforeUpdate,
106    /// Component is updating
107    Updating,
108    /// Component is about to be unmounted
109    BeforeUnmount,
110    /// Component is being unmounted
111    Unmounting,
112    /// Component is unmounted and inactive
113    Unmounted,
114}
115
116/// Type for lifecycle callback functions
117pub type LifecycleCallback = Box<dyn FnMut(&mut dyn AnyComponent) + Send + Sync>;
118
119/// Lifecycle hook options for components
120#[derive(Default)]
121pub struct LifecycleHooks {
122    /// Called when component is mounted to the DOM/renderer
123    on_mount: Vec<LifecycleCallback>,
124    /// Called before updating the DOM/renderer
125    on_before_update: Vec<LifecycleCallback>,
126    /// Called when props or state change
127    on_update: Vec<LifecycleCallback>,
128    /// Called when component is about to be unmounted
129    on_before_unmount: Vec<LifecycleCallback>,
130    /// Called when component is removed
131    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    /// Create a new empty set of lifecycle hooks
160    pub fn new() -> Self {
161        Self::default()
162    }
163
164    /// Register a callback for when the component is mounted
165    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    /// Register a callback for before the component updates
173    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    /// Register a callback for when the component updates
181    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    /// Register a callback for before the component unmounts
189    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    /// Register a callback for when the component unmounts
197    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    /// Execute all mount callbacks
205    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    /// Execute all before update callbacks
212    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    /// Execute all update callbacks
219    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    /// Execute all before unmount callbacks
226    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    /// Execute all unmount callbacks
233    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
240/// Props trait - implemented by all component props types
241pub trait Props: 'static + Send + Sync + std::any::Any {
242    /// Get the type name for debugging
243    fn type_name(&self) -> &'static str;
244
245    /// Clone the props
246    fn box_clone(&self) -> Box<dyn Props>;
247
248    /// Convert to Any for downcasting
249    fn as_any(&self) -> &dyn std::any::Any;
250
251    /// Convert to mutable Any for downcasting
252    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
273/// Marker trait to ensure props are sized
274pub trait SizedProps: Props + Sized {}
275
276/// Wraps a component instance with its metadata
277pub struct ComponentInstance {
278    /// Component instance
279    pub instance: Arc<Mutex<Box<dyn AnyComponent>>>,
280    /// Current props
281    pub props: Box<dyn Props>,
282    /// Component type ID for type checking
283    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    /// Create a new component instance
308    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    /// Get the ID of the component
317    pub fn id(&self) -> ComponentId {
318        if let Ok(component) = self.instance.lock() {
319            component.component_id()
320        } else {
321            // Return a new ID if we can't get the component - should rarely happen
322            ComponentId::new()
323        }
324    }
325
326    /// Update the component instance with new props
327    pub fn update<P: Props>(&mut self, props: P) -> Result<(), ComponentError> {
328        let prop_type_id = TypeId::of::<P>();
329
330        // Check that the props type matches
331        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        // Store the new props
339        self.props = Box::new(props);
340
341        // Update the component with the new props
342        let mut _instance = self.instance.lock().map_err(|_| {
343            ComponentError::LockError("Failed to lock component for update".to_string())
344        })?;
345
346        // This is a simplified implementation - in practice we'd need more sophisticated prop handling
347        Ok(())
348    }
349
350    /// Get the component's type ID
351    pub fn type_id(&self) -> TypeId {
352        self.type_id
353    }
354}
355
356/// Context provided during component mounting
357#[derive(Debug, Clone)]
358pub struct MountContext {
359    /// Component ID being mounted
360    pub component_id: ComponentId,
361    /// Parent component ID (if any)
362    pub parent_id: Option<ComponentId>,
363    /// Mount timestamp
364    pub timestamp: std::time::Instant,
365    /// Mount options and configuration
366    pub options: MountOptions,
367}
368
369/// Options for component mounting
370#[derive(Debug, Clone, Default)]
371pub struct MountOptions {
372    /// Whether to enable automatic state tracking
373    pub enable_state_tracking: bool,
374    /// Whether to register lifecycle hooks
375    pub register_hooks: bool,
376    /// Custom mounting data
377    pub custom_data: HashMap<String, String>,
378}
379
380/// Context provided during component unmounting
381#[derive(Debug, Clone)]
382pub struct UnmountContext {
383    /// Component ID being unmounted
384    pub component_id: ComponentId,
385    /// Parent component ID (if any)
386    pub parent_id: Option<ComponentId>,
387    /// Unmount timestamp
388    pub timestamp: std::time::Instant,
389    /// Unmount reason
390    pub reason: UnmountReason,
391    /// Whether cleanup should be forced
392    pub force_cleanup: bool,
393}
394
395/// Reasons for component unmounting
396#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397pub enum UnmountReason {
398    /// Component was explicitly removed
399    Removed,
400    /// Parent component was unmounted
401    ParentUnmounted,
402    /// Component replacement
403    Replaced,
404    /// Application shutdown
405    Shutdown,
406    /// Error condition
407    Error,
408}
409
410impl MountContext {
411    /// Create a new mount context
412    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    /// Create a mount context with parent
422    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    /// Set mount options
432    pub fn with_options(mut self, options: MountOptions) -> Self {
433        self.options = options;
434        self
435    }
436}
437
438impl UnmountContext {
439    /// Create a new unmount context
440    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    /// Create an unmount context with parent
451    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    /// Set force cleanup flag
466    pub fn with_force_cleanup(mut self, force: bool) -> Self {
467        self.force_cleanup = force;
468        self
469    }
470}
471
472// Clone implementation already exists above
473
474/// Type-erased component trait for dynamic dispatch
475pub trait AnyComponent: Send + Sync + std::any::Any {
476    /// Get unique component ID for debugging and tracking
477    fn component_id(&self) -> ComponentId;
478
479    /// Get current lifecycle phase
480    fn lifecycle_phase(&self) -> LifecyclePhase;
481
482    /// Set lifecycle phase (framework internal)
483    fn set_lifecycle_phase(&mut self, phase: LifecyclePhase);
484
485    /// Request that this component be re-rendered
486    fn request_update(&mut self) -> Result<(), ComponentError>;
487
488    /// Convert to Any for downcasting
489    fn as_any(&self) -> &dyn std::any::Any;
490
491    /// Convert to mutable Any for downcasting
492    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
493
494    /// Get component type name for debugging
495    fn type_name(&self) -> &'static str;
496
497    // Lifecycle methods for dynamic dispatch
498    /// Initialize the component (post-creation)
499    fn any_initialize(&mut self) -> Result<(), ComponentError>;
500
501    /// Mount component - called when component is first added to the tree
502    fn any_mount(&mut self) -> Result<(), ComponentError>;
503
504    /// Called before component updates with new props
505    fn any_before_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError>;
506
507    /// Update component with new props (type-erased)
508    fn any_update(&mut self, props: Box<dyn Props>) -> Result<(), ComponentError>;
509
510    /// Called after the component has updated
511    fn any_after_update(&mut self) -> Result<(), ComponentError>;
512    /// Called before component is unmounted
513    fn any_before_unmount(&mut self) -> Result<(), ComponentError>;
514
515    /// Unmount component - called when component is removed from the tree
516    fn any_unmount(&mut self) -> Result<(), ComponentError>;
517
518    // Enhanced lifecycle methods for dynamic dispatch
519    /// Enhanced mount with context
520    fn any_on_mount(&mut self, context: &MountContext) -> Result<(), ComponentError>;
521
522    /// Before mount hook
523    fn any_before_mount(&mut self) -> Result<(), ComponentError>;
524
525    /// After mount hook  
526    fn any_after_mount(&mut self) -> Result<(), ComponentError>;
527
528    /// Enhanced update with state changes
529    fn any_on_update(&mut self, changes: &StateChanges) -> Result<(), ComponentError>;
530
531    /// Enhanced unmount with context
532    fn any_on_unmount(&mut self, context: &UnmountContext) -> Result<(), ComponentError>;
533
534    /// After unmount hook
535    fn any_after_unmount(&mut self) -> Result<(), ComponentError>;
536}
537
538/// Enhanced component trait with improved lifecycle management
539pub trait Component: AnyComponent + Send + Sync + std::any::Any {
540    /// The props type for this component
541    type Props: Props + Clone;
542
543    /// Get unique component ID for debugging and tracking
544    fn component_id(&self) -> ComponentId;
545
546    /// Create a new component instance with enhanced tracking
547    fn create(props: Self::Props, context: Context) -> Self
548    where
549        Self: Sized;
550
551    /// Initialize the component - called immediately after creation
552    /// Use this for setting up initial state and registering lifecycle hooks
553    fn initialize(&mut self) -> Result<(), ComponentError> {
554        Ok(())
555    }
556    /// Mount component - called when component is first added to the tree
557    /// Automatic state change detection and update scheduling is enabled after this point
558    fn mount(&mut self) -> Result<(), ComponentError> {
559        Ok(())
560    }
561
562    /// Enhanced lifecycle hook - called when component is mounted with context
563    fn on_mount(&mut self, _context: &MountContext) -> Result<(), ComponentError> {
564        // Default implementation calls the basic mount
565        self.mount()
566    }
567
568    /// Enhanced lifecycle hook - called before mount for initialization
569    fn before_mount(&mut self) -> Result<(), ComponentError> {
570        Ok(())
571    }
572
573    /// Enhanced lifecycle hook - called after mount for post-initialization
574    fn after_mount(&mut self) -> Result<(), ComponentError> {
575        Ok(())
576    }
577
578    /// Called when component state changes and updates are needed
579    fn state_changed(&mut self, _state_key: &str) -> Result<(), ComponentError> {
580        // Default implementation requests a re-render
581        Component::request_update(self)
582    }
583
584    /// Enhanced lifecycle hook - called when state changes are detected
585    fn on_update(&mut self, _changes: &StateChanges) -> Result<(), ComponentError> {
586        Ok(())
587    }
588
589    /// Request that this component be re-rendered
590    fn request_update(&mut self) -> Result<(), ComponentError> {
591        // Implementation provided by the framework
592        // This triggers the component's render cycle
593        Ok(())
594    }
595
596    /// Check if component should update given new props
597    /// Override for performance optimization
598    fn should_update(&self, _new_props: &Self::Props) -> bool {
599        // Default: always update
600        // Override this for memoization and performance
601        true
602    }
603
604    /// Called before component updates with new props
605    fn before_update(&mut self, _new_props: &Self::Props) -> Result<(), ComponentError> {
606        Ok(())
607    }
608
609    /// Update component with new props
610    fn update(&mut self, props: Self::Props) -> Result<(), ComponentError>;
611
612    /// Called after the component has updated
613    fn after_update(&mut self) -> Result<(), ComponentError> {
614        Ok(())
615    }
616    /// Called before component is unmounted
617    /// Automatic cleanup of state subscriptions happens after this
618    fn before_unmount(&mut self) -> Result<(), ComponentError> {
619        Ok(())
620    }
621
622    /// Enhanced lifecycle hook - called when component is unmounted with context
623    fn on_unmount(&mut self, _context: &UnmountContext) -> Result<(), ComponentError> {
624        // Default implementation calls the basic unmount
625        self.unmount()
626    }
627
628    /// Enhanced lifecycle hook - called after unmount for final cleanup
629    fn after_unmount(&mut self) -> Result<(), ComponentError> {
630        Ok(())
631    }
632
633    /// Unmount component - called when component is removed from the tree
634    fn unmount(&mut self) -> Result<(), ComponentError> {
635        Ok(())
636    }
637
638    /// Perform automatic cleanup (called by framework)
639    fn cleanup(&mut self) -> Result<(), ComponentError> {
640        // Framework-provided cleanup:
641        // - Remove state subscriptions
642        // - Clear event listeners
643        // - Release resources
644        Ok(())
645    }
646
647    /// Render component - returns child nodes
648    fn render(&self) -> Result<Vec<Node>, ComponentError>;
649
650    /// Get current lifecycle phase
651    fn lifecycle_phase(&self) -> LifecyclePhase {
652        LifecyclePhase::Created // Default, overridden by framework
653    }
654
655    /// Convert to Any for downcasting
656    fn as_any(&self) -> &dyn std::any::Any;
657
658    /// Convert to mutable Any for downcasting
659    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
660}
661
662/// Base component functionality that all components share
663#[derive(Debug)]
664pub struct ComponentBase {
665    /// Unique identifier for this component
666    id: ComponentId,
667    /// Current lifecycle phase
668    lifecycle_phase: LifecyclePhase,
669    /// Context for state and event management
670    context: Context,
671    /// Layout style for this component
672    layout_style: LayoutStyle,
673}
674
675impl ComponentBase {
676    /// Create a new component base with unique ID
677    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    /// Create a new component base with custom layout style
687    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    /// Get the component ID
697    pub fn id(&self) -> ComponentId {
698        self.id
699    }
700
701    /// Get the current lifecycle phase
702    pub fn lifecycle_phase(&self) -> LifecyclePhase {
703        self.lifecycle_phase
704    }
705
706    /// Set the lifecycle phase (framework internal)
707    pub fn set_lifecycle_phase(&mut self, phase: LifecyclePhase) {
708        self.lifecycle_phase = phase;
709        self.context.set_lifecycle_phase(phase);
710    }
711
712    /// Get reference to the layout style
713    pub fn layout_style(&self) -> &LayoutStyle {
714        &self.layout_style
715    }
716
717    /// Get mutable reference to the layout style
718    pub fn layout_style_mut(&mut self) -> &mut LayoutStyle {
719        &mut self.layout_style
720    }
721
722    /// Set the layout style
723    pub fn set_layout_style(&mut self, layout_style: LayoutStyle) {
724        self.layout_style = layout_style;
725    }
726
727    /// Create a layout node for this component
728    pub fn create_layout_node(&self) -> LayoutNode {
729        LayoutNode::new(self.id, self.layout_style.clone())
730    }
731
732    /// Get reference to the context
733    pub fn context(&self) -> &Context {
734        &self.context
735    }
736
737    /// Get mutable reference to the context
738    pub fn context_mut(&mut self) -> &mut Context {
739        &mut self.context
740    }
741}
742
743/// Basic Component implementation for ComponentBase (primarily for testing)
744impl Component for ComponentBase {
745    type Props = (); // ComponentBase doesn't need props
746
747    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        // ComponentBase doesn't have props to update
757        Ok(())
758    }
759
760    fn render(&self) -> Result<Vec<Node>, ComponentError> {
761        // ComponentBase doesn't render anything by default
762        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
777/// Automatic implementation of AnyComponent for all Components
778impl<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        // Default implementation does nothing
789        // Concrete implementations can override this through AnyComponent if needed
790    }
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    // Lifecycle method delegations to the typed Component trait
809    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        // Try to downcast the props to the component's Props type
819        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        // Try to downcast the props to the component's Props type
831        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    // Enhanced lifecycle method delegations
853    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/// Context passed to components providing access to state, events, and shared context
879#[derive(Clone)]
880pub struct Context {
881    /// Unique ID for this context instance
882    id: ComponentId,
883
884    /// State container for managing component and app state
885    state: StateContainer,
886
887    /// Event emitter for handling UI events
888    events: EventEmitter,
889
890    /// Lifecycle hooks container
891    lifecycle_hooks: Arc<Mutex<LifecycleHooks>>,
892
893    /// Current lifecycle phase
894    lifecycle_phase: LifecyclePhase,
895
896    /// Context provider for parent-child communication
897    context_provider: ContextProvider,
898
899    /// Update scheduler for batching state changes
900    update_scheduler: Arc<Mutex<UpdateScheduler>>,
901}
902
903/// Manages batched updates for improved performance
904#[derive(Debug, Default)]
905pub struct UpdateScheduler {
906    /// Components waiting for updates
907    pending_updates: HashMap<ComponentId, bool>,
908    /// Whether an update batch is currently scheduled
909    batch_scheduled: bool,
910}
911
912impl UpdateScheduler {
913    /// Schedule a component for update
914    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            // In a real implementation, this would schedule a microtask
919            // For now, we'll handle updates immediately
920        }
921    }
922
923    /// Check if a component has pending updates
924    pub fn has_pending_update(&self, component_id: ComponentId) -> bool {
925        self.pending_updates.contains_key(&component_id)
926    }
927
928    /// Clear pending updates for a component
929    pub fn clear_pending(&mut self, component_id: ComponentId) {
930        self.pending_updates.remove(&component_id);
931    }
932
933    /// Get all components with pending updates
934    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    /// Create a new context with unique ID and default state
959    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    /// Get the context ID
972    pub fn id(&self) -> ComponentId {
973        self.id
974    }
975
976    /// Get access to the state container
977    pub fn state(&self) -> &StateContainer {
978        &self.state
979    }
980
981    /// Get access to the event emitter
982    pub fn events(&self) -> &EventEmitter {
983        &self.events
984    }
985
986    /// Get the current lifecycle phase
987    pub fn lifecycle_phase(&self) -> LifecyclePhase {
988        self.lifecycle_phase
989    }
990
991    /// Set the lifecycle phase (framework internal)
992    pub(crate) fn set_lifecycle_phase(&mut self, phase: LifecyclePhase) {
993        self.lifecycle_phase = phase;
994    }
995
996    /// Schedule a component update
997    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    /// Check if component has pending updates
1004    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    /// Create a reactive state that triggers component updates
1013    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        // Set up state change listener to trigger component updates
1020        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    /// Register lifecycle hooks
1031    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    /// Execute lifecycle hooks for a specific phase
1041    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                _ => {} // No hooks for other phases yet
1050            }
1051        }
1052    }
1053
1054    /// Get context provider for parent-child communication
1055    pub fn context_provider(&self) -> &ContextProvider {
1056        &self.context_provider
1057    }
1058}