@perspective-dev/viewer 4.4.0 → 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 (228) 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 -0
  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 +6 -0
  26. package/dist/esm/perspective-viewer.d.ts +4 -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 +21 -77
  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 +39 -0
  36. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
  37. package/dist/wasm/perspective-viewer.d.ts +88 -24
  38. package/dist/wasm/perspective-viewer.js +320 -151
  39. package/dist/wasm/perspective-viewer.wasm +0 -0
  40. package/dist/wasm/perspective-viewer.wasm.d.ts +22 -17
  41. package/package.json +24 -2
  42. package/src/css/column-selector.css +3 -2
  43. package/src/css/column-settings-panel.css +36 -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/status-bar.css +1 -1
  53. package/src/css/viewer.css +65 -3
  54. package/src/rust/components/column_dropdown.rs +3 -1
  55. package/src/rust/components/column_selector/active_column.rs +13 -19
  56. package/src/rust/components/column_selector/config_selector.rs +20 -20
  57. package/src/rust/components/column_selector/filter_column.rs +14 -14
  58. package/src/rust/components/column_selector/inactive_column.rs +9 -15
  59. package/src/rust/components/column_selector/pivot_column.rs +7 -7
  60. package/src/rust/components/column_selector/sort_column.rs +7 -7
  61. package/src/rust/components/column_selector.rs +55 -37
  62. package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +15 -7
  63. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +394 -0
  64. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +15 -6
  65. package/src/rust/components/column_settings_sidebar/style_tab.rs +267 -136
  66. package/src/rust/components/column_settings_sidebar.rs +43 -49
  67. package/src/rust/components/containers/dragdrop_list.rs +5 -5
  68. package/src/rust/components/containers/mod.rs +0 -1
  69. package/src/rust/components/containers/scroll_panel.rs +21 -7
  70. package/src/rust/components/containers/sidebar.rs +8 -6
  71. package/src/rust/components/containers/split_panel.rs +3 -3
  72. package/src/rust/components/containers/tab_list.rs +3 -9
  73. package/src/rust/components/copy_dropdown.rs +2 -3
  74. package/src/rust/components/datetime_column_style.rs +19 -81
  75. package/src/rust/components/editable_header.rs +2 -3
  76. package/src/rust/components/export_dropdown.rs +2 -3
  77. package/src/rust/components/expression_editor.rs +29 -17
  78. package/src/rust/components/filter_dropdown.rs +2 -1
  79. package/src/rust/components/form/color_range_selector.rs +14 -7
  80. package/src/rust/components/form/debug.rs +47 -37
  81. package/src/rust/components/main_panel.rs +24 -65
  82. package/src/rust/components/mod.rs +2 -1
  83. package/src/rust/components/number_series_style.rs +161 -0
  84. package/src/rust/components/plugin_tab.rs +221 -0
  85. package/src/rust/components/settings_panel.rs +181 -59
  86. package/src/rust/components/status_bar.rs +140 -173
  87. package/src/rust/components/status_indicator.rs +15 -22
  88. package/src/rust/components/string_column_style.rs +20 -82
  89. package/src/rust/components/style_controls/number_string_format.rs +14 -30
  90. package/src/rust/components/viewer.rs +92 -132
  91. package/src/rust/config/column_config_schema.rs +195 -0
  92. package/src/rust/config/columns_config.rs +4 -97
  93. package/src/rust/config/datetime_column_style.rs +0 -5
  94. package/src/rust/config/mod.rs +8 -2
  95. package/src/rust/config/number_series_style.rs +79 -0
  96. package/src/rust/config/plugin_static_config.rs +144 -0
  97. package/src/rust/config/string_column_style.rs +0 -5
  98. package/src/rust/config/viewer_config.rs +7 -8
  99. package/src/rust/custom_elements/copy_dropdown.rs +30 -18
  100. package/src/rust/custom_elements/debug_plugin.rs +5 -7
  101. package/src/rust/custom_elements/export_dropdown.rs +26 -18
  102. package/src/rust/custom_elements/viewer.rs +77 -77
  103. package/src/rust/custom_events.rs +181 -224
  104. package/src/rust/js/plugin.rs +45 -117
  105. package/src/rust/lib.rs +39 -5
  106. package/src/rust/presentation/drag_helpers.rs +206 -0
  107. package/src/rust/presentation/props.rs +8 -0
  108. package/src/rust/presentation.rs +256 -41
  109. package/src/rust/{tasks → queries}/column_locator.rs +17 -73
  110. package/src/rust/queries/column_values.rs +59 -0
  111. package/src/rust/{tasks → queries}/columns_iter_set.rs +11 -18
  112. package/src/rust/queries/exports.rs +96 -0
  113. package/src/rust/queries/fetch_column_stats.rs +94 -0
  114. package/src/rust/queries/get_viewer_config.rs +54 -0
  115. package/src/rust/queries/mod.rs +44 -0
  116. package/src/rust/queries/plugin_column_styles.rs +101 -0
  117. package/src/rust/{engines.rs → queries/validate_expression.rs} +26 -15
  118. package/src/rust/renderer/activate.rs +1 -0
  119. package/src/rust/renderer/limits.rs +9 -4
  120. package/src/rust/renderer/plugin_store.rs +12 -0
  121. package/src/rust/renderer/props.rs +28 -3
  122. package/src/rust/renderer/registry.rs +40 -15
  123. package/src/rust/renderer.rs +649 -55
  124. package/src/rust/session/column_defaults_update.rs +20 -28
  125. package/src/rust/session/drag_drop_update.rs +10 -10
  126. package/src/rust/session/metadata.rs +31 -16
  127. package/src/rust/session/props.rs +15 -6
  128. package/src/rust/session/view_subscription.rs +10 -0
  129. package/src/rust/session.rs +109 -147
  130. package/src/rust/tasks/copy_export.rs +178 -158
  131. package/src/rust/tasks/{structural.rs → dismiss_render_warning.rs} +20 -40
  132. package/src/rust/tasks/edit_expression.rs +68 -88
  133. package/src/rust/tasks/eject.rs +25 -22
  134. package/src/rust/tasks/intersection_observer.rs +8 -21
  135. package/src/rust/tasks/mod.rs +19 -21
  136. package/src/rust/tasks/reset_all.rs +78 -0
  137. package/src/rust/tasks/resize_observer.rs +11 -33
  138. package/src/rust/tasks/restore_and_render.rs +117 -89
  139. package/src/rust/tasks/{get_viewer_config.rs → send_column_config.rs} +38 -35
  140. package/src/rust/tasks/send_plugin_config.rs +32 -33
  141. package/src/rust/tasks/update_and_render.rs +66 -47
  142. package/src/rust/{components/containers/trap_door_panel.rs → tasks/update_theme.rs} +34 -33
  143. package/src/rust/tasks/validate_expression.rs +61 -0
  144. package/src/rust/utils/browser/selection.rs +4 -4
  145. package/src/rust/utils/mod.rs +0 -63
  146. package/src/svg/datagrid-select-row-tree.svg +13 -0
  147. package/src/svg/mega-menu-icons-density.svg +23 -0
  148. package/src/svg/mega-menu-icons-map-density.svg +24 -0
  149. package/src/svg/mega-menu-icons-map-line.svg +19 -0
  150. package/src/themes/botanical.css +27 -53
  151. package/src/themes/defaults.css +42 -36
  152. package/src/themes/dracula.css +36 -54
  153. package/src/themes/gruvbox-dark.css +39 -59
  154. package/src/themes/gruvbox.css +16 -28
  155. package/src/themes/icons.css +4 -18
  156. package/src/themes/intl/de.css +42 -6
  157. package/src/themes/intl/es.css +42 -6
  158. package/src/themes/intl/fr.css +42 -6
  159. package/src/themes/intl/ja.css +42 -6
  160. package/src/themes/intl/pt.css +42 -6
  161. package/src/themes/intl/zh.css +42 -6
  162. package/src/themes/intl.css +37 -4
  163. package/src/themes/monokai.css +45 -61
  164. package/src/themes/phosphor.css +175 -0
  165. package/src/themes/pro-dark.css +25 -34
  166. package/src/themes/solarized-dark.css +21 -36
  167. package/src/themes/solarized.css +13 -23
  168. package/src/themes/themes.css +1 -0
  169. package/src/themes/vaporwave.css +40 -74
  170. package/src/ts/bootstrap.ts +14 -3
  171. package/src/ts/column-format.ts +162 -0
  172. package/src/ts/extensions.ts +12 -1
  173. package/src/ts/perspective-viewer.ts +10 -1
  174. package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
  175. package/src/ts/plugin.ts +29 -105
  176. package/src/ts/ts-rs/{FormatUnit.ts → ColumnSelectMode.ts} +1 -1
  177. package/src/ts/ts-rs/PluginStaticConfig.ts +78 -0
  178. package/src/ts/ts-rs/ViewerConfig.ts +14 -0
  179. package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -3
  180. package/dist/esm/ts-rs/ColumnConfigValues.d.ts +0 -31
  181. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +0 -1
  182. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +0 -15
  183. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +0 -18
  184. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
  185. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +0 -6
  186. package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
  187. package/dist/esm/ts-rs/FormatUnit.d.ts +0 -1
  188. package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +0 -1
  189. package/dist/esm/ts-rs/NumberForegroundMode.d.ts +0 -1
  190. package/dist/esm/ts-rs/PluginConfig.d.ts +0 -2
  191. package/dist/esm/ts-rs/RoundingMode.d.ts +0 -1
  192. package/dist/esm/ts-rs/RoundingPriority.d.ts +0 -1
  193. package/dist/esm/ts-rs/SignDisplay.d.ts +0 -1
  194. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +0 -1
  195. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +0 -6
  196. package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
  197. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +0 -1
  198. package/dist/esm/ts-rs/UseGrouping.d.ts +0 -1
  199. package/src/rust/components/number_column_style.rs +0 -483
  200. package/src/rust/config/number_column_style.rs +0 -132
  201. package/src/rust/dragdrop.rs +0 -481
  202. package/src/rust/tasks/plugin_column_styles.rs +0 -98
  203. package/src/ts/ts-rs/ColumnConfigValues.ts +0 -14
  204. package/src/ts/ts-rs/CustomDatetimeFormat.ts +0 -3
  205. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +0 -5
  206. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +0 -8
  207. package/src/ts/ts-rs/DatetimeColorMode.ts +0 -3
  208. package/src/ts/ts-rs/DatetimeFormatType.ts +0 -8
  209. package/src/ts/ts-rs/FormatMode.ts +0 -3
  210. package/src/ts/ts-rs/NumberBackgroundMode.ts +0 -3
  211. package/src/ts/ts-rs/NumberForegroundMode.ts +0 -3
  212. package/src/ts/ts-rs/PluginConfig.ts +0 -4
  213. package/src/ts/ts-rs/RoundingMode.ts +0 -3
  214. package/src/ts/ts-rs/RoundingPriority.ts +0 -3
  215. package/src/ts/ts-rs/SignDisplay.ts +0 -3
  216. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +0 -3
  217. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +0 -4
  218. package/src/ts/ts-rs/StringColorMode.ts +0 -3
  219. package/src/ts/ts-rs/TrailingZeroDisplay.ts +0 -3
  220. package/src/ts/ts-rs/UseGrouping.ts +0 -3
  221. /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline0.js +0 -0
  222. /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline1.js +0 -0
  223. /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline2.js +0 -0
  224. /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline3.js +0 -0
  225. /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline4.js +0 -0
  226. /package/src/rust/{tasks → config}/export_method.rs +0 -0
  227. /package/src/rust/{tasks → queries}/export_app.rs +0 -0
  228. /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,
@@ -294,7 +232,6 @@ impl Component for PerspectiveViewer {
294
232
  ToggleSettingsComplete(_, resolve)
295
233
  if matches!(self.fonts.get_status(), FontLoaderStatus::Finished) =>
296
234
  {
297
- ctx.props().presentation.set_open_column_settings(None);
298
235
  if let Err(e) = resolve.send(()) {
299
236
  tracing::error!("toggle settings failed {:?}", e);
300
237
  }
@@ -336,6 +273,10 @@ impl Component for PerspectiveViewer {
336
273
  ctx.props()
337
274
  .presentation
338
275
  .set_open_column_settings(Some(open_column_settings));
276
+
277
+ if locator.is_some() {
278
+ self.settings_panel_selected_tab = SelectedTab::Query;
279
+ }
339
280
  }
340
281
 
341
282
  if let Some(sender) = sender {
@@ -350,7 +291,22 @@ impl Component for PerspectiveViewer {
350
291
  },
351
292
  SettingsPanelSizeUpdate(None) => {
352
293
  self.settings_panel_width_override = None;
353
- 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
+ }
354
310
  },
355
311
  ColumnSettingsPanelSizeUpdate(Some(x)) => {
356
312
  self.column_settings_panel_width_override = Some(x);
@@ -450,8 +406,6 @@ impl Component for PerspectiveViewer {
450
406
 
451
407
  fn view(&self, ctx: &Context<Self>) -> Html {
452
408
  let Self::Properties {
453
- custom_events,
454
- dragdrop,
455
409
  presentation,
456
410
  renderer,
457
411
  session,
@@ -471,7 +425,7 @@ impl Component for PerspectiveViewer {
471
425
  }
472
426
 
473
427
  let on_open_expr_panel = ctx.link().callback(|c| OpenColumnSettings {
474
- locator: Some(c),
428
+ locator: c,
475
429
  sender: None,
476
430
  toggle: true,
477
431
  });
@@ -497,17 +451,13 @@ impl Component for PerspectiveViewer {
497
451
  let plugin_name = self.renderer_props.plugin_name.clone();
498
452
  let available_plugins = self.renderer_props.available_plugins.clone();
499
453
  let has_table = self.session_props.has_table.clone();
500
- let named_column_count = self
501
- .renderer_props
502
- .requirements
503
- .names
504
- .as_ref()
505
- .map(|n| n.len())
506
- .unwrap_or(0);
454
+ let named_column_count = self.renderer_props.config.config_column_names.len();
507
455
 
508
456
  let view_config = self.session_props.config.clone();
509
457
  let drag_column = self.dragdrop_props.column.clone();
510
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);
511
461
  let settings_panel = html! {
512
462
  if is_settings_open {
513
463
  <SettingsPanel
@@ -521,11 +471,16 @@ impl Component for PerspectiveViewer {
521
471
  {has_table}
522
472
  {named_column_count}
523
473
  {view_config}
474
+ plugin_config={self.renderer_props.plugin_config.clone()}
524
475
  {drag_column}
525
476
  metadata={metadata.clone()}
526
477
  open_column_settings={self.presentation_props.open_column_settings.clone()}
527
478
  selected_theme={self.presentation_props.selected_theme.clone()}
528
- {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}
529
484
  {presentation}
530
485
  {renderer}
531
486
  {session}
@@ -553,8 +508,8 @@ impl Component for PerspectiveViewer {
553
508
  plugin_name={self.renderer_props.plugin_name.clone()}
554
509
  {metadata}
555
510
  view_config={self.session_props.config.clone()}
511
+ column_stats={self.session_props.column_stats.clone()}
556
512
  selected_theme={self.presentation_props.selected_theme.clone()}
557
- {custom_events}
558
513
  {presentation}
559
514
  {renderer}
560
515
  {session}
@@ -565,43 +520,23 @@ impl Component for PerspectiveViewer {
565
520
  };
566
521
 
567
522
  let on_reset = ctx.link().callback(|all| Reset(all, None));
568
- let render_limits = self.renderer_props.render_limits;
569
- let has_table = self.session_props.has_table.clone();
570
- let is_errored = self.session_props.error.is_some();
571
- let stats = self.session_props.stats.clone();
572
- let update_count = self.update_count;
573
- let error = self.session_props.error.clone();
574
523
  let is_settings_open = self.settings_open
575
524
  && matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
576
- let title = self.session_props.title.clone();
577
- let selected_theme = self.presentation_props.selected_theme.clone();
578
- let available_themes = self.presentation_props.available_themes.clone();
579
525
  let main_panel = html! {
580
526
  <MainPanel
581
527
  {on_settings}
582
528
  {on_reset}
583
- {render_limits}
584
- {has_table}
585
- {is_errored}
586
- {stats}
587
- {update_count}
588
- {error}
529
+ session_props={self.session_props.clone()}
530
+ renderer_props={self.renderer_props.clone()}
531
+ presentation_props={self.presentation_props.clone()}
589
532
  {is_settings_open}
590
- {title}
591
- {selected_theme}
592
- {available_themes}
593
- is_workspace={self.presentation_props.is_workspace}
594
- {custom_events}
533
+ update_count={self.update_count}
595
534
  {presentation}
596
535
  {renderer}
597
536
  {session}
598
537
  />
599
538
  };
600
539
 
601
- let debug_panel = html! {
602
- if self.debug_open { <DebugPanel {presentation} {renderer} {session} /> }
603
- };
604
-
605
540
  html! {
606
541
  <StyleProvider root={ctx.props().elem.clone()}>
607
542
  <LocalStyle href={css!("viewer")} />
@@ -614,9 +549,8 @@ impl Component for PerspectiveViewer {
614
549
  initial_size={self.settings_panel_width_override}
615
550
  on_reset={ctx.link().callback(|_| SettingsPanelSizeUpdate(None))}
616
551
  on_resize={on_split_panel_resize.clone()}
617
- on_resize_finished={ctx.props().render_callback()}
552
+ on_resize_finished={render_callback(&ctx.props().session, &ctx.props().renderer)}
618
553
  >
619
- { debug_panel }
620
554
  { settings_panel }
621
555
  <div id="main_column_container">
622
556
  { main_panel }
@@ -736,17 +670,43 @@ fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
736
670
  .view_created
737
671
  .add_listener(ctx.link().callback(|_| DecrementUpdateCount));
738
672
 
739
- 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]
740
680
  };
741
681
 
742
682
  let renderer_props_sub = {
743
683
  let renderer = ctx.props().renderer.clone();
744
684
  let cb_plugin = ctx.link().callback({
685
+ let renderer = renderer.clone();
745
686
  move |_: JsPerspectiveViewerPlugin| UpdateRenderer(Box::new(renderer.to_props(None)))
746
687
  });
747
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
+
748
702
  let sub1 = ctx.props().renderer.plugin_changed.add_listener(cb_plugin);
749
- 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]
750
710
  };
751
711
 
752
712
  let presentation_props_sub = {
@@ -780,7 +740,7 @@ fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
780
740
  let cb_clear = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
781
741
  let sub1 = ctx
782
742
  .props()
783
- .dragdrop
743
+ .presentation
784
744
  .drop_received
785
745
  .add_notify_listener(&cb_clear);
786
746
 
@@ -859,19 +819,19 @@ fn inject_engine_callbacks(ctx: &Context<PerspectiveViewer>) {
859
819
  .borrow_mut() = Some(cb);
860
820
  }
861
821
 
862
- // DragDrop: on_dragstart
822
+ // Drag/drop: on_dragstart (post-merge: lives on Presentation)
863
823
  {
864
- let dragdrop = ctx.props().dragdrop.clone();
865
- let cb = ctx
866
- .link()
867
- .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
+ });
868
828
 
869
- *ctx.props().dragdrop.on_dragstart.borrow_mut() = Some(cb);
829
+ *ctx.props().presentation.on_dragstart.borrow_mut() = Some(cb);
870
830
  }
871
831
 
872
- // DragDrop: on_dragend
832
+ // Drag/drop: on_dragend
873
833
  {
874
834
  let cb = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
875
- *ctx.props().dragdrop.on_dragend.borrow_mut() = Some(cb);
835
+ *ctx.props().presentation.on_dragend.borrow_mut() = Some(cb);
876
836
  }
877
837
  }