@effindomv2/fui-rs 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/COMMERCIAL.md +7 -0
  2. package/Cargo.toml +34 -0
  3. package/LICENSE.md +9 -0
  4. package/README.md +88 -0
  5. package/package.json +54 -0
  6. package/scripts/build.sh +227 -0
  7. package/scripts/check-runtime-dependency.sh +41 -0
  8. package/scripts/framework-host-services.ts +40 -0
  9. package/scripts/generate-host-events.ts +17 -0
  10. package/scripts/generate-host-services.ts +28 -0
  11. package/scripts/hostgen/common.ts +73 -0
  12. package/scripts/hostgen/registry.ts +159 -0
  13. package/scripts/hostgen/rust-host-events.ts +171 -0
  14. package/scripts/hostgen/rust-host-services.ts +257 -0
  15. package/src/animation.rs +625 -0
  16. package/src/app.rs +324 -0
  17. package/src/assets.rs +572 -0
  18. package/src/bindings/mod.rs +1 -0
  19. package/src/bindings/ui.rs +705 -0
  20. package/src/bitmap.rs +317 -0
  21. package/src/bridge_callbacks.rs +242 -0
  22. package/src/context_menu_manager.rs +332 -0
  23. package/src/controls/anti_selection_area.rs +54 -0
  24. package/src/controls/button.rs +542 -0
  25. package/src/controls/checkbox.rs +372 -0
  26. package/src/controls/combobox.rs +1574 -0
  27. package/src/controls/context_menu.rs +1367 -0
  28. package/src/controls/control_template_set.rs +46 -0
  29. package/src/controls/control_tokens.rs +596 -0
  30. package/src/controls/dialog.rs +590 -0
  31. package/src/controls/dropdown.rs +1010 -0
  32. package/src/controls/form.rs +229 -0
  33. package/src/controls/internal/button_presenter.rs +142 -0
  34. package/src/controls/internal/checkbox_indicator_presenter.rs +210 -0
  35. package/src/controls/internal/dropdown_chevron_presenter.rs +134 -0
  36. package/src/controls/internal/dropdown_field_presenter.rs +269 -0
  37. package/src/controls/internal/dropdown_option_row_presenter.rs +184 -0
  38. package/src/controls/internal/mod.rs +13 -0
  39. package/src/controls/internal/pressable_indicator_presenter.rs +26 -0
  40. package/src/controls/internal/pressable_labeled_control.rs +492 -0
  41. package/src/controls/internal/radio_indicator_presenter.rs +208 -0
  42. package/src/controls/internal/selectable_popup_list.rs +597 -0
  43. package/src/controls/internal/slider_presenter.rs +282 -0
  44. package/src/controls/internal/switch_indicator_presenter.rs +235 -0
  45. package/src/controls/internal/text_input_core.rs +1074 -0
  46. package/src/controls/internal/text_input_presenter.rs +108 -0
  47. package/src/controls/mod.rs +235 -0
  48. package/src/controls/nav_link.rs +395 -0
  49. package/src/controls/popup.rs +191 -0
  50. package/src/controls/progress_bar.rs +287 -0
  51. package/src/controls/radio_button.rs +348 -0
  52. package/src/controls/radio_group.rs +283 -0
  53. package/src/controls/selection_area.rs +82 -0
  54. package/src/controls/shared.rs +68 -0
  55. package/src/controls/slider.rs +701 -0
  56. package/src/controls/switch.rs +293 -0
  57. package/src/controls/templating.rs +49 -0
  58. package/src/controls/tests.rs +3905 -0
  59. package/src/controls/text_area.rs +207 -0
  60. package/src/controls/text_input.rs +192 -0
  61. package/src/debug.rs +146 -0
  62. package/src/drag_drop.rs +424 -0
  63. package/src/drag_gesture.rs +258 -0
  64. package/src/drawing.rs +385 -0
  65. package/src/event.rs +1603 -0
  66. package/src/external_drop.rs +467 -0
  67. package/src/fetch.rs +500 -0
  68. package/src/ffi.rs +3542 -0
  69. package/src/file.rs +1677 -0
  70. package/src/focus_adorner.rs +307 -0
  71. package/src/focus_visibility.rs +121 -0
  72. package/src/frame_scheduler.rs +159 -0
  73. package/src/frame_signal.rs +64 -0
  74. package/src/generated/ffi.rs +798 -0
  75. package/src/generated/framework_host_services.rs +74 -0
  76. package/src/generated/mod.rs +2 -0
  77. package/src/host_services.rs +162 -0
  78. package/src/image_sampling.rs +78 -0
  79. package/src/keyboard_scroll.rs +137 -0
  80. package/src/keyboard_scroll_tracker.rs +385 -0
  81. package/src/lib.rs +547 -0
  82. package/src/logger.rs +56 -0
  83. package/src/mobile_text_selection_toolbar.rs +1034 -0
  84. package/src/navigation.rs +48 -0
  85. package/src/node/core.rs +2210 -0
  86. package/src/node/custom_drawable.rs +149 -0
  87. package/src/node/flex_box.rs +874 -0
  88. package/src/node/grid.rs +304 -0
  89. package/src/node/helpers.rs +442 -0
  90. package/src/node/image.rs +506 -0
  91. package/src/node/mod.rs +315 -0
  92. package/src/node/scroll_bar.rs +845 -0
  93. package/src/node/scroll_box.rs +514 -0
  94. package/src/node/scroll_state.rs +121 -0
  95. package/src/node/scroll_view.rs +557 -0
  96. package/src/node/svg_node.rs +474 -0
  97. package/src/node/text_node.rs +633 -0
  98. package/src/node/virtual_list.rs +678 -0
  99. package/src/panic_hook.rs +36 -0
  100. package/src/persisted.rs +274 -0
  101. package/src/platform.rs +556 -0
  102. package/src/popup_presenter.rs +344 -0
  103. package/src/selection_handle_adorner.rs +838 -0
  104. package/src/signal.rs +134 -0
  105. package/src/text.rs +1065 -0
  106. package/src/theme.rs +571 -0
  107. package/src/timers.rs +106 -0
  108. package/src/tool_tip.rs +167 -0
  109. package/src/tool_tip_manager.rs +691 -0
  110. package/src/transitions.rs +41 -0
  111. package/src/typography.rs +520 -0
  112. package/src/viewport.rs +108 -0
  113. package/src/worker.rs +308 -0
  114. package/src/worker_job.rs +82 -0
  115. package/src/worker_runtime.rs +172 -0
@@ -0,0 +1,269 @@
1
+ use crate::controls::{DropdownColors, DropdownSizing};
2
+ use crate::ffi::{AlignItems, FlexDirection, JustifyContent, TextVerticalAlign, Unit};
3
+ use crate::node::{flex_box, text, FlexBox, TextNode};
4
+ use crate::theme::Theme;
5
+ use std::rc::Rc;
6
+
7
+ const DEFAULT_CHEVRON_BOX_SIZE: f32 = 16.0;
8
+ const DEFAULT_FIELD_PADDING_X: f32 = 16.0;
9
+ const DEFAULT_FIELD_FONT_SIZE: f32 = 16.0;
10
+ const DEFAULT_FIELD_HEIGHT: f32 = 32.0;
11
+
12
+ #[derive(Clone, Copy, Debug, PartialEq)]
13
+ pub struct DropdownFieldMetrics {
14
+ pub height: f32,
15
+ pub font_size: f32,
16
+ pub chevron_box_size: f32,
17
+ pub padding_left: f32,
18
+ pub padding_top: f32,
19
+ pub padding_right: f32,
20
+ pub padding_bottom: f32,
21
+ }
22
+
23
+ impl DropdownFieldMetrics {
24
+ pub const fn new(
25
+ height: f32,
26
+ font_size: f32,
27
+ chevron_box_size: f32,
28
+ padding_left: f32,
29
+ padding_top: f32,
30
+ padding_right: f32,
31
+ padding_bottom: f32,
32
+ ) -> Self {
33
+ Self {
34
+ height,
35
+ font_size,
36
+ chevron_box_size,
37
+ padding_left,
38
+ padding_top,
39
+ padding_right,
40
+ padding_bottom,
41
+ }
42
+ }
43
+ }
44
+
45
+ pub const DEFAULT_DROPDOWN_FIELD_METRICS: DropdownFieldMetrics = DropdownFieldMetrics::new(
46
+ DEFAULT_FIELD_HEIGHT,
47
+ DEFAULT_FIELD_FONT_SIZE,
48
+ DEFAULT_CHEVRON_BOX_SIZE,
49
+ DEFAULT_FIELD_PADDING_X,
50
+ 0.0,
51
+ DEFAULT_FIELD_PADDING_X,
52
+ 0.0,
53
+ );
54
+
55
+ fn resolve_field_metrics(sizing: Option<DropdownSizing>) -> DropdownFieldMetrics {
56
+ let Some(sizing) = sizing else {
57
+ return DEFAULT_DROPDOWN_FIELD_METRICS;
58
+ };
59
+ if !sizing.has_field_height() && !sizing.has_field_font_size() && !sizing.has_chevron_box_size()
60
+ {
61
+ return DEFAULT_DROPDOWN_FIELD_METRICS;
62
+ }
63
+ let font_size = if sizing.has_field_font_size() {
64
+ sizing.field_font_size_px()
65
+ } else {
66
+ DEFAULT_DROPDOWN_FIELD_METRICS.font_size
67
+ };
68
+ let chevron_box_size = if sizing.has_chevron_box_size() {
69
+ sizing.chevron_box_size_px()
70
+ } else {
71
+ DEFAULT_DROPDOWN_FIELD_METRICS.chevron_box_size
72
+ };
73
+ let content_height = font_size.max(chevron_box_size);
74
+ let height = if sizing.has_field_height() {
75
+ sizing.field_height_px()
76
+ } else {
77
+ DEFAULT_DROPDOWN_FIELD_METRICS.height.max(content_height)
78
+ };
79
+ DropdownFieldMetrics::new(
80
+ height,
81
+ font_size,
82
+ chevron_box_size,
83
+ DEFAULT_FIELD_PADDING_X,
84
+ 0.0,
85
+ DEFAULT_FIELD_PADDING_X,
86
+ 0.0,
87
+ )
88
+ }
89
+
90
+ #[derive(Clone, Debug, PartialEq, Eq)]
91
+ pub struct DropdownFieldVisualState {
92
+ pub open: bool,
93
+ pub focused: bool,
94
+ pub enabled: bool,
95
+ pub pressed: bool,
96
+ pub selected_label: String,
97
+ }
98
+
99
+ impl DropdownFieldVisualState {
100
+ pub fn new(
101
+ open: bool,
102
+ focused: bool,
103
+ enabled: bool,
104
+ pressed: bool,
105
+ selected_label: impl Into<String>,
106
+ ) -> Self {
107
+ Self {
108
+ open,
109
+ focused,
110
+ enabled,
111
+ pressed,
112
+ selected_label: selected_label.into(),
113
+ }
114
+ }
115
+ }
116
+
117
+ pub trait DropdownFieldPresenter {
118
+ fn root(&self) -> FlexBox;
119
+ fn value_host(&self) -> FlexBox;
120
+ fn value_node(&self) -> TextNode;
121
+ fn chevron_host(&self) -> FlexBox;
122
+ fn metrics(&self) -> DropdownFieldMetrics;
123
+ fn apply(&self, theme: Theme, state: &DropdownFieldVisualState, colors: Option<DropdownColors>);
124
+ }
125
+
126
+ pub trait DropdownFieldTemplate {
127
+ fn create(&self, sizing: Option<DropdownSizing>) -> Rc<dyn DropdownFieldPresenter>;
128
+ }
129
+
130
+ #[derive(Clone)]
131
+ pub struct DefaultDropdownFieldPresenter {
132
+ root: FlexBox,
133
+ value_host: FlexBox,
134
+ value_node: TextNode,
135
+ chevron_host: FlexBox,
136
+ metrics: DropdownFieldMetrics,
137
+ }
138
+
139
+ impl DefaultDropdownFieldPresenter {
140
+ pub fn new(metrics: DropdownFieldMetrics) -> Self {
141
+ let theme = crate::theme::current_theme();
142
+ let value_node = text("");
143
+ value_node
144
+ .selectable(false, theme.colors.selection)
145
+ .fill_size()
146
+ .text_limits(0, 1)
147
+ .wrapping(false);
148
+ value_node
149
+ .text_overflow_fade(true, false)
150
+ .text_vertical_align(TextVerticalAlign::Center);
151
+ let value_host = flex_box();
152
+ value_host.fill_size().child(&value_node);
153
+ let chevron_host = flex_box();
154
+ chevron_host
155
+ .width(metrics.chevron_box_size, Unit::Pixel)
156
+ .height(metrics.chevron_box_size, Unit::Pixel)
157
+ .align_items(AlignItems::Center)
158
+ .justify_content(JustifyContent::Center);
159
+ let root = flex_box();
160
+ root.flex_direction(FlexDirection::Row)
161
+ .align_items(AlignItems::Center)
162
+ .child(&value_host)
163
+ .child(&chevron_host);
164
+ Self {
165
+ root,
166
+ value_host,
167
+ value_node: value_node.clone(),
168
+ chevron_host,
169
+ metrics,
170
+ }
171
+ }
172
+ }
173
+
174
+ impl DropdownFieldPresenter for DefaultDropdownFieldPresenter {
175
+ fn root(&self) -> FlexBox {
176
+ self.root.clone()
177
+ }
178
+
179
+ fn value_host(&self) -> FlexBox {
180
+ self.value_host.clone()
181
+ }
182
+
183
+ fn value_node(&self) -> TextNode {
184
+ self.value_node.clone()
185
+ }
186
+
187
+ fn chevron_host(&self) -> FlexBox {
188
+ self.chevron_host.clone()
189
+ }
190
+
191
+ fn metrics(&self) -> DropdownFieldMetrics {
192
+ self.metrics
193
+ }
194
+
195
+ fn apply(
196
+ &self,
197
+ theme: Theme,
198
+ state: &DropdownFieldVisualState,
199
+ colors: Option<DropdownColors>,
200
+ ) {
201
+ let metrics = self.metrics;
202
+ let content_height = metrics
203
+ .font_size
204
+ .max(metrics.height - metrics.padding_top - metrics.padding_bottom);
205
+ let bg = if colors.is_some_and(|colors| colors.has_background()) {
206
+ colors.unwrap().background_color()
207
+ } else if state.pressed && state.enabled {
208
+ theme.colors.background
209
+ } else {
210
+ theme.colors.surface
211
+ };
212
+ let border_color = colors
213
+ .filter(|colors| colors.has_border())
214
+ .map(|colors| colors.border_color())
215
+ .unwrap_or(theme.colors.border);
216
+ self.root
217
+ .flex_direction(FlexDirection::Row)
218
+ .align_items(AlignItems::Center)
219
+ .height(metrics.height, Unit::Pixel)
220
+ .corner_radius(theme.spacing.sm)
221
+ .border(2.0, border_color)
222
+ .padding(
223
+ metrics.padding_left,
224
+ metrics.padding_top,
225
+ metrics.padding_right,
226
+ metrics.padding_bottom,
227
+ )
228
+ .bg_color(bg);
229
+ self.value_host.fill_size();
230
+ let text_color = if !state.enabled {
231
+ theme.colors.text_muted
232
+ } else {
233
+ colors
234
+ .filter(|colors| colors.has_text_primary())
235
+ .map(|colors| colors.text_primary_color())
236
+ .unwrap_or(theme.colors.text_primary)
237
+ };
238
+ self.value_node
239
+ .font_family(theme.fonts.body_family.clone())
240
+ .font_size(metrics.font_size)
241
+ .line_height(content_height)
242
+ .text_color(text_color);
243
+ self.chevron_host
244
+ .width(metrics.chevron_box_size, Unit::Pixel)
245
+ .height(metrics.chevron_box_size, Unit::Pixel)
246
+ .align_items(AlignItems::Center)
247
+ .justify_content(JustifyContent::Center);
248
+ }
249
+ }
250
+
251
+ #[derive(Clone, Copy, Debug, Default)]
252
+ pub struct DefaultDropdownFieldTemplate;
253
+
254
+ impl DropdownFieldTemplate for DefaultDropdownFieldTemplate {
255
+ fn create(&self, sizing: Option<DropdownSizing>) -> Rc<dyn DropdownFieldPresenter> {
256
+ create_default_dropdown_field_presenter(sizing)
257
+ }
258
+ }
259
+
260
+ pub const DEFAULT_DROPDOWN_FIELD_TEMPLATE: DefaultDropdownFieldTemplate =
261
+ DefaultDropdownFieldTemplate;
262
+
263
+ pub fn create_default_dropdown_field_presenter(
264
+ sizing: Option<DropdownSizing>,
265
+ ) -> Rc<dyn DropdownFieldPresenter> {
266
+ Rc::new(DefaultDropdownFieldPresenter::new(resolve_field_metrics(
267
+ sizing,
268
+ )))
269
+ }
@@ -0,0 +1,184 @@
1
+ use crate::controls::{DropdownColors, DropdownSizing};
2
+ use crate::ffi::{AlignItems, TextVerticalAlign};
3
+ use crate::node::{flex_box, text, FlexBox, TextNode};
4
+ use crate::theme::Theme;
5
+ use std::rc::Rc;
6
+
7
+ #[derive(Clone, Copy, Debug, PartialEq)]
8
+ pub struct DropdownOptionRowMetrics {
9
+ pub height: f32,
10
+ pub padding_left: f32,
11
+ pub padding_right: f32,
12
+ pub font_size: f32,
13
+ }
14
+
15
+ impl DropdownOptionRowMetrics {
16
+ pub const fn new(height: f32, padding_left: f32, padding_right: f32, font_size: f32) -> Self {
17
+ Self {
18
+ height,
19
+ padding_left,
20
+ padding_right,
21
+ font_size,
22
+ }
23
+ }
24
+ }
25
+
26
+ pub const DEFAULT_DROPDOWN_OPTION_ROW_METRICS: DropdownOptionRowMetrics =
27
+ DropdownOptionRowMetrics::new(34.0, 10.0, 10.0, 16.0);
28
+
29
+ fn resolve_option_row_metrics(sizing: Option<DropdownSizing>) -> DropdownOptionRowMetrics {
30
+ let Some(sizing) = sizing else {
31
+ return DEFAULT_DROPDOWN_OPTION_ROW_METRICS;
32
+ };
33
+ if !sizing.has_option_height() && !sizing.has_option_font_size() {
34
+ return DEFAULT_DROPDOWN_OPTION_ROW_METRICS;
35
+ }
36
+ let font_size = if sizing.has_option_font_size() {
37
+ sizing.option_font_size_px()
38
+ } else {
39
+ DEFAULT_DROPDOWN_OPTION_ROW_METRICS.font_size
40
+ };
41
+ let height = if sizing.has_option_height() {
42
+ sizing.option_height_px()
43
+ } else {
44
+ DEFAULT_DROPDOWN_OPTION_ROW_METRICS.height
45
+ };
46
+ DropdownOptionRowMetrics::new(
47
+ height,
48
+ DEFAULT_DROPDOWN_OPTION_ROW_METRICS.padding_left,
49
+ DEFAULT_DROPDOWN_OPTION_ROW_METRICS.padding_right,
50
+ font_size,
51
+ )
52
+ }
53
+
54
+ #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
55
+ pub struct DropdownOptionRowVisualState {
56
+ pub highlighted: bool,
57
+ pub selected: bool,
58
+ pub enabled: bool,
59
+ }
60
+
61
+ impl DropdownOptionRowVisualState {
62
+ pub const fn new(highlighted: bool, selected: bool, enabled: bool) -> Self {
63
+ Self {
64
+ highlighted,
65
+ selected,
66
+ enabled,
67
+ }
68
+ }
69
+ }
70
+
71
+ pub trait DropdownOptionRowPresenter {
72
+ fn root(&self) -> FlexBox;
73
+ fn label_node(&self) -> TextNode;
74
+ fn metrics(&self) -> DropdownOptionRowMetrics;
75
+ fn apply(
76
+ &self,
77
+ theme: Theme,
78
+ state: DropdownOptionRowVisualState,
79
+ colors: Option<DropdownColors>,
80
+ );
81
+ }
82
+
83
+ pub trait DropdownOptionRowTemplate {
84
+ fn create(&self, sizing: Option<DropdownSizing>) -> Rc<dyn DropdownOptionRowPresenter>;
85
+ }
86
+
87
+ #[derive(Clone)]
88
+ pub struct DefaultDropdownOptionRowPresenter {
89
+ root: FlexBox,
90
+ label_node: TextNode,
91
+ metrics: DropdownOptionRowMetrics,
92
+ }
93
+
94
+ impl DefaultDropdownOptionRowPresenter {
95
+ pub fn new(metrics: DropdownOptionRowMetrics) -> Self {
96
+ let theme = crate::theme::current_theme();
97
+ let label_node = text("");
98
+ label_node
99
+ .selectable(false, theme.colors.selection)
100
+ .fill_size()
101
+ .text_limits(0, 1)
102
+ .wrapping(false);
103
+ label_node
104
+ .text_overflow_fade(true, false)
105
+ .text_vertical_align(TextVerticalAlign::Center);
106
+ let root = flex_box();
107
+ root.fill_size()
108
+ .align_items(AlignItems::Center)
109
+ .child(&label_node);
110
+ Self {
111
+ root,
112
+ label_node: label_node.clone(),
113
+ metrics,
114
+ }
115
+ }
116
+ }
117
+
118
+ impl DropdownOptionRowPresenter for DefaultDropdownOptionRowPresenter {
119
+ fn root(&self) -> FlexBox {
120
+ self.root.clone()
121
+ }
122
+
123
+ fn label_node(&self) -> TextNode {
124
+ self.label_node.clone()
125
+ }
126
+
127
+ fn metrics(&self) -> DropdownOptionRowMetrics {
128
+ self.metrics
129
+ }
130
+
131
+ fn apply(
132
+ &self,
133
+ theme: Theme,
134
+ state: DropdownOptionRowVisualState,
135
+ colors: Option<DropdownColors>,
136
+ ) {
137
+ let metrics = self.metrics;
138
+ self.root
139
+ .padding(metrics.padding_left, 0.0, metrics.padding_right, 0.0)
140
+ .corner_radius(theme.spacing.xs)
141
+ .bg_color(if state.highlighted {
142
+ theme.context_menu.item.hover_background
143
+ } else {
144
+ 0x00000000
145
+ });
146
+ let label_color = if !state.enabled {
147
+ theme.colors.text_muted
148
+ } else if state.selected {
149
+ colors
150
+ .filter(|colors| colors.has_accent())
151
+ .map(|colors| colors.accent_color())
152
+ .unwrap_or(theme.colors.accent)
153
+ } else {
154
+ colors
155
+ .filter(|colors| colors.has_text_primary())
156
+ .map(|colors| colors.text_primary_color())
157
+ .unwrap_or(theme.colors.text_primary)
158
+ };
159
+ self.label_node
160
+ .font_family(theme.fonts.body_family.clone())
161
+ .font_size(metrics.font_size)
162
+ .text_color(label_color);
163
+ }
164
+ }
165
+
166
+ #[derive(Clone, Copy, Debug, Default)]
167
+ pub struct DefaultDropdownOptionRowTemplate;
168
+
169
+ impl DropdownOptionRowTemplate for DefaultDropdownOptionRowTemplate {
170
+ fn create(&self, sizing: Option<DropdownSizing>) -> Rc<dyn DropdownOptionRowPresenter> {
171
+ create_default_dropdown_option_row_presenter(sizing)
172
+ }
173
+ }
174
+
175
+ pub const DEFAULT_DROPDOWN_OPTION_ROW_TEMPLATE: DefaultDropdownOptionRowTemplate =
176
+ DefaultDropdownOptionRowTemplate;
177
+
178
+ pub fn create_default_dropdown_option_row_presenter(
179
+ sizing: Option<DropdownSizing>,
180
+ ) -> Rc<dyn DropdownOptionRowPresenter> {
181
+ Rc::new(DefaultDropdownOptionRowPresenter::new(
182
+ resolve_option_row_metrics(sizing),
183
+ ))
184
+ }
@@ -0,0 +1,13 @@
1
+ pub(crate) mod button_presenter;
2
+ pub(crate) mod checkbox_indicator_presenter;
3
+ pub(crate) mod dropdown_chevron_presenter;
4
+ pub(crate) mod dropdown_field_presenter;
5
+ pub(crate) mod dropdown_option_row_presenter;
6
+ pub(crate) mod pressable_indicator_presenter;
7
+ pub(crate) mod pressable_labeled_control;
8
+ pub(crate) mod radio_indicator_presenter;
9
+ pub(crate) mod selectable_popup_list;
10
+ pub(crate) mod slider_presenter;
11
+ pub(crate) mod switch_indicator_presenter;
12
+ pub(crate) mod text_input_core;
13
+ pub(crate) mod text_input_presenter;
@@ -0,0 +1,26 @@
1
+ use crate::node::FlexBox;
2
+
3
+ #[derive(Clone, Copy, Debug, PartialEq)]
4
+ pub struct PressableIndicatorMetrics {
5
+ pub width: f32,
6
+ pub height: f32,
7
+ }
8
+
9
+ impl PressableIndicatorMetrics {
10
+ pub const fn new(width: f32, height: f32) -> Self {
11
+ Self { width, height }
12
+ }
13
+ }
14
+
15
+ #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
16
+ pub struct PressableIndicatorVisualState {
17
+ pub hovered: bool,
18
+ pub pressed: bool,
19
+ pub focused: bool,
20
+ pub enabled: bool,
21
+ }
22
+
23
+ pub trait PressableIndicatorPresenter {
24
+ fn root(&self) -> FlexBox;
25
+ fn metrics(&self) -> PressableIndicatorMetrics;
26
+ }