ui_grid_core/
viewmodel.rs1use crate::{
2 constants::SortDirection,
3 models::{GridColumnDef, GridIcon, GridIcons, GridLabels, GridOptions, GridRow},
4};
5
6pub fn resolve_grid_labels(overrides: Option<&GridLabels>) -> GridLabels {
7 overrides.cloned().unwrap_or_default()
8}
9
10pub fn resolve_grid_icons(overrides: Option<&GridIcons>) -> GridIcons {
11 overrides.cloned().unwrap_or_default()
12}
13
14pub fn is_grid_tree_enabled(options: &GridOptions) -> bool {
15 options.enable_tree_view
16}
17
18pub fn is_grid_grouping_enabled(options: &GridOptions) -> bool {
19 options.enable_grouping && !is_grid_tree_enabled(options)
20}
21
22pub fn can_grid_expand_rows(options: &GridOptions) -> bool {
23 options.enable_expandable
24}
25
26pub fn is_grid_pagination_enabled(options: &GridOptions) -> bool {
27 options.enable_pagination || options.pagination_page_size.unwrap_or(0) > 0
28}
29
30pub fn should_show_grid_pagination_controls(options: &GridOptions) -> bool {
31 is_grid_pagination_enabled(options) && options.enable_pagination_controls
32}
33
34pub fn is_grid_infinite_scroll_enabled(options: &GridOptions) -> bool {
35 options.infinite_scroll_rows_from_end.is_some()
36 || options.infinite_scroll_up
37 || options.infinite_scroll_down.is_some()
38}
39
40pub fn is_grid_sorting_enabled(options: &GridOptions) -> bool {
41 options.enable_sorting
42}
43
44pub fn is_grid_filtering_enabled(options: &GridOptions) -> bool {
45 options.enable_filtering
46}
47
48pub fn can_grid_move_columns(options: &GridOptions) -> bool {
49 options.enable_column_moving
50}
51
52pub fn can_grid_resize_columns(options: &GridOptions) -> bool {
53 options.enable_column_resizing
54}
55
56pub fn is_grid_primary_column(visible_columns: &[GridColumnDef], column: &GridColumnDef) -> bool {
57 visible_columns
58 .first()
59 .is_some_and(|candidate| candidate.name == column.name)
60}
61
62pub fn is_grid_column_sortable(options: &GridOptions, column: &GridColumnDef) -> bool {
63 is_grid_sorting_enabled(options) && column.sortable && column.enable_sorting
64}
65
66pub fn is_grid_column_filterable(options: &GridOptions, column: &GridColumnDef) -> bool {
67 is_grid_filtering_enabled(options) && column.filterable && column.enable_filtering
68}
69
70pub fn should_show_grid_tree_toggle(
71 options: &GridOptions,
72 visible_columns: &[GridColumnDef],
73 row: &GridRow,
74 column: &GridColumnDef,
75) -> bool {
76 is_grid_primary_column(visible_columns, column)
77 && is_grid_tree_enabled(options)
78 && (row.has_children || options.show_tree_expand_no_children)
79}
80
81pub fn should_show_grid_expand_toggle(
82 options: &GridOptions,
83 visible_columns: &[GridColumnDef],
84 column: &GridColumnDef,
85) -> bool {
86 is_grid_primary_column(visible_columns, column) && can_grid_expand_rows(options)
87}
88
89pub fn grid_sort_button_label(direction: SortDirection, labels: &GridLabels) -> String {
90 match direction {
91 SortDirection::Asc => labels.sort_asc.clone(),
92 SortDirection::Desc => labels.sort_desc.clone(),
93 SortDirection::None => labels.sort_default.clone(),
94 }
95}
96
97pub fn grid_sort_button_icon(direction: SortDirection, icons: &GridIcons) -> GridIcon {
98 match direction {
99 SortDirection::Asc => icons.sort_asc.clone(),
100 SortDirection::Desc => icons.sort_desc.clone(),
101 SortDirection::None => icons.sort_default.clone(),
102 }
103}
104
105pub fn grid_sort_aria_sort(direction: SortDirection) -> String {
106 match direction {
107 SortDirection::Asc => "ascending".to_string(),
108 SortDirection::Desc => "descending".to_string(),
109 SortDirection::None => "none".to_string(),
110 }
111}
112
113pub fn grid_grouping_button_label(is_grouped: bool, labels: &GridLabels) -> String {
114 if is_grouped {
115 labels.ungroup_column.clone()
116 } else {
117 labels.group_column.clone()
118 }
119}
120
121pub fn grid_grouping_button_icon(is_grouped: bool, icons: &GridIcons) -> GridIcon {
122 if is_grouped {
123 icons.ungroup_column.clone()
124 } else {
125 icons.group_column.clone()
126 }
127}
128
129pub fn grid_filter_placeholder(is_filterable: bool, labels: &GridLabels) -> String {
130 if is_filterable {
131 labels.filter_placeholder.clone()
132 } else {
133 labels.filter_disabled.clone()
134 }
135}
136
137pub fn grid_group_disclosure_label(collapsed: bool, labels: &GridLabels) -> String {
138 if collapsed {
139 labels.group_expand.clone()
140 } else {
141 labels.group_collapse.clone()
142 }
143}
144
145pub fn grid_group_disclosure_icon(collapsed: bool, icons: &GridIcons) -> GridIcon {
146 if collapsed {
147 icons.group_expand.clone()
148 } else {
149 icons.group_collapse.clone()
150 }
151}
152
153pub fn grid_editor_input_type(column: &GridColumnDef) -> String {
154 match column.r#type {
155 crate::models::GridColumnType::Number => "number".to_string(),
156 crate::models::GridColumnType::Date => "date".to_string(),
157 crate::models::GridColumnType::String
158 | crate::models::GridColumnType::Boolean
159 | crate::models::GridColumnType::Object => "text".to_string(),
160 }
161}
162
163pub fn grid_column_width(column: &GridColumnDef) -> String {
164 column
165 .width
166 .clone()
167 .unwrap_or_else(|| "minmax(11rem, max-content)".to_string())
168}
169
170pub fn grid_cell_indent(
171 options: &GridOptions,
172 visible_columns: &[GridColumnDef],
173 row: &GridRow,
174 column: &GridColumnDef,
175) -> String {
176 if !is_grid_primary_column(visible_columns, column) || !is_grid_tree_enabled(options) {
177 return "0px".to_string();
178 }
179
180 format!("{}px", row.tree_level * options.tree_indent.unwrap_or(10))
181}
182
183pub fn grid_tree_toggle_label(expanded: bool, labels: &GridLabels) -> String {
184 if expanded {
185 labels.tree_collapse.clone()
186 } else {
187 labels.tree_expand.clone()
188 }
189}
190
191pub fn grid_tree_toggle_icon(expanded: bool, icons: &GridIcons) -> GridIcon {
192 if expanded {
193 icons.tree_collapse.clone()
194 } else {
195 icons.tree_expand.clone()
196 }
197}
198
199pub fn grid_expand_toggle_label(expanded: bool, labels: &GridLabels) -> String {
200 if expanded {
201 labels.collapse_detail.clone()
202 } else {
203 labels.expand_detail.clone()
204 }
205}
206
207pub fn grid_expand_toggle_icon(expanded: bool, icons: &GridIcons) -> GridIcon {
208 if expanded {
209 icons.collapse_detail.clone()
210 } else {
211 icons.expand_detail.clone()
212 }
213}
214
215pub fn grid_drag_handle_icon(icons: &GridIcons) -> GridIcon {
216 icons.drag_handle.clone()
217}
218
219pub fn grid_move_left_icon(icons: &GridIcons) -> GridIcon {
220 icons.move_left.clone()
221}
222
223pub fn grid_move_right_icon(icons: &GridIcons) -> GridIcon {
224 icons.move_right.clone()
225}
226
227pub fn grid_pin_left_icon(icons: &GridIcons) -> GridIcon {
228 icons.pin_left.clone()
229}
230
231pub fn grid_pin_right_icon(icons: &GridIcons) -> GridIcon {
232 icons.pin_right.clone()
233}
234
235pub fn grid_unpin_icon(icons: &GridIcons) -> GridIcon {
236 icons.unpin.clone()
237}
238
239pub fn is_grid_column_grouped(group_by_columns: &[String], column: &GridColumnDef) -> bool {
240 group_by_columns.iter().any(|name| name == &column.name)
241}
242
243pub fn is_grid_tree_row_expanded(
244 expanded_tree_rows: &std::collections::BTreeMap<String, bool>,
245 row: &GridRow,
246) -> bool {
247 expanded_tree_rows.get(&row.id).copied().unwrap_or(false)
248}
249
250pub fn grid_tree_toggle_label_for_row(
251 expanded_tree_rows: &std::collections::BTreeMap<String, bool>,
252 row: &GridRow,
253 labels: &GridLabels,
254) -> String {
255 grid_tree_toggle_label(is_grid_tree_row_expanded(expanded_tree_rows, row), labels)
256}
257
258pub fn grid_expand_toggle_label_for_row(row: &GridRow, labels: &GridLabels) -> String {
259 grid_expand_toggle_label(row.expanded, labels)
260}