Skip to main content

rosace_core/
component.rs

1use crate::context::Context;
2use crate::element::Element;
3use crate::types::ComponentId;
4
5/// The core trait every ROSACE component implements.
6///
7/// A component is a pure function from props (`&self`) and [`Context`] to an
8/// [`Element`] tree. The framework calls `build` every frame (Phase 1) or when
9/// the component is marked dirty by a state change (Phase 2+).
10///
11/// # Example
12/// ```rust,ignore
13/// struct Greeting { name: String }
14///
15/// impl Component for Greeting {
16///     fn build(&self, ctx: &mut Context) -> Element {
17///         Text::new(format!("Hello, {}!", self.name)).into_element()
18///     }
19/// }
20/// ```
21pub trait Component: Send + Sync + 'static {
22    /// Produce the element tree for this component.
23    fn build(&self, ctx: &mut Context) -> Element;
24
25    /// Called once after the component first appears in the tree.
26    ///
27    /// Default implementation is a no-op. Override for side effects that
28    /// should run on mount (e.g., starting timers, subscriptions).
29    fn on_mount(&self) {}
30
31    /// Called once after the component is removed from the tree.
32    ///
33    /// Default implementation is a no-op. Override for cleanup that cannot
34    /// be expressed as a `ctx.on_cleanup` closure (e.g., releasing platform
35    /// resources held by `self`).
36    fn on_unmount(&self) {}
37
38    /// Fully-qualified type name used in diagnostics.
39    fn type_name(&self) -> &'static str {
40        std::any::type_name::<Self>()
41    }
42
43    /// Convert this component into an [`Element`] so it can be embedded
44    /// inside another component's `build()` output.
45    ///
46    /// The reconciler assigns the real position-based [`ComponentId`] during
47    /// the tree walk; `ComponentId(0)` here is a placeholder.
48    fn into_element(self) -> Element
49    where
50        Self: Sized,
51    {
52        use crate::element::{ComponentElement, Element};
53        use std::sync::Arc;
54
55        Element::Component(ComponentElement {
56            id: ComponentId(0),
57            key: None,
58            component: Arc::new(self),
59            children: vec![],
60        })
61    }
62}