@perspective-dev/viewer 4.0.0 → 4.1.0

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 (184) hide show
  1. package/dist/cdn/perspective-viewer.js +2 -2
  2. package/dist/cdn/perspective-viewer.js.map +4 -4
  3. package/dist/css/dracula.css +1 -1
  4. package/dist/css/gruvbox-dark.css +1 -1
  5. package/dist/css/gruvbox.css +1 -1
  6. package/dist/css/icons.css +1 -1
  7. package/dist/css/monokai.css +1 -1
  8. package/dist/css/pro-dark.css +1 -1
  9. package/dist/css/pro.css +1 -1
  10. package/dist/css/solarized-dark.css +1 -1
  11. package/dist/css/solarized.css +1 -1
  12. package/dist/css/themes.css +1 -1
  13. package/dist/css/vaporwave.css +1 -1
  14. package/dist/esm/extensions.d.ts +23 -2
  15. package/dist/esm/perspective-viewer.d.ts +2 -7
  16. package/dist/esm/perspective-viewer.inline.js +2 -2
  17. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  18. package/dist/esm/perspective-viewer.js +2 -2
  19. package/dist/esm/perspective-viewer.js.map +4 -4
  20. package/dist/esm/plugin.d.ts +1 -1
  21. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +1 -0
  22. package/dist/wasm/perspective-viewer.d.ts +218 -46
  23. package/dist/wasm/perspective-viewer.js +1251 -762
  24. package/dist/wasm/perspective-viewer.wasm +0 -0
  25. package/dist/wasm/perspective-viewer.wasm.d.ts +38 -19
  26. package/package.json +1 -1
  27. package/src/less/containers/scroll-panel.less +0 -1
  28. package/src/less/plugin-selector.less +15 -5
  29. package/src/less/status-bar.less +75 -27
  30. package/src/less/viewer.less +140 -58
  31. package/src/rust/components/column_dropdown.rs +21 -21
  32. package/src/rust/components/column_selector/active_column.rs +131 -120
  33. package/src/rust/components/column_selector/add_expression_button.rs +5 -0
  34. package/src/rust/components/column_selector/aggregate_selector.rs +8 -4
  35. package/src/rust/components/column_selector/config_selector.rs +170 -161
  36. package/src/rust/components/column_selector/empty_column.rs +16 -11
  37. package/src/rust/components/column_selector/{expression_toolbar.rs → expr_edit_button.rs} +7 -0
  38. package/src/rust/components/column_selector/filter_column.rs +195 -194
  39. package/src/rust/components/column_selector/inactive_column.rs +82 -67
  40. package/src/rust/components/column_selector/pivot_column.rs +16 -11
  41. package/src/rust/components/column_selector/sort_column.rs +9 -7
  42. package/src/rust/components/column_selector.rs +42 -37
  43. package/src/rust/components/column_settings_sidebar/save_settings.rs +3 -1
  44. package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +58 -0
  45. package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +6 -6
  46. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +2 -94
  47. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +111 -0
  48. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +3 -3
  49. package/src/rust/components/column_settings_sidebar/style_tab.rs +23 -83
  50. package/src/rust/components/{column_settings_sidebar/sidebar.rs → column_settings_sidebar.rs} +198 -171
  51. package/src/rust/components/containers/dragdrop_list.rs +20 -20
  52. package/src/rust/components/containers/dropdown_menu.rs +4 -6
  53. package/src/rust/components/containers/mod.rs +1 -4
  54. package/src/rust/components/containers/scroll_panel.rs +80 -80
  55. package/src/rust/components/containers/scroll_panel_item.rs +36 -36
  56. package/src/rust/components/containers/select.rs +46 -44
  57. package/src/rust/components/containers/sidebar.rs +3 -19
  58. package/src/rust/components/{column_settings_sidebar/style_tab/symbol/symbol_config.rs → containers/sidebar_close_button.rs} +15 -9
  59. package/src/rust/components/containers/split_panel.rs +212 -200
  60. package/src/rust/components/containers/tab_list.rs +11 -11
  61. package/src/rust/components/copy_dropdown.rs +22 -25
  62. package/src/rust/components/datetime_column_style/custom.rs +19 -19
  63. package/src/rust/components/datetime_column_style/simple.rs +13 -14
  64. package/src/rust/components/datetime_column_style.rs +75 -76
  65. package/src/rust/components/editable_header.rs +18 -14
  66. package/src/rust/components/empty_row.rs +5 -5
  67. package/src/rust/components/export_dropdown.rs +42 -42
  68. package/src/rust/components/expression_editor.rs +25 -19
  69. package/src/rust/components/filter_dropdown.rs +22 -22
  70. package/src/rust/components/font_loader.rs +11 -9
  71. package/src/rust/components/form/code_editor.rs +106 -105
  72. package/src/rust/components/form/color_range_selector.rs +14 -12
  73. package/src/rust/components/form/color_selector.rs +3 -1
  74. package/src/rust/components/form/debug.rs +95 -94
  75. package/src/rust/components/form/highlight.rs +5 -3
  76. package/src/rust/components/form/mod.rs +3 -2
  77. package/src/rust/components/form/optional_field.rs +2 -2
  78. package/src/rust/components/form/{select_field.rs → select_enum_field.rs} +1 -46
  79. package/src/rust/components/form/select_value_field.rs +64 -0
  80. package/src/rust/components/function_dropdown.rs +21 -21
  81. package/src/rust/components/main_panel.rs +219 -0
  82. package/src/rust/components/mod.rs +6 -6
  83. package/src/rust/components/modal.rs +42 -42
  84. package/src/rust/components/number_column_style.rs +34 -88
  85. package/src/rust/components/plugin_selector.rs +22 -25
  86. package/src/rust/components/render_warning.rs +9 -6
  87. package/src/rust/components/settings_panel.rs +82 -0
  88. package/src/rust/components/status_bar.rs +250 -146
  89. package/src/rust/components/status_bar_counter.rs +26 -119
  90. package/src/rust/components/status_indicator.rs +95 -79
  91. package/src/rust/components/string_column_style.rs +45 -45
  92. package/src/rust/components/style/style_provider.rs +1 -15
  93. package/src/rust/components/style_controls/number_string_format/digits_section.rs +1 -1
  94. package/src/rust/components/style_controls/number_string_format/misc_section.rs +1 -1
  95. package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -1
  96. package/src/rust/components/style_controls/number_string_format.rs +45 -46
  97. package/src/rust/components/type_icon.rs +14 -11
  98. package/src/rust/components/viewer.rs +241 -384
  99. package/src/rust/config/columns_config.rs +2 -2
  100. package/src/rust/config/datetime_column_style.rs +1 -6
  101. package/src/rust/config/mod.rs +1 -0
  102. package/src/rust/config/number_column_style.rs +0 -6
  103. package/src/rust/config/number_string_format.rs +27 -4
  104. package/src/rust/config/viewer_config.rs +27 -167
  105. package/src/rust/custom_elements/copy_dropdown.rs +14 -6
  106. package/src/rust/custom_elements/export_dropdown.rs +15 -7
  107. package/src/rust/custom_elements/filter_dropdown.rs +4 -4
  108. package/src/rust/custom_elements/mod.rs +3 -0
  109. package/src/rust/custom_elements/viewer.rs +353 -161
  110. package/src/rust/custom_events.rs +55 -32
  111. package/src/rust/dragdrop.rs +4 -24
  112. package/src/rust/exprtk/cursor.rs +10 -1
  113. package/src/rust/exprtk/mod.rs +2 -0
  114. package/src/rust/exprtk/tokenize.rs +20 -3
  115. package/src/rust/js/clipboard.rs +2 -2
  116. package/src/rust/js/mimetype.rs +2 -7
  117. package/src/rust/js/mod.rs +0 -1
  118. package/src/rust/js/plugin.rs +7 -0
  119. package/src/rust/lib.rs +18 -5
  120. package/src/rust/model/column_locator.rs +82 -0
  121. package/src/rust/model/columns_iter_set.rs +1 -0
  122. package/src/rust/model/copy_export.rs +50 -14
  123. package/src/rust/model/edit_expression.rs +2 -5
  124. package/src/rust/model/eject.rs +41 -0
  125. package/src/rust/model/export_app.rs +3 -2
  126. package/src/rust/model/get_viewer_config.rs +4 -28
  127. package/src/rust/model/intersection_observer.rs +20 -8
  128. package/src/rust/model/mod.rs +11 -4
  129. package/src/rust/model/plugin_column_styles.rs +0 -31
  130. package/src/rust/model/reset_all.rs +38 -0
  131. package/src/rust/model/resize_observer.rs +34 -7
  132. package/src/rust/model/restore_and_render.rs +12 -7
  133. package/src/rust/{utils/scope.rs → model/send_plugin_config.rs} +32 -35
  134. package/src/rust/model/structural.rs +194 -23
  135. package/src/rust/model/update_and_render.rs +14 -4
  136. package/src/rust/{model/create_col.rs → presentation/column_locator.rs} +73 -42
  137. package/src/rust/{utils/wasm_abi.rs → presentation/sheets.rs} +54 -40
  138. package/src/rust/presentation.rs +60 -119
  139. package/src/rust/renderer/activate.rs +20 -5
  140. package/src/rust/renderer/limits.rs +0 -149
  141. package/src/rust/renderer/render_timer.rs +1 -1
  142. package/src/rust/renderer.rs +34 -18
  143. package/src/rust/root.rs +50 -0
  144. package/src/rust/session/column_defaults_update.rs +4 -4
  145. package/src/rust/session/drag_drop_update.rs +1 -1
  146. package/src/rust/session/metadata.rs +3 -17
  147. package/src/rust/session/replace_expression_update.rs +1 -2
  148. package/src/rust/session.rs +162 -82
  149. package/src/rust/utils/browser/blob.rs +16 -2
  150. package/src/rust/utils/browser/download.rs +1 -0
  151. package/src/rust/{components/column_settings_sidebar/mod.rs → utils/browser/dragdrop.rs} +14 -5
  152. package/src/rust/utils/browser/mod.rs +8 -4
  153. package/src/rust/utils/browser/selection.rs +5 -0
  154. package/src/rust/utils/custom_element.rs +28 -13
  155. package/src/rust/utils/datetime.rs +5 -0
  156. package/src/rust/utils/debounce.rs +7 -1
  157. package/src/rust/utils/hooks/use_async_callback.rs +7 -17
  158. package/src/rust/utils/mod.rs +28 -40
  159. package/src/rust/utils/number_format.rs +6 -5
  160. package/src/rust/utils/pubsub.rs +15 -10
  161. package/src/rust/utils/weak_scope.rs +11 -1
  162. package/src/svg/bookmark-icon.svg +4 -0
  163. package/src/svg/drag-handle copy.svg +10 -0
  164. package/src/svg/drawer-tab-hover.svg +5 -7
  165. package/src/svg/drawer-tab-invert-hover.svg +4 -8
  166. package/src/svg/drawer-tab-invert.svg +4 -7
  167. package/src/svg/drawer-tab.svg +4 -6
  168. package/src/svg/status_ok.svg +24 -24
  169. package/src/ts/extensions.ts +51 -3
  170. package/src/ts/perspective-viewer.ts +2 -14
  171. package/src/ts/plugin.ts +1 -1
  172. package/src/ts/ts-rs/ViewerConfigUpdate.ts +1 -1
  173. package/src/rust/components/column_settings_sidebar/style_tab/column_style.rs +0 -177
  174. package/src/rust/components/containers/tests/mod.rs +0 -11
  175. package/src/rust/components/containers/tests/split_panel.rs +0 -91
  176. package/src/rust/js/testing.rs +0 -149
  177. package/src/rust/utils/tee.rs +0 -88
  178. /package/dist/wasm/snippets/{perspective-viewer-c69283f6f62a5f14 → perspective-viewer-0d326a25c1022412}/inline0.js +0 -0
  179. /package/dist/wasm/snippets/{perspective-viewer-c69283f6f62a5f14 → perspective-viewer-0d326a25c1022412}/inline1.js +0 -0
  180. /package/dist/wasm/snippets/{perspective-viewer-c69283f6f62a5f14 → perspective-viewer-0d326a25c1022412}/inline2.js +0 -0
  181. /package/dist/wasm/snippets/{perspective-viewer-c69283f6f62a5f14 → perspective-viewer-0d326a25c1022412}/inline3.js +0 -0
  182. /package/dist/wasm/snippets/{perspective-viewer-c69283f6f62a5f14 → perspective-viewer-0d326a25c1022412}/inline4.js +0 -0
  183. /package/src/rust/components/{style_controls.rs → style_controls/mod.rs} +0 -0
  184. /package/src/rust/{components/containers → config}/kvpair.rs +0 -0
@@ -23,19 +23,8 @@ use yew::virtual_dom::VChild;
23
23
 
24
24
  use super::scroll_panel_item::ScrollPanelItem;
25
25
  use crate::components::style::LocalStyle;
26
+ use crate::css;
26
27
  use crate::utils::*;
27
- use crate::*;
28
-
29
- pub struct ScrollPanel {
30
- viewport_ref: NodeRef,
31
- viewport_height: f64,
32
- viewport_width: f64,
33
- content_window: Option<ContentWindow>,
34
- needs_rerender: bool,
35
- total_height: f64,
36
- _dimensions_reset_sub: Option<Subscription>,
37
- _resize_sub: Option<Subscription>,
38
- }
39
28
 
40
29
  #[derive(Properties)]
41
30
  pub struct ScrollPanelProps {
@@ -96,71 +85,15 @@ pub enum ScrollPanelMsg {
96
85
  ChildrenChanged,
97
86
  }
98
87
 
99
- impl ScrollPanel {
100
- fn viewport<'a, 'b: 'a, 'c: 'a>(&'b self, ctx: &'c Context<Self>) -> &'a NodeRef {
101
- ctx.props()
102
- .viewport_ref
103
- .as_ref()
104
- .unwrap_or(&self.viewport_ref)
105
- }
106
-
107
- fn viewport_elem(&self, ctx: &Context<Self>) -> Element {
108
- self.viewport(ctx).cast::<Element>().unwrap()
109
- }
110
- }
111
-
112
- #[derive(PartialEq)]
113
- struct ContentWindow {
114
- scroll_top: f64,
115
- start_y: f64,
116
- visible_range: Range<usize>,
117
- }
118
-
119
- impl ScrollPanel {
120
- fn calculate_window_content(&mut self, ctx: &Context<Self>) -> bool {
121
- let viewport = self.viewport_elem(ctx);
122
- let scroll_top = viewport.scroll_top() as f64;
123
- let mut start_node = 0;
124
- let mut start_y = 0_f64;
125
- let mut offset = 0_f64;
126
- let end_node = ctx
127
- .props()
128
- .children
129
- .iter()
130
- .enumerate()
131
- .find_or_last(|(i, x)| {
132
- if offset + x.props.get_size() < scroll_top {
133
- start_node = *i + 1;
134
- start_y = offset + x.props.get_size();
135
- }
136
-
137
- offset += x.props.get_size();
138
- offset > scroll_top + self.viewport_height
139
- })
140
- .map(|x| x.0)
141
- .unwrap_or_default();
142
-
143
- // Why is this `end_node + 2`, I can see you asking yourself? `end_node` is the
144
- // index of the last visible child, but [`Range`] is an open interval so we must
145
- // increment by 1. The next rendered element is always occluded by the parent
146
- // container, it may seem unnecessary to render it, however not doing so causing
147
- // scroll glitching in Chrome:
148
- // * When the first pixel of the `end_node + 1` child is scrolled into view, the
149
- // container element it is embedded in will expand past the end of the scroll
150
- // container.
151
- // * Chrome detects this and helpfully scrolls this new element into view,
152
- // re-triggering the on scroll callback.
153
- let visible_range = start_node..min!(ctx.props().children.len(), end_node + 2);
154
- let content_window = Some(ContentWindow {
155
- scroll_top,
156
- start_y,
157
- visible_range,
158
- });
159
-
160
- let re_render = self.content_window != content_window;
161
- self.content_window = content_window;
162
- re_render
163
- }
88
+ pub struct ScrollPanel {
89
+ viewport_ref: NodeRef,
90
+ viewport_height: f64,
91
+ viewport_width: f64,
92
+ content_window: Option<ContentWindow>,
93
+ needs_rerender: bool,
94
+ total_height: f64,
95
+ _dimensions_reset_sub: Option<Subscription>,
96
+ _resize_sub: Option<Subscription>,
164
97
  }
165
98
 
166
99
  impl Component for ScrollPanel {
@@ -211,12 +144,12 @@ impl Component for ScrollPanel {
211
144
  let viewport = self.viewport_elem(ctx);
212
145
  let rect = viewport.get_bounding_client_rect();
213
146
  let viewport_height = rect.height() - 8.0;
214
- let viewport_width = max!(self.viewport_width, rect.width() - 6.0);
147
+ let viewport_width = self.viewport_width.max(rect.width() - 6.0);
215
148
  let re_render = self.viewport_height != viewport_height
216
149
  || self.viewport_width != viewport_width;
217
150
 
218
151
  self.viewport_height = rect.height() - 8.0;
219
- self.viewport_width = max!(self.viewport_width, rect.width() - 6.0);
152
+ self.viewport_width = self.viewport_width.max(rect.width() - 6.0);
220
153
  re_render
221
154
  },
222
155
  ScrollPanelMsg::CalculateWindowContent => self.calculate_window_content(ctx),
@@ -254,7 +187,7 @@ impl Component for ScrollPanel {
254
187
  ),
255
188
  };
256
189
 
257
- let width_style = format!("width:{}px", max!(self.viewport_width, 0.0));
190
+ let width_style = format!("width:{}px", self.viewport_width.max(0.0));
258
191
  let items = if !windowed_items.is_empty() {
259
192
  let onscroll = ctx.link().batch_callback(|_| {
260
193
  vec![
@@ -309,3 +242,70 @@ impl Component for ScrollPanel {
309
242
  ]);
310
243
  }
311
244
  }
245
+
246
+ impl ScrollPanel {
247
+ fn viewport<'a, 'b: 'a, 'c: 'a>(&'b self, ctx: &'c Context<Self>) -> &'a NodeRef {
248
+ ctx.props()
249
+ .viewport_ref
250
+ .as_ref()
251
+ .unwrap_or(&self.viewport_ref)
252
+ }
253
+
254
+ fn viewport_elem(&self, ctx: &Context<Self>) -> Element {
255
+ self.viewport(ctx).cast::<Element>().unwrap()
256
+ }
257
+ }
258
+
259
+ #[derive(PartialEq)]
260
+ struct ContentWindow {
261
+ scroll_top: f64,
262
+ start_y: f64,
263
+ visible_range: Range<usize>,
264
+ }
265
+
266
+ impl ScrollPanel {
267
+ fn calculate_window_content(&mut self, ctx: &Context<Self>) -> bool {
268
+ let viewport = self.viewport_elem(ctx);
269
+ let scroll_top = viewport.scroll_top() as f64;
270
+ let mut start_node = 0;
271
+ let mut start_y = 0_f64;
272
+ let mut offset = 0_f64;
273
+ let end_node = ctx
274
+ .props()
275
+ .children
276
+ .iter()
277
+ .enumerate()
278
+ .find_or_last(|(i, x)| {
279
+ if offset + x.props.get_size() < scroll_top {
280
+ start_node = *i + 1;
281
+ start_y = offset + x.props.get_size();
282
+ }
283
+
284
+ offset += x.props.get_size();
285
+ offset > scroll_top + self.viewport_height
286
+ })
287
+ .map(|x| x.0)
288
+ .unwrap_or_default();
289
+
290
+ // Why is this `end_node + 2`, I can see you asking yourself? `end_node` is the
291
+ // index of the last visible child, but [`Range`] is an open interval so we must
292
+ // increment by 1. The next rendered element is always occluded by the parent
293
+ // container, it may seem unnecessary to render it, however not doing so causing
294
+ // scroll glitching in Chrome:
295
+ // * When the first pixel of the `end_node + 1` child is scrolled into view, the
296
+ // container element it is embedded in will expand past the end of the scroll
297
+ // container.
298
+ // * Chrome detects this and helpfully scrolls this new element into view,
299
+ // re-triggering the on scroll callback.
300
+ let visible_range = start_node..ctx.props().children.len().min(end_node + 2);
301
+ let content_window = Some(ContentWindow {
302
+ scroll_top,
303
+ start_y,
304
+ visible_range,
305
+ });
306
+
307
+ let re_render = self.content_window != content_window;
308
+ self.content_window = content_window;
309
+ re_render
310
+ }
311
+ }
@@ -13,88 +13,88 @@
13
13
  // Forked from https://github.com/AircastDev/yew-virtual-scroller (Apache 2.0)
14
14
  // Adds support for Yew 0.19, auto-width and a simplified message structure.
15
15
 
16
- #[cfg(debug_assertions)]
17
16
  use std::cell::Cell;
18
- #[cfg(debug_assertions)]
19
17
  use std::rc::Rc;
20
18
 
21
19
  use yew::prelude::*;
22
20
 
23
21
  #[derive(PartialEq, Properties)]
24
22
  pub struct ScrollPanelItemProps {
23
+ pub children: Children,
24
+
25
25
  /// The expected size of this component in pixels. Calculating this value
26
26
  /// ahead of time makes it easier to implement a high-performance virtual
27
27
  /// renderer without resorting to weird tricks, _but_ checking that this
28
28
  /// hint is correct is nearly as expensive. So, we only generate the
29
29
  /// validation code in debug builds.
30
30
  pub size_hint: f64,
31
- pub children: Children,
32
31
 
33
- #[cfg(debug_assertions)]
32
+ /// Should we measure the child sizes or just rely on the hint? This
33
+ /// option may be enabled during debugging to validation render optimization
34
+ /// via [`Self::size_hint`], but will faile tests due to the extra DOM
35
+ /// structure it emits.
36
+ #[prop_or_default]
37
+ pub is_debug_mode: bool,
38
+
39
+ /// Communicate the panel size to virtual parent
34
40
  #[prop_or_default]
35
41
  measured_size: Rc<Cell<Option<f64>>>,
36
42
  }
37
43
 
38
44
  impl ScrollPanelItemProps {
39
- #[cfg(debug_assertions)]
40
- pub fn get_size(&self) -> f64 {
41
- self.measured_size.get().unwrap_or(self.size_hint)
42
- }
43
-
44
- #[cfg(not(debug_assertions))]
45
- pub fn get_size(&self) -> f64 {
46
- self.size_hint
45
+ pub(crate) fn get_size(&self) -> f64 {
46
+ if self.is_debug_mode {
47
+ self.measured_size.get().unwrap_or(self.size_hint)
48
+ } else {
49
+ self.size_hint
50
+ }
47
51
  }
48
52
  }
49
53
 
50
- #[cfg(debug_assertions)]
51
54
  pub struct ScrollPanelItem {
52
55
  node: NodeRef,
53
56
  }
54
57
 
55
- #[cfg(not(debug_assertions))]
56
- pub struct ScrollPanelItem {}
57
-
58
58
  impl Component for ScrollPanelItem {
59
59
  type Message = ();
60
60
  type Properties = ScrollPanelItemProps;
61
61
 
62
- #[cfg(debug_assertions)]
63
62
  fn create(ctx: &Context<Self>) -> Self {
64
- ctx.props().measured_size.set(Some(ctx.props().size_hint));
63
+ if ctx.props().is_debug_mode {
64
+ ctx.props().measured_size.set(Some(ctx.props().size_hint));
65
+ }
66
+
65
67
  Self {
66
68
  node: NodeRef::default(),
67
69
  }
68
70
  }
69
71
 
70
- #[cfg(not(debug_assertions))]
71
- fn create(_ctx: &Context<Self>) -> Self {
72
- Self {}
73
- }
74
-
75
- #[cfg(debug_assertions)]
76
72
  fn view(&self, ctx: &Context<Self>) -> Html {
77
73
  html! {
78
- <div class="debug-size-wrapper" style="display: flow-root" ref={self.node.clone()}>
79
- { for ctx.props().children.iter() }
80
- </div>
74
+ if ctx.props().is_debug_mode {
75
+ <div class="debug-size-wrapper" style="display: flow-root" ref={self.node.clone()}>
76
+ for child in ctx.props().children.iter() {
77
+ { child }
78
+ }
79
+ </div>
80
+ } else {
81
+ for child in ctx.props().children.iter() {
82
+ { child }
83
+ }
84
+ }
81
85
  }
82
86
  }
83
87
 
84
- #[cfg(not(debug_assertions))]
85
- fn view(&self, ctx: &Context<Self>) -> Html {
86
- html! { { for ctx.props().children.iter() } }
87
- }
88
-
89
- #[cfg(debug_assertions)]
90
88
  fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
91
- ctx.props().measured_size.set(Some(ctx.props().size_hint));
89
+ if ctx.props().is_debug_mode {
90
+ ctx.props().measured_size.set(Some(ctx.props().size_hint));
91
+ }
92
+
92
93
  true
93
94
  }
94
95
 
95
- #[cfg(debug_assertions)]
96
96
  fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
97
- if first_render {
97
+ if first_render && ctx.props().is_debug_mode {
98
98
  let elem = self.node.cast::<web_sys::HtmlElement>().unwrap();
99
99
  let new_height = elem.get_bounding_client_rect().height();
100
100
  if ctx.props().measured_size.get() != Some(new_height) {
@@ -17,26 +17,6 @@ use std::rc::Rc;
17
17
  use wasm_bindgen::JsCast;
18
18
  use yew::prelude::*;
19
19
 
20
- #[derive(Clone, Eq, PartialEq)]
21
- pub enum SelectItem<T> {
22
- Option(T),
23
- OptGroup(Cow<'static, str>, Vec<T>),
24
- }
25
-
26
- impl<T: Display> SelectItem<T> {
27
- pub fn name<'a>(&self) -> Cow<'a, str> {
28
- match self {
29
- Self::Option(x) => format!("{x}").into(),
30
- Self::OptGroup(x, _) => x.clone(),
31
- }
32
- }
33
- }
34
-
35
- pub enum SelectMsg {
36
- SelectedChanged(i32),
37
- KeyboardInput(bool, i32, String),
38
- }
39
-
40
20
  #[derive(Properties)]
41
21
  pub struct SelectProps<T>
42
22
  where
@@ -71,6 +51,11 @@ where
71
51
  }
72
52
  }
73
53
 
54
+ pub enum SelectMsg {
55
+ SelectedChanged(i32),
56
+ KeyboardInput(bool, i32, String),
57
+ }
58
+
74
59
  /// A `<select>` HTML elements, lifted to support parameterization over a set of
75
60
  /// values of a type `T`.
76
61
  pub struct Select<T>
@@ -81,23 +66,6 @@ where
81
66
  selected: T,
82
67
  }
83
68
 
84
- fn find_nth<T>(mut count: i32, items: &[SelectItem<T>]) -> Option<&T> {
85
- for ref item in items.iter() {
86
- match item {
87
- SelectItem::Option(_) if count > 0 => {
88
- count -= 1;
89
- },
90
- SelectItem::OptGroup(_, items) if count >= items.len() as i32 => {
91
- count -= items.len() as i32;
92
- },
93
- SelectItem::OptGroup(_, items) => return items.get(count as usize),
94
- SelectItem::Option(x) => return Some(x),
95
- }
96
- }
97
-
98
- None
99
- }
100
-
101
69
  impl<T> Component for Select<T>
102
70
  where
103
71
  T: Clone + Display + PartialEq + 'static,
@@ -132,12 +100,12 @@ where
132
100
  ctx.props().on_select.emit(self.selected.clone());
133
101
  return true;
134
102
  }
135
- } else if code.as_str() == "ArrowDown"
136
- && let Some(x) = find_nth(idx + 1, &ctx.props().values)
137
- {
138
- self.selected = x.clone();
139
- ctx.props().on_select.emit(self.selected.clone());
140
- return true;
103
+ } else if code.as_str() == "ArrowDown" {
104
+ if let Some(x) = find_nth(idx + 1, &ctx.props().values) {
105
+ self.selected = x.clone();
106
+ ctx.props().on_select.emit(self.selected.clone());
107
+ return true;
108
+ }
141
109
  }
142
110
  }
143
111
 
@@ -259,7 +227,9 @@ where
259
227
 
260
228
  html! {
261
229
  if is_group_selected && ctx.props().label.is_some() {
262
- <label>{ ctx.props().label.to_owned() }</label>
230
+ <label>
231
+ { ctx.props().label.as_ref().map(|x| x.to_string()).unwrap_or_default() }
232
+ </label>
263
233
  <div class={wrapper_class} data-value={value.clone()}>{ select }</div>
264
234
  } else {
265
235
  <div class={wrapper_class} data-value={value}>{ select }</div>
@@ -267,3 +237,35 @@ where
267
237
  }
268
238
  }
269
239
  }
240
+
241
+ #[derive(Clone, Eq, PartialEq)]
242
+ pub enum SelectItem<T> {
243
+ Option(T),
244
+ OptGroup(Cow<'static, str>, Vec<T>),
245
+ }
246
+
247
+ impl<T: Display> SelectItem<T> {
248
+ pub fn name<'a>(&self) -> Cow<'a, str> {
249
+ match self {
250
+ Self::Option(x) => format!("{x}").into(),
251
+ Self::OptGroup(x, _) => x.clone(),
252
+ }
253
+ }
254
+ }
255
+
256
+ fn find_nth<T>(mut count: i32, items: &[SelectItem<T>]) -> Option<&T> {
257
+ for ref item in items.iter() {
258
+ match item {
259
+ SelectItem::Option(_) if count > 0 => {
260
+ count -= 1;
261
+ },
262
+ SelectItem::OptGroup(_, items) if count >= items.len() as i32 => {
263
+ count -= items.len() as i32;
264
+ },
265
+ SelectItem::OptGroup(_, items) => return items.get(count as usize),
266
+ SelectItem::Option(x) => return Some(x),
267
+ }
268
+ }
269
+
270
+ None
271
+ }
@@ -13,10 +13,11 @@
13
13
  use perspective_client::clone;
14
14
  use web_sys::Element;
15
15
  use yew::{
16
- AttrValue, Callback, Children, Html, Properties, function_component, html, use_effect_with,
17
- use_node_ref, use_state_eq,
16
+ Callback, Children, Html, Properties, function_component, html, use_effect_with, use_node_ref,
17
+ use_state_eq,
18
18
  };
19
19
 
20
+ use crate::components::containers::sidebar_close_button::SidebarCloseButton;
20
21
  use crate::components::editable_header::{EditableHeader, EditableHeaderProps};
21
22
 
22
23
  #[derive(PartialEq, Clone, Properties)]
@@ -70,20 +71,3 @@ pub fn Sidebar(p: &SidebarProps) -> Html {
70
71
  </div>
71
72
  }
72
73
  }
73
-
74
- #[derive(PartialEq, Clone, Properties)]
75
- pub struct SidebarCloseButtonProps {
76
- pub on_close_sidebar: Callback<()>,
77
- pub id: AttrValue,
78
- }
79
-
80
- #[function_component]
81
- pub fn SidebarCloseButton(p: &SidebarCloseButtonProps) -> Html {
82
- let onclick = yew::use_callback(p.on_close_sidebar.clone(), |_, cb| cb.emit(()));
83
- let id = &p.id;
84
- html! {
85
- <div {onclick} {id} class="sidebar_close_button">
86
- <div class="sidebar_close_button_inner" />
87
- </div>
88
- }
89
- }
@@ -10,15 +10,21 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- use std::collections::HashMap;
13
+ use yew::{AttrValue, Callback, Html, Properties, function_component, html};
14
14
 
15
- use serde::{Deserialize, Serialize};
16
-
17
- use crate::components::containers::kvpair::KVPair;
18
-
19
- #[derive(Serialize, Deserialize)]
20
- pub struct SymbolConfig {
21
- pub symbols: HashMap<String, String>,
15
+ #[derive(PartialEq, Clone, Properties)]
16
+ pub struct SidebarCloseButtonProps {
17
+ pub on_close_sidebar: Callback<()>,
18
+ pub id: AttrValue,
22
19
  }
23
20
 
24
- pub type SymbolKVPair = KVPair<Option<String>, String>;
21
+ #[function_component]
22
+ pub fn SidebarCloseButton(p: &SidebarCloseButtonProps) -> Html {
23
+ let onclick = yew::use_callback(p.on_close_sidebar.clone(), |_, cb| cb.emit(()));
24
+ let id = &p.id;
25
+ html! {
26
+ <div {onclick} {id} class="sidebar_close_button">
27
+ <div class="sidebar_close_button_inner" />
28
+ </div>
29
+ }
30
+ }