hypen_engine/ir/
node.rs

1use serde::{Deserialize, Serialize};
2use slotmap::new_key_type;
3use indexmap::IndexMap;
4use crate::reactive::Binding;
5
6// Stable, unique node identifier for reconciliation
7new_key_type! {
8    pub struct NodeId;
9}
10
11/// IR value - either static or a binding to reactive state
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub enum Value {
14    /// Static value (string, number, bool, etc.)
15    Static(serde_json::Value),
16    /// Binding to state: parsed from ${state.user.name}
17    Binding(Binding),
18    /// Template string with embedded bindings: "Count: ${state.count}"
19    /// Stores the template string and all bindings found within it
20    TemplateString {
21        template: String,
22        bindings: Vec<Binding>,
23    },
24    /// Action reference: @actions.signIn
25    Action(String),
26}
27
28/// Properties map for a component/element
29pub type Props = IndexMap<String, Value>;
30
31/// Core IR element representing a component instance or primitive
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct Element {
34    /// Component/element type (e.g., "Column", "Text", "Button")
35    pub element_type: String,
36
37    /// Properties passed to this element
38    pub props: Props,
39
40    /// Children elements
41    pub children: Vec<Element>,
42
43    /// Optional key for reconciliation (from user or auto-generated)
44    pub key: Option<String>,
45
46    // Event handling is now done at the renderer level
47}
48
49impl Element {
50    pub fn new(element_type: impl Into<String>) -> Self {
51        Self {
52            element_type: element_type.into(),
53            props: Props::new(),
54            children: Vec::new(),
55            key: None,
56        }
57    }
58
59    pub fn with_prop(mut self, key: impl Into<String>, value: Value) -> Self {
60        self.props.insert(key.into(), value);
61        self
62    }
63
64    pub fn with_child(mut self, child: Element) -> Self {
65        self.children.push(child);
66        self
67    }
68
69    pub fn with_key(mut self, key: impl Into<String>) -> Self {
70        self.key = Some(key.into());
71        self
72    }
73
74    // Event handling methods removed - now done at renderer level
75}