@perspective-dev/viewer 4.4.1 → 4.5.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 (225) hide show
  1. package/dist/cdn/perspective-viewer.js +1 -2
  2. package/dist/cdn/perspective-viewer.js.map +4 -4
  3. package/dist/css/botanical.css +1 -1
  4. package/dist/css/dracula.css +1 -1
  5. package/dist/css/gruvbox-dark.css +1 -1
  6. package/dist/css/gruvbox.css +1 -1
  7. package/dist/css/icons.css +1 -1
  8. package/dist/css/intl/de.css +1 -1
  9. package/dist/css/intl/es.css +1 -1
  10. package/dist/css/intl/fr.css +1 -1
  11. package/dist/css/intl/ja.css +1 -1
  12. package/dist/css/intl/pt.css +1 -1
  13. package/dist/css/intl/zh.css +1 -1
  14. package/dist/css/intl.css +1 -1
  15. package/dist/css/monokai.css +1 -1
  16. package/dist/css/phosphor.css +1 -1
  17. package/dist/css/pro-dark.css +1 -1
  18. package/dist/css/pro.css +1 -1
  19. package/dist/css/solarized-dark.css +1 -1
  20. package/dist/css/solarized.css +1 -1
  21. package/dist/css/themes.css +1 -1
  22. package/dist/css/vaporwave.css +1 -1
  23. package/dist/esm/bootstrap.d.ts +2 -1
  24. package/dist/esm/column-format.d.ts +51 -0
  25. package/dist/esm/extensions.d.ts +2 -0
  26. package/dist/esm/perspective-viewer.d.ts +3 -1
  27. package/dist/esm/perspective-viewer.inline.js +1 -2
  28. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  29. package/dist/esm/perspective-viewer.js +1 -2
  30. package/dist/esm/perspective-viewer.js.map +4 -4
  31. package/dist/esm/perspective-viewer.worker.d.ts +2 -0
  32. package/dist/esm/plugin.d.ts +16 -72
  33. package/dist/esm/ts-rs/ColumnSelectMode.d.ts +1 -0
  34. package/dist/esm/ts-rs/PluginStaticConfig.d.ts +77 -0
  35. package/dist/esm/ts-rs/ViewerConfig.d.ts +6 -3
  36. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
  37. package/dist/wasm/perspective-viewer.d.ts +77 -18
  38. package/dist/wasm/perspective-viewer.js +293 -144
  39. package/dist/wasm/perspective-viewer.wasm +0 -0
  40. package/dist/wasm/perspective-viewer.wasm.d.ts +20 -15
  41. package/package.json +24 -2
  42. package/src/css/column-selector.css +3 -2
  43. package/src/css/column-settings-panel.css +35 -6
  44. package/src/css/column-style.css +27 -2
  45. package/src/css/containers/scroll-panel.css +2 -1
  46. package/src/css/containers/tabs.css +8 -52
  47. package/src/css/dom/checkbox.css +0 -4
  48. package/src/css/form/code-editor.css +1 -0
  49. package/src/css/form/debug.css +3 -10
  50. package/src/css/plugin-selector.css +33 -0
  51. package/src/css/plugin-settings-panel.css +99 -0
  52. package/src/css/viewer.css +65 -3
  53. package/src/rust/components/column_dropdown.rs +3 -1
  54. package/src/rust/components/column_selector/active_column.rs +13 -19
  55. package/src/rust/components/column_selector/config_selector.rs +20 -20
  56. package/src/rust/components/column_selector/filter_column.rs +14 -14
  57. package/src/rust/components/column_selector/inactive_column.rs +9 -15
  58. package/src/rust/components/column_selector/pivot_column.rs +7 -7
  59. package/src/rust/components/column_selector/sort_column.rs +7 -7
  60. package/src/rust/components/column_selector.rs +55 -37
  61. package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +15 -7
  62. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +394 -0
  63. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +15 -6
  64. package/src/rust/components/column_settings_sidebar/style_tab.rs +267 -136
  65. package/src/rust/components/column_settings_sidebar.rs +43 -49
  66. package/src/rust/components/containers/dragdrop_list.rs +5 -5
  67. package/src/rust/components/containers/mod.rs +0 -1
  68. package/src/rust/components/containers/scroll_panel.rs +21 -7
  69. package/src/rust/components/containers/sidebar.rs +8 -6
  70. package/src/rust/components/containers/split_panel.rs +3 -3
  71. package/src/rust/components/containers/tab_list.rs +3 -9
  72. package/src/rust/components/copy_dropdown.rs +2 -3
  73. package/src/rust/components/datetime_column_style.rs +19 -81
  74. package/src/rust/components/editable_header.rs +2 -3
  75. package/src/rust/components/export_dropdown.rs +2 -3
  76. package/src/rust/components/expression_editor.rs +29 -17
  77. package/src/rust/components/filter_dropdown.rs +2 -1
  78. package/src/rust/components/form/color_range_selector.rs +14 -7
  79. package/src/rust/components/form/debug.rs +47 -37
  80. package/src/rust/components/main_panel.rs +24 -65
  81. package/src/rust/components/mod.rs +2 -1
  82. package/src/rust/components/number_series_style.rs +161 -0
  83. package/src/rust/components/plugin_tab.rs +221 -0
  84. package/src/rust/components/settings_panel.rs +181 -59
  85. package/src/rust/components/status_bar.rs +140 -173
  86. package/src/rust/components/status_indicator.rs +15 -22
  87. package/src/rust/components/string_column_style.rs +20 -82
  88. package/src/rust/components/style_controls/number_string_format.rs +14 -30
  89. package/src/rust/components/viewer.rs +92 -131
  90. package/src/rust/config/column_config_schema.rs +195 -0
  91. package/src/rust/config/columns_config.rs +4 -97
  92. package/src/rust/config/datetime_column_style.rs +0 -5
  93. package/src/rust/config/mod.rs +8 -2
  94. package/src/rust/config/number_series_style.rs +79 -0
  95. package/src/rust/config/plugin_static_config.rs +144 -0
  96. package/src/rust/config/string_column_style.rs +0 -5
  97. package/src/rust/config/viewer_config.rs +5 -6
  98. package/src/rust/custom_elements/copy_dropdown.rs +30 -18
  99. package/src/rust/custom_elements/debug_plugin.rs +1 -3
  100. package/src/rust/custom_elements/export_dropdown.rs +26 -18
  101. package/src/rust/custom_elements/viewer.rs +62 -73
  102. package/src/rust/custom_events.rs +181 -224
  103. package/src/rust/js/plugin.rs +45 -117
  104. package/src/rust/lib.rs +34 -5
  105. package/src/rust/presentation/drag_helpers.rs +206 -0
  106. package/src/rust/presentation/props.rs +8 -0
  107. package/src/rust/presentation.rs +256 -41
  108. package/src/rust/{tasks → queries}/column_locator.rs +17 -73
  109. package/src/rust/queries/column_values.rs +59 -0
  110. package/src/rust/{tasks → queries}/columns_iter_set.rs +11 -18
  111. package/src/rust/queries/exports.rs +96 -0
  112. package/src/rust/queries/fetch_column_stats.rs +94 -0
  113. package/src/rust/queries/get_viewer_config.rs +54 -0
  114. package/src/rust/queries/mod.rs +44 -0
  115. package/src/rust/queries/plugin_column_styles.rs +101 -0
  116. package/src/rust/{engines.rs → queries/validate_expression.rs} +26 -15
  117. package/src/rust/renderer/activate.rs +1 -0
  118. package/src/rust/renderer/limits.rs +9 -4
  119. package/src/rust/renderer/plugin_store.rs +12 -0
  120. package/src/rust/renderer/props.rs +28 -3
  121. package/src/rust/renderer/registry.rs +40 -15
  122. package/src/rust/renderer.rs +640 -51
  123. package/src/rust/session/column_defaults_update.rs +20 -28
  124. package/src/rust/session/drag_drop_update.rs +10 -10
  125. package/src/rust/session/metadata.rs +31 -16
  126. package/src/rust/session/props.rs +15 -6
  127. package/src/rust/session/view_subscription.rs +10 -0
  128. package/src/rust/session.rs +109 -147
  129. package/src/rust/tasks/copy_export.rs +178 -158
  130. package/src/rust/tasks/{structural.rs → dismiss_render_warning.rs} +20 -40
  131. package/src/rust/tasks/edit_expression.rs +68 -88
  132. package/src/rust/tasks/eject.rs +25 -22
  133. package/src/rust/tasks/intersection_observer.rs +8 -21
  134. package/src/rust/tasks/mod.rs +19 -21
  135. package/src/rust/tasks/reset_all.rs +78 -0
  136. package/src/rust/tasks/resize_observer.rs +11 -33
  137. package/src/rust/tasks/restore_and_render.rs +117 -90
  138. package/src/rust/tasks/{get_viewer_config.rs → send_column_config.rs} +38 -35
  139. package/src/rust/tasks/send_plugin_config.rs +32 -33
  140. package/src/rust/tasks/update_and_render.rs +66 -47
  141. package/src/rust/{components/containers/trap_door_panel.rs → tasks/update_theme.rs} +34 -33
  142. package/src/rust/tasks/validate_expression.rs +61 -0
  143. package/src/rust/utils/browser/selection.rs +4 -4
  144. package/src/rust/utils/mod.rs +0 -63
  145. package/src/svg/mega-menu-icons-density.svg +23 -0
  146. package/src/svg/mega-menu-icons-map-density.svg +24 -0
  147. package/src/svg/mega-menu-icons-map-line.svg +19 -0
  148. package/src/themes/botanical.css +27 -53
  149. package/src/themes/defaults.css +24 -36
  150. package/src/themes/dracula.css +36 -54
  151. package/src/themes/gruvbox-dark.css +39 -59
  152. package/src/themes/gruvbox.css +16 -28
  153. package/src/themes/icons.css +3 -0
  154. package/src/themes/intl/de.css +42 -6
  155. package/src/themes/intl/es.css +42 -6
  156. package/src/themes/intl/fr.css +42 -6
  157. package/src/themes/intl/ja.css +42 -6
  158. package/src/themes/intl/pt.css +42 -6
  159. package/src/themes/intl/zh.css +42 -6
  160. package/src/themes/intl.css +37 -4
  161. package/src/themes/monokai.css +45 -61
  162. package/src/themes/phosphor.css +20 -29
  163. package/src/themes/pro-dark.css +25 -34
  164. package/src/themes/solarized-dark.css +21 -36
  165. package/src/themes/solarized.css +13 -23
  166. package/src/themes/vaporwave.css +40 -74
  167. package/src/ts/bootstrap.ts +14 -3
  168. package/src/ts/column-format.ts +162 -0
  169. package/src/ts/extensions.ts +4 -0
  170. package/src/ts/perspective-viewer.ts +9 -1
  171. package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
  172. package/src/ts/plugin.ts +25 -101
  173. package/src/ts/ts-rs/{FormatUnit.ts → ColumnSelectMode.ts} +1 -1
  174. package/src/ts/ts-rs/PluginStaticConfig.ts +78 -0
  175. package/src/ts/ts-rs/ViewerConfig.ts +1 -2
  176. package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -3
  177. package/dist/esm/ts-rs/ColumnConfigValues.d.ts +0 -31
  178. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +0 -1
  179. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +0 -15
  180. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +0 -18
  181. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
  182. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +0 -6
  183. package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
  184. package/dist/esm/ts-rs/FormatUnit.d.ts +0 -1
  185. package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +0 -1
  186. package/dist/esm/ts-rs/NumberForegroundMode.d.ts +0 -1
  187. package/dist/esm/ts-rs/PluginConfig.d.ts +0 -2
  188. package/dist/esm/ts-rs/RoundingMode.d.ts +0 -1
  189. package/dist/esm/ts-rs/RoundingPriority.d.ts +0 -1
  190. package/dist/esm/ts-rs/SignDisplay.d.ts +0 -1
  191. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +0 -1
  192. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +0 -6
  193. package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
  194. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +0 -1
  195. package/dist/esm/ts-rs/UseGrouping.d.ts +0 -1
  196. package/src/rust/components/number_column_style.rs +0 -491
  197. package/src/rust/config/number_column_style.rs +0 -136
  198. package/src/rust/dragdrop.rs +0 -481
  199. package/src/rust/tasks/plugin_column_styles.rs +0 -98
  200. package/src/ts/ts-rs/ColumnConfigValues.ts +0 -14
  201. package/src/ts/ts-rs/CustomDatetimeFormat.ts +0 -3
  202. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +0 -5
  203. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +0 -8
  204. package/src/ts/ts-rs/DatetimeColorMode.ts +0 -3
  205. package/src/ts/ts-rs/DatetimeFormatType.ts +0 -8
  206. package/src/ts/ts-rs/FormatMode.ts +0 -3
  207. package/src/ts/ts-rs/NumberBackgroundMode.ts +0 -3
  208. package/src/ts/ts-rs/NumberForegroundMode.ts +0 -3
  209. package/src/ts/ts-rs/PluginConfig.ts +0 -4
  210. package/src/ts/ts-rs/RoundingMode.ts +0 -3
  211. package/src/ts/ts-rs/RoundingPriority.ts +0 -3
  212. package/src/ts/ts-rs/SignDisplay.ts +0 -3
  213. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +0 -3
  214. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +0 -4
  215. package/src/ts/ts-rs/StringColorMode.ts +0 -3
  216. package/src/ts/ts-rs/TrailingZeroDisplay.ts +0 -3
  217. package/src/ts/ts-rs/UseGrouping.ts +0 -3
  218. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline0.js +0 -0
  219. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline1.js +0 -0
  220. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline2.js +0 -0
  221. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline3.js +0 -0
  222. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline4.js +0 -0
  223. /package/src/rust/{tasks → config}/export_method.rs +0 -0
  224. /package/src/rust/{tasks → queries}/export_app.rs +0 -0
  225. /package/src/rust/{tasks → queries}/is_invalid_drop.rs +0 -0
@@ -12,7 +12,7 @@
12
12
  mod attributes_tab;
13
13
 
14
14
  mod save_settings;
15
- mod style_tab;
15
+ pub(crate) mod style_tab;
16
16
 
17
17
  use std::rc::Rc;
18
18
 
@@ -33,14 +33,10 @@ use crate::components::editable_header::EditableHeaderProps;
33
33
  use crate::components::expression_editor::ExpressionEditorProps;
34
34
  use crate::components::style::LocalStyle;
35
35
  use crate::components::type_icon::TypeIconType;
36
- use crate::custom_events::CustomEvents;
37
36
  use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation};
38
37
  use crate::renderer::Renderer;
39
38
  use crate::session::{Session, SessionMetadataRc};
40
- use crate::tasks::{
41
- EditExpression, HasCustomEvents, HasPresentation, HasRenderer, HasSession,
42
- can_render_column_styles, locator_name_or_default, locator_view_type,
43
- };
39
+ use crate::tasks::{delete_expr, save_expr, update_expr};
44
40
  use crate::utils::PtrEqRc;
45
41
  use crate::*;
46
42
 
@@ -64,13 +60,13 @@ pub struct ColumnSettingsPanelProps {
64
60
  /// View config snapshot — threaded from `SessionProps`.
65
61
  pub view_config: PtrEqRc<ViewConfig>,
66
62
 
63
+ /// Per-column stats snapshot — threaded from `SessionProps`.
64
+ pub column_stats: PtrEqRc<std::collections::HashMap<String, crate::session::ColumnStats>>,
65
+
67
66
  /// Selected theme name, threaded for PortalModal consumers.
68
67
  pub selected_theme: Option<String>,
69
68
 
70
69
  // State
71
- #[derivative(Debug = "ignore")]
72
- pub custom_events: CustomEvents,
73
-
74
70
  #[derivative(Debug = "ignore")]
75
71
  pub presentation: Presentation,
76
72
 
@@ -88,34 +84,11 @@ impl PartialEq for ColumnSettingsPanelProps {
88
84
  && self.plugin_name == other.plugin_name
89
85
  && self.metadata == other.metadata
90
86
  && self.view_config == other.view_config
87
+ && self.column_stats == other.column_stats
91
88
  && self.selected_theme == other.selected_theme
92
89
  }
93
90
  }
94
91
 
95
- impl HasCustomEvents for ColumnSettingsPanelProps {
96
- fn custom_events(&self) -> &CustomEvents {
97
- &self.custom_events
98
- }
99
- }
100
-
101
- impl HasPresentation for ColumnSettingsPanelProps {
102
- fn presentation(&self) -> &Presentation {
103
- &self.presentation
104
- }
105
- }
106
-
107
- impl HasRenderer for ColumnSettingsPanelProps {
108
- fn renderer(&self) -> &Renderer {
109
- &self.renderer
110
- }
111
- }
112
-
113
- impl HasSession for ColumnSettingsPanelProps {
114
- fn session(&self) -> &Session {
115
- &self.session
116
- }
117
- }
118
-
119
92
  #[derive(Debug)]
120
93
  pub enum ColumnSettingsPanelMsg {
121
94
  SetExprValue(Rc<String>),
@@ -239,11 +212,20 @@ impl Component for ColumnSettingsPanel {
239
212
  ColumnLocator::Table(_) => {
240
213
  tracing::error!("Tried to save non-expression column!")
241
214
  },
242
- ColumnLocator::Expression(name) => {
243
- ctx.props().update_expr(name.clone(), new_expr)
244
- },
215
+ ColumnLocator::Expression(name) => update_expr(
216
+ &ctx.props().session,
217
+ &ctx.props().renderer,
218
+ &ctx.props().presentation,
219
+ name.clone(),
220
+ new_expr,
221
+ ),
245
222
  ColumnLocator::NewExpression => {
246
- if let Err(err) = ctx.props().save_expr(new_expr) {
223
+ if let Err(err) = save_expr(
224
+ &ctx.props().session,
225
+ &ctx.props().renderer,
226
+ &ctx.props().presentation,
227
+ new_expr,
228
+ ) {
247
229
  tracing::warn!("{}", err);
248
230
  }
249
231
  },
@@ -258,7 +240,12 @@ impl Component for ColumnSettingsPanel {
258
240
  },
259
241
  ColumnSettingsPanelMsg::OnDelete(()) => {
260
242
  if ctx.props().selected_column.is_saved_expr() {
261
- ctx.props().delete_expr(&self.column_name).unwrap_or_log();
243
+ delete_expr(
244
+ &ctx.props().session,
245
+ &ctx.props().renderer,
246
+ &self.column_name,
247
+ )
248
+ .unwrap_or_log();
262
249
  }
263
250
 
264
251
  ctx.props().on_close.emit(());
@@ -347,8 +334,8 @@ impl Component for ColumnSettingsPanel {
347
334
  group_by_depth: ctx.props().view_config.group_by.len() as u32,
348
335
  view_config: ctx.props().view_config.clone(),
349
336
  metadata: ctx.props().metadata.clone(),
337
+ column_stats: ctx.props().column_stats.clone(),
350
338
  selected_theme: ctx.props().selected_theme.clone(),
351
- custom_events: ctx.props().custom_events.clone(),
352
339
  presentation: ctx.props().presentation.clone(),
353
340
  renderer: ctx.props().renderer.clone(),
354
341
  session: ctx.props().session.clone(),
@@ -398,8 +385,10 @@ impl ColumnSettingsPanel {
398
385
  }
399
386
 
400
387
  fn initialize(&mut self, ctx: &yew::prelude::Context<Self>) {
401
- let column_name =
402
- locator_name_or_default(&ctx.props().metadata, &ctx.props().selected_column);
388
+ let column_name = ctx
389
+ .props()
390
+ .metadata
391
+ .locator_name_or_default(&ctx.props().selected_column);
403
392
 
404
393
  let initial_expr_value = ctx
405
394
  .props()
@@ -411,19 +400,23 @@ impl ColumnSettingsPanel {
411
400
  let initial_header_value =
412
401
  (*initial_expr_value != column_name).then_some(column_name.clone());
413
402
 
414
- let maybe_ty = locator_view_type(&ctx.props().metadata, &ctx.props().selected_column);
403
+ let maybe_ty = ctx
404
+ .props()
405
+ .metadata
406
+ .locator_view_type(&ctx.props().selected_column);
415
407
 
416
408
  let tabs = {
417
409
  let mut tabs = vec![];
418
410
  let is_new_expr = ctx.props().selected_column.is_new_expr();
419
411
  let show_styles = !is_new_expr
420
- && can_render_column_styles(
421
- &ctx.props().renderer,
422
- &ctx.props().view_config,
423
- &ctx.props().metadata,
424
- &column_name,
425
- )
426
- .unwrap_or_default();
412
+ && ctx.props().renderer.can_render_column_styles()
413
+ && ctx.props().view_config.columns.contains(&Some(
414
+ ctx.props()
415
+ .selected_column
416
+ .name()
417
+ .map(|x| x.to_string())
418
+ .unwrap_or_default(),
419
+ ));
427
420
 
428
421
  if !is_new_expr && show_styles {
429
422
  tabs.push(ColumnSettingsTab::Style);
@@ -432,6 +425,7 @@ impl ColumnSettingsPanel {
432
425
  if ctx.props().selected_column.is_expr() {
433
426
  tabs.push(ColumnSettingsTab::Attributes);
434
427
  }
428
+
435
429
  tabs
436
430
  };
437
431
 
@@ -22,7 +22,7 @@ use yew::prelude::*;
22
22
  use crate::components::column_dropdown::ColumnDropDownElement;
23
23
  use crate::components::column_selector::{EmptyColumn, InPlaceColumn, InvalidColumn};
24
24
  use crate::components::type_icon::TypeIcon;
25
- use crate::dragdrop::*;
25
+ use crate::presentation::{DragDropContainer, Presentation};
26
26
  use crate::utils::DragTarget;
27
27
 
28
28
  #[derive(Properties, Derivative)]
@@ -35,7 +35,7 @@ where
35
35
  {
36
36
  pub parent: Scope<T>,
37
37
 
38
- pub dragdrop: DragDrop,
38
+ pub presentation: Presentation,
39
39
  pub name: &'static str,
40
40
  pub column_dropdown: ColumnDropDownElement,
41
41
  pub exclude: HashSet<String>,
@@ -185,11 +185,11 @@ where
185
185
  );
186
186
 
187
187
  let drop = Callback::from({
188
- let dragdrop = ctx.props().dragdrop.clone();
188
+ let presentation = ctx.props().presentation.clone();
189
189
  let link = ctx.link().clone();
190
190
  move |event| {
191
191
  link.send_message(DragDropListMsg::Freeze(false));
192
- dragdrop.notify_drop(&event);
192
+ presentation.notify_drop(&event);
193
193
  }
194
194
  });
195
195
 
@@ -210,7 +210,7 @@ where
210
210
  let is_append = index == columns.len();
211
211
  let is_self_move = ctx
212
212
  .props()
213
- .dragdrop
213
+ .presentation
214
214
  .get_drag_target()
215
215
  .map(|x| V::is_self_move(x))
216
216
  .unwrap_or_default();
@@ -22,4 +22,3 @@ pub mod sidebar;
22
22
  pub mod sidebar_close_button;
23
23
  pub mod split_panel;
24
24
  pub mod tab_list;
25
- pub mod trap_door_panel;
@@ -63,6 +63,9 @@ pub struct ScrollPanelProps {
63
63
 
64
64
  #[prop_or_default]
65
65
  pub drop: Callback<DragEvent>,
66
+
67
+ #[prop_or_default]
68
+ pub omit_autosize_div: bool,
66
69
  }
67
70
 
68
71
  impl ScrollPanelProps {
@@ -146,16 +149,25 @@ impl Component for ScrollPanel {
146
149
  self.viewport_width = 0.0;
147
150
  self.calculate_window_content(ctx)
148
151
  },
152
+
153
+ // TODO don't hardcode pixel offsets - fix the CSS container to not
154
+ // require pixel offsets to work.
149
155
  ScrollPanelMsg::UpdateViewportDimensions => {
150
156
  let viewport = self.viewport_elem(ctx);
151
157
  let rect = viewport.get_bounding_client_rect();
152
158
  let viewport_height = rect.height() - 8.0;
153
- let viewport_width = self.viewport_width.max(rect.width() - 6.0);
159
+ let scroll_offset = if ctx.props().omit_autosize_div {
160
+ 0.0
161
+ } else {
162
+ 6.0
163
+ };
164
+
165
+ let viewport_width = self.viewport_width.max(rect.width() - scroll_offset);
154
166
  let re_render = self.viewport_height != viewport_height
155
167
  || self.viewport_width != viewport_width;
156
168
 
157
169
  self.viewport_height = rect.height() - 8.0;
158
- self.viewport_width = self.viewport_width.max(rect.width() - 6.0);
170
+ self.viewport_width = self.viewport_width.max(rect.width() - scroll_offset);
159
171
  ctx.props().on_auto_width.emit(self.viewport_width);
160
172
  re_render
161
173
  },
@@ -218,11 +230,13 @@ impl Component for ScrollPanel {
218
230
  >
219
231
  <div class="scroll-panel-container" style={window_style}>
220
232
  { for windowed_items.iter().cloned().map(Html::from) }
221
- <div
222
- key="__scroll-panel-auto-width__"
223
- class="scroll-panel-auto-width"
224
- style={width_style}
225
- />
233
+ if !ctx.props().omit_autosize_div {
234
+ <div
235
+ key="__scroll-panel-auto-width__"
236
+ class="scroll-panel-auto-width"
237
+ style={width_style}
238
+ />
239
+ }
226
240
  </div>
227
241
  <div class="scroll-panel-content" style={content_style} />
228
242
  </div>
@@ -62,12 +62,14 @@ pub fn Sidebar(p: &SidebarProps) -> Html {
62
62
 
63
63
  let width_style = format!("min-width: 200px; width: {}px", *auto_width);
64
64
  html! {
65
- <div class="sidebar_column" id={format!("{id}_sidebar")} ref={noderef}>
65
+ <>
66
66
  <SidebarCloseButton id={format!("{id}_close_button")} on_close_sidebar={&p.on_close} />
67
- <div class="sidebar_header"><EditableHeader ..p.header_props.clone() /></div>
68
- <div class="sidebar_border" id={format!("{id}_border")} />
69
- { p.children.iter().collect::<Html>() }
70
- <div class="sidebar-auto-width" style={width_style} />
71
- </div>
67
+ <div class="sidebar_column" id={format!("{id}_sidebar")} ref={noderef}>
68
+ <div class="sidebar_header"><EditableHeader ..p.header_props.clone() /></div>
69
+ <div class="sidebar_border" id={format!("{id}_border")} />
70
+ { p.children.iter().collect::<Html>() }
71
+ <div class="sidebar-auto-width" style={width_style} />
72
+ </div>
73
+ </>
72
74
  }
73
75
  }
@@ -20,7 +20,7 @@ use yew::html::Scope;
20
20
  use yew::prelude::*;
21
21
 
22
22
  use crate::components::style::LocalStyle;
23
- use crate::{css, maybe};
23
+ use crate::css;
24
24
 
25
25
  #[derive(Properties, Default)]
26
26
  pub struct SplitPanelProps {
@@ -359,14 +359,14 @@ impl Drop for ResizingState {
359
359
  /// `body`. Without this, the `Closure` objects would not leak, but the
360
360
  /// document will continue to call them, causing runtime exceptions.
361
361
  fn drop(&mut self) {
362
- let result: ApiResult<()> = maybe! {
362
+ let result: ApiResult<()> = (|| {
363
363
  let mousemove = self.mousemove.as_ref().unchecked_ref();
364
364
  global::body().remove_event_listener_with_callback("mousemove", mousemove)?;
365
365
  let mouseup = self.mouseup.as_ref().unchecked_ref();
366
366
  global::body().remove_event_listener_with_callback("mouseup", mouseup)?;
367
367
  self.release_cursor()?;
368
368
  Ok(())
369
- };
369
+ })();
370
370
 
371
371
  result.expect("Drop failed")
372
372
  }
@@ -71,9 +71,9 @@ impl<T: ColumnTab> Component for TabList<T> {
71
71
  fn view(&self, ctx: &yew::Context<Self>) -> Html {
72
72
  let p = ctx.props();
73
73
  let gutter_tabs = p.tabs.iter().enumerate().map(|(idx, tab)| {
74
- let mut class = classes!("tab");
74
+ let mut class = classes!("settings_tab");
75
75
  if idx == self.selected_idx {
76
- class.push("selected");
76
+ class.push("selected_tab");
77
77
  }
78
78
 
79
79
  let onclick = ctx.link().callback(move |_| TabListMsg::SetSelected(idx));
@@ -88,13 +88,7 @@ impl<T: ColumnTab> Component for TabList<T> {
88
88
  html! {
89
89
  <>
90
90
  <LocalStyle href={css!("containers/tabs")} />
91
- <div class="tab-gutter">
92
- { for gutter_tabs }
93
- <span class="tab tab-padding">
94
- <div class="tab-title">{ "\u{00a0}" }</div>
95
- <div class="tab-border" />
96
- </span>
97
- </div>
91
+ <div id="settings_tab_bar">{ for gutter_tabs }</div>
98
92
  <div id="format-tab" class="tab-content scrollable">
99
93
  { ctx.props().children.iter().nth(self.selected_idx) }
100
94
  </div>
@@ -15,8 +15,8 @@ use std::rc::Rc;
15
15
  use yew::prelude::*;
16
16
 
17
17
  use super::containers::dropdown_menu::*;
18
+ use crate::config::*;
18
19
  use crate::renderer::*;
19
- use crate::tasks::*;
20
20
 
21
21
  type CopyDropDownMenuItem = DropDownMenuItem<ExportFile>;
22
22
 
@@ -41,8 +41,7 @@ impl Component for CopyDropDownMenu {
41
41
  }
42
42
 
43
43
  fn view(&self, ctx: &Context<Self>) -> yew::virtual_dom::VNode {
44
- let plugin = ctx.props().renderer.get_active_plugin().unwrap();
45
- let is_chart = plugin.name().as_str() != "Datagrid";
44
+ let is_chart = ctx.props().renderer.is_chart();
46
45
  let has_selection = ctx.props().renderer.get_selection().is_some();
47
46
  html! {
48
47
  <>
@@ -21,28 +21,30 @@ use perspective_js::json;
21
21
  use perspective_js::utils::global::navigator;
22
22
  use wasm_bindgen::prelude::*;
23
23
  use yew::prelude::*;
24
- use yew::*;
25
24
 
26
- use super::form::color_selector::*;
27
25
  use super::modal::{ModalLink, SetModalLink};
28
26
  use super::style::LocalStyle;
29
27
  use crate::components::datetime_column_style::custom::DatetimeStyleCustom;
30
28
  use crate::components::datetime_column_style::simple::DatetimeStyleSimple;
31
- use crate::components::form::select_enum_field::SelectEnumField;
32
29
  use crate::components::form::select_value_field::SelectValueField;
33
30
  use crate::config::*;
34
31
  use crate::css;
35
32
  use crate::utils::WeakScope;
36
33
 
34
+ /// Format-only widget for `datetime` columns. Renders the `date_format`
35
+ /// hierarchy (Simple|Custom + timezone); color/color-mode UI is provided
36
+ /// externally as primitive `Enum` + `Color` schema fields.
37
37
  #[derive(Properties, Derivative)]
38
38
  #[derivative(Debug)]
39
39
  pub struct DatetimeColumnStyleProps {
40
40
  pub enable_time_config: bool,
41
41
  pub config: Option<DatetimeColumnStyleConfig>,
42
- pub default_config: DatetimeColumnStyleDefaultConfig,
43
42
 
44
43
  #[prop_or_default]
45
- pub on_change: Callback<ColumnConfigValueUpdate>,
44
+ pub on_change: Callback<ColumnConfigFieldUpdate>,
45
+
46
+ #[prop_or_default]
47
+ pub keys: Vec<String>,
46
48
 
47
49
  #[prop_or_default]
48
50
  #[derivative(Debug = "ignore")]
@@ -57,9 +59,7 @@ impl ModalLink<DatetimeColumnStyle> for DatetimeColumnStyleProps {
57
59
 
58
60
  impl PartialEq for DatetimeColumnStyleProps {
59
61
  fn eq(&self, other: &Self) -> bool {
60
- self.enable_time_config == other.enable_time_config
61
- && self.config == other.config
62
- && self.default_config == other.default_config
62
+ self.enable_time_config == other.enable_time_config && self.config == other.config
63
63
  }
64
64
  }
65
65
 
@@ -67,16 +67,11 @@ pub enum DatetimeColumnStyleMsg {
67
67
  SimpleDatetimeStyleConfigChanged(SimpleDatetimeStyleConfig),
68
68
  CustomDatetimeStyleConfigChanged(CustomDatetimeStyleConfig),
69
69
  TimezoneChanged(Option<String>),
70
- ColorModeChanged(Option<DatetimeColorMode>),
71
- ColorChanged(String),
72
- ColorReset,
73
70
  }
74
71
 
75
- /// Column style controls for the `datetime` type.
76
72
  #[derive(Debug)]
77
73
  pub struct DatetimeColumnStyle {
78
74
  config: DatetimeColumnStyleConfig,
79
- default_config: DatetimeColumnStyleDefaultConfig,
80
75
  }
81
76
 
82
77
  impl Component for DatetimeColumnStyle {
@@ -87,11 +82,9 @@ impl Component for DatetimeColumnStyle {
87
82
  ctx.set_modal_link();
88
83
  Self {
89
84
  config: ctx.props().config.clone().unwrap_or_default(),
90
- default_config: ctx.props().default_config.clone(),
91
85
  }
92
86
  }
93
87
 
94
- // Always re-render when config changes.
95
88
  fn changed(&mut self, ctx: &Context<Self>, old: &Self::Properties) -> bool {
96
89
  let mut rerender = false;
97
90
  let mut new_config = ctx.props().config.clone().unwrap_or_default();
@@ -105,7 +98,6 @@ impl Component for DatetimeColumnStyle {
105
98
  rerender
106
99
  }
107
100
 
108
- // TODO could be more conservative here with re-rendering
109
101
  fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
110
102
  match msg {
111
103
  DatetimeColumnStyleMsg::TimezoneChanged(val) => {
@@ -118,17 +110,6 @@ impl Component for DatetimeColumnStyle {
118
110
  self.dispatch_config(ctx);
119
111
  true
120
112
  },
121
- DatetimeColumnStyleMsg::ColorModeChanged(mode) => {
122
- self.config.datetime_color_mode = mode.unwrap_or_default();
123
- self.dispatch_config(ctx);
124
- true
125
- },
126
- DatetimeColumnStyleMsg::ColorChanged(color) => {
127
- self.config.color = Some(color);
128
- self.dispatch_config(ctx);
129
- true
130
- },
131
-
132
113
  DatetimeColumnStyleMsg::SimpleDatetimeStyleConfigChanged(simple) => {
133
114
  self.config.date_format = DatetimeFormatType::Simple(simple);
134
115
  self.dispatch_config(ctx);
@@ -139,40 +120,14 @@ impl Component for DatetimeColumnStyle {
139
120
  self.dispatch_config(ctx);
140
121
  true
141
122
  },
142
- DatetimeColumnStyleMsg::ColorReset => {
143
- self.config.color = Some(self.default_config.color.clone());
144
- self.dispatch_config(ctx);
145
- true
146
- },
147
123
  }
148
124
  }
149
125
 
150
126
  fn view(&self, ctx: &Context<Self>) -> Html {
151
- let selected_color_mode = self.config.datetime_color_mode;
152
- let color_mode_changed = ctx
153
- .link()
154
- .callback(DatetimeColumnStyleMsg::ColorModeChanged);
155
-
156
- let color_controls = match selected_color_mode {
157
- DatetimeColorMode::None => html! {},
158
- DatetimeColorMode::Foreground => {
159
- self.color_select_row(ctx, &DatetimeColorMode::Foreground, "foreground-label")
160
- },
161
- DatetimeColorMode::Background => {
162
- self.color_select_row(ctx, &DatetimeColorMode::Background, "background-label")
163
- },
164
- };
165
-
166
127
  html! {
167
128
  <>
168
129
  <LocalStyle href={css!("column-style")} />
169
130
  <div id="column-style-container" class="datetime-column-style-container">
170
- <SelectEnumField<DatetimeColorMode>
171
- label="color"
172
- on_change={color_mode_changed}
173
- current_value={selected_color_mode}
174
- />
175
- { color_controls }
176
131
  if ctx.props().enable_time_config {
177
132
  <SelectValueField<String>
178
133
  label="timezone"
@@ -251,35 +206,18 @@ static USER_TIMEZONE: LazyLock<String> = LazyLock::new(|| {
251
206
  impl DatetimeColumnStyle {
252
207
  /// When this config has changed, we must signal the wrapper element.
253
208
  fn dispatch_config(&self, ctx: &Context<Self>) {
254
- let update =
255
- Some(self.config.clone()).filter(|x| x != &DatetimeColumnStyleConfig::default());
256
- ctx.props()
257
- .on_change
258
- .emit(ColumnConfigValueUpdate::DatagridDatetimeStyle(update));
259
- }
260
-
261
- /// Generate a color selector component for a specific `StringColorMode`
262
- /// variant.
263
- fn color_select_row(&self, ctx: &Context<Self>, mode: &DatetimeColorMode, title: &str) -> Html {
264
- let on_color = ctx.link().callback(DatetimeColumnStyleMsg::ColorChanged);
265
- let color = self
266
- .config
267
- .color
268
- .clone()
269
- .unwrap_or_else(|| self.default_config.color.to_owned());
209
+ let value = if self.config == DatetimeColumnStyleConfig::default() {
210
+ serde_json::Map::new()
211
+ } else {
212
+ match serde_json::to_value(&self.config) {
213
+ Ok(serde_json::Value::Object(m)) => m,
214
+ _ => serde_json::Map::new(),
215
+ }
216
+ };
270
217
 
271
- let color_props = props!(ColorProps {
272
- title: title.to_owned(),
273
- on_color,
274
- is_modified: color != self.default_config.color,
275
- color,
276
- on_reset: ctx.link().callback(|_| DatetimeColumnStyleMsg::ColorReset)
218
+ ctx.props().on_change.emit(ColumnConfigFieldUpdate {
219
+ keys: ctx.props().keys.clone(),
220
+ value,
277
221
  });
278
-
279
- if &self.config.datetime_color_mode == mode {
280
- html! { <div class="row"><ColorSelector ..color_props /></div> }
281
- } else {
282
- html! {}
283
- }
284
222
  }
285
223
  }
@@ -18,7 +18,6 @@ use yew::{Callback, Component, Html, NodeRef, Properties, TargetCast, classes, h
18
18
 
19
19
  use super::type_icon::TypeIconType;
20
20
  use crate::components::type_icon::TypeIcon;
21
- use crate::maybe;
22
21
  use crate::session::{Session, SessionMetadataRc};
23
22
 
24
23
  #[derive(Clone, PartialEq, Properties)]
@@ -103,7 +102,7 @@ impl Component for EditableHeader {
103
102
  let maybe_value = (!new_value.is_empty()).then_some(new_value.clone());
104
103
  self.edited = ctx.props().initial_value != maybe_value;
105
104
 
106
- self.valid = maybe!({
105
+ self.valid = (|| -> Option<bool> {
107
106
  if maybe_value
108
107
  .as_ref()
109
108
  .map(|v| v == &self.placeholder)
@@ -122,7 +121,7 @@ impl Component for EditableHeader {
122
121
  .chain(expressions)
123
122
  .contains(&new_value);
124
123
  Some(!found)
125
- })
124
+ })()
126
125
  .unwrap_or(true);
127
126
 
128
127
  self.value.clone_from(&maybe_value);
@@ -15,9 +15,9 @@ use std::rc::Rc;
15
15
  use yew::prelude::*;
16
16
 
17
17
  use super::containers::dropdown_menu::*;
18
+ use crate::config::*;
18
19
  use crate::renderer::*;
19
20
  use crate::session::Session;
20
- use crate::tasks::*;
21
21
 
22
22
  pub type ExportDropDownMenuItem = DropDownMenuItem<ExportFile>;
23
23
 
@@ -45,8 +45,7 @@ impl Component for ExportDropDownMenu {
45
45
 
46
46
  fn view(&self, ctx: &Context<Self>) -> yew::virtual_dom::VNode {
47
47
  let callback = ctx.link().callback(|_| ExportDropDownMenuMsg::TitleChange);
48
- let plugin = ctx.props().renderer.get_active_plugin().unwrap();
49
- let is_chart = plugin.name().as_str() != "Datagrid";
48
+ let is_chart = ctx.props().renderer.is_chart();
50
49
  html! {
51
50
  <>
52
51
  <span class="dropdown-group-label">{ "Save as" }</span>