@perspective-dev/viewer 5.2.0 → 5.3.1

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 (179) hide show
  1. package/dist/cdn/perspective-viewer.js +8 -8
  2. package/dist/cdn/perspective-viewer.js.map +3 -3
  3. package/dist/css/blueprint.css +1 -0
  4. package/dist/css/botanical.css +1 -1
  5. package/dist/css/dracula.css +1 -1
  6. package/dist/css/eggplant.css +1 -0
  7. package/dist/css/gruvbox-dark.css +1 -1
  8. package/dist/css/gruvbox.css +1 -1
  9. package/dist/css/icons.css +1 -1
  10. package/dist/css/intl/de.css +1 -1
  11. package/dist/css/intl/es.css +1 -1
  12. package/dist/css/intl/fr.css +1 -1
  13. package/dist/css/intl/ja.css +1 -1
  14. package/dist/css/intl/pt.css +1 -1
  15. package/dist/css/intl/zh.css +1 -1
  16. package/dist/css/intl.css +1 -1
  17. package/dist/css/ledger.css +1 -0
  18. package/dist/css/monokai.css +1 -1
  19. package/dist/css/nord.css +1 -0
  20. package/dist/css/phosphor.css +1 -1
  21. package/dist/css/pro-dark.css +1 -1
  22. package/dist/css/pro.css +1 -1
  23. package/dist/css/solarized-dark.css +1 -1
  24. package/dist/css/solarized.css +1 -1
  25. package/dist/css/themes.css +1 -1
  26. package/dist/css/vaporwave.css +1 -1
  27. package/dist/css/velvet.css +1 -0
  28. package/dist/docs/perspective-docs.json +1 -1
  29. package/dist/esm/column-format.d.ts +16 -3
  30. package/dist/esm/perspective-viewer.d.ts +1 -0
  31. package/dist/esm/perspective-viewer.inline.js +9 -9
  32. package/dist/esm/perspective-viewer.inline.js.map +3 -3
  33. package/dist/esm/perspective-viewer.js +8 -8
  34. package/dist/esm/perspective-viewer.js.map +3 -3
  35. package/dist/esm/plugin.d.ts +10 -0
  36. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +1 -1
  37. package/dist/esm/ts-rs/SaveWorkspaceOptions.d.ts +10 -0
  38. package/dist/esm/ts-rs/ViewerConfig.d.ts +1 -1
  39. package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
  40. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +13 -3
  41. package/dist/wasm/perspective-viewer.d.ts +43 -36
  42. package/dist/wasm/perspective-viewer.js +198 -136
  43. package/dist/wasm/perspective-viewer.wasm +0 -0
  44. package/dist/wasm/perspective-viewer.wasm.d.ts +19 -17
  45. package/package.json +1 -1
  46. package/src/css/column-settings-panel.css +28 -5
  47. package/src/css/column-style.css +291 -31
  48. package/src/css/containers/tabs.css +13 -3
  49. package/src/css/dom/select.css +21 -9
  50. package/src/css/form/code-editor.css +4 -4
  51. package/src/css/plugin-selector.css +1 -0
  52. package/src/css/plugin-settings-panel.css +72 -0
  53. package/src/css/viewer.css +0 -5
  54. package/src/rust/agent/tools.rs +53 -19
  55. package/src/rust/components/column_selector/active_column.rs +2 -2
  56. package/src/rust/components/column_selector/add_expression_button.rs +3 -3
  57. package/src/rust/components/column_selector/aggregate_selector.rs +2 -3
  58. package/src/rust/components/column_selector/config_selector.rs +8 -0
  59. package/src/rust/components/column_selector/expr_edit_button.rs +4 -10
  60. package/src/rust/components/column_selector/inactive_column.rs +2 -2
  61. package/src/rust/components/column_selector.rs +48 -4
  62. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +293 -126
  63. package/src/rust/components/column_settings_sidebar/style_tab.rs +330 -234
  64. package/src/rust/components/column_settings_sidebar.rs +88 -69
  65. package/src/rust/components/containers/control_group.rs +91 -0
  66. package/src/rust/components/containers/mod.rs +1 -0
  67. package/src/rust/components/containers/select.rs +8 -2
  68. package/src/rust/components/datetime_column_style/simple.rs +15 -4
  69. package/src/rust/components/datetime_column_style.rs +50 -10
  70. package/src/rust/components/editable_header.rs +85 -144
  71. package/src/rust/components/expression_editor.rs +9 -16
  72. package/src/rust/components/form/code_editor.rs +16 -6
  73. package/src/rust/components/form/debug.rs +1 -0
  74. package/src/rust/components/form/mod.rs +3 -1
  75. package/src/rust/components/form/multi_stop_gradient_selector.rs +476 -0
  76. package/src/rust/components/form/named_value_picker.rs +86 -0
  77. package/src/rust/components/form/palette_selector.rs +440 -0
  78. package/src/rust/components/main_panel/msg.rs +2 -2
  79. package/src/rust/components/main_panel/reconcile.rs +4 -4
  80. package/src/rust/components/plugin_tab.rs +126 -112
  81. package/src/rust/components/settings_panel.rs +26 -20
  82. package/src/rust/components/status_bar.rs +0 -1
  83. package/src/rust/components/style_controls/number_string_format/digits_section.rs +22 -10
  84. package/src/rust/components/style_controls/number_string_format/misc_section.rs +6 -2
  85. package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -0
  86. package/src/rust/components/style_controls/number_string_format/types.rs +24 -0
  87. package/src/rust/components/style_controls/number_string_format.rs +37 -14
  88. package/src/rust/components/viewer/msg.rs +46 -7
  89. package/src/rust/components/viewer/panels.rs +11 -9
  90. package/src/rust/components/viewer/render.rs +8 -3
  91. package/src/rust/components/viewer/settings.rs +163 -23
  92. package/src/rust/components/viewer/snapshots.rs +46 -21
  93. package/src/rust/components/viewer/wiring.rs +14 -25
  94. package/src/rust/components/viewer.rs +12 -8
  95. package/src/rust/config/column_config_schema.rs +435 -45
  96. package/src/rust/config/css_scale.rs +882 -0
  97. package/src/rust/config/datetime_column_style.rs +4 -21
  98. package/src/rust/config/mod.rs +2 -0
  99. package/src/rust/config/number_string_format.rs +211 -18
  100. package/src/rust/config/options.rs +10 -0
  101. package/src/rust/config/viewer_config.rs +49 -55
  102. package/src/rust/config/workspace_config.rs +132 -5
  103. package/src/rust/custom_elements/viewer.rs +214 -155
  104. package/src/rust/custom_events.rs +14 -1
  105. package/src/rust/js/regular_layout.rs +3 -3
  106. package/src/rust/lib.rs +2 -0
  107. package/src/rust/presentation/column_locator.rs +19 -5
  108. package/src/rust/presentation.rs +209 -36
  109. package/src/rust/queries/column_locator.rs +74 -44
  110. package/src/rust/queries/get_viewer_config.rs +0 -3
  111. package/src/rust/queries/mod.rs +2 -0
  112. package/src/rust/queries/palette_set.rs +82 -0
  113. package/src/rust/queries/plugin_column_styles.rs +6 -2
  114. package/src/rust/renderer/dispatch.rs +50 -12
  115. package/src/rust/renderer/plugin_config.rs +362 -53
  116. package/src/rust/renderer.rs +15 -42
  117. package/src/rust/session/column_defaults_update.rs +15 -8
  118. package/src/rust/session/metadata.rs +5 -1
  119. package/src/rust/session/props.rs +1 -0
  120. package/src/rust/session.rs +9 -6
  121. package/src/rust/tasks/create_panel.rs +44 -57
  122. package/src/rust/tasks/edit_expression.rs +19 -23
  123. package/src/rust/tasks/edit_window.rs +8 -10
  124. package/src/rust/tasks/eject.rs +4 -1
  125. package/src/rust/tasks/pipeline.rs +2 -2
  126. package/src/rust/tasks/presize_panels.rs +44 -5
  127. package/src/rust/tasks/reset_all.rs +4 -4
  128. package/src/rust/tasks/restore_and_render.rs +17 -44
  129. package/src/rust/tasks/restore_panel.rs +11 -13
  130. package/src/rust/tasks/set_edit_mode.rs +3 -1
  131. package/src/rust/tasks/sync_update_panels.rs +11 -1
  132. package/src/rust/tasks/update_theme.rs +23 -18
  133. package/src/rust/utils/css_vars.rs +26 -0
  134. package/src/rust/utils/mod.rs +2 -0
  135. package/src/rust/utils/spawn.rs +1 -1
  136. package/src/rust/workspace.rs +435 -272
  137. package/src/svg/lock.svg +7 -0
  138. package/src/themes/blueprint.css +190 -0
  139. package/src/themes/botanical.css +14 -17
  140. package/src/themes/defaults.css +4 -110
  141. package/src/themes/dracula.css +19 -14
  142. package/src/themes/eggplant.css +189 -0
  143. package/src/themes/gruvbox-dark.css +23 -15
  144. package/src/themes/gruvbox.css +11 -1
  145. package/src/themes/icons.css +2 -2
  146. package/src/themes/intl/de.css +23 -1
  147. package/src/themes/intl/es.css +23 -1
  148. package/src/themes/intl/fr.css +23 -1
  149. package/src/themes/intl/ja.css +23 -1
  150. package/src/themes/intl/pt.css +23 -1
  151. package/src/themes/intl/zh.css +23 -1
  152. package/src/themes/intl.css +26 -4
  153. package/src/themes/ledger.css +195 -0
  154. package/src/themes/monokai.css +24 -14
  155. package/src/themes/nord.css +186 -0
  156. package/src/themes/phosphor.css +7 -14
  157. package/src/themes/pro-dark.css +12 -16
  158. package/src/themes/pro.css +118 -0
  159. package/src/themes/solarized-dark.css +9 -16
  160. package/src/themes/solarized.css +7 -0
  161. package/src/themes/themes.css +10 -5
  162. package/src/themes/vaporwave.css +22 -14
  163. package/src/themes/velvet.css +192 -0
  164. package/src/ts/column-format.ts +52 -2
  165. package/src/ts/perspective-viewer.ts +1 -0
  166. package/src/ts/plugin.ts +14 -0
  167. package/src/ts/ts-rs/PanelViewerConfig.ts +1 -1
  168. package/src/ts/ts-rs/SaveWorkspaceOptions.ts +11 -0
  169. package/src/ts/ts-rs/ViewerConfig.ts +1 -1
  170. package/src/ts/ts-rs/WorkspaceConfig.ts +8 -2
  171. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +11 -3
  172. package/src/rust/components/form/color_range_selector.rs +0 -137
  173. package/src/svg/dropdown-selector-light.svg +0 -3
  174. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline0.js +0 -0
  175. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline1.js +0 -0
  176. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline2.js +0 -0
  177. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline3.js +0 -0
  178. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline4.js +0 -0
  179. /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-87bd21b215d0631a}/inline5.js +0 -0
@@ -20,9 +20,11 @@ use perspective_client::config::ViewConfig;
20
20
  use yew::prelude::*;
21
21
 
22
22
  use crate::components::column_settings_sidebar::style_tab::primitive_field::{
23
- BoolField, ColorField, ColorRangeField, EnumField, NumberFieldPrimitive,
23
+ BoolField, ColorField, EnumField, NumberFieldPrimitive,
24
24
  };
25
+ use crate::components::containers::control_group::ControlGroup;
25
26
  use crate::config::ControlSpec;
27
+ use crate::presentation::Presentation;
26
28
  use crate::queries::get_plugin_config_schema;
27
29
  use crate::renderer::Renderer;
28
30
  use crate::session::Session;
@@ -47,6 +49,7 @@ pub struct PluginTabProps {
47
49
  pub plugin_config: PtrEqRc<serde_json::Map<String, serde_json::Value>>,
48
50
 
49
51
  // State
52
+ pub presentation: Presentation,
50
53
  pub renderer: Renderer,
51
54
  pub session: Session,
52
55
  }
@@ -95,122 +98,133 @@ pub fn PluginTab(props: &PluginTabProps) -> Html {
95
98
  })
96
99
  };
97
100
 
98
- let raw_config = &*props.plugin_config;
99
- let components = schema
100
- .iter()
101
- .cloned()
102
- .filter_map(|spec| {
103
- let component = match spec {
104
- ControlSpec::Enum {
105
- key,
106
- variants,
107
- default,
108
- } => {
109
- let current = raw_config
110
- .get(&key)
111
- .and_then(|v| v.as_str().map(|s| s.to_string()));
112
- html! {
113
- <EnumField
114
- field_key={key}
115
- {variants}
116
- {default}
117
- {current}
118
- on_change={on_change.clone()}
119
- />
120
- }
121
- },
122
- ControlSpec::Bool { key, default } => {
123
- let current = raw_config.get(&key).and_then(|v| v.as_bool());
124
- html! {
125
- <BoolField
126
- field_key={key}
127
- {default}
128
- {current}
129
- on_change={on_change.clone()}
130
- />
131
- }
132
- },
133
- ControlSpec::Color { key, default } => {
134
- let current = raw_config
135
- .get(&key)
136
- .and_then(|v| v.as_str().map(|s| s.to_string()));
137
- html! {
138
- <ColorField
139
- field_key={key}
140
- {default}
141
- {current}
142
- on_change={on_change.clone()}
143
- />
144
- }
145
- },
146
- ControlSpec::ColorRange {
147
- key_pos,
148
- key_neg,
149
- default_pos,
150
- default_neg,
151
- is_gradient,
152
- } => {
153
- let current_pos = raw_config
154
- .get(&key_pos)
155
- .and_then(|v| v.as_str().map(|s| s.to_string()));
156
- let current_neg = raw_config
157
- .get(&key_neg)
158
- .and_then(|v| v.as_str().map(|s| s.to_string()));
159
- html! {
160
- <ColorRangeField
161
- field_key_pos={key_pos}
162
- field_key_neg={key_neg}
163
- {default_pos}
164
- {default_neg}
165
- {current_pos}
166
- {current_neg}
167
- {is_gradient}
168
- on_change={on_change.clone()}
169
- />
170
- }
171
- },
172
- ControlSpec::Number {
173
- key,
174
- default,
175
- min,
176
- max,
177
- step,
178
- include,
179
- } => {
180
- let current = raw_config.get(&key).and_then(|v| v.as_f64());
181
- html! {
182
- <NumberFieldPrimitive
183
- field_key={key}
184
- {default}
185
- {current}
186
- {min}
187
- {max}
188
- {step}
189
- {include}
190
- on_change={on_change.clone()}
191
- />
192
- }
193
- },
194
- // Column-scoped variants don't apply to
195
- // plugin-level config; drop silently.
196
- ControlSpec::AggregateDepth
197
- | ControlSpec::NumberSeriesStyle { .. }
198
- | ControlSpec::DatetimeFormat
199
- | ControlSpec::StringFormat
200
- | ControlSpec::Symbols { .. }
201
- | ControlSpec::NumberFormat
202
- | ControlSpec::String { .. } => {
203
- return None;
204
- },
205
- };
206
-
207
- Some(html! { <fieldset class="style-control">{ component }</fieldset> })
101
+ let on_group_toggle = {
102
+ let presentation = props.presentation.clone();
103
+ yew::Callback::from(move |(key, open): (String, bool)| {
104
+ presentation.set_control_group_collapsed(&key, !open);
208
105
  })
209
- .collect_vec();
106
+ };
210
107
 
108
+ let raw_config = &*props.plugin_config;
109
+ let components = render_specs(
110
+ &schema,
111
+ raw_config,
112
+ &on_change,
113
+ &props.presentation,
114
+ &on_group_toggle,
115
+ );
211
116
  html! {
212
117
  <div id="plugin-tab" class="sidebar_column scrollable">
213
118
  <div id="plugin-config-container" class="tab-section">{ components }</div>
214
119
  </div>
215
120
  }
216
121
  }
122
+
123
+ fn render_specs(
124
+ specs: &[ControlSpec],
125
+ raw_config: &serde_json::Map<String, serde_json::Value>,
126
+ on_change: &Callback<crate::config::ColumnConfigFieldUpdate>,
127
+ presentation: &Presentation,
128
+ on_group_toggle: &Callback<(String, bool)>,
129
+ ) -> Vec<Html> {
130
+ specs
131
+ .iter()
132
+ .filter_map(|spec| match spec {
133
+ ControlSpec::Group { key, fields } => {
134
+ let children =
135
+ render_specs(fields, raw_config, on_change, presentation, on_group_toggle);
136
+
137
+ (!children.is_empty()).then(|| {
138
+ html! {
139
+ <ControlGroup
140
+ key={format!("group::{key}")}
141
+ group_key={key.clone()}
142
+ open={!presentation.is_control_group_collapsed(key)}
143
+ on_toggle={on_group_toggle.clone()}
144
+ >
145
+ { children }
146
+ </ControlGroup>
147
+ }
148
+ })
149
+ },
150
+ leaf => {
151
+ let key = leaf.serialized_keys().join("+");
152
+ let component = render_leaf(leaf, raw_config, on_change)?;
153
+ Some(html! { <fieldset class="style-control" {key}>{ component }</fieldset> })
154
+ },
155
+ })
156
+ .collect_vec()
157
+ }
158
+
159
+ fn render_leaf(
160
+ spec: &ControlSpec,
161
+ raw_config: &serde_json::Map<String, serde_json::Value>,
162
+ on_change: &Callback<crate::config::ColumnConfigFieldUpdate>,
163
+ ) -> Option<Html> {
164
+ match spec.clone() {
165
+ ControlSpec::Enum {
166
+ key,
167
+ variants,
168
+ default,
169
+ } => {
170
+ let current = raw_config
171
+ .get(&key)
172
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
173
+ Some(html! {
174
+ <EnumField
175
+ field_key={key}
176
+ {variants}
177
+ {default}
178
+ {current}
179
+ on_change={on_change.clone()}
180
+ />
181
+ })
182
+ },
183
+ ControlSpec::Bool { key, default } => {
184
+ let current = raw_config.get(&key).and_then(|v| v.as_bool());
185
+ Some(html! {
186
+ <BoolField field_key={key} {default} {current} on_change={on_change.clone()} />
187
+ })
188
+ },
189
+ ControlSpec::Color { key, default } => {
190
+ let current = raw_config
191
+ .get(&key)
192
+ .and_then(|v| v.as_str().map(|s| s.to_string()));
193
+ Some(html! {
194
+ <ColorField field_key={key} {default} {current} on_change={on_change.clone()} />
195
+ })
196
+ },
197
+ ControlSpec::Number {
198
+ key,
199
+ default,
200
+ min,
201
+ max,
202
+ step,
203
+ include,
204
+ } => {
205
+ let current = raw_config.get(&key).and_then(|v| v.as_f64());
206
+ Some(html! {
207
+ <NumberFieldPrimitive
208
+ field_key={key}
209
+ {default}
210
+ {current}
211
+ {min}
212
+ {max}
213
+ {step}
214
+ {include}
215
+ on_change={on_change.clone()}
216
+ />
217
+ })
218
+ },
219
+ ControlSpec::Group { .. }
220
+ | ControlSpec::AggregateDepth
221
+ | ControlSpec::NumberSeriesStyle { .. }
222
+ | ControlSpec::DatetimeFormat { .. }
223
+ | ControlSpec::StringFormat
224
+ | ControlSpec::Symbols { .. }
225
+ | ControlSpec::NumberFormat { .. }
226
+ | ControlSpec::String { .. }
227
+ | ControlSpec::Palette { .. }
228
+ | ControlSpec::GradientStops { .. } => None,
229
+ }
230
+ }
@@ -22,7 +22,8 @@ use super::plugin_tab::PluginTab;
22
22
  use crate::components::containers::sidebar_close_button::SidebarCloseButton;
23
23
  use crate::components::form::debug::DebugPanel;
24
24
  use crate::config::{PluginStaticConfig, PluginUpdate};
25
- use crate::presentation::{ColumnLocator, OpenColumnSettings, Presentation};
25
+ use crate::presentation::{ColumnLocator, ColumnSettingsTarget, OpenColumnSettings, Presentation};
26
+ use crate::queries::classify_column;
26
27
  use crate::renderer::*;
27
28
  use crate::session::column_defaults_update::*;
28
29
  use crate::session::*;
@@ -34,7 +35,7 @@ use crate::workspace::Workspace;
34
35
  pub struct SettingsPanelProps {
35
36
  pub on_close: Callback<()>,
36
37
  pub on_resize: Rc<PubSub<()>>,
37
- pub on_select_column: Callback<Option<ColumnLocator>>,
38
+ pub on_select_column: Callback<Option<ColumnSettingsTarget>>,
38
39
  pub on_debug: Callback<()>,
39
40
  pub is_debug: bool,
40
41
 
@@ -145,25 +146,28 @@ pub fn SettingsPanel(props: &SettingsPanelProps) -> Html {
145
146
  } = &props;
146
147
 
147
148
  let selected_column = {
148
- let locator = props.open_column_settings.locator.clone();
149
149
  let config = &props.view_config;
150
- locator.filter(|locator| match locator {
151
- ColumnLocator::Table(_name) => {
152
- locator
153
- .name()
154
- .map(|n| {
155
- config.columns.iter().any(|maybe_col| {
156
- maybe_col.as_ref().map(|col| col == n).unwrap_or_default()
157
- }) || config.group_by.iter().any(|col| col == n)
158
- || config.split_by.iter().any(|col| col == n)
159
- || config.filter.iter().any(|col| col.column() == n)
160
- || config.sort.iter().any(|col| &col.0 == n)
161
- })
162
- .unwrap_or_default()
163
- && props.renderer.can_render_column_styles()
164
- },
165
- _ => true,
166
- })
150
+ props
151
+ .open_column_settings
152
+ .target
153
+ .as_ref()
154
+ .and_then(|target| match target {
155
+ ColumnSettingsTarget::NewExpression => Some(ColumnLocator::NewExpression),
156
+ ColumnSettingsTarget::Column(n) => {
157
+ let locator = classify_column(n, config, &props.metadata)?;
158
+ if !matches!(locator, ColumnLocator::Table(_)) {
159
+ return Some(locator);
160
+ }
161
+
162
+ let used = config.columns.iter().any(|maybe_col| {
163
+ maybe_col.as_ref().map(|col| col == n).unwrap_or_default()
164
+ }) || config.group_by.iter().any(|col| col == n)
165
+ || config.split_by.iter().any(|col| col == n)
166
+ || config.filter.iter().any(|col| col.column() == n)
167
+ || config.sort.iter().any(|col| &col.0 == n);
168
+ (used && props.renderer.can_render_column_styles()).then_some(locator)
169
+ },
170
+ })
167
171
  };
168
172
 
169
173
  let plugin_name = props.plugin_name.clone();
@@ -217,6 +221,7 @@ pub fn SettingsPanel(props: &SettingsPanelProps) -> Html {
217
221
 
218
222
  update.set_update_column_defaults(
219
223
  &session_metadata,
224
+ &view_config,
220
225
  &view_config.columns,
221
226
  plugin_config,
222
227
  );
@@ -365,6 +370,7 @@ pub fn SettingsPanel(props: &SettingsPanelProps) -> Html {
365
370
  <PluginTab
366
371
  view_config={props.view_config.clone()}
367
372
  plugin_config={props.plugin_config.clone()}
373
+ presentation={presentation.clone()}
368
374
  renderer={renderer.clone()}
369
375
  session={session.clone()}
370
376
  // initial_width={width}
@@ -429,7 +429,6 @@ fn ThemeSelector(props: &ThemeSelectorProps) -> Html {
429
429
  <span class="icon" />
430
430
  <Select<String>
431
431
  id="theme_selector"
432
- class="invert"
433
432
  {values}
434
433
  selected={selected.to_owned()}
435
434
  on_select={props.on_change.clone()}
@@ -37,7 +37,7 @@ impl CustomNumberFormat {
37
37
  min=1.
38
38
  max=21.
39
39
  step=1.
40
- default=1.
40
+ default={ctx.props().defaults.minimum_integer_digits}
41
41
  current_value={self.config.minimum_integer_digits}
42
42
  on_change={ctx.link().callback(CustomNumberFormatMsg::MinimumIntegerDigits)}
43
43
  />
@@ -84,14 +84,23 @@ impl CustomNumberFormat {
84
84
  }
85
85
 
86
86
  fn float_section(&self, ctx: &yew::prelude::Context<Self>) -> yew::prelude::Html {
87
+ let defaults = &ctx.props().defaults;
87
88
  let fractional_value = Some((
88
- self.config.minimum_fraction_digits.unwrap_or(2.),
89
- self.config.maximum_fraction_digits.unwrap_or(2.),
89
+ self.config
90
+ .minimum_fraction_digits
91
+ .unwrap_or(defaults.fraction.0),
92
+ self.config
93
+ .maximum_fraction_digits
94
+ .unwrap_or(defaults.fraction.1),
90
95
  ));
91
96
 
92
97
  let significant_value = Some((
93
- self.config.minimum_significant_digits.unwrap_or(1.),
94
- self.config.maximum_significant_digits.unwrap_or(21.),
98
+ self.config
99
+ .minimum_significant_digits
100
+ .unwrap_or(defaults.significant.0),
101
+ self.config
102
+ .maximum_significant_digits
103
+ .unwrap_or(defaults.significant.1),
95
104
  ));
96
105
 
97
106
  html! {
@@ -102,7 +111,7 @@ impl CustomNumberFormat {
102
111
  min=0.
103
112
  max=20.
104
113
  step=1.
105
- default={(2., 2.)}
114
+ default={defaults.fraction}
106
115
  current_value={fractional_value}
107
116
  on_change={ctx.link().callback(CustomNumberFormatMsg::FracChange)}
108
117
  />
@@ -113,7 +122,7 @@ impl CustomNumberFormat {
113
122
  min=1.
114
123
  max=21.
115
124
  step=1.
116
- default={(1., 21.)}
125
+ default={defaults.significant}
117
126
  current_value={significant_value}
118
127
  on_change={ctx.link().callback(CustomNumberFormatMsg::SigChange)}
119
128
  />
@@ -121,17 +130,20 @@ impl CustomNumberFormat {
121
130
  { self.rounding_increment(ctx) }
122
131
  <SelectEnumField<RoundingPriority>
123
132
  label="rounding-priority"
124
- current_value={self.config.rounding_priority}
133
+ current_value={self.config.rounding_priority.unwrap_or(defaults.rounding_priority)}
134
+ default_value={defaults.rounding_priority}
125
135
  on_change={ctx.link().callback(CustomNumberFormatMsg::RoundingPriority)}
126
136
  />
127
137
  <SelectEnumField<RoundingMode>
128
138
  label="rounding-mode"
129
- current_value={self.config.rounding_mode}
139
+ current_value={self.config.rounding_mode.unwrap_or(defaults.rounding_mode)}
140
+ default_value={defaults.rounding_mode}
130
141
  on_change={ctx.link().callback(CustomNumberFormatMsg::RoundingMode)}
131
142
  />
132
143
  <SelectEnumField<TrailingZeroDisplay>
133
144
  label="trailing-zero-display"
134
- current_value={self.config.trailing_zero_display}
145
+ current_value={self.config.trailing_zero_display.unwrap_or(defaults.trailing_zero_display)}
146
+ default_value={defaults.trailing_zero_display}
135
147
  on_change={ctx.link().callback(CustomNumberFormatMsg::TrailingZero)}
136
148
  />
137
149
  </>
@@ -32,23 +32,27 @@ impl CustomNumberFormat {
32
32
  None
33
33
  };
34
34
 
35
+ let defaults = &ctx.props().defaults;
35
36
  html! {
36
37
  <>
37
38
  <SelectEnumField<NotationName>
38
39
  label="notation"
39
40
  on_change={ctx.link().callback(CustomNumberFormatMsg::NotationChanged)}
40
41
  current_value={self.notation.unwrap_or_default()}
42
+ default_value={NotationName::from(&defaults.notation)}
41
43
  />
42
44
  { compact_display_checkbox }
43
45
  <SelectEnumField<UseGrouping>
44
46
  label="use-grouping"
45
47
  on_change={ctx.link().callback(CustomNumberFormatMsg::UseGrouping)}
46
- current_value={self.config.use_grouping.unwrap_or_default()}
48
+ current_value={self.config.use_grouping.unwrap_or(defaults.use_grouping)}
49
+ default_value={defaults.use_grouping}
47
50
  />
48
51
  <SelectEnumField<SignDisplay>
49
52
  label="sign-display"
50
53
  on_change={ctx.link().callback(CustomNumberFormatMsg::SignDisplay)}
51
- current_value={self.config.sign_display.unwrap_or_default()}
54
+ current_value={self.config.sign_display.unwrap_or(defaults.sign_display)}
55
+ default_value={defaults.sign_display}
52
56
  />
53
57
  </>
54
58
  }
@@ -60,6 +60,7 @@ impl CustomNumberFormat {
60
60
  <SelectEnumField<NumberStyle>
61
61
  label="style"
62
62
  current_value={self.style}
63
+ default_value={NumberStyle::from(&ctx.props().defaults.style)}
63
64
  on_change={ctx.link().callback(CustomNumberFormatMsg::StyleChanged)}
64
65
  />
65
66
  { section }
@@ -12,6 +12,8 @@
12
12
 
13
13
  use strum::{Display, EnumIter};
14
14
 
15
+ use crate::config::{Notation, NumberFormatStyle};
16
+
15
17
  #[derive(Clone, PartialEq, Debug, Copy, Default, EnumIter, Display)]
16
18
  pub enum NumberStyle {
17
19
  #[default]
@@ -21,6 +23,17 @@ pub enum NumberStyle {
21
23
  Unit,
22
24
  }
23
25
 
26
+ impl From<&NumberFormatStyle> for NumberStyle {
27
+ fn from(style: &NumberFormatStyle) -> Self {
28
+ match style {
29
+ NumberFormatStyle::Decimal => Self::Decimal,
30
+ NumberFormatStyle::Currency(_) => Self::Currency,
31
+ NumberFormatStyle::Percent => Self::Percent,
32
+ NumberFormatStyle::Unit(_) => Self::Unit,
33
+ }
34
+ }
35
+ }
36
+
24
37
  #[derive(Clone, PartialEq, Debug, Copy, Default, Display, EnumIter)]
25
38
  pub enum NotationName {
26
39
  #[default]
@@ -29,3 +42,14 @@ pub enum NotationName {
29
42
  Engineering,
30
43
  Compact,
31
44
  }
45
+
46
+ impl From<&Notation> for NotationName {
47
+ fn from(notation: &Notation) -> Self {
48
+ match notation {
49
+ Notation::Standard => Self::Standard,
50
+ Notation::Scientific => Self::Scientific,
51
+ Notation::Engineering => Self::Engineering,
52
+ Notation::Compact(_) => Self::Compact,
53
+ }
54
+ }
55
+ }
@@ -15,6 +15,8 @@ mod misc_section;
15
15
  mod style_section;
16
16
  mod types;
17
17
 
18
+ use std::rc::Rc;
19
+
18
20
  use perspective_client::config::ColumnType;
19
21
  pub use types::*;
20
22
  use yew::{Callback, Component, Properties, html};
@@ -27,6 +29,10 @@ pub struct CustomNumberFormatProps {
27
29
  pub on_change: Callback<ColumnConfigFieldUpdate>,
28
30
  pub view_type: ColumnType,
29
31
  pub column_name: String,
32
+
33
+ /// Resolved default values for this column under the active plugin.
34
+ pub defaults: Rc<NumberFormatDefaults>,
35
+
30
36
  #[prop_or_default]
31
37
  pub keys: Vec<String>,
32
38
  }
@@ -147,25 +153,39 @@ impl Component for CustomNumberFormat {
147
153
  self.config.minimum_integer_digits = val;
148
154
  },
149
155
  CustomNumberFormatMsg::FracChange(val) => {
156
+ let defaults = &ctx.props().defaults;
150
157
  self.config.rounding_increment = None;
151
158
  self.config.maximum_fraction_digits = val.map(|(_, val)| {
152
- let min = self.config.minimum_fraction_digits.unwrap_or(2.);
159
+ let min = self
160
+ .config
161
+ .minimum_fraction_digits
162
+ .unwrap_or(defaults.fraction.0);
153
163
  val.max(min)
154
164
  });
155
165
 
156
166
  self.config.minimum_fraction_digits = val.map(|(val, _)| {
157
- let max = self.config.maximum_fraction_digits.unwrap_or(2.);
167
+ let max = self
168
+ .config
169
+ .maximum_fraction_digits
170
+ .unwrap_or(defaults.fraction.1);
158
171
  val.min(max)
159
172
  });
160
173
  },
161
174
  CustomNumberFormatMsg::SigChange(val) => {
175
+ let defaults = &ctx.props().defaults;
162
176
  self.config.maximum_significant_digits = val.map(|(_, val)| {
163
- let min = self.config.minimum_significant_digits.unwrap_or(1.);
177
+ let min = self
178
+ .config
179
+ .minimum_significant_digits
180
+ .unwrap_or(defaults.significant.0);
164
181
  val.max(min)
165
182
  });
166
183
 
167
184
  self.config.minimum_significant_digits = val.map(|(val, _)| {
168
- let max = self.config.maximum_significant_digits.unwrap_or(21.);
185
+ let max = self
186
+ .config
187
+ .maximum_significant_digits
188
+ .unwrap_or(defaults.significant.1);
169
189
  val.min(max)
170
190
  });
171
191
  },
@@ -191,8 +211,7 @@ impl Component for CustomNumberFormat {
191
211
  },
192
212
  };
193
213
 
194
- let is_float = ctx.props().view_type == ColumnType::Float;
195
- let filtered_config = self.config.clone().filter_default(is_float);
214
+ let filtered_config = self.config.clone().filter_default(&ctx.props().defaults);
196
215
  let mut value = serde_json::Map::new();
197
216
  if filtered_config != CustomNumberFormatConfig::default() {
198
217
  value.insert(
@@ -216,20 +235,24 @@ impl Component for CustomNumberFormat {
216
235
 
217
236
  impl CustomNumberFormat {
218
237
  fn initialize(ctx: &yew::prelude::Context<Self>) -> Self {
219
- let config = ctx.props().restored_config.clone();
238
+ let defaults = &ctx.props().defaults;
239
+ let mut config = ctx.props().restored_config.clone();
240
+ if config._style.is_none() && defaults.style != NumberFormatStyle::Decimal {
241
+ config._style = Some(defaults.style.clone());
242
+ }
243
+
244
+ if config._notation.is_none() && defaults.notation != Notation::Standard {
245
+ config._notation = Some(defaults.notation.clone());
246
+ }
247
+
220
248
  Self {
221
249
  style: config
222
250
  ._style
223
251
  .as_ref()
224
- .map(|style| match style {
225
- NumberFormatStyle::Decimal => NumberStyle::Decimal,
226
- NumberFormatStyle::Currency(_) => NumberStyle::Currency,
227
- NumberFormatStyle::Percent => NumberStyle::Percent,
228
- NumberFormatStyle::Unit(_) => NumberStyle::Unit,
229
- })
252
+ .map(NumberStyle::from)
230
253
  .unwrap_or_default(),
254
+ notation: config._notation.as_ref().map(NotationName::from),
231
255
  config,
232
- notation: None,
233
256
  }
234
257
  }
235
258
  }