dampen_core/ir/
node.rs

1use crate::ir::layout::{Breakpoint, LayoutConstraints};
2use crate::ir::span::Span;
3use crate::ir::style::StyleProperties;
4use std::collections::HashMap;
5
6/// A node in the widget tree
7#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
8pub struct WidgetNode {
9    pub kind: WidgetKind,
10    pub id: Option<String>,
11    pub attributes: HashMap<String, AttributeValue>,
12    pub events: Vec<EventBinding>,
13    pub children: Vec<WidgetNode>,
14    pub span: Span,
15
16    // Styling extensions
17    pub style: Option<StyleProperties>,
18    pub layout: Option<LayoutConstraints>,
19    pub theme_ref: Option<String>,
20    pub classes: Vec<String>,
21    pub breakpoint_attributes: HashMap<Breakpoint, HashMap<String, AttributeValue>>,
22}
23
24/// Enumeration of all supported widget types
25#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
26pub enum WidgetKind {
27    #[default]
28    Column,
29    Row,
30    Container,
31    Scrollable,
32    Stack,
33    Text,
34    Image,
35    Svg,
36    Button,
37    TextInput,
38    Checkbox,
39    Slider,
40    PickList,
41    Toggler,
42    Space,
43    Rule,
44    Radio,
45    // Advanced widgets
46    ComboBox,
47    ProgressBar,
48    Tooltip,
49    Grid,
50    Canvas,
51    Float,
52    // Control flow
53    For,
54    Custom(String),
55}
56
57/// A value that can be either static or dynamically bound
58#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
59pub enum AttributeValue {
60    Static(String),
61    Binding(crate::expr::BindingExpr),
62    Interpolated(Vec<InterpolatedPart>),
63}
64
65impl Default for AttributeValue {
66    fn default() -> Self {
67        AttributeValue::Static(String::new())
68    }
69}
70
71/// Part of an interpolated string
72#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
73pub enum InterpolatedPart {
74    Literal(String),
75    Binding(crate::expr::BindingExpr),
76}
77
78impl Default for InterpolatedPart {
79    fn default() -> Self {
80        InterpolatedPart::Literal(String::new())
81    }
82}
83
84/// Attribute structures for advanced widgets
85#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
86pub struct ComboBoxAttributes {
87    pub options: Vec<String>,
88    pub selected: Option<crate::expr::BindingExpr>,
89    pub placeholder: Option<String>,
90    pub on_select: Option<String>,
91}
92
93#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
94pub struct PickListAttributes {
95    pub options: Vec<String>,
96    pub selected: Option<crate::expr::BindingExpr>,
97    pub placeholder: Option<String>,
98    pub on_select: Option<String>,
99}
100
101#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
102pub struct CanvasAttributes {
103    pub width: f32,
104    pub height: f32,
105    pub program: Option<crate::expr::BindingExpr>,
106    pub on_click: Option<String>,
107}
108
109#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
110pub struct ProgressBarAttributes {
111    pub min: Option<f32>,
112    pub max: Option<f32>,
113    pub value: crate::expr::BindingExpr,
114    pub style: Option<ProgressBarStyle>,
115}
116
117#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
118pub enum ProgressBarStyle {
119    Primary,
120    Success,
121    Warning,
122    Danger,
123    Secondary,
124}
125
126#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
127pub struct TooltipAttributes {
128    pub message: String,
129    pub position: Option<TooltipPosition>,
130    pub delay: Option<u64>,
131}
132
133#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
134pub enum TooltipPosition {
135    FollowCursor,
136    Top,
137    Bottom,
138    Left,
139    Right,
140}
141
142#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
143pub struct GridAttributes {
144    pub columns: u32,
145    pub spacing: Option<f32>,
146    pub padding: Option<f32>,
147}
148
149#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
150pub struct FloatAttributes {
151    pub position: Option<FloatPosition>,
152    pub offset_x: Option<f32>,
153    pub offset_y: Option<f32>,
154    pub z_index: Option<u32>,
155}
156
157#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
158pub enum FloatPosition {
159    TopLeft,
160    TopRight,
161    BottomLeft,
162    BottomRight,
163}
164
165/// An event binding from XML to a Rust handler
166#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
167pub struct EventBinding {
168    pub event: EventKind,
169    pub handler: String,
170    /// Optional parameter expression (e.g., for on_click="delete:{item.id}")
171    pub param: Option<crate::expr::BindingExpr>,
172    pub span: Span,
173}
174
175/// Supported event types
176#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
177pub enum EventKind {
178    #[default]
179    Click,
180    Press,
181    Release,
182    Change,
183    Input,
184    Submit,
185    Select,
186    Toggle,
187    Scroll,
188}
189
190impl WidgetKind {
191    /// Returns the minimum schema version required for this widget type.
192    ///
193    /// This method provides infrastructure for version-gating widgets in future releases.
194    /// Currently, all widgets return version 1.0 as they are part of the initial release.
195    ///
196    /// # Future Usage
197    ///
198    /// When new widgets are added in future schema versions (e.g., 1.1, 1.2), this method
199    /// will be updated to return the appropriate minimum version for those widgets.
200    /// The parser can then validate that documents declaring older schema versions
201    /// do not use widgets that were introduced in later versions.
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// use dampen_core::{WidgetKind, SchemaVersion};
207    ///
208    /// let column = WidgetKind::Column;
209    /// assert_eq!(column.minimum_version(), SchemaVersion { major: 1, minor: 0 });
210    /// ```
211    ///
212    /// # Returns
213    ///
214    /// The minimum `SchemaVersion` required to use this widget type.
215    pub fn minimum_version(&self) -> crate::ir::SchemaVersion {
216        // Canvas is a v1.1 widget (experimental, not fully functional)
217        // All other widgets are part of v1.0
218        match self {
219            WidgetKind::Canvas => crate::ir::SchemaVersion { major: 1, minor: 1 },
220            _ => crate::ir::SchemaVersion { major: 1, minor: 0 },
221        }
222    }
223}