@perspective-dev/viewer 5.1.0 → 5.3.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 (245) hide show
  1. package/dist/cdn/perspective-viewer.js +9 -9
  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/docs/perspective-docs.json +1 -0
  24. package/dist/esm/column-format.d.ts +19 -28
  25. package/dist/esm/perspective-viewer.d.ts +3 -0
  26. package/dist/esm/perspective-viewer.inline.js +9 -9
  27. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  28. package/dist/esm/perspective-viewer.js +9 -9
  29. package/dist/esm/perspective-viewer.js.map +4 -4
  30. package/dist/esm/plugin.d.ts +10 -0
  31. package/dist/esm/providers.d.ts +79 -0
  32. package/dist/esm/ts-rs/CompactDisplay.d.ts +5 -0
  33. package/dist/esm/ts-rs/CurrencyCode.d.ts +1 -0
  34. package/dist/esm/ts-rs/CurrencyDisplay.d.ts +1 -0
  35. package/dist/esm/ts-rs/CurrencyNumberFormatStyle.d.ts +8 -0
  36. package/dist/esm/ts-rs/CurrencySign.d.ts +1 -0
  37. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +1 -0
  38. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +54 -0
  39. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +34 -0
  40. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +1 -0
  41. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +6 -0
  42. package/dist/esm/ts-rs/FormatMode.d.ts +1 -0
  43. package/dist/esm/ts-rs/FormatUnit.d.ts +1 -0
  44. package/dist/esm/ts-rs/Notation.d.ts +17 -0
  45. package/dist/esm/ts-rs/NumberFormatStyle.d.ts +18 -0
  46. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +42 -2
  47. package/dist/esm/ts-rs/PluginStaticConfig.d.ts +35 -0
  48. package/dist/esm/ts-rs/RestoreOptions.d.ts +19 -0
  49. package/dist/esm/ts-rs/RoundingMode.d.ts +1 -0
  50. package/dist/esm/ts-rs/RoundingPriority.d.ts +1 -0
  51. package/dist/esm/ts-rs/SaveWorkspaceOptions.d.ts +10 -0
  52. package/dist/esm/ts-rs/SignDisplay.d.ts +1 -0
  53. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +1 -0
  54. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +24 -0
  55. package/dist/esm/ts-rs/SplitRollupMode.d.ts +9 -0
  56. package/dist/esm/ts-rs/StringColorMode.d.ts +1 -0
  57. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +1 -0
  58. package/dist/esm/ts-rs/Unit.d.ts +1 -0
  59. package/dist/esm/ts-rs/UnitDisplay.d.ts +1 -0
  60. package/dist/esm/ts-rs/UnitNumberFormatStyle.d.ts +6 -0
  61. package/dist/esm/ts-rs/UseGrouping.d.ts +1 -0
  62. package/dist/esm/ts-rs/ViewerConfig.d.ts +42 -2
  63. package/dist/esm/ts-rs/ViewerConfigInitial.d.ts +175 -0
  64. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +63 -0
  65. package/dist/esm/ts-rs/WindowSpec.d.ts +3 -2
  66. package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
  67. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +20 -9
  68. package/dist/wasm/perspective-viewer.d.ts +157 -41
  69. package/dist/wasm/perspective-viewer.js +452 -151
  70. package/dist/wasm/perspective-viewer.wasm +0 -0
  71. package/dist/wasm/perspective-viewer.wasm.d.ts +22 -17
  72. package/package.json +2 -1
  73. package/src/css/_viewer_bundle.css +1 -0
  74. package/src/css/column-selector.css +8 -0
  75. package/src/css/column-settings-panel.css +9 -5
  76. package/src/css/column-style.css +209 -31
  77. package/src/css/config-selector.css +38 -3
  78. package/src/css/dom/select.css +2 -1
  79. package/src/css/form/code-editor.css +6 -7
  80. package/src/css/form/mirrored-textarea.css +81 -0
  81. package/src/css/viewer.css +328 -0
  82. package/src/rust/agent/client/mod.rs +19 -0
  83. package/src/rust/agent/client/protocol.rs +320 -0
  84. package/src/rust/agent/client/transport.rs +287 -0
  85. package/src/rust/agent/client/turn.rs +174 -0
  86. package/src/rust/agent/config.rs +159 -0
  87. package/src/rust/agent/docs.rs +293 -0
  88. package/src/rust/agent/markdown/block.rs +509 -0
  89. package/src/rust/agent/markdown/entity.rs +52 -0
  90. package/src/rust/agent/markdown/events.rs +71 -0
  91. package/src/rust/agent/markdown/inline.rs +497 -0
  92. package/src/rust/agent/markdown/mod.rs +466 -0
  93. package/src/rust/agent/mod.rs +23 -0
  94. package/src/rust/agent/preamble.md +16 -0
  95. package/src/rust/agent/runtime.rs +201 -0
  96. package/src/rust/agent/slot.rs +236 -0
  97. package/src/rust/agent/tools.rs +1141 -0
  98. package/src/rust/components/chat_panel.rs +289 -0
  99. package/src/rust/components/column_selector/active_column.rs +2 -2
  100. package/src/rust/components/column_selector/add_expression_button.rs +3 -3
  101. package/src/rust/components/column_selector/aggregate_selector.rs +2 -3
  102. package/src/rust/components/column_selector/config_selector.rs +84 -7
  103. package/src/rust/components/column_selector/expr_edit_button.rs +4 -10
  104. package/src/rust/components/column_selector/inactive_column.rs +2 -2
  105. package/src/rust/components/column_selector.rs +55 -4
  106. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +293 -126
  107. package/src/rust/components/column_settings_sidebar/style_tab.rs +262 -225
  108. package/src/rust/components/column_settings_sidebar.rs +88 -69
  109. package/src/rust/components/containers/dragdrop_list.rs +37 -0
  110. package/src/rust/components/editable_header.rs +85 -144
  111. package/src/rust/components/expression_editor.rs +9 -16
  112. package/src/rust/components/form/code_editor.rs +29 -28
  113. package/src/rust/components/form/debug.rs +9 -5
  114. package/src/rust/components/form/mirrored_textarea.rs +165 -0
  115. package/src/rust/components/form/mod.rs +4 -1
  116. package/src/rust/components/form/multi_stop_gradient_selector.rs +476 -0
  117. package/src/rust/components/form/named_value_picker.rs +86 -0
  118. package/src/rust/components/form/palette_selector.rs +440 -0
  119. package/src/rust/components/main_panel/msg.rs +2 -2
  120. package/src/rust/components/main_panel/reconcile.rs +4 -4
  121. package/src/rust/components/mod.rs +2 -0
  122. package/src/rust/components/plugin_tab.rs +4 -28
  123. package/src/rust/components/settings_panel.rs +105 -22
  124. package/src/rust/components/viewer/msg.rs +46 -7
  125. package/src/rust/components/viewer/panels.rs +17 -20
  126. package/src/rust/components/viewer/render.rs +10 -3
  127. package/src/rust/components/viewer/settings.rs +163 -23
  128. package/src/rust/components/viewer/snapshots.rs +46 -21
  129. package/src/rust/components/viewer/wiring.rs +14 -25
  130. package/src/rust/components/viewer.rs +12 -8
  131. package/src/rust/components/window_editor.rs +75 -103
  132. package/src/rust/config/column_config_schema.rs +100 -41
  133. package/src/rust/config/css_scale.rs +882 -0
  134. package/src/rust/config/datetime_column_style/custom.rs +17 -0
  135. package/src/rust/config/datetime_column_style/simple.rs +10 -0
  136. package/src/rust/config/mod.rs +2 -0
  137. package/src/rust/config/number_string_format.rs +33 -0
  138. package/src/rust/config/options.rs +28 -0
  139. package/src/rust/config/plugin_static_config.rs +120 -5
  140. package/src/rust/config/viewer_config.rs +216 -3
  141. package/src/rust/config/workspace_config.rs +138 -10
  142. package/src/rust/custom_elements/viewer.rs +369 -119
  143. package/src/rust/custom_events.rs +43 -1
  144. package/src/rust/js/regular_layout.rs +3 -3
  145. package/src/rust/lib.rs +15 -0
  146. package/src/rust/presentation/column_locator.rs +19 -5
  147. package/src/rust/presentation.rs +200 -36
  148. package/src/rust/queries/column_locator.rs +74 -44
  149. package/src/rust/queries/get_viewer_config.rs +2 -1
  150. package/src/rust/queries/mod.rs +2 -0
  151. package/src/rust/queries/palette_set.rs +82 -0
  152. package/src/rust/queries/plugin_column_styles.rs +6 -2
  153. package/src/rust/renderer/dispatch.rs +16 -4
  154. package/src/rust/renderer/plugin_config.rs +309 -47
  155. package/src/rust/renderer.rs +15 -42
  156. package/src/rust/session/column_defaults_update.rs +32 -7
  157. package/src/rust/session/metadata.rs +23 -21
  158. package/src/rust/session/props.rs +1 -0
  159. package/src/rust/session/replace_expression_update.rs +1 -0
  160. package/src/rust/session.rs +9 -6
  161. package/src/rust/tasks/create_panel.rs +46 -49
  162. package/src/rust/tasks/edit_expression.rs +19 -23
  163. package/src/rust/tasks/edit_window.rs +9 -11
  164. package/src/rust/tasks/eject.rs +4 -1
  165. package/src/rust/tasks/pipeline.rs +2 -2
  166. package/src/rust/tasks/presize_panels.rs +44 -5
  167. package/src/rust/tasks/reset_all.rs +4 -4
  168. package/src/rust/tasks/restore_and_render.rs +17 -44
  169. package/src/rust/tasks/restore_panel.rs +37 -22
  170. package/src/rust/tasks/set_edit_mode.rs +3 -1
  171. package/src/rust/tasks/sync_update_panels.rs +18 -24
  172. package/src/rust/tasks/update_theme.rs +23 -18
  173. package/src/rust/utils/css_vars.rs +26 -0
  174. package/src/rust/utils/mod.rs +2 -0
  175. package/src/rust/utils/spawn.rs +1 -1
  176. package/src/rust/workspace.rs +454 -199
  177. package/src/svg/lock.svg +7 -0
  178. package/src/themes/botanical.css +10 -0
  179. package/src/themes/defaults.css +12 -0
  180. package/src/themes/dracula.css +17 -0
  181. package/src/themes/gruvbox-dark.css +20 -0
  182. package/src/themes/gruvbox.css +10 -0
  183. package/src/themes/icons.css +1 -0
  184. package/src/themes/intl/de.css +16 -0
  185. package/src/themes/intl/es.css +16 -0
  186. package/src/themes/intl/fr.css +16 -0
  187. package/src/themes/intl/ja.css +16 -0
  188. package/src/themes/intl/pt.css +16 -0
  189. package/src/themes/intl/zh.css +16 -0
  190. package/src/themes/intl.css +16 -0
  191. package/src/themes/monokai.css +22 -0
  192. package/src/themes/phosphor.css +5 -0
  193. package/src/themes/pro-dark.css +10 -0
  194. package/src/themes/solarized-dark.css +7 -0
  195. package/src/themes/solarized.css +7 -0
  196. package/src/themes/vaporwave.css +20 -0
  197. package/src/ts/column-format.ts +67 -46
  198. package/src/ts/perspective-viewer.ts +3 -0
  199. package/src/ts/plugin.ts +14 -0
  200. package/src/ts/providers.ts +96 -0
  201. package/src/ts/ts-rs/CompactDisplay.ts +3 -0
  202. package/src/ts/ts-rs/CurrencyCode.ts +3 -0
  203. package/src/ts/ts-rs/CurrencyDisplay.ts +3 -0
  204. package/src/ts/ts-rs/CurrencyNumberFormatStyle.ts +6 -0
  205. package/src/ts/ts-rs/CurrencySign.ts +3 -0
  206. package/src/ts/ts-rs/CustomDatetimeFormat.ts +3 -0
  207. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +54 -0
  208. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +25 -0
  209. package/src/ts/ts-rs/DatetimeColorMode.ts +3 -0
  210. package/src/ts/ts-rs/DatetimeFormatType.ts +8 -0
  211. package/src/ts/ts-rs/FormatMode.ts +3 -0
  212. package/src/ts/ts-rs/FormatUnit.ts +3 -0
  213. package/src/ts/ts-rs/Notation.ts +11 -0
  214. package/src/ts/ts-rs/NumberFormatStyle.ts +12 -0
  215. package/src/ts/ts-rs/PanelViewerConfig.ts +48 -2
  216. package/src/ts/ts-rs/PluginStaticConfig.ts +36 -1
  217. package/src/ts/ts-rs/RestoreOptions.ts +20 -0
  218. package/src/ts/ts-rs/RoundingMode.ts +3 -0
  219. package/src/ts/ts-rs/RoundingPriority.ts +3 -0
  220. package/src/ts/ts-rs/SaveWorkspaceOptions.ts +11 -0
  221. package/src/ts/ts-rs/SignDisplay.ts +3 -0
  222. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +3 -0
  223. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +25 -0
  224. package/src/ts/ts-rs/SplitRollupMode.ts +11 -0
  225. package/src/ts/ts-rs/StringColorMode.ts +3 -0
  226. package/src/ts/ts-rs/TrailingZeroDisplay.ts +3 -0
  227. package/src/ts/ts-rs/Unit.ts +3 -0
  228. package/src/ts/ts-rs/UnitDisplay.ts +3 -0
  229. package/src/ts/ts-rs/UnitNumberFormatStyle.ts +5 -0
  230. package/src/ts/ts-rs/UseGrouping.ts +3 -0
  231. package/src/ts/ts-rs/ViewerConfig.ts +48 -2
  232. package/src/ts/ts-rs/ViewerConfigInitial.ts +164 -0
  233. package/src/ts/ts-rs/ViewerConfigUpdate.ts +72 -2
  234. package/src/ts/ts-rs/WindowSpec.ts +3 -2
  235. package/src/ts/ts-rs/WorkspaceConfig.ts +8 -2
  236. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +18 -9
  237. package/dist/esm/ts-rs/WindowAggregate.d.ts +0 -1
  238. package/src/rust/components/form/color_range_selector.rs +0 -137
  239. package/src/ts/ts-rs/WindowAggregate.ts +0 -3
  240. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline0.js +0 -0
  241. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline1.js +0 -0
  242. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline2.js +0 -0
  243. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline3.js +0 -0
  244. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline4.js +0 -0
  245. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline5.js +0 -0
@@ -15,6 +15,7 @@ pub(crate) mod primitive_field;
15
15
  mod symbol;
16
16
 
17
17
  use std::collections::HashMap;
18
+ use std::rc::Rc;
18
19
 
19
20
  use itertools::Itertools;
20
21
  use perspective_client::config::ColumnType;
@@ -22,7 +23,7 @@ use yew::{Html, Properties, function_component, html};
22
23
 
23
24
  use self::agg_depth_selector::*;
24
25
  use self::primitive_field::{
25
- BoolField, ColorField, ColorRangeField, EnumField, NumberFieldPrimitive,
26
+ BoolField, ColorField, EnumField, GradientStopsField, NumberFieldPrimitive, PaletteField,
26
27
  };
27
28
  use crate::components::column_settings_sidebar::style_tab::symbol::SymbolStyle;
28
29
  use crate::components::datetime_column_style::DatetimeColumnStyle;
@@ -30,15 +31,16 @@ use crate::components::number_series_style::NumberSeriesStyle;
30
31
  use crate::components::string_column_style::StringColumnStyle;
31
32
  use crate::components::style_controls::CustomNumberFormat;
32
33
  use crate::config::{
33
- ControlSpec, CustomNumberFormatConfig, DatetimeColumnStyleConfig, NumberSeriesStyleConfig,
34
- StringColumnStyleConfig,
34
+ ControlSpec, CssKind, CustomNumberFormatConfig, DatetimeColumnStyleConfig,
35
+ NumberSeriesStyleConfig, StringColumnStyleConfig,
35
36
  };
36
37
  use crate::presentation::Presentation;
37
- use crate::queries::{fetch_column_abs_max, get_column_config_schema};
38
+ use crate::queries::{fetch_column_abs_max, get_column_config_schema, named_values};
38
39
  use crate::renderer::Renderer;
39
40
  use crate::session::Session;
40
41
  use crate::tasks::send_column_config;
41
42
  use crate::utils::PtrEqRc;
43
+ use crate::workspace::Workspace;
42
44
 
43
45
  #[derive(Clone, PartialEq, Properties)]
44
46
  pub struct StyleTabProps {
@@ -62,6 +64,7 @@ pub struct StyleTabProps {
62
64
  pub presentation: Presentation,
63
65
  pub renderer: Renderer,
64
66
  pub session: Session,
67
+ pub workspace: Workspace,
65
68
  }
66
69
 
67
70
  #[function_component]
@@ -93,6 +96,33 @@ pub fn StyleTab(props: &StyleTabProps) -> Html {
93
96
  });
94
97
 
95
98
  let raw_config = props.renderer.get_columns_config(&props.column_name);
99
+
100
+ let named_for = |kind| Rc::new(named_values(&props.workspace, &props.presentation, kind));
101
+ let named_gradients = named_for(CssKind::Gradient);
102
+ let named_palettes = named_for(CssKind::Palette);
103
+ let named_colors = named_for(CssKind::Color);
104
+
105
+ let restored = Rc::new(props.presentation.palette());
106
+ let on_pin = {
107
+ let presentation = props.presentation.clone();
108
+ let revision = revision.clone();
109
+ yew::Callback::from(move |(kind, literal): (CssKind, String)| {
110
+ if let Err(error) = presentation.pin_style(kind, &literal) {
111
+ tracing::warn!("Failed to pin named {kind:?}: {error:?}");
112
+ }
113
+
114
+ revision.set(*revision + 1);
115
+ })
116
+ };
117
+ let schema = get_column_config_schema(
118
+ &props.renderer,
119
+ &props.view_config,
120
+ &props.metadata,
121
+ &props.column_name,
122
+ raw_config.as_ref(),
123
+ abs_max,
124
+ );
125
+
96
126
  let on_change = {
97
127
  let state = props.clone();
98
128
  let column_name = props.column_name.clone();
@@ -110,231 +140,238 @@ pub fn StyleTab(props: &StyleTabProps) -> Html {
110
140
  .and_then(|m| serde_json::from_value::<T>(serde_json::Value::Object(m.clone())).ok())
111
141
  }
112
142
 
113
- let components = get_column_config_schema(
114
- &props.renderer,
115
- &props.view_config,
116
- &props.metadata,
117
- &props.column_name,
118
- raw_config.as_ref(),
119
- abs_max,
120
- )
121
- .map(|schema| {
122
- schema
123
- .fields
124
- .into_iter()
125
- .filter_map(|spec| {
126
- let keys: Vec<String> = spec
127
- .serialized_keys()
128
- .into_iter()
129
- .map(|s| s.to_string())
130
- .collect();
131
- let component = match spec {
132
- ControlSpec::AggregateDepth => {
133
- let aggregate_depth = raw_config
134
- .as_ref()
135
- .and_then(|m| m.get("aggregate_depth"))
136
- .and_then(|v| v.as_u64())
137
- .unwrap_or(0) as u32;
138
- html! {
139
- <AggregateDepthSelector
140
- group_by_depth={props.group_by_depth}
141
- on_change={on_change.clone()}
142
- column_name={props.column_name.to_owned()}
143
- value={aggregate_depth}
144
- keys={keys.clone()}
145
- />
146
- }
147
- },
148
- ControlSpec::NumberSeriesStyle {
149
- default: default_config,
150
- } => {
151
- let config: Option<NumberSeriesStyleConfig> = deser_sub(&raw_config);
152
- html! {
153
- <NumberSeriesStyle
154
- {config}
155
- {default_config}
156
- on_change={on_change.clone()}
157
- keys={keys.clone()}
158
- />
159
- }
160
- },
161
- ControlSpec::DatetimeFormat => {
162
- let config: Option<DatetimeColumnStyleConfig> = deser_sub(&raw_config);
163
- let enable_time_config = props.ty.unwrap() == ColumnType::Datetime;
164
- html! {
165
- <DatetimeColumnStyle
166
- {enable_time_config}
167
- {config}
168
- on_change={on_change.clone()}
169
- keys={keys.clone()}
170
- />
171
- }
172
- },
173
- ControlSpec::StringFormat => {
174
- let config: Option<StringColumnStyleConfig> = deser_sub(&raw_config);
175
- html! {
176
- <StringColumnStyle
177
- {config}
178
- on_change={on_change.clone()}
179
- keys={keys.clone()}
180
- />
181
- }
182
- },
183
- ControlSpec::Symbols {
184
- default: default_config,
185
- } => {
186
- let restored_config: HashMap<String, String> = raw_config
187
- .as_ref()
188
- .and_then(|m| m.get("symbols"))
189
- .and_then(|v| serde_json::from_value(v.clone()).ok())
190
- .unwrap_or_default();
143
+ let components = schema
144
+ .map(|schema| {
145
+ schema
146
+ .fields
147
+ .into_iter()
148
+ .filter_map(|spec| {
149
+ let keys: Vec<String> = spec
150
+ .serialized_keys()
151
+ .into_iter()
152
+ .map(|s| s.to_string())
153
+ .collect();
154
+ let component = match spec {
155
+ ControlSpec::AggregateDepth => {
156
+ let aggregate_depth = raw_config
157
+ .as_ref()
158
+ .and_then(|m| m.get("aggregate_depth"))
159
+ .and_then(|v| v.as_u64())
160
+ .unwrap_or(0)
161
+ as u32;
162
+ html! {
163
+ <AggregateDepthSelector
164
+ group_by_depth={props.group_by_depth}
165
+ on_change={on_change.clone()}
166
+ column_name={props.column_name.to_owned()}
167
+ value={aggregate_depth}
168
+ keys={keys.clone()}
169
+ />
170
+ }
171
+ },
172
+ ControlSpec::NumberSeriesStyle {
173
+ default: default_config,
174
+ } => {
175
+ let config: Option<NumberSeriesStyleConfig> = deser_sub(&raw_config);
176
+ html! {
177
+ <NumberSeriesStyle
178
+ {config}
179
+ {default_config}
180
+ on_change={on_change.clone()}
181
+ keys={keys.clone()}
182
+ />
183
+ }
184
+ },
185
+ ControlSpec::DatetimeFormat => {
186
+ let config: Option<DatetimeColumnStyleConfig> = deser_sub(&raw_config);
187
+ let enable_time_config = props.ty.unwrap() == ColumnType::Datetime;
188
+ html! {
189
+ <DatetimeColumnStyle
190
+ {enable_time_config}
191
+ {config}
192
+ on_change={on_change.clone()}
193
+ keys={keys.clone()}
194
+ />
195
+ }
196
+ },
197
+ ControlSpec::StringFormat => {
198
+ let config: Option<StringColumnStyleConfig> = deser_sub(&raw_config);
199
+ html! {
200
+ <StringColumnStyle
201
+ {config}
202
+ on_change={on_change.clone()}
203
+ keys={keys.clone()}
204
+ />
205
+ }
206
+ },
207
+ ControlSpec::Symbols {
208
+ default: default_config,
209
+ } => {
210
+ let restored_config: HashMap<String, String> = raw_config
211
+ .as_ref()
212
+ .and_then(|m| m.get("symbols"))
213
+ .and_then(|v| serde_json::from_value(v.clone()).ok())
214
+ .unwrap_or_default();
191
215
 
192
- html! {
193
- <SymbolStyle
194
- {default_config}
195
- restored_config={Some(restored_config)}
196
- on_change={on_change.clone()}
197
- column_name={props.column_name.clone()}
198
- selected_theme={props.selected_theme.clone()}
199
- session={props.session.clone()}
200
- keys={keys.clone()}
201
- />
202
- }
203
- },
204
- ControlSpec::NumberFormat => {
205
- let restored_config: CustomNumberFormatConfig = raw_config
206
- .as_ref()
207
- .and_then(|m| m.get("number_format"))
208
- .and_then(|v| serde_json::from_value(v.clone()).ok())
209
- .unwrap_or_default();
216
+ html! {
217
+ <SymbolStyle
218
+ {default_config}
219
+ restored_config={Some(restored_config)}
220
+ on_change={on_change.clone()}
221
+ column_name={props.column_name.clone()}
222
+ selected_theme={props.selected_theme.clone()}
223
+ session={props.session.clone()}
224
+ keys={keys.clone()}
225
+ />
226
+ }
227
+ },
228
+ ControlSpec::NumberFormat => {
229
+ let restored_config: CustomNumberFormatConfig = raw_config
230
+ .as_ref()
231
+ .and_then(|m| m.get("number_format"))
232
+ .and_then(|v| serde_json::from_value(v.clone()).ok())
233
+ .unwrap_or_default();
210
234
 
211
- html! {
212
- <CustomNumberFormat
213
- {restored_config}
214
- on_change={on_change.clone()}
215
- view_type={props.ty.unwrap()}
216
- column_name={props.column_name.clone()}
217
- keys={keys.clone()}
218
- />
219
- }
220
- },
221
- ControlSpec::Enum {
222
- key,
223
- variants,
224
- default,
225
- } => {
226
- let current = raw_config
227
- .as_ref()
228
- .and_then(|m| m.get(&key))
229
- .and_then(|v| v.as_str().map(|s| s.to_string()));
235
+ html! {
236
+ <CustomNumberFormat
237
+ {restored_config}
238
+ on_change={on_change.clone()}
239
+ view_type={props.ty.unwrap()}
240
+ column_name={props.column_name.clone()}
241
+ keys={keys.clone()}
242
+ />
243
+ }
244
+ },
245
+ ControlSpec::Enum {
246
+ key,
247
+ variants,
248
+ default,
249
+ } => {
250
+ let current = raw_config
251
+ .as_ref()
252
+ .and_then(|m| m.get(&key))
253
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
230
254
 
231
- html! {
232
- <EnumField
233
- field_key={key}
234
- {variants}
235
- {default}
236
- {current}
237
- on_change={on_change.clone()}
238
- />
239
- }
240
- },
241
- ControlSpec::Bool { key, default } => {
242
- let current = raw_config
243
- .as_ref()
244
- .and_then(|m| m.get(&key))
245
- .and_then(|v| v.as_bool());
246
- html! {
247
- <BoolField
248
- field_key={key}
249
- {default}
250
- {current}
251
- on_change={on_change.clone()}
252
- />
253
- }
254
- },
255
- ControlSpec::Color { key, default } => {
256
- let current = raw_config
257
- .as_ref()
258
- .and_then(|m| m.get(&key))
259
- .and_then(|v| v.as_str().map(|s| s.to_string()));
260
- html! {
261
- <ColorField
262
- field_key={key}
263
- {default}
264
- {current}
265
- on_change={on_change.clone()}
266
- />
267
- }
268
- },
269
- ControlSpec::ColorRange {
270
- key_pos,
271
- key_neg,
272
- default_pos,
273
- default_neg,
274
- is_gradient,
275
- } => {
276
- let current_pos = raw_config
277
- .as_ref()
278
- .and_then(|m| m.get(&key_pos))
279
- .and_then(|v| v.as_str().map(|s| s.to_string()));
280
- let current_neg = raw_config
281
- .as_ref()
282
- .and_then(|m| m.get(&key_neg))
283
- .and_then(|v| v.as_str().map(|s| s.to_string()));
284
- html! {
285
- <ColorRangeField
286
- field_key_pos={key_pos}
287
- field_key_neg={key_neg}
288
- {default_pos}
289
- {default_neg}
290
- {current_pos}
291
- {current_neg}
292
- {is_gradient}
293
- on_change={on_change.clone()}
294
- />
295
- }
296
- },
297
- ControlSpec::Number {
298
- key,
299
- default,
300
- min,
301
- max,
302
- step,
303
- include,
304
- } => {
305
- let current = raw_config
306
- .as_ref()
307
- .and_then(|m| m.get(&key))
308
- .and_then(|v| v.as_f64());
309
- html! {
310
- <NumberFieldPrimitive
311
- field_key={key}
312
- {default}
313
- {current}
314
- {min}
315
- {max}
316
- {step}
317
- {include}
318
- on_change={on_change.clone()}
319
- />
320
- }
321
- },
322
- // String primitive has no caller yet — wire when a
323
- // plugin emits one.
324
- ControlSpec::String { .. } => {
325
- return None;
326
- },
327
- };
255
+ html! {
256
+ <EnumField
257
+ field_key={key}
258
+ {variants}
259
+ {default}
260
+ {current}
261
+ on_change={on_change.clone()}
262
+ />
263
+ }
264
+ },
265
+ ControlSpec::Bool { key, default } => {
266
+ let current = raw_config
267
+ .as_ref()
268
+ .and_then(|m| m.get(&key))
269
+ .and_then(|v| v.as_bool());
270
+ html! {
271
+ <BoolField
272
+ field_key={key}
273
+ {default}
274
+ {current}
275
+ on_change={on_change.clone()}
276
+ />
277
+ }
278
+ },
279
+ ControlSpec::Color { key, default } => {
280
+ let current = raw_config
281
+ .as_ref()
282
+ .and_then(|m| m.get(&key))
283
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
284
+ html! {
285
+ <ColorField
286
+ field_key={key}
287
+ {default}
288
+ {current}
289
+ named={named_colors.clone()}
290
+ restored={restored.clone()}
291
+ on_pin={on_pin.clone()}
292
+ on_change={on_change.clone()}
293
+ />
294
+ }
295
+ },
296
+ ControlSpec::Palette { key, default, max } => {
297
+ let current = raw_config
298
+ .as_ref()
299
+ .and_then(|m| m.get(&key))
300
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
301
+ html! {
302
+ <PaletteField
303
+ field_key={key}
304
+ {default}
305
+ {max}
306
+ {current}
307
+ named={named_palettes.clone()}
308
+ restored={restored.clone()}
309
+ on_pin={on_pin.clone()}
310
+ on_change={on_change.clone()}
311
+ />
312
+ }
313
+ },
314
+ ControlSpec::GradientStops {
315
+ key,
316
+ default,
317
+ discrete,
318
+ } => {
319
+ let current = raw_config
320
+ .as_ref()
321
+ .and_then(|m| m.get(&key))
322
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
323
+ html! {
324
+ <GradientStopsField
325
+ field_key={key}
326
+ {default}
327
+ {discrete}
328
+ {current}
329
+ named={named_gradients.clone()}
330
+ restored={restored.clone()}
331
+ on_pin={on_pin.clone()}
332
+ on_change={on_change.clone()}
333
+ />
334
+ }
335
+ },
336
+ ControlSpec::Number {
337
+ key,
338
+ default,
339
+ min,
340
+ max,
341
+ step,
342
+ include,
343
+ } => {
344
+ let current = raw_config
345
+ .as_ref()
346
+ .and_then(|m| m.get(&key))
347
+ .and_then(|v| v.as_f64());
348
+ html! {
349
+ <NumberFieldPrimitive
350
+ field_key={key}
351
+ {default}
352
+ {current}
353
+ {min}
354
+ {max}
355
+ {step}
356
+ {include}
357
+ on_change={on_change.clone()}
358
+ />
359
+ }
360
+ },
361
+ ControlSpec::String { .. } => {
362
+ return None;
363
+ },
364
+ };
328
365
 
329
- let key = format!("{}::{}", props.column_name, keys.join("+"));
330
- Some(html! { <fieldset class="style-control" {key}>{ component }</fieldset> })
331
- })
332
- .collect_vec()
333
- })
334
- .unwrap_or_else(|error| {
335
- tracing::error!("{}", error);
336
- vec![]
337
- });
366
+ let key = format!("{}::{}", props.column_name, keys.join("+"));
367
+ Some(html! { <fieldset class="style-control" {key}>{ component }</fieldset> })
368
+ })
369
+ .collect_vec()
370
+ })
371
+ .unwrap_or_else(|error| {
372
+ tracing::error!("{}", error);
373
+ vec![]
374
+ });
338
375
 
339
376
  html! {
340
377
  <div id="style-tab">