@perspective-dev/viewer 5.3.1 → 5.4.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 (255) hide show
  1. package/dist/cdn/perspective-viewer.js +6 -6
  2. package/dist/cdn/perspective-viewer.js.map +2 -2
  3. package/dist/css/blueprint.css +1 -1
  4. package/dist/css/botanical.css +1 -1
  5. package/dist/css/dracula.css +1 -1
  6. package/dist/css/eggplant.css +1 -1
  7. package/dist/css/gruvbox-dark.css +1 -1
  8. package/dist/css/gruvbox.css +1 -1
  9. package/dist/css/icons.css +1 -1
  10. package/dist/css/intl/ar.css +1 -0
  11. package/dist/css/intl/de.css +1 -1
  12. package/dist/css/intl/es.css +1 -1
  13. package/dist/css/intl/fr.css +1 -1
  14. package/dist/css/intl/ja.css +1 -1
  15. package/dist/css/intl/pt.css +1 -1
  16. package/dist/css/intl/zh.css +1 -1
  17. package/dist/css/intl.css +1 -1
  18. package/dist/css/ledger.css +1 -1
  19. package/dist/css/monokai.css +1 -1
  20. package/dist/css/nord.css +1 -1
  21. package/dist/css/phosphor.css +1 -1
  22. package/dist/css/pro-dark.css +1 -1
  23. package/dist/css/pro.css +1 -1
  24. package/dist/css/solarized-dark.css +1 -1
  25. package/dist/css/solarized.css +1 -1
  26. package/dist/css/themes.css +1 -1
  27. package/dist/css/vaporwave.css +1 -1
  28. package/dist/css/velvet.css +1 -1
  29. package/dist/docs/perspective-docs.json +1 -1
  30. package/dist/esm/extensions.d.ts +0 -5
  31. package/dist/esm/perspective-viewer.inline.js +9 -9
  32. package/dist/esm/perspective-viewer.inline.js.map +3 -3
  33. package/dist/esm/perspective-viewer.js +5 -5
  34. package/dist/esm/perspective-viewer.js.map +2 -2
  35. package/dist/esm/ts-rs/ViewOnUpdateResp.d.ts +1 -1
  36. package/dist/wasm/perspective-viewer.d.ts +62 -73
  37. package/dist/wasm/perspective-viewer.js +226 -238
  38. package/dist/wasm/perspective-viewer.wasm +0 -0
  39. package/dist/wasm/perspective-viewer.wasm.d.ts +18 -28
  40. package/package.json +7 -7
  41. package/src/css/_context_menu.css +1 -1
  42. package/src/css/_dropdown_menu.css +1 -1
  43. package/src/css/_viewer_bundle.css +7 -8
  44. package/src/css/column-dropdown.css +0 -3
  45. package/src/css/column-selector.css +8 -5
  46. package/src/css/column-settings-panel.css +0 -225
  47. package/src/css/column-style.css +13 -0
  48. package/src/css/config-selector.css +18 -10
  49. package/src/css/filter-dropdown.css +5 -5
  50. package/src/css/form/debug.css +28 -4
  51. package/src/css/function-dropdown.css +5 -5
  52. package/src/css/panel-tab.css +23 -0
  53. package/src/css/plugin-selector.css +5 -5
  54. package/src/css/render-warning.css +1 -1
  55. package/src/css/status-bar.css +52 -21
  56. package/src/css/type-icon.css +1 -3
  57. package/src/css/{containers → ui/containers}/context-menu.css +22 -16
  58. package/src/css/ui/containers/dropdown-menu-items.css +66 -0
  59. package/src/css/{containers → ui/containers}/dropdown-menu.css +8 -53
  60. package/src/css/viewer.css +32 -26
  61. package/src/rust/components/chat_panel.rs +1 -1
  62. package/src/rust/components/{form/code_editor.rs → code_editor.rs} +4 -2
  63. package/src/rust/components/column_dropdown.rs +2 -2
  64. package/src/rust/components/column_selector/active_column.rs +15 -9
  65. package/src/rust/components/column_selector/aggregate_selector.rs +1 -1
  66. package/src/rust/components/column_selector/config_selector.rs +2 -2
  67. package/src/rust/components/column_selector/filter_column.rs +8 -5
  68. package/src/rust/components/column_selector/inactive_column.rs +4 -2
  69. package/src/rust/components/column_selector/pivot_column.rs +4 -3
  70. package/src/rust/components/column_selector/sort_column.rs +7 -4
  71. package/src/rust/components/column_selector.rs +3 -3
  72. package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +1 -1
  73. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +15 -17
  74. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +1 -1
  75. package/src/rust/components/column_settings_sidebar/style_tab.rs +4 -5
  76. package/src/rust/components/column_settings_sidebar.rs +3 -4
  77. package/src/rust/components/copy_dropdown.rs +1 -1
  78. package/src/rust/components/datetime_column_style/custom.rs +1 -3
  79. package/src/rust/components/datetime_column_style/simple.rs +1 -2
  80. package/src/rust/components/datetime_column_style.rs +1 -2
  81. package/src/rust/components/{form/debug.rs → debug_panel.rs} +5 -5
  82. package/src/rust/components/{containers/dragdrop_list.rs → dragdrop_list.rs} +2 -10
  83. package/src/rust/components/export_dropdown.rs +1 -1
  84. package/src/rust/components/expression_editor.rs +1 -1
  85. package/src/rust/components/filter_dropdown.rs +2 -2
  86. package/src/rust/components/function_dropdown.rs +2 -2
  87. package/src/rust/components/main_panel/frame_theme.rs +3 -59
  88. package/src/rust/components/main_panel/reconcile.rs +9 -4
  89. package/src/rust/components/main_panel/render.rs +62 -11
  90. package/src/rust/components/main_panel/update.rs +39 -10
  91. package/src/rust/components/main_panel.rs +26 -2
  92. package/src/rust/components/mod.rs +5 -7
  93. package/src/rust/components/new_panel_menu.rs +97 -0
  94. package/src/rust/components/number_series_style.rs +2 -3
  95. package/src/rust/components/panel_menu.rs +61 -87
  96. package/src/rust/components/panel_tab.rs +100 -43
  97. package/src/rust/components/plugin_tab.rs +1 -1
  98. package/src/rust/components/render_warning.rs +2 -2
  99. package/src/rust/components/{status_bar_counter.rs → rows_counter.rs} +10 -10
  100. package/src/rust/components/settings_panel.rs +2 -2
  101. package/src/rust/components/status_bar.rs +113 -19
  102. package/src/rust/components/status_indicator.rs +5 -14
  103. package/src/rust/components/string_column_style.rs +1 -2
  104. package/src/rust/components/{style/mod.rs → style.rs} +32 -15
  105. package/src/rust/components/style_controls/number_string_format/digits_section.rs +3 -5
  106. package/src/rust/components/style_controls/number_string_format/misc_section.rs +1 -1
  107. package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -1
  108. package/src/rust/components/viewer/msg.rs +43 -30
  109. package/src/rust/components/viewer/panels.rs +50 -19
  110. package/src/rust/components/viewer/render.rs +15 -13
  111. package/src/rust/components/viewer/settings.rs +137 -68
  112. package/src/rust/components/viewer/snapshots.rs +5 -10
  113. package/src/rust/components/viewer/wiring.rs +1 -21
  114. package/src/rust/components/viewer.rs +15 -10
  115. package/src/rust/components/window_editor.rs +8 -9
  116. package/src/rust/config/column_config_schema.rs +2 -27
  117. package/src/rust/config/mod.rs +0 -2
  118. package/src/rust/config/workspace_config.rs +2 -1
  119. package/src/rust/custom_elements/debug_plugin.rs +1 -10
  120. package/src/rust/custom_elements/mod.rs +0 -3
  121. package/src/rust/custom_elements/viewer.rs +0 -18
  122. package/src/rust/js/plugin.rs +0 -86
  123. package/src/rust/lib.rs +12 -15
  124. package/src/rust/presentation/column_locator.rs +3 -7
  125. package/src/rust/presentation.rs +68 -38
  126. package/src/rust/queries/hosted_tables.rs +38 -0
  127. package/src/rust/queries/mod.rs +2 -0
  128. package/src/rust/queries/palette_set.rs +1 -1
  129. package/src/rust/renderer/activate.rs +1 -3
  130. package/src/rust/renderer/dispatch.rs +83 -22
  131. package/src/rust/renderer/limits.rs +24 -5
  132. package/src/rust/renderer/plugin_config.rs +1 -0
  133. package/src/rust/renderer/props.rs +2 -1
  134. package/src/rust/renderer.rs +14 -27
  135. package/src/rust/session/props.rs +4 -3
  136. package/src/rust/session/view_subscription.rs +19 -6
  137. package/src/rust/session.rs +38 -70
  138. package/src/rust/tasks/create_panel.rs +1 -1
  139. package/src/rust/tasks/dismiss_render_warning.rs +1 -1
  140. package/src/rust/tasks/eject.rs +1 -0
  141. package/src/rust/tasks/pipeline.rs +0 -60
  142. package/src/rust/tasks/presize_panels.rs +24 -1
  143. package/src/rust/tasks/restore_and_render.rs +0 -17
  144. package/src/rust/tasks/send_column_config.rs +1 -1
  145. package/src/rust/tasks/send_plugin_config.rs +1 -1
  146. package/src/rust/tasks/set_edit_mode.rs +1 -1
  147. package/src/rust/{components → ui}/containers/control_group.rs +25 -3
  148. package/src/rust/{components → ui}/containers/dropdown_menu.rs +5 -2
  149. package/src/rust/{components → ui}/containers/mod.rs +0 -4
  150. package/src/rust/{components → ui}/containers/scroll_panel.rs +0 -22
  151. package/src/rust/{components → ui}/containers/scroll_panel_item.rs +0 -13
  152. package/src/rust/{components → ui}/containers/select.rs +0 -6
  153. package/src/rust/{components → ui}/containers/sidebar.rs +5 -32
  154. package/src/rust/{components → ui}/containers/split_panel.rs +8 -80
  155. package/src/rust/{components → ui}/containers/tab_list.rs +15 -9
  156. package/src/rust/{components → ui}/context_menu.rs +8 -13
  157. package/src/rust/{presentation/drag_helpers.rs → ui/dragdrop.rs} +26 -31
  158. package/src/rust/{components → ui}/font_loader.rs +0 -26
  159. package/src/rust/{components → ui}/form/color_selector.rs +4 -2
  160. package/src/rust/ui/form/intl_label.rs +81 -0
  161. package/src/rust/{components → ui}/form/mirrored_textarea.rs +0 -53
  162. package/src/rust/{components → ui}/form/mod.rs +1 -10
  163. package/src/rust/{components → ui}/form/multi_stop_gradient_selector.rs +4 -5
  164. package/src/rust/{components → ui}/form/named_value_picker.rs +1 -6
  165. package/src/rust/{components → ui}/form/number_field.rs +1 -1
  166. package/src/rust/{components → ui}/form/number_range_field.rs +1 -1
  167. package/src/rust/{components → ui}/form/optional_field.rs +3 -1
  168. package/src/rust/{components → ui}/form/palette_selector.rs +4 -5
  169. package/src/rust/{components → ui}/form/select_enum_field.rs +2 -2
  170. package/src/rust/{components → ui}/form/select_value_field.rs +2 -2
  171. package/src/rust/ui/mod.rs +56 -0
  172. package/src/rust/ui/modal.rs +61 -0
  173. package/src/rust/{components → ui}/portal.rs +174 -79
  174. package/src/rust/{components/style/style_provider.rs → ui/style.rs} +4 -34
  175. package/src/rust/utils/completion.rs +0 -6
  176. package/src/rust/{config/css_scale.rs → utils/css.rs} +38 -35
  177. package/src/rust/utils/mod.rs +2 -0
  178. package/src/rust/workspace.rs +35 -0
  179. package/src/svg/boolean-type.svg +3 -2
  180. package/src/svg/checkbox-checked-icon.svg +4 -7
  181. package/src/svg/checkbox-hover.svg +3 -3
  182. package/src/svg/checkbox-off.svg +2 -3
  183. package/src/svg/checkbox-on.svg +3 -3
  184. package/src/svg/checkbox-unchecked-icon.svg +3 -3
  185. package/src/svg/datagrid-select-column.svg +8 -15
  186. package/src/svg/datagrid-select-region.svg +8 -15
  187. package/src/svg/datagrid-select-row-tree.svg +7 -12
  188. package/src/svg/datagrid-select-row.svg +8 -13
  189. package/src/svg/date-type.svg +4 -23
  190. package/src/svg/drawer-tab-hover.svg +4 -6
  191. package/src/svg/drawer-tab-invert-hover.svg +5 -5
  192. package/src/svg/drawer-tab-invert.svg +3 -5
  193. package/src/svg/drawer-tab.svg +5 -5
  194. package/src/svg/mega-menu-icons-candlestick.svg +5 -37
  195. package/src/svg/mega-menu-icons-ohlc.svg +4 -39
  196. package/src/svg/mega-menu-icons-sunburst.svg +4 -38
  197. package/src/svg/mega-menu-icons-treemap.svg +3 -43
  198. package/src/svg/mega-menu-icons-y-scatter.svg +12 -72
  199. package/src/svg/new-panel-icon.svg +4 -0
  200. package/src/svg/number-type.svg +3 -3
  201. package/src/svg/radio-hover.svg +3 -3
  202. package/src/svg/radio-off.svg +3 -3
  203. package/src/svg/radio-on.svg +3 -3
  204. package/src/svg/status_ok.svg +3 -26
  205. package/src/svg/string-type.svg +4 -8
  206. package/src/svg/theme-icon.svg +5 -5
  207. package/src/themes/blueprint.css +0 -57
  208. package/src/themes/botanical.css +0 -36
  209. package/src/themes/defaults.css +1 -24
  210. package/src/themes/dracula.css +0 -58
  211. package/src/themes/eggplant.css +0 -58
  212. package/src/themes/gruvbox-dark.css +0 -65
  213. package/src/themes/gruvbox.css +1 -39
  214. package/src/themes/icons.css +1 -8
  215. package/src/themes/intl/ar.css +185 -0
  216. package/src/themes/intl/de.css +45 -35
  217. package/src/themes/intl/es.css +40 -30
  218. package/src/themes/intl/fr.css +39 -29
  219. package/src/themes/intl/ja.css +41 -31
  220. package/src/themes/intl/pt.css +37 -27
  221. package/src/themes/intl/zh.css +47 -37
  222. package/src/themes/intl.css +16 -3
  223. package/src/themes/ledger.css +1 -59
  224. package/src/themes/monokai.css +0 -51
  225. package/src/themes/nord.css +0 -55
  226. package/src/themes/phosphor.css +0 -48
  227. package/src/themes/pro-dark.css +0 -37
  228. package/src/themes/pro.css +3 -23
  229. package/src/themes/solarized-dark.css +0 -31
  230. package/src/themes/solarized.css +1 -24
  231. package/src/themes/vaporwave.css +0 -44
  232. package/src/themes/velvet.css +0 -60
  233. package/src/ts/extensions.ts +0 -13
  234. package/src/ts/ts-rs/ViewOnUpdateResp.ts +1 -1
  235. package/src/css/plugin-settings-panel.css +0 -171
  236. package/src/rust/components/modal.rs +0 -177
  237. package/src/rust/custom_elements/copy_dropdown.rs +0 -219
  238. package/src/rust/custom_elements/export_dropdown.rs +0 -216
  239. package/src/rust/custom_elements/modal.rs +0 -299
  240. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline0.js +0 -0
  241. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline1.js +0 -0
  242. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline2.js +0 -0
  243. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline3.js +0 -0
  244. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline4.js +0 -0
  245. /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-adc6f3f79141112b}/inline5.js +0 -0
  246. /package/src/css/{containers → ui/containers}/scroll-panel.css +0 -0
  247. /package/src/css/{containers → ui/containers}/split-panel.css +0 -0
  248. /package/src/css/{containers → ui/containers}/tabs.css +0 -0
  249. /package/src/css/{dom → ui/dom}/checkbox.css +0 -0
  250. /package/src/css/{dom → ui/dom}/scrollbar.css +0 -0
  251. /package/src/css/{dom → ui/dom}/select.css +0 -0
  252. /package/src/css/{form → ui/form}/mirrored-textarea.css +0 -0
  253. /package/src/rust/components/{form → code_editor}/highlight.rs +0 -0
  254. /package/src/rust/{components → ui}/containers/sidebar_close_button.rs +0 -0
  255. /package/src/rust/{components → ui}/form/number_input.rs +0 -0
@@ -70,6 +70,9 @@ pub struct ActiveColumnProps {
70
70
  #[prop_or_default]
71
71
  pub is_window: bool,
72
72
 
73
+ #[prop_or_default]
74
+ pub is_last_column: bool,
75
+
73
76
  /// Whether the expression/config edit button should be shown. Computed
74
77
  /// by the parent (`is_expression || can_render_column_styles`).
75
78
  #[prop_or_default]
@@ -287,7 +290,7 @@ impl Component for ActiveColumn {
287
290
  <div
288
291
  class={outer_classes}
289
292
  data-label={label}
290
- style={format!("--default-column-title:var(--column-selector-column-{path}--content)")}
293
+ style={format!("--default-column-title:var(--psp-label--column-{path}--content)")}
291
294
  data-index={ctx.props().idx.to_string()}
292
295
  ondragenter={ondragenter.clone()}
293
296
  >
@@ -301,7 +304,7 @@ impl Component for ActiveColumn {
301
304
  <div
302
305
  class={outer_classes}
303
306
  data-label={label}
304
- style={format!("--default-column-title:var(--column-selector-column-{path}--content)")}
307
+ style={format!("--default-column-title:var(--psp-label--column-{path}--content)")}
305
308
  data-index={ctx.props().idx.to_string()}
306
309
  ondragenter={ondragenter.clone()}
307
310
  >
@@ -310,7 +313,9 @@ impl Component for ActiveColumn {
310
313
  }
311
314
  },
312
315
  ((label, ColumnState::Named(name)), Some(col_type)) => {
313
- let is_required = ctx.props().get_is_required(ctx.props().idx);
316
+ let is_required =
317
+ ctx.props().is_last_column || ctx.props().get_is_required(ctx.props().idx);
318
+
314
319
  let remove_column = if is_required {
315
320
  None
316
321
  } else {
@@ -330,11 +335,12 @@ impl Component for ActiveColumn {
330
335
  let event_name = name.to_owned();
331
336
  let presentation = ctx.props().presentation.clone();
332
337
  move |event: DragEvent| {
333
- presentation.set_drag_image(&event).unwrap();
334
- presentation.notify_drag_start(
335
- event_name.to_string(),
336
- DragEffect::Move(DragTarget::Active),
337
- );
338
+ if presentation.set_drag_image(&event) {
339
+ presentation.notify_drag_start(
340
+ event_name.to_string(),
341
+ DragEffect::Move(DragTarget::Active),
342
+ );
343
+ }
338
344
 
339
345
  MouseLeave(false)
340
346
  }
@@ -359,7 +365,7 @@ impl Component for ActiveColumn {
359
365
  <div
360
366
  class={outer_classes}
361
367
  data-label={label}
362
- style={format!("--default-column-title:var(--column-selector-column-{path}--content)")}
368
+ style={format!("--default-column-title:var(--psp-label--column-{path}--content)")}
363
369
  data-index={ctx.props().idx.to_string()}
364
370
  {onmouseover}
365
371
  {onmouseout}
@@ -16,10 +16,10 @@ use itertools::Itertools;
16
16
  use perspective_client::config::*;
17
17
  use yew::prelude::*;
18
18
 
19
- use crate::components::containers::select::*;
20
19
  use crate::renderer::*;
21
20
  use crate::session::*;
22
21
  use crate::tasks::apply_and_render;
22
+ use crate::ui::{Select, SelectItem};
23
23
  use crate::utils::{PtrEqRc, spawn_owned};
24
24
 
25
25
  #[derive(Properties)]
@@ -21,8 +21,7 @@ use super::filter_column::*;
21
21
  use super::pivot_column::*;
22
22
  use super::sort_column::*;
23
23
  use crate::components::column_dropdown::{ColumnDropDownElement, ColumnDropDownPortal};
24
- use crate::components::containers::dragdrop_list::*;
25
- use crate::components::containers::select::{Select, SelectItem};
24
+ use crate::components::dragdrop_list::*;
26
25
  use crate::components::filter_dropdown::{FilterDropDownElement, FilterDropDownPortal};
27
26
  use crate::config::PluginStaticConfig;
28
27
  use crate::presentation::Presentation;
@@ -30,6 +29,7 @@ use crate::renderer::*;
30
29
  use crate::session::drag_drop_update::*;
31
30
  use crate::session::*;
32
31
  use crate::tasks::apply_and_render;
32
+ use crate::ui::{Select, SelectItem};
33
33
  use crate::utils::*;
34
34
 
35
35
  #[derive(Clone, Properties)]
@@ -19,14 +19,14 @@ use wasm_bindgen::JsCast;
19
19
  use web_sys::*;
20
20
  use yew::prelude::*;
21
21
 
22
- use crate::components::containers::dragdrop_list::*;
23
- use crate::components::containers::select::*;
22
+ use crate::components::dragdrop_list::*;
24
23
  use crate::components::filter_dropdown::FilterDropDownElement;
25
24
  use crate::components::type_icon::TypeIcon;
26
25
  use crate::presentation::Presentation;
27
26
  use crate::renderer::*;
28
27
  use crate::session::*;
29
28
  use crate::tasks::apply_and_render;
29
+ use crate::ui::{Select, SelectItem};
30
30
  use crate::utils::*;
31
31
 
32
32
  #[derive(Clone, Properties)]
@@ -240,9 +240,12 @@ impl Component for FilterColumn {
240
240
  let event_name = ctx.props().filter.column().to_owned();
241
241
  let presentation = ctx.props().presentation.clone();
242
242
  move |event: DragEvent| {
243
- presentation.set_drag_image(&event).unwrap();
244
- presentation
245
- .notify_drag_start(event_name.to_string(), DragEffect::Move(DragTarget::Filter))
243
+ if presentation.set_drag_image(&event) {
244
+ presentation.notify_drag_start(
245
+ event_name.to_string(),
246
+ DragEffect::Move(DragTarget::Filter),
247
+ )
248
+ }
246
249
  }
247
250
  });
248
251
 
@@ -141,8 +141,10 @@ impl Component for InactiveColumn {
141
141
  let event_name = ctx.props().name.to_owned();
142
142
  let presentation = ctx.props().presentation.clone();
143
143
  move |event: DragEvent| {
144
- presentation.set_drag_image(&event).unwrap();
145
- presentation.notify_drag_start(event_name.to_string(), DragEffect::Copy);
144
+ if presentation.set_drag_image(&event) {
145
+ presentation.notify_drag_start(event_name.to_string(), DragEffect::Copy);
146
+ }
147
+
146
148
  MouseLeave(true)
147
149
  }
148
150
  });
@@ -14,7 +14,7 @@ use perspective_client::config::ColumnType;
14
14
  use web_sys::*;
15
15
  use yew::prelude::*;
16
16
 
17
- use crate::components::containers::dragdrop_list::*;
17
+ use crate::components::dragdrop_list::*;
18
18
  use crate::components::type_icon::TypeIcon;
19
19
  use crate::presentation::Presentation;
20
20
  use crate::session::*;
@@ -73,8 +73,9 @@ impl Component for PivotColumn {
73
73
  let presentation = ctx.props().presentation.clone();
74
74
  let action = ctx.props().action;
75
75
  move |event: DragEvent| {
76
- presentation.set_drag_image(&event).unwrap();
77
- presentation.notify_drag_start(event_name.to_string(), DragEffect::Move(action))
76
+ if presentation.set_drag_image(&event) {
77
+ presentation.notify_drag_start(event_name.to_string(), DragEffect::Move(action))
78
+ }
78
79
  }
79
80
  });
80
81
 
@@ -14,7 +14,7 @@ use perspective_client::config::*;
14
14
  use web_sys::*;
15
15
  use yew::prelude::*;
16
16
 
17
- use crate::components::containers::dragdrop_list::*;
17
+ use crate::components::dragdrop_list::*;
18
18
  use crate::components::type_icon::TypeIcon;
19
19
  use crate::presentation::Presentation;
20
20
  use crate::renderer::*;
@@ -104,9 +104,12 @@ impl Component for SortColumn {
104
104
  let event_name = ctx.props().sort.0.to_owned();
105
105
  let presentation = ctx.props().presentation.clone();
106
106
  move |event: DragEvent| {
107
- presentation.set_drag_image(&event).unwrap();
108
- presentation
109
- .notify_drag_start(event_name.to_string(), DragEffect::Move(DragTarget::Sort))
107
+ if presentation.set_drag_image(&event) {
108
+ presentation.notify_drag_start(
109
+ event_name.to_string(),
110
+ DragEffect::Move(DragTarget::Sort),
111
+ )
112
+ }
110
113
  }
111
114
  });
112
115
 
@@ -38,10 +38,7 @@ use self::active_column::*;
38
38
  use self::add_expression_button::AddExpressionButton;
39
39
  use self::config_selector::ConfigSelector;
40
40
  use self::inactive_column::*;
41
- use super::containers::scroll_panel::*;
42
- use super::containers::split_panel::{Orientation, SplitPanel};
43
41
  use crate::components::column_dropdown::{ColumnDropDownElement, ColumnDropDownPortal};
44
- use crate::components::containers::scroll_panel_item::ScrollPanelItem;
45
42
  use crate::config::PluginStaticConfig;
46
43
  use crate::presentation::{ColumnLocator, ColumnSettingsTarget, DragDropContainer, Presentation};
47
44
  use crate::queries::{
@@ -51,6 +48,7 @@ use crate::renderer::*;
51
48
  use crate::session::drag_drop_update::*;
52
49
  use crate::session::*;
53
50
  use crate::tasks::apply_and_render;
51
+ use crate::ui::{Orientation, ScrollPanel, ScrollPanelItem, SplitPanel};
54
52
  use crate::utils::*;
55
53
 
56
54
  #[derive(Properties)]
@@ -333,6 +331,7 @@ impl Component for ColumnSelector {
333
331
  prop_config.clone()
334
332
  };
335
333
 
334
+ let is_last_column = config.columns.len() == 1;
336
335
  let is_aggregated = config.is_aggregated();
337
336
  let columns_iter = ColumnsIteratorSet::new(&config, metadata, renderer, presentation);
338
337
  let onselect = ctx.link().callback(|()| Redraw);
@@ -468,6 +467,7 @@ impl Component for ColumnSelector {
468
467
  {is_window}
469
468
  {show_edit_btn}
470
469
  {col_type}
470
+ {is_last_column}
471
471
  view_config={config.clone()}
472
472
  metadata={metadata.clone()}
473
473
  {name}
@@ -13,8 +13,8 @@
13
13
  use perspective_client::clone;
14
14
  use yew::{Callback, Html, Properties, function_component, html};
15
15
 
16
- use crate::components::form::number_field::NumberField;
17
16
  use crate::config::ColumnConfigFieldUpdate;
17
+ use crate::ui::NumberField;
18
18
 
19
19
  // ░░░█▀█░█▀▄░█▀█░█▀█░█▀▀░█▀▄░▀█▀░▀█▀░█▀▀░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
20
20
  // ░░░█▀▀░█▀▄░█░█░█▀▀░█▀▀░█▀▄░░█░░░█░░█▀▀░▀▀█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
@@ -26,17 +26,14 @@ use wasm_bindgen::JsCast;
26
26
  use web_sys::{HtmlInputElement, MouseEvent};
27
27
  use yew::{Callback, Html, Properties, function_component, html, use_callback};
28
28
 
29
- use crate::components::containers::select::{Select, SelectItem};
30
- use crate::components::form::color_selector::ColorSelector;
31
- use crate::components::form::multi_stop_gradient_selector::MultiStopGradientSelector;
32
- use crate::components::form::named_value_picker::NamedValuePicker;
33
- use crate::components::form::number_field::NumberField;
34
- use crate::components::form::optional_field::OptionalField;
35
- use crate::components::form::palette_selector::PaletteSelector;
36
- use crate::config::{
37
- ColumnConfigFieldUpdate, CssColor, CssGradient, CssKind, CssPalette, EnumVariant,
38
- GradientStopSpec, NamedValue, canonicalize_css_color, discrete_pair, gradient_to_css,
39
- palette_name_for,
29
+ use crate::config::{ColumnConfigFieldUpdate, EnumVariant, discrete_pair};
30
+ use crate::ui::{
31
+ ColorSelector, MultiStopGradientSelector, NamedValuePicker, NumberField, OptionalField,
32
+ PaletteSelector, Select, SelectItem,
33
+ };
34
+ use crate::utils::{
35
+ CssColor, CssGradient, CssKind, CssPalette, GradientStopSpec, NamedValue,
36
+ canonicalize_css_color, gradient_to_css, palette_name_for,
40
37
  };
41
38
 
42
39
  fn emit(on_change: &Callback<ColumnConfigFieldUpdate>, key: &str, value: Option<Value>) {
@@ -150,9 +147,10 @@ pub fn BoolField(props: &BoolFieldProps) -> Html {
150
147
  checked={current}
151
148
  {oninput}
152
149
  />
153
- <label for={format!("{}-checkbox", props.field_key)} class="bool-field-desc">
154
- { if current { "Enabled" } else { "Disabled" } }
155
- </label>
150
+ <label
151
+ for={format!("{}-checkbox", props.field_key)}
152
+ class={if current { "bool-field-desc enabled" } else { "bool-field-desc disabled" }}
153
+ />
156
154
  </div>
157
155
  </OptionalField>
158
156
  </div>
@@ -346,7 +344,7 @@ pub fn PaletteField(props: &PaletteFieldProps) -> Html {
346
344
  on_change={on_change_palette}
347
345
  {on_reset}
348
346
  {is_modified}
349
- title={Some(format!("{}-label", props.field_key))}
347
+ label={Some(props.field_key.clone())}
350
348
  />
351
349
  </div>
352
350
  }
@@ -459,7 +457,7 @@ pub fn GradientStopsField(props: &GradientStopsFieldProps) -> Html {
459
457
  on_change={on_change_stops}
460
458
  {on_reset}
461
459
  {is_modified}
462
- title={Some(format!("{}-label", props.field_key))}
460
+ label={Some(props.field_key.clone())}
463
461
  />
464
462
  </div>
465
463
  }
@@ -555,7 +553,7 @@ pub fn ColorField(props: &ColorFieldProps) -> Html {
555
553
  {on_color}
556
554
  {on_reset}
557
555
  {is_modified}
558
- title={Some(format!("{}-label", props.field_key))}
556
+ label={Some(props.field_key.clone())}
559
557
  />
560
558
  </div>
561
559
  }
@@ -13,7 +13,7 @@
13
13
  use itertools::Itertools;
14
14
  use yew::{Callback, Html, Properties, function_component, html};
15
15
 
16
- use crate::components::containers::select::{Select, SelectItem};
16
+ use crate::ui::{Select, SelectItem};
17
17
  use crate::utils::PtrEqRc;
18
18
 
19
19
  #[derive(Properties, PartialEq)]
@@ -26,22 +26,21 @@ use self::primitive_field::{
26
26
  BoolField, ColorField, EnumField, GradientStopsField, NumberFieldPrimitive, PaletteField,
27
27
  };
28
28
  use crate::components::column_settings_sidebar::style_tab::symbol::SymbolStyle;
29
- use crate::components::containers::control_group::ControlGroup;
30
29
  use crate::components::datetime_column_style::DatetimeColumnStyle;
31
30
  use crate::components::number_series_style::NumberSeriesStyle;
32
31
  use crate::components::string_column_style::StringColumnStyle;
33
32
  use crate::components::style_controls::CustomNumberFormat;
34
33
  use crate::config::{
35
- ColumnConfigFieldUpdate, ControlSpec, CssKind, CustomNumberFormatConfig,
36
- DatetimeColumnStyleConfig, NamedValue, NumberFormatDefaults, NumberSeriesStyleConfig,
37
- StringColumnStyleConfig,
34
+ ColumnConfigFieldUpdate, ControlSpec, CustomNumberFormatConfig, DatetimeColumnStyleConfig,
35
+ NumberFormatDefaults, NumberSeriesStyleConfig, StringColumnStyleConfig,
38
36
  };
39
37
  use crate::presentation::Presentation;
40
38
  use crate::queries::{fetch_column_abs_max, get_column_config_schema, named_values};
41
39
  use crate::renderer::Renderer;
42
40
  use crate::session::Session;
43
41
  use crate::tasks::send_column_config;
44
- use crate::utils::PtrEqRc;
42
+ use crate::ui::ControlGroup;
43
+ use crate::utils::{CssKind, NamedValue, PtrEqRc};
45
44
  use crate::workspace::Workspace;
46
45
 
47
46
  #[derive(Clone, PartialEq, Properties)]
@@ -29,9 +29,7 @@ use crate::components::column_settings_sidebar::attributes_tab::AttributesTab;
29
29
  use crate::components::column_settings_sidebar::save_settings::SaveSettingsProps;
30
30
  use crate::components::column_settings_sidebar::style_tab::StyleTab;
31
31
  use crate::components::column_settings_sidebar::window_tab::{WindowTab, WindowTabProps};
32
- use crate::components::containers::sidebar::Sidebar;
33
- use crate::components::containers::tab_list::TabList;
34
- use crate::components::editable_header::EditableHeaderProps;
32
+ use crate::components::editable_header::{EditableHeader, EditableHeaderProps};
35
33
  use crate::components::expression_editor::ExpressionEditorProps;
36
34
  use crate::components::type_icon::TypeIconType;
37
35
  use crate::components::window_editor::WindowEditorProps;
@@ -41,6 +39,7 @@ use crate::session::{Session, SessionMetadataRc};
41
39
  use crate::tasks::{
42
40
  delete_expr, delete_window, save_expr, save_window, update_expr, update_window,
43
41
  };
42
+ use crate::ui::{Sidebar, TabList};
44
43
  use crate::utils::PtrEqRc;
45
44
  use crate::workspace::Workspace;
46
45
 
@@ -519,7 +518,7 @@ impl Component for ColumnSettingsPanel {
519
518
  is_pinned={ctx.props().is_pinned}
520
519
  on_toggle_pin={Some(ctx.props().on_toggle_pin.clone())}
521
520
  selected_tab={selected_tab_idx}
522
- {header_props}
521
+ header={html! { <EditableHeader ..header_props /> }}
523
522
  >
524
523
  <TabList<ColumnSettingsTab>
525
524
  tabs={self.tabs.clone()}
@@ -14,9 +14,9 @@ use std::rc::Rc;
14
14
 
15
15
  use yew::prelude::*;
16
16
 
17
- use super::containers::dropdown_menu::*;
18
17
  use crate::config::*;
19
18
  use crate::renderer::*;
19
+ use crate::ui::{DropDownMenu, DropDownMenuItem};
20
20
 
21
21
  type CopyDropDownMenuItem = DropDownMenuItem<ExportFile>;
22
22
 
@@ -14,10 +14,8 @@ use std::rc::Rc;
14
14
 
15
15
  use yew::prelude::*;
16
16
 
17
- use crate::components::form::number_field::NumberField;
18
- use crate::components::form::select_value_field::SelectValueField;
19
- use crate::components::modal::{ModalLink, SetModalLink};
20
17
  use crate::config::*;
18
+ use crate::ui::{ModalLink, NumberField, SelectValueField, SetModalLink};
21
19
  use crate::utils::WeakScope;
22
20
 
23
21
  #[derive(Properties)]
@@ -12,9 +12,8 @@
12
12
 
13
13
  use yew::prelude::*;
14
14
 
15
- use crate::components::form::select_enum_field::SelectEnumField;
16
- use crate::components::modal::{ModalLink, SetModalLink};
17
15
  use crate::config::*;
16
+ use crate::ui::{ModalLink, SelectEnumField, SetModalLink};
18
17
  use crate::utils::WeakScope;
19
18
 
20
19
  #[derive(Properties)]
@@ -22,11 +22,10 @@ use perspective_js::utils::global::navigator;
22
22
  use wasm_bindgen::prelude::*;
23
23
  use yew::prelude::*;
24
24
 
25
- use super::modal::{ModalLink, SetModalLink};
26
25
  use crate::components::datetime_column_style::custom::DatetimeStyleCustom;
27
26
  use crate::components::datetime_column_style::simple::DatetimeStyleSimple;
28
- use crate::components::form::select_value_field::SelectValueField;
29
27
  use crate::config::*;
28
+ use crate::ui::{ModalLink, SelectValueField, SetModalLink};
30
29
  use crate::utils::WeakScope;
31
30
 
32
31
  /// Format-only widget for `datetime` columns. Renders the `date_format`
@@ -17,7 +17,7 @@ use perspective_js::utils::{ApiFuture, JsValueSerdeExt};
17
17
  use wasm_bindgen::prelude::*;
18
18
  use yew::prelude::*;
19
19
 
20
- use crate::components::form::code_editor::CodeEditor;
20
+ use crate::components::code_editor::CodeEditor;
21
21
  use crate::js::{MimeType, copy_to_clipboard, paste_from_clipboard};
22
22
  use crate::presentation::*;
23
23
  use crate::renderer::*;
@@ -169,10 +169,10 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
169
169
  <div id="debug-panel-overflow">
170
170
  <div id="debug-panel" class="sidebar_column" ref={sizer}>
171
171
  <div id="debug-panel-controls">
172
- <button disabled={!*modified} onclick={onapply}>{ "Apply" }</button>
173
- <button disabled={!*modified} onclick={onreset}>{ "Reset" }</button>
174
- <button onclick={oncopy}>{ "Copy" }</button>
175
- <button onclick={onpaste}>{ "Paste" }</button>
172
+ <button id="debug-panel-apply" disabled={!*modified} onclick={onapply} />
173
+ <button id="debug-panel-reset" disabled={!*modified} onclick={onreset} />
174
+ <button id="debug-panel-copy" onclick={oncopy} />
175
+ <button id="debug-panel-paste" onclick={onpaste} />
176
176
  </div>
177
177
  <div id="debug-panel-editor">
178
178
  <CodeEditor
@@ -23,6 +23,7 @@ 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
25
  use crate::presentation::{DragDropContainer, Presentation};
26
+ use crate::ui::intl_slug;
26
27
  use crate::utils::DragTarget;
27
28
 
28
29
  #[derive(Properties, Derivative)]
@@ -405,16 +406,7 @@ where
405
406
  // here while the var VALUE stays in the stylesheets - custom
406
407
  // properties inherit, so the label's `:before` picks it up.
407
408
  let role_style = ctx.props().role_label.as_ref().map(|role| {
408
- let slug = role
409
- .chars()
410
- .map(|x| {
411
- if x.is_ascii_alphanumeric() {
412
- x.to_ascii_lowercase()
413
- } else {
414
- '-'
415
- }
416
- })
417
- .collect::<String>();
409
+ let slug = intl_slug(role);
418
410
 
419
411
  // The second var is a PRESENCE FLAG: CSS cannot ask whether a
420
412
  // custom property is set, so the slot's stylesheet reads it as
@@ -14,10 +14,10 @@ use std::rc::Rc;
14
14
 
15
15
  use yew::prelude::*;
16
16
 
17
- use super::containers::dropdown_menu::*;
18
17
  use crate::config::*;
19
18
  use crate::renderer::*;
20
19
  use crate::session::Session;
20
+ use crate::ui::{DropDownMenu, DropDownMenuItem};
21
21
 
22
22
  pub type ExportDropDownMenuItem = DropDownMenuItem<ExportFile>;
23
23
 
@@ -15,7 +15,7 @@ use std::rc::Rc;
15
15
  use perspective_client::{ExprValidationError, clone};
16
16
  use yew::prelude::*;
17
17
 
18
- use super::form::code_editor::*;
18
+ use super::code_editor::CodeEditor;
19
19
  use crate::session::{Session, SessionMetadataRc};
20
20
  use crate::tasks::{ExprValidation, validate_expression};
21
21
 
@@ -19,9 +19,9 @@ use web_sys::*;
19
19
  use yew::html::ImplicitClone;
20
20
  use yew::prelude::*;
21
21
 
22
- use super::portal::PortalModal;
23
22
  use super::style::StyleSurface;
24
23
  use crate::session::Session;
24
+ use crate::ui::PortalModal;
25
25
  use crate::utils::*;
26
26
  use crate::*;
27
27
 
@@ -219,7 +219,7 @@ impl Component for FilterDropDownPortal {
219
219
  html! {
220
220
  <PortalModal
221
221
  tag_name="perspective-dropdown"
222
- surface={StyleSurface::FilterDropdown}
222
+ sheet={StyleSurface::FilterDropdown.sheet()}
223
223
  {target}
224
224
  own_focus=false
225
225
  {on_close}
@@ -19,8 +19,8 @@ use web_sys::*;
19
19
  use yew::html::ImplicitClone;
20
20
  use yew::prelude::*;
21
21
 
22
- use super::portal::PortalModal;
23
22
  use super::style::StyleSurface;
23
+ use crate::ui::PortalModal;
24
24
  use crate::utils::*;
25
25
 
26
26
  #[derive(Default)]
@@ -157,7 +157,7 @@ impl Component for FunctionDropDownPortal {
157
157
  html! {
158
158
  <PortalModal
159
159
  tag_name="perspective-dropdown"
160
- surface={StyleSurface::FunctionDropdown}
160
+ sheet={StyleSurface::FunctionDropdown.sheet()}
161
161
  {target}
162
162
  own_focus=false
163
163
  {on_close}
@@ -21,42 +21,6 @@
21
21
  //! own per-panel themed background), but while the plugin is missing — not yet
22
22
  //! mounted, first draw pending, or torn down — the host-theme container shows
23
23
  //! through a panel themed differently, as a visible artifact.
24
- //!
25
- //! There is no native cascade channel from the light-DOM plugin to the frame
26
- //! (siblings in the flattened tree), so the value is mirrored imperatively:
27
- //! each panel's *plugin element* — light-DOM, slotted under the panel's slot,
28
- //! mounted eagerly at panel creation (`create_panel_model` /
29
- //! `Renderer::mount_active_plugin`) — is where the document theme rules
30
- //! actually resolve, so its computed `--psp--background-color` is copied onto
31
- //! the frame's inline style, where the frame's shadow parts inherit it. The
32
- //! plugin is the ONLY sound source element:
33
- //!
34
- //! - An owned hidden probe child of the viewer does NOT work: an *unslotted*
35
- //! light-DOM child of a shadow host is outside the flattened tree, and
36
- //! `getComputedStyle` returns all-empty for it even though the document rules
37
- //! match it syntactically (selector matching is DOM-tree; style computation
38
- //! is flat-tree).
39
- //! - The `<perspective-viewer-tab>` is slotted, but stamps its own `theme` attr
40
- //! in `PanelTab::rendered` — an unordered sibling lifecycle relative to this
41
- //! pass (the theme-stamp-lag class of bug).
42
- //! - The plugin's `theme` attr, by contrast, is stamped *synchronously at the
43
- //! mutation sites* (`update_theme`, `restorePanel`, …) before the events that
44
- //! schedule this render, so it is current when this pass reads it.
45
- //!
46
- //! A read is trusted ONLY when the plugin's stamped attr equals the theme
47
- //! being mirrored: a freshly-created panel's plugin is mounted *unstamped*
48
- //! (the attr first lands inside its first locked dispatch), and reading it
49
- //! early would silently mirror the HOST theme's values. Trusted reads seed
50
- //! [`MainPanel::theme_backgrounds`], the fallback for frames with no readable
51
- //! plugin (an unregistered plugin name stays lazily unmounted; plugin-switch
52
- //! and teardown transients). A frame with neither leaves the pass gate
53
- //! unlatched, so it retries on subsequent renders until the dispatch stamp
54
- //! lands (the render that follows that dispatch's `update_count` bump).
55
- //!
56
- //! Unlike the plugin `theme`/`active` stamps (see the NOTE in [`reconcile`]),
57
- //! the frame is pure viewer chrome — no plugin dispatch reads it — so
58
- //! stamping it from this async `rendered` pass cannot split a plugin draw
59
- //! across paints, and it needs no lock.
60
24
 
61
25
  use wasm_bindgen::prelude::*;
62
26
  use yew::prelude::*;
@@ -69,12 +33,7 @@ use crate::workspace::PanelId;
69
33
  /// `.rl-panel::part(container)` background resolves.
70
34
  const BACKGROUND_VAR: &str = "--psp--background-color";
71
35
 
72
- /// The inputs the frame backgrounds were last computed from; re-mirroring is
73
- /// skipped while these are unchanged, so the forced style recalcs of
74
- /// `getComputedStyle` don't run on every render (e.g. the per-update
75
- /// `update_count` renders of a streaming table). `available_themes` is part of
76
- /// the key because theme CSS registering late changes the *computed* value
77
- /// under an unchanged theme name.
36
+ /// The inputs the frame backgrounds were last computed from.
78
37
  pub(super) type FrameThemeSnapshot = (
79
38
  Vec<PanelId>,
80
39
  Vec<(String, Option<String>)>,
@@ -82,12 +41,7 @@ pub(super) type FrameThemeSnapshot = (
82
41
  );
83
42
 
84
43
  impl MainPanel {
85
- /// Mirror each panel's effective theme background (its own theme, else the
86
- /// registry default — the same fallback the tab/menu use) onto its
87
- /// `<regular-layout-frame>`'s inline `--psp--background-color`, read off
88
- /// the panel's stamped plugin element (else the theme-keyed cache of prior
89
- /// reads). A panel with no resolvable theme has the property removed,
90
- /// falling back to the inherited host-theme value.
44
+ /// Mirror each panel's effective theme background.
91
45
  pub(super) fn stamp_frame_themes(&mut self, ctx: &Context<Self>) {
92
46
  let Some(layout) = self.layout_ref.cast::<web_sys::Element>() else {
93
47
  return;
@@ -104,8 +58,6 @@ impl MainPanel {
104
58
  return;
105
59
  }
106
60
 
107
- // A theme-registry change can re-value an unchanged theme name, so
108
- // cached reads from the previous registry are unsound.
109
61
  if let Some((_, _, prev_themes)) = &self.stamped_frame_themes
110
62
  && prev_themes != &snapshot.2
111
63
  {
@@ -155,19 +107,11 @@ impl MainPanel {
155
107
  }
156
108
  }
157
109
 
158
- // Latch only a fully-resolved pass; an unresolved frame (unmounted or
159
- // not-yet-stamped plugin) retries each render until its dispatch
160
- // stamp lands.
161
110
  self.stamped_frame_themes = complete.then_some(snapshot);
162
111
  }
163
112
  }
164
113
 
165
- /// Read the computed [`BACKGROUND_VAR`] off `slot`'s plugin element — the
166
- /// viewer light-DOM child mounted under exactly that slot name (the tab and
167
- /// toolbar use `tab-`/`statusbar-extra-` prefixed slots). Requires the
168
- /// plugin's `theme` attr to already equal `theme` — during a plugin switch
169
- /// two elements briefly share the slot, and a freshly-mounted plugin is not
170
- /// yet stamped; both are disambiguated by the attr check.
114
+ /// Read the computed [`BACKGROUND_VAR`] off `slot`'s plugin element.
171
115
  fn read_plugin_background(viewer: &web_sys::Element, slot: &str, theme: &str) -> Option<String> {
172
116
  let children = viewer.children();
173
117
  let plugin = (0..children.length())