1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use crate::IRStyle;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct IRNode {
8 pub node_id: String,
9 pub node_type: String,
10 pub style: IRStyle,
11 pub hover_style: Option<IRStyle>,
12 pub active_style: Option<IRStyle>,
13 pub children: Vec<IRNode>,
14 pub events: Vec<IREvent>,
15 pub text_content: String,
16 pub attrs: HashMap<String, String>,
17 pub reactive_attrs: HashMap<String, String>,
18 pub reactive_text: String,
19 pub reactive_class: String,
20 pub reactive_style: HashMap<String, String>,
21 pub class_conditional_effects: Vec<IRConditionalClassEffect>,
22 pub condition_expr: String,
23 pub then_nodes: Vec<IRNode>,
24 pub else_nodes: Vec<IRNode>,
25 pub list_expr: String,
26 pub list_key_expr: String,
27 pub item_template: Option<Box<IRNode>>,
28 pub animations: Vec<IRAnimation>,
29 pub hover_animations: Vec<IRAnimation>,
30 pub x: f32,
31 pub y: f32,
32 pub w: f32,
33 pub h: f32,
34 pub transition_duration: f32,
35 pub transition_easing: String,
36}
37
38impl Default for IRNode {
39 fn default() -> Self {
40 Self {
41 node_id: String::new(),
42 node_type: String::new(),
43 style: IRStyle::new(),
44 hover_style: None,
45 active_style: None,
46 children: vec![],
47 events: vec![],
48 text_content: String::new(),
49 attrs: HashMap::new(),
50 reactive_attrs: HashMap::new(),
51 reactive_text: String::new(),
52 reactive_class: String::new(),
53 reactive_style: HashMap::new(),
54 class_conditional_effects: vec![],
55 condition_expr: String::new(),
56 then_nodes: vec![],
57 else_nodes: vec![],
58 list_expr: String::new(),
59 list_key_expr: String::new(),
60 item_template: None,
61 animations: vec![],
62 hover_animations: vec![],
63 x: 0.0,
64 y: 0.0,
65 w: 0.0,
66 h: 0.0,
67 transition_duration: 0.0,
68 transition_easing: "ease-in-out".to_string(),
69 }
70 }
71}
72
73#[derive(Debug, Clone, Default, Serialize, Deserialize)]
74pub struct IRWindow {
75 pub window_id: String,
76 pub title: String,
77 pub width: u32,
78 pub height: u32,
79 pub visible: bool,
80 pub min_width: Option<u32>,
81 pub max_width: Option<u32>,
82 pub min_height: Option<u32>,
83 pub max_height: Option<u32>,
84 pub modal: bool,
85 pub renderer: String,
86 pub nodes: Vec<IRNode>,
87 pub startup_logs: Vec<String>,
88 pub premain_functions: Vec<String>,
89 pub extra_headers: Vec<String>,
90 pub state_vars: Vec<HashMap<String, String>>,
91 pub reactive_consts: Vec<String>,
92 pub effect_decls: Vec<HashMap<String, String>>,
93 pub cpp_imports: Vec<HashMap<String, String>>,
94 pub keyframes: HashMap<String, Vec<IRKeyframe>>,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct IREvent {
99 pub trigger: String,
100 pub action: String,
101 pub target: String,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct IRConditionalClassEffect {
109 pub condition: String,
110 pub on_styles: HashMap<String, String>,
111 pub off_styles: HashMap<String, String>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct IRAnimation {
116 pub name: String,
117 pub easing: String,
118 pub direction: String,
119 pub fill_mode: String,
120 pub play_state: String,
121 pub duration: f32,
122 pub delay: f32,
123 pub iterations: f32,
124}
125
126impl Default for IRAnimation {
127 fn default() -> Self {
128 Self {
129 name: String::new(),
130 easing: "linear".into(),
131 direction: "normal".into(),
132 fill_mode: "none".into(),
133 play_state: "running".into(),
134 duration: 0.0,
135 delay: 0.0,
136 iterations: 1.0,
137 }
138 }
139}
140
141#[derive(Debug, Clone, Default, Serialize, Deserialize)]
142pub struct IRKeyframe {
143 pub offset: f32,
144 pub style: IRStyle,
145 pub declared: Vec<String>,
147 pub raw: HashMap<String, String>,
150}