@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
@@ -11,9 +11,7 @@
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
13
  use yew::prelude::*;
14
- use yew::*;
15
14
 
16
- use super::form::color_selector::*;
17
15
  use super::modal::{ModalLink, SetModalLink};
18
16
  use super::style::LocalStyle;
19
17
  use crate::components::form::select_enum_field::SelectEnumField;
@@ -21,13 +19,18 @@ use crate::config::*;
21
19
  use crate::css;
22
20
  use crate::utils::WeakScope;
23
21
 
22
+ /// Format-only widget for [`String`] columns. Renders the `format` enum
23
+ /// only; color/color-mode UI is provided externally as primitive `Enum`
24
+ /// + `Color` schema fields.
24
25
  #[derive(Properties)]
25
26
  pub struct StringColumnStyleProps {
26
27
  pub config: Option<StringColumnStyleConfig>,
27
- pub default_config: StringColumnStyleDefaultConfig,
28
28
 
29
29
  #[prop_or_default]
30
- pub on_change: Callback<ColumnConfigValueUpdate>,
30
+ pub on_change: Callback<ColumnConfigFieldUpdate>,
31
+
32
+ #[prop_or_default]
33
+ pub keys: Vec<String>,
31
34
 
32
35
  #[prop_or_default]
33
36
  weak_link: WeakScope<StringColumnStyle>,
@@ -41,22 +44,16 @@ impl ModalLink<StringColumnStyle> for StringColumnStyleProps {
41
44
 
42
45
  impl PartialEq for StringColumnStyleProps {
43
46
  fn eq(&self, other: &Self) -> bool {
44
- self.config == other.config && self.default_config == other.default_config
47
+ self.config == other.config
45
48
  }
46
49
  }
47
50
 
48
51
  pub enum StringColumnStyleMsg {
49
- Reset(StringColumnStyleConfig),
50
52
  FormatChanged(Option<FormatMode>),
51
- ColorModeChanged(Option<StringColorMode>),
52
- ColorChanged(String),
53
- ColorReset,
54
53
  }
55
54
 
56
- /// A component for the style form control for [`String`] columns.
57
55
  pub struct StringColumnStyle {
58
56
  config: StringColumnStyleConfig,
59
- default_config: StringColumnStyleDefaultConfig,
60
57
  }
61
58
 
62
59
  impl Component for StringColumnStyle {
@@ -67,11 +64,9 @@ impl Component for StringColumnStyle {
67
64
  ctx.set_modal_link();
68
65
  Self {
69
66
  config: ctx.props().config.clone().unwrap_or_default(),
70
- default_config: ctx.props().default_config.clone(),
71
67
  }
72
68
  }
73
69
 
74
- // Always re-render when config changes.
75
70
  fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
76
71
  let mut new_config = ctx.props().config.clone().unwrap_or_default();
77
72
  if self.config != new_config {
@@ -84,51 +79,16 @@ impl Component for StringColumnStyle {
84
79
 
85
80
  fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
86
81
  match msg {
87
- StringColumnStyleMsg::Reset(config) => {
88
- self.config = config;
89
- true
90
- },
91
82
  StringColumnStyleMsg::FormatChanged(val) => {
92
83
  self.config.format = val.unwrap_or_default();
93
84
  self.dispatch_config(ctx);
94
85
  true
95
86
  },
96
- StringColumnStyleMsg::ColorModeChanged(mode) => {
97
- self.config.string_color_mode = mode.unwrap_or_default();
98
- self.dispatch_config(ctx);
99
- true
100
- },
101
- StringColumnStyleMsg::ColorChanged(color) => {
102
- self.config.color = Some(color);
103
- self.dispatch_config(ctx);
104
- true
105
- },
106
- StringColumnStyleMsg::ColorReset => {
107
- self.config.color = Some(self.default_config.color.clone());
108
- self.dispatch_config(ctx);
109
- true
110
- },
111
87
  }
112
88
  }
113
89
 
114
90
  fn view(&self, ctx: &Context<Self>) -> Html {
115
- let format_mode_selected = self.config.format;
116
91
  let format_mode_changed = ctx.link().callback(StringColumnStyleMsg::FormatChanged);
117
- let selected_color_mode = self.config.string_color_mode;
118
- let color_mode_changed = ctx.link().callback(StringColumnStyleMsg::ColorModeChanged);
119
- let color_controls = match selected_color_mode {
120
- StringColorMode::Foreground => {
121
- self.color_select_row(ctx, &StringColorMode::Foreground, "foreground-label")
122
- },
123
- StringColorMode::Background => {
124
- self.color_select_row(ctx, &StringColorMode::Background, "background-label")
125
- },
126
- StringColorMode::Series => {
127
- self.color_select_row(ctx, &StringColorMode::Series, "series-label")
128
- },
129
- StringColorMode::None => html! {},
130
- };
131
-
132
92
  html! {
133
93
  <>
134
94
  <LocalStyle href={css!("column-style")} />
@@ -136,14 +96,8 @@ impl Component for StringColumnStyle {
136
96
  <SelectEnumField<FormatMode>
137
97
  label="format"
138
98
  on_change={format_mode_changed}
139
- current_value={format_mode_selected}
140
- />
141
- <SelectEnumField<StringColorMode>
142
- label="color"
143
- on_change={color_mode_changed}
144
- current_value={selected_color_mode}
99
+ current_value={self.config.format}
145
100
  />
146
- { color_controls }
147
101
  </div>
148
102
  </>
149
103
  }
@@ -153,34 +107,18 @@ impl Component for StringColumnStyle {
153
107
  impl StringColumnStyle {
154
108
  /// When this config has changed, we must signal the wrapper element.
155
109
  fn dispatch_config(&self, ctx: &Context<Self>) {
156
- let update = Some(self.config.clone()).filter(|x| x != &StringColumnStyleConfig::default());
157
- ctx.props()
158
- .on_change
159
- .emit(ColumnConfigValueUpdate::DatagridStringStyle(update));
160
- }
110
+ let value = if self.config == StringColumnStyleConfig::default() {
111
+ serde_json::Map::new()
112
+ } else {
113
+ match serde_json::to_value(&self.config) {
114
+ Ok(serde_json::Value::Object(m)) => m,
115
+ _ => serde_json::Map::new(),
116
+ }
117
+ };
161
118
 
162
- /// Generate a color selector component for a specific `StringColorMode`
163
- /// variant.
164
- fn color_select_row(&self, ctx: &Context<Self>, mode: &StringColorMode, title: &str) -> Html {
165
- let on_color = ctx.link().callback(StringColumnStyleMsg::ColorChanged);
166
- let color = self
167
- .config
168
- .color
169
- .clone()
170
- .unwrap_or_else(|| self.default_config.color.to_owned());
171
-
172
- let color_props = props!(ColorProps {
173
- title: title.to_owned(),
174
- on_color,
175
- is_modified: color != self.default_config.color,
176
- color,
177
- on_reset: ctx.link().callback(|_| StringColumnStyleMsg::ColorReset)
119
+ ctx.props().on_change.emit(ColumnConfigFieldUpdate {
120
+ keys: ctx.props().keys.clone(),
121
+ value,
178
122
  });
179
-
180
- if &self.config.string_color_mode == mode {
181
- html! { <div class="row"><ColorSelector ..color_props /></div> }
182
- } else {
183
- html! {}
184
- }
185
123
  }
186
124
  }
@@ -26,9 +26,11 @@ use crate::css;
26
26
  #[derive(Properties, PartialEq, Clone)]
27
27
  pub struct CustomNumberFormatProps {
28
28
  pub restored_config: CustomNumberFormatConfig,
29
- pub on_change: Callback<ColumnConfigValueUpdate>,
29
+ pub on_change: Callback<ColumnConfigFieldUpdate>,
30
30
  pub view_type: ColumnType,
31
31
  pub column_name: String,
32
+ #[prop_or_default]
33
+ pub keys: Vec<String>,
32
34
  }
33
35
 
34
36
  pub enum CustomNumberFormatMsg {
@@ -56,10 +58,6 @@ pub struct CustomNumberFormat {
56
58
  config: CustomNumberFormatConfig,
57
59
  style: NumberStyle,
58
60
  notation: Option<NotationName>,
59
- // show_frac: bool,
60
- // show_sig: bool,
61
- // disable_rounding_increment: bool,
62
- // disable_rounding_priority: bool,
63
61
  }
64
62
 
65
63
  impl Component for CustomNumberFormat {
@@ -197,11 +195,17 @@ impl Component for CustomNumberFormat {
197
195
 
198
196
  let is_float = ctx.props().view_type == ColumnType::Float;
199
197
  let filtered_config = self.config.clone().filter_default(is_float);
200
- let value =
201
- (filtered_config != CustomNumberFormatConfig::default()).then_some(filtered_config);
202
-
203
- let update = ColumnConfigValueUpdate::CustomNumberStringFormat(value);
204
- ctx.props().on_change.emit(update);
198
+ let mut value = serde_json::Map::new();
199
+ if filtered_config != CustomNumberFormatConfig::default() {
200
+ value.insert(
201
+ "number_format".to_owned(),
202
+ serde_json::to_value(&filtered_config).unwrap_or(serde_json::Value::Null),
203
+ );
204
+ }
205
+ ctx.props().on_change.emit(ColumnConfigFieldUpdate {
206
+ keys: ctx.props().keys.clone(),
207
+ value,
208
+ });
205
209
  true
206
210
  }
207
211
 
@@ -220,22 +224,6 @@ impl Component for CustomNumberFormat {
220
224
  impl CustomNumberFormat {
221
225
  fn initialize(ctx: &yew::prelude::Context<Self>) -> Self {
222
226
  let config = ctx.props().restored_config.clone();
223
- // let show_frac = config
224
- // .minimum_fraction_digits
225
- // .or(config.maximum_fraction_digits)
226
- // .or(config.rounding_increment)
227
- // .is_some();
228
- // let show_sig = config
229
- // .minimum_significant_digits
230
- // .or(config.maximum_significant_digits)
231
- // .is_some();
232
- // let disable_rounding_increment = show_sig
233
- // || show_frac
234
- // || !matches!(
235
- // config.rounding_priority,
236
- // Some(RoundingPriority::Auto) | None
237
- // );
238
- // let disable_rounding_priority = !(show_frac && show_sig);
239
227
  Self {
240
228
  style: config
241
229
  ._style
@@ -248,10 +236,6 @@ impl CustomNumberFormat {
248
236
  })
249
237
  .unwrap_or_default(),
250
238
  config,
251
- // show_frac,
252
- // show_sig,
253
- // disable_rounding_increment,
254
- // disable_rounding_priority,
255
239
  notation: None,
256
240
  }
257
241
  }
@@ -19,17 +19,17 @@ use yew::prelude::*;
19
19
 
20
20
  use super::containers::split_panel::SplitPanel;
21
21
  use super::font_loader::{FontLoader, FontLoaderProps, FontLoaderStatus};
22
- use super::form::debug::DebugPanel;
23
22
  use super::style::{LocalStyle, StyleProvider};
24
23
  use crate::components::column_settings_sidebar::ColumnSettingsPanel;
25
24
  use crate::components::main_panel::MainPanel;
26
- use crate::components::settings_panel::SettingsPanel;
25
+ use crate::components::settings_panel::{SelectedTab, SettingsPanel};
27
26
  use crate::config::*;
28
27
  use crate::css;
29
- use crate::custom_events::CustomEvents;
30
- use crate::dragdrop::{DragDropProps, *};
31
28
  use crate::js::JsPerspectiveViewerPlugin;
32
- use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation, PresentationProps};
29
+ use crate::presentation::{
30
+ ColumnLocator, ColumnSettingsTab, DragDropProps, Presentation, PresentationProps,
31
+ };
32
+ use crate::queries::*;
33
33
  use crate::renderer::{RendererProps, *};
34
34
  use crate::session::{SessionProps, *};
35
35
  use crate::tasks::*;
@@ -41,8 +41,6 @@ pub struct PerspectiveViewerProps {
41
41
  pub elem: web_sys::HtmlElement,
42
42
 
43
43
  /// State
44
- pub custom_events: CustomEvents,
45
- pub dragdrop: DragDrop,
46
44
  pub session: Session,
47
45
  pub renderer: Renderer,
48
46
  pub presentation: Presentation,
@@ -54,44 +52,6 @@ impl PartialEq for PerspectiveViewerProps {
54
52
  }
55
53
  }
56
54
 
57
- impl HasCustomEvents for PerspectiveViewerProps {
58
- fn custom_events(&self) -> &CustomEvents {
59
- &self.custom_events
60
- }
61
- }
62
-
63
- impl HasDragDrop for PerspectiveViewerProps {
64
- fn dragdrop(&self) -> &DragDrop {
65
- &self.dragdrop
66
- }
67
- }
68
-
69
- impl HasPresentation for PerspectiveViewerProps {
70
- fn presentation(&self) -> &Presentation {
71
- &self.presentation
72
- }
73
- }
74
-
75
- impl HasRenderer for PerspectiveViewerProps {
76
- fn renderer(&self) -> &Renderer {
77
- &self.renderer
78
- }
79
- }
80
-
81
- impl HasSession for PerspectiveViewerProps {
82
- fn session(&self) -> &Session {
83
- &self.session
84
- }
85
- }
86
-
87
- impl StateProvider for PerspectiveViewerProps {
88
- type State = PerspectiveViewerProps;
89
-
90
- fn clone_state(&self) -> Self::State {
91
- self.clone()
92
- }
93
- }
94
-
95
55
  #[derive(Debug)]
96
56
  pub enum PerspectiveViewerMsg {
97
57
  ColumnSettingsPanelSizeUpdate(Option<i32>),
@@ -105,6 +65,8 @@ pub enum PerspectiveViewerMsg {
105
65
  Reset(bool, Option<Sender<()>>),
106
66
  Resize,
107
67
  SettingsPanelSizeUpdate(Option<i32>),
68
+ SettingsPanelTabChanged(SelectedTab),
69
+ SettingsPanelAutoWidth(f64),
108
70
  ToggleDebug,
109
71
  ToggleSettingsComplete(SettingsUpdate, Sender<()>),
110
72
  ToggleSettingsInit(Option<SettingsUpdate>, Option<Sender<ApiResult<JsValue>>>),
@@ -142,8 +104,11 @@ pub struct PerspectiveViewer {
142
104
  on_close_column_settings: Callback<()>,
143
105
  on_rendered: Option<Sender<()>>,
144
106
  on_resize: Rc<PubSub<()>>,
107
+ on_settings_panel_dimensions_reset: Rc<PubSub<()>>,
145
108
  settings_open: bool,
146
109
  settings_panel_width_override: Option<i32>,
110
+ settings_panel_selected_tab: SelectedTab,
111
+ settings_panel_auto_width: f64,
147
112
 
148
113
  /// Value-semantic state snapshots (Step 4 scaffold).
149
114
  /// Populated by `UpdateSession` / `UpdateRenderer` / `UpdatePresentation` /
@@ -203,8 +168,11 @@ impl Component for PerspectiveViewer {
203
168
  on_close_column_settings,
204
169
  on_rendered: None,
205
170
  on_resize: Default::default(),
171
+ on_settings_panel_dimensions_reset: Default::default(),
206
172
  settings_open: false,
207
173
  settings_panel_width_override: None,
174
+ settings_panel_selected_tab: SelectedTab::default(),
175
+ settings_panel_auto_width: 0.0,
208
176
  session_props,
209
177
  renderer_props,
210
178
  presentation_props,
@@ -221,43 +189,13 @@ impl Component for PerspectiveViewer {
221
189
  false
222
190
  },
223
191
  Reset(all, sender) => {
224
- ctx.props().presentation.set_open_column_settings(None);
225
- clone!(
226
- ctx.props().renderer,
227
- ctx.props().session,
228
- ctx.props().presentation
192
+ reset_all(
193
+ &ctx.props().session,
194
+ &ctx.props().renderer,
195
+ &ctx.props().presentation,
196
+ all,
197
+ sender,
229
198
  );
230
-
231
- ApiFuture::spawn(async move {
232
- session
233
- .reset(ResetOptions {
234
- config: true,
235
- expressions: all,
236
- ..ResetOptions::default()
237
- })
238
- .await?;
239
- let columns_config = if all {
240
- presentation.reset_columns_configs();
241
- None
242
- } else {
243
- Some(presentation.all_columns_configs())
244
- };
245
-
246
- renderer.reset(columns_config.as_ref()).await?;
247
- presentation.reset_available_themes(None).await;
248
- if all {
249
- presentation.reset_theme().await?;
250
- }
251
-
252
- let result = renderer.draw(session.validate().await?.create_view()).await;
253
- if let Some(sender) = sender {
254
- sender.send(()).unwrap();
255
- }
256
-
257
- renderer.reset_changed.emit(());
258
- result
259
- });
260
-
261
199
  false
262
200
  },
263
201
  ToggleSettingsInit(Some(SettingsUpdate::Missing), None) => false,
@@ -335,6 +273,10 @@ impl Component for PerspectiveViewer {
335
273
  ctx.props()
336
274
  .presentation
337
275
  .set_open_column_settings(Some(open_column_settings));
276
+
277
+ if locator.is_some() {
278
+ self.settings_panel_selected_tab = SelectedTab::Query;
279
+ }
338
280
  }
339
281
 
340
282
  if let Some(sender) = sender {
@@ -349,7 +291,22 @@ impl Component for PerspectiveViewer {
349
291
  },
350
292
  SettingsPanelSizeUpdate(None) => {
351
293
  self.settings_panel_width_override = None;
352
- false
294
+ self.settings_panel_auto_width = 0.0;
295
+ self.on_settings_panel_dimensions_reset.emit(());
296
+ true
297
+ },
298
+ SettingsPanelTabChanged(tab) => {
299
+ let changed = tab != self.settings_panel_selected_tab;
300
+ self.settings_panel_selected_tab = tab;
301
+ changed
302
+ },
303
+ SettingsPanelAutoWidth(w) => {
304
+ if w > self.settings_panel_auto_width {
305
+ self.settings_panel_auto_width = w;
306
+ true
307
+ } else {
308
+ false
309
+ }
353
310
  },
354
311
  ColumnSettingsPanelSizeUpdate(Some(x)) => {
355
312
  self.column_settings_panel_width_override = Some(x);
@@ -449,8 +406,6 @@ impl Component for PerspectiveViewer {
449
406
 
450
407
  fn view(&self, ctx: &Context<Self>) -> Html {
451
408
  let Self::Properties {
452
- custom_events,
453
- dragdrop,
454
409
  presentation,
455
410
  renderer,
456
411
  session,
@@ -470,7 +425,7 @@ impl Component for PerspectiveViewer {
470
425
  }
471
426
 
472
427
  let on_open_expr_panel = ctx.link().callback(|c| OpenColumnSettings {
473
- locator: Some(c),
428
+ locator: c,
474
429
  sender: None,
475
430
  toggle: true,
476
431
  });
@@ -496,17 +451,13 @@ impl Component for PerspectiveViewer {
496
451
  let plugin_name = self.renderer_props.plugin_name.clone();
497
452
  let available_plugins = self.renderer_props.available_plugins.clone();
498
453
  let has_table = self.session_props.has_table.clone();
499
- let named_column_count = self
500
- .renderer_props
501
- .requirements
502
- .names
503
- .as_ref()
504
- .map(|n| n.len())
505
- .unwrap_or(0);
454
+ let named_column_count = self.renderer_props.config.config_column_names.len();
506
455
 
507
456
  let view_config = self.session_props.config.clone();
508
457
  let drag_column = self.dragdrop_props.column.clone();
509
458
  let metadata = self.session_props.metadata.clone();
459
+ let on_select_tab = ctx.link().callback(SettingsPanelTabChanged);
460
+ let on_auto_width = ctx.link().callback(SettingsPanelAutoWidth);
510
461
  let settings_panel = html! {
511
462
  if is_settings_open {
512
463
  <SettingsPanel
@@ -520,11 +471,16 @@ impl Component for PerspectiveViewer {
520
471
  {has_table}
521
472
  {named_column_count}
522
473
  {view_config}
474
+ plugin_config={self.renderer_props.plugin_config.clone()}
523
475
  {drag_column}
524
476
  metadata={metadata.clone()}
525
477
  open_column_settings={self.presentation_props.open_column_settings.clone()}
526
478
  selected_theme={self.presentation_props.selected_theme.clone()}
527
- {dragdrop}
479
+ selected_tab={self.settings_panel_selected_tab}
480
+ auto_width={self.settings_panel_auto_width}
481
+ on_dimensions_reset={&self.on_settings_panel_dimensions_reset}
482
+ {on_select_tab}
483
+ {on_auto_width}
528
484
  {presentation}
529
485
  {renderer}
530
486
  {session}
@@ -552,8 +508,8 @@ impl Component for PerspectiveViewer {
552
508
  plugin_name={self.renderer_props.plugin_name.clone()}
553
509
  {metadata}
554
510
  view_config={self.session_props.config.clone()}
511
+ column_stats={self.session_props.column_stats.clone()}
555
512
  selected_theme={self.presentation_props.selected_theme.clone()}
556
- {custom_events}
557
513
  {presentation}
558
514
  {renderer}
559
515
  {session}
@@ -564,43 +520,23 @@ impl Component for PerspectiveViewer {
564
520
  };
565
521
 
566
522
  let on_reset = ctx.link().callback(|all| Reset(all, None));
567
- let render_limits = self.renderer_props.render_limits;
568
- let has_table = self.session_props.has_table.clone();
569
- let is_errored = self.session_props.error.is_some();
570
- let stats = self.session_props.stats.clone();
571
- let update_count = self.update_count;
572
- let error = self.session_props.error.clone();
573
523
  let is_settings_open = self.settings_open
574
524
  && matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
575
- let title = self.session_props.title.clone();
576
- let selected_theme = self.presentation_props.selected_theme.clone();
577
- let available_themes = self.presentation_props.available_themes.clone();
578
525
  let main_panel = html! {
579
526
  <MainPanel
580
527
  {on_settings}
581
528
  {on_reset}
582
- {render_limits}
583
- {has_table}
584
- {is_errored}
585
- {stats}
586
- {update_count}
587
- {error}
529
+ session_props={self.session_props.clone()}
530
+ renderer_props={self.renderer_props.clone()}
531
+ presentation_props={self.presentation_props.clone()}
588
532
  {is_settings_open}
589
- {title}
590
- {selected_theme}
591
- {available_themes}
592
- is_workspace={self.presentation_props.is_workspace}
593
- {custom_events}
533
+ update_count={self.update_count}
594
534
  {presentation}
595
535
  {renderer}
596
536
  {session}
597
537
  />
598
538
  };
599
539
 
600
- let debug_panel = html! {
601
- if self.debug_open { <DebugPanel {presentation} {renderer} {session} /> }
602
- };
603
-
604
540
  html! {
605
541
  <StyleProvider root={ctx.props().elem.clone()}>
606
542
  <LocalStyle href={css!("viewer")} />
@@ -613,9 +549,8 @@ impl Component for PerspectiveViewer {
613
549
  initial_size={self.settings_panel_width_override}
614
550
  on_reset={ctx.link().callback(|_| SettingsPanelSizeUpdate(None))}
615
551
  on_resize={on_split_panel_resize.clone()}
616
- on_resize_finished={ctx.props().render_callback()}
552
+ on_resize_finished={render_callback(&ctx.props().session, &ctx.props().renderer)}
617
553
  >
618
- { debug_panel }
619
554
  { settings_panel }
620
555
  <div id="main_column_container">
621
556
  { main_panel }
@@ -735,17 +670,43 @@ fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
735
670
  .view_created
736
671
  .add_listener(ctx.link().callback(|_| DecrementUpdateCount));
737
672
 
738
- vec![sub1, sub2, sub3, sub4, sub5, sub6, sub7]
673
+ // Stats fetch resolution (populates session.column_stats) triggers
674
+ // a fresh `SessionProps` so `column_stats` reaches downstream
675
+ // components and the StyleTab re-queries the schema with the
676
+ // new value.
677
+ let sub8 = s.column_stats_changed.add_notify_listener(&cb);
678
+
679
+ vec![sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8]
739
680
  };
740
681
 
741
682
  let renderer_props_sub = {
742
683
  let renderer = ctx.props().renderer.clone();
743
684
  let cb_plugin = ctx.link().callback({
685
+ let renderer = renderer.clone();
744
686
  move |_: JsPerspectiveViewerPlugin| UpdateRenderer(Box::new(renderer.to_props(None)))
745
687
  });
746
688
 
689
+ // Re-snapshot RendererProps when the plugin_config bucket
690
+ // changes (in-tab edit via `send_plugin_config`, JSON paste via
691
+ // `restore_and_render`, full clear via `reset_all` with
692
+ // `all=true`). Without this, `RendererProps.plugin_config`
693
+ // would stay frozen at its construct-time value and `PluginTab`
694
+ // would render stale.
695
+ let cb_plugin_config = ctx.link().callback({
696
+ let renderer = renderer.clone();
697
+ move |_: serde_json::Map<String, serde_json::Value>| {
698
+ UpdateRenderer(Box::new(renderer.to_props(None)))
699
+ }
700
+ });
701
+
747
702
  let sub1 = ctx.props().renderer.plugin_changed.add_listener(cb_plugin);
748
- vec![sub1]
703
+ let sub2 = ctx
704
+ .props()
705
+ .renderer
706
+ .plugin_config_changed
707
+ .add_listener(cb_plugin_config);
708
+
709
+ vec![sub1, sub2]
749
710
  };
750
711
 
751
712
  let presentation_props_sub = {
@@ -779,7 +740,7 @@ fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
779
740
  let cb_clear = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
780
741
  let sub1 = ctx
781
742
  .props()
782
- .dragdrop
743
+ .presentation
783
744
  .drop_received
784
745
  .add_notify_listener(&cb_clear);
785
746
 
@@ -858,19 +819,19 @@ fn inject_engine_callbacks(ctx: &Context<PerspectiveViewer>) {
858
819
  .borrow_mut() = Some(cb);
859
820
  }
860
821
 
861
- // DragDrop: on_dragstart
822
+ // Drag/drop: on_dragstart (post-merge: lives on Presentation)
862
823
  {
863
- let dragdrop = ctx.props().dragdrop.clone();
864
- let cb = ctx
865
- .link()
866
- .callback(move |_: DragEffect| UpdateDragDrop(Box::new(dragdrop.to_props())));
824
+ let presentation = ctx.props().presentation.clone();
825
+ let cb = ctx.link().callback(move |_: DragEffect| {
826
+ UpdateDragDrop(Box::new(presentation.drag_drop_props()))
827
+ });
867
828
 
868
- *ctx.props().dragdrop.on_dragstart.borrow_mut() = Some(cb);
829
+ *ctx.props().presentation.on_dragstart.borrow_mut() = Some(cb);
869
830
  }
870
831
 
871
- // DragDrop: on_dragend
832
+ // Drag/drop: on_dragend
872
833
  {
873
834
  let cb = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
874
- *ctx.props().dragdrop.on_dragend.borrow_mut() = Some(cb);
835
+ *ctx.props().presentation.on_dragend.borrow_mut() = Some(cb);
875
836
  }
876
837
  }