@perspective-dev/viewer 5.4.0 → 5.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 (129) hide show
  1. package/dist/cdn/perspective-viewer.js +4 -4
  2. package/dist/cdn/perspective-viewer.js.map +2 -2
  3. package/dist/css/blueprint.css +1 -1
  4. package/dist/css/botanical.css +1 -1
  5. package/dist/css/dracula.css +1 -1
  6. package/dist/css/eggplant.css +1 -1
  7. package/dist/css/gruvbox-dark.css +1 -1
  8. package/dist/css/gruvbox.css +1 -1
  9. package/dist/css/icons.css +1 -1
  10. package/dist/css/intl/ar.css +1 -1
  11. package/dist/css/intl/de.css +1 -1
  12. package/dist/css/intl/es.css +1 -1
  13. package/dist/css/intl/fr.css +1 -1
  14. package/dist/css/intl/ja.css +1 -1
  15. package/dist/css/intl/pt.css +1 -1
  16. package/dist/css/intl/zh.css +1 -1
  17. package/dist/css/intl.css +1 -1
  18. package/dist/css/ledger.css +1 -1
  19. package/dist/css/monokai.css +1 -1
  20. package/dist/css/nord.css +1 -1
  21. package/dist/css/phosphor.css +1 -1
  22. package/dist/css/pro-dark.css +1 -1
  23. package/dist/css/pro.css +1 -1
  24. package/dist/css/solarized-dark.css +1 -1
  25. package/dist/css/solarized.css +1 -1
  26. package/dist/css/themes.css +1 -1
  27. package/dist/css/vaporwave.css +1 -1
  28. package/dist/css/velvet.css +1 -1
  29. package/dist/docs/perspective-docs.json +1 -1
  30. package/dist/esm/perspective-viewer.d.ts +2 -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 +4 -4
  34. package/dist/esm/perspective-viewer.js.map +2 -2
  35. package/dist/esm/plugin.d.ts +9 -0
  36. package/dist/esm/ts-rs/AddPanelOptions.d.ts +9 -0
  37. package/dist/esm/ts-rs/GetViewMode.d.ts +4 -0
  38. package/dist/esm/ts-rs/GetViewOptions.d.ts +8 -0
  39. package/dist/esm/ts-rs/RestoreOptions.d.ts +6 -0
  40. package/dist/esm/ts-rs/RestoreWorkspaceOptions.d.ts +9 -0
  41. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +30 -22
  42. package/dist/wasm/perspective-viewer.d.ts +91 -47
  43. package/dist/wasm/perspective-viewer.js +216 -136
  44. package/dist/wasm/perspective-viewer.wasm +0 -0
  45. package/dist/wasm/perspective-viewer.wasm.d.ts +18 -18
  46. package/package.json +5 -5
  47. package/src/css/column-selector.css +11 -3
  48. package/src/css/column-style.css +162 -0
  49. package/src/css/config-selector.css +1 -1
  50. package/src/css/form/debug.css +9 -0
  51. package/src/css/status-bar.css +11 -0
  52. package/src/css/ui/containers/tabs.css +2 -1
  53. package/src/rust/agent/tools.rs +80 -7
  54. package/src/rust/components/column_selector/active_column.rs +9 -0
  55. package/src/rust/components/column_selector.rs +11 -0
  56. package/src/rust/components/column_settings_sidebar/style_tab/alignment_field.rs +90 -0
  57. package/src/rust/components/column_settings_sidebar/style_tab/font_field.rs +267 -0
  58. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +1 -1
  59. package/src/rust/components/column_settings_sidebar/style_tab.rs +68 -9
  60. package/src/rust/components/debug_panel.rs +107 -50
  61. package/src/rust/components/main_panel/msg.rs +4 -0
  62. package/src/rust/components/main_panel.rs +14 -0
  63. package/src/rust/components/mod.rs +0 -1
  64. package/src/rust/components/plugin_tab.rs +57 -3
  65. package/src/rust/components/settings_panel.rs +6 -0
  66. package/src/rust/components/status_indicator.rs +4 -0
  67. package/src/rust/components/viewer/panels.rs +3 -0
  68. package/src/rust/components/viewer/render.rs +1 -0
  69. package/src/rust/components/viewer/wiring.rs +10 -1
  70. package/src/rust/config/column_config_schema.rs +312 -8
  71. package/src/rust/config/datetime_column_style.rs +0 -11
  72. package/src/rust/config/mod.rs +0 -2
  73. package/src/rust/config/options.rs +50 -0
  74. package/src/rust/config/workspace_config.rs +69 -24
  75. package/src/rust/custom_elements/viewer.rs +194 -97
  76. package/src/rust/js/plugin.rs +3 -1
  77. package/src/rust/lib.rs +7 -3
  78. package/src/rust/queries/plugin_column_styles.rs +6 -5
  79. package/src/rust/renderer/plugin_config.rs +200 -41
  80. package/src/rust/renderer/plugin_store.rs +2 -1
  81. package/src/rust/renderer/props.rs +5 -0
  82. package/src/rust/renderer.rs +9 -0
  83. package/src/rust/session/props.rs +4 -0
  84. package/src/rust/session.rs +151 -80
  85. package/src/rust/tasks/create_panel.rs +4 -1
  86. package/src/rust/tasks/pipeline.rs +18 -7
  87. package/src/rust/tasks/restore_panel.rs +129 -30
  88. package/src/rust/tasks/send_column_config.rs +3 -0
  89. package/src/rust/tasks/sync_update_panels.rs +147 -67
  90. package/src/rust/tasks/table_lifecycle.rs +7 -1
  91. package/src/rust/ui/containers/tab_list.rs +1 -1
  92. package/src/rust/ui/form/intl_label.rs +4 -23
  93. package/src/rust/ui/portal.rs +1 -0
  94. package/src/rust/utils/css_vars.rs +13 -0
  95. package/src/rust/utils/local_fonts.rs +395 -0
  96. package/src/rust/utils/mod.rs +2 -0
  97. package/src/rust/workspace.rs +12 -0
  98. package/src/svg/status_pending.svg +3 -0
  99. package/src/themes/icons.css +1 -0
  100. package/src/themes/intl/ar.css +20 -7
  101. package/src/themes/intl/de.css +20 -7
  102. package/src/themes/intl/es.css +20 -7
  103. package/src/themes/intl/fr.css +20 -7
  104. package/src/themes/intl/ja.css +20 -7
  105. package/src/themes/intl/pt.css +20 -7
  106. package/src/themes/intl/zh.css +20 -7
  107. package/src/themes/intl.css +20 -7
  108. package/src/ts/perspective-viewer.ts +2 -0
  109. package/src/ts/plugin.ts +9 -0
  110. package/src/ts/ts-rs/AddPanelOptions.ts +10 -0
  111. package/src/ts/ts-rs/{DatetimeColorMode.ts → GetViewMode.ts} +4 -1
  112. package/src/ts/ts-rs/GetViewOptions.ts +7 -0
  113. package/src/ts/ts-rs/RestoreOptions.ts +7 -1
  114. package/src/ts/ts-rs/RestoreWorkspaceOptions.ts +10 -0
  115. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +31 -20
  116. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
  117. package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
  118. package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
  119. package/src/rust/components/string_column_style.rs +0 -120
  120. package/src/rust/config/datetime_column_style/color_mode.rs +0 -62
  121. package/src/rust/config/string_column_style.rs +0 -135
  122. package/src/ts/ts-rs/FormatMode.ts +0 -3
  123. package/src/ts/ts-rs/StringColorMode.ts +0 -3
  124. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline0.js +0 -0
  125. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline1.js +0 -0
  126. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline2.js +0 -0
  127. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline3.js +0 -0
  128. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline4.js +0 -0
  129. /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-ea71a3990cad35d7}/inline5.js +0 -0
@@ -22,7 +22,6 @@ mod number_series_style;
22
22
  mod number_string_format;
23
23
  mod options;
24
24
  mod plugin_static_config;
25
- mod string_column_style;
26
25
  pub mod view_config;
27
26
  mod viewer_config;
28
27
  mod workspace_config;
@@ -35,7 +34,6 @@ pub use number_series_style::*;
35
34
  pub use number_string_format::*;
36
35
  pub use options::*;
37
36
  pub use plugin_static_config::*;
38
- pub use string_column_style::*;
39
37
  pub use view_config::*;
40
38
  pub use viewer_config::*;
41
39
  pub use workspace_config::*;
@@ -44,6 +44,28 @@ pub struct RestoreOptions {
44
44
  /// known-good config to recover exactly.
45
45
  #[ts(optional)]
46
46
  pub suppress_errors: Option<bool>,
47
+
48
+ /// When `true`, a `table` no loaded client hosts yet leaves the panel
49
+ /// empty and pending until the table is created, instead of the default
50
+ /// error.
51
+ #[ts(optional)]
52
+ pub wait_for_table: Option<bool>,
53
+ }
54
+
55
+ /// Options for the `restoreWorkspace()` method.
56
+ #[derive(Deserialize, Default, TS)]
57
+ pub struct RestoreWorkspaceOptions {
58
+ /// As `RestoreOptions::wait_for_table`, applied to every panel entry.
59
+ #[ts(optional)]
60
+ pub wait_for_table: Option<bool>,
61
+ }
62
+
63
+ /// Options for the `addPanel()` method.
64
+ #[derive(Deserialize, Default, TS)]
65
+ pub struct AddPanelOptions {
66
+ /// As `RestoreOptions::wait_for_table`.
67
+ #[ts(optional)]
68
+ pub wait_for_table: Option<bool>,
47
69
  }
48
70
 
49
71
  /// The `eject` argument: the loaded client to remove by name; the active
@@ -77,6 +99,34 @@ pub struct GetTableOptions {
77
99
  pub panel: Option<String>,
78
100
  }
79
101
 
102
+ /// How `getView` resolves the `View` it returns.
103
+ #[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq, TS)]
104
+ #[serde(rename_all = "lowercase")]
105
+ pub enum GetViewMode {
106
+ /// The panel's own bound `View`, which the viewer replaces on config
107
+ /// change and deletes on auto-pause or `delete()`; rejects when none is
108
+ /// bound.
109
+ #[default]
110
+ Live,
111
+
112
+ /// A caller-owned `View` built from the panel's effective config,
113
+ /// independent of the render lifecycle.
114
+ Clone,
115
+
116
+ /// `live` when the panel has a bound `View`, else `clone`.
117
+ Auto,
118
+ }
119
+
120
+ /// The `getView` argument: the `mode` and the target panel.
121
+ #[derive(Deserialize, Default, TS)]
122
+ pub struct GetViewOptions {
123
+ #[ts(optional)]
124
+ pub mode: Option<GetViewMode>,
125
+
126
+ #[ts(optional)]
127
+ pub panel: Option<String>,
128
+ }
129
+
80
130
  /// The `getClient` argument: whether to `wait` for a `Client`, and the target
81
131
  /// panel.
82
132
  #[derive(Deserialize, Default, TS)]
@@ -14,7 +14,7 @@ use std::collections::BTreeMap;
14
14
 
15
15
  use perspective_client::config::Filter;
16
16
 
17
- use crate::config::{PanelViewerConfig, ViewerConfigInitial};
17
+ use crate::config::{OptionalUpdate, PanelViewerConfig, ViewerConfigInitial};
18
18
  use crate::utils::CssKind;
19
19
 
20
20
  /// The workspace config format (`{version, active?, layout, panels}`) —
@@ -67,48 +67,52 @@ pub struct WorkspaceConfig {
67
67
  pub palette: BTreeMap<String, String>,
68
68
  }
69
69
 
70
- /// The parse target of a workspace config in
71
- /// [`PerspectiveViewerElement::restoreWorkspace`]. Mirrors
72
- /// [`WorkspaceConfig`], but `panels` entries are [`ViewerConfigInitial`]s —
73
- /// every entry creates a NEW panel, so `table` is required by type (a
74
- /// stray per-panel `settings` key is ignored; it is element-level state,
75
- /// carried by the top-level `active` field).
70
+ /// The [`PerspectiveViewerElement::restoreWorkspace`] argument: a field-wise
71
+ /// update of the element's workspace state, like [`ViewerConfigUpdate`] for a
72
+ /// panel, where an absent key is unchanged, `null` resets and a value
73
+ /// replaces.
76
74
  #[derive(serde::Deserialize, ts_rs::TS)]
77
75
  pub struct WorkspaceConfigUpdate {
76
+ /// The panel to activate with the settings sidebar open, by `panels` key
77
+ /// or existing panel id; `null` closes the sidebar.
78
78
  #[serde(default)]
79
+ #[ts(as = "Option<_>")]
79
80
  #[ts(optional)]
80
- pub active: Option<String>,
81
+ pub active: OptionalUpdate<String>,
81
82
 
83
+ /// The layout tree to stage, naming `panels` keys or existing panel ids.
82
84
  #[serde(default)]
83
85
  #[ts(optional)]
84
86
  pub layout: Option<crate::js::Layout>,
85
87
 
86
- pub panels: BTreeMap<String, ViewerConfigInitial>,
88
+ /// The complete replacement panel set, each [`ViewerConfigInitial`] entry
89
+ /// creating a new panel (`{}` empties the element); absent keeps the
90
+ /// existing panels.
91
+ #[serde(default)]
92
+ #[ts(optional)]
93
+ pub panels: Option<BTreeMap<String, ViewerConfigInitial>>,
87
94
 
88
- /// The element-level global (master/detail cross-) filters to re-apply as
89
- /// a transient overlay on every DETAIL panel. Restored as one
90
- /// unattributed bucket: the next selection on any master replaces it.
91
- /// `Option` so an explicit `undefined` property deserializes as
92
- /// `None` like an absent key (also `masters` / `palette` below).
95
+ /// The element-level cross-filter set applied to every detail panel as
96
+ /// one unattributed bucket, replacing the current set; `null` clears it.
93
97
  #[serde(default)]
94
98
  #[ts(as = "Option<_>")]
95
99
  #[ts(optional)]
96
- pub global_filters: Option<Vec<Filter>>,
100
+ pub global_filters: OptionalUpdate<Vec<Filter>>,
97
101
 
98
- /// The master (filter-source) panels, by saved `panels` key. An id not in
99
- /// `panels` warns and is dropped.
102
+ /// The master (filter-source) panels by `panels` key or existing panel
103
+ /// id, unknown ids dropped with a warning; `null` demotes every panel.
100
104
  #[serde(default)]
101
105
  #[ts(as = "Option<_>")]
102
106
  #[ts(optional)]
103
- pub masters: Option<Vec<String>>,
107
+ pub masters: OptionalUpdate<Vec<String>>,
104
108
 
105
- /// Named color-scale definitions to apply to the host (see
106
- /// [`WorkspaceConfig::palette`]), replacing any previously restored
107
- /// palette.
109
+ /// Named color-scale definitions applied to the host (see
110
+ /// [`WorkspaceConfig::palette`]), replacing the previous palette; `null`
111
+ /// clears it.
108
112
  #[serde(default)]
109
113
  #[ts(as = "Option<_>")]
110
114
  #[ts(optional)]
111
- pub palette: Option<BTreeMap<String, String>>,
115
+ pub palette: OptionalUpdate<BTreeMap<String, String>>,
112
116
  }
113
117
 
114
118
  /// Validate a restored palette map: each key's `--psp-user--<kind>-`
@@ -173,11 +177,48 @@ mod tests {
173
177
  );
174
178
  }
175
179
 
180
+ #[test]
181
+ fn update_absent_fields_are_missing_and_null_resets() {
182
+ let update: WorkspaceConfigUpdate = serde_json::from_value(json!({})).unwrap();
183
+ assert!(update.panels.is_none());
184
+ assert!(update.layout.is_none());
185
+ assert_eq!(update.active, OptionalUpdate::Missing);
186
+ assert_eq!(update.global_filters, OptionalUpdate::Missing);
187
+ assert_eq!(update.masters, OptionalUpdate::Missing);
188
+ assert_eq!(update.palette, OptionalUpdate::Missing);
189
+
190
+ let update: WorkspaceConfigUpdate = serde_json::from_value(json!({
191
+ "panels": null,
192
+ "active": null,
193
+ "global_filters": null,
194
+ "masters": null,
195
+ "palette": null,
196
+ }))
197
+ .unwrap();
198
+
199
+ assert!(update.panels.is_none());
200
+ assert_eq!(update.active, OptionalUpdate::SetDefault);
201
+ assert_eq!(update.global_filters, OptionalUpdate::SetDefault);
202
+ assert_eq!(update.masters, OptionalUpdate::SetDefault);
203
+ assert_eq!(update.palette, OptionalUpdate::SetDefault);
204
+
205
+ let update: WorkspaceConfigUpdate = serde_json::from_value(json!({
206
+ "panels": {},
207
+ "global_filters": [["Region", "==", "West"]],
208
+ "masters": ["a"],
209
+ }))
210
+ .unwrap();
211
+
212
+ assert_eq!(update.panels.map(|p| p.len()), Some(0));
213
+ assert_eq!(update.masters, OptionalUpdate::Update(vec!["a".to_owned()]));
214
+ assert!(matches!(update.global_filters, OptionalUpdate::Update(ref f) if f.len() == 1));
215
+ }
216
+
176
217
  #[test]
177
218
  fn update_palette_defaults_empty_and_validates_by_prefix() {
178
219
  let update: WorkspaceConfigUpdate =
179
220
  serde_json::from_value(json!({ "panels": {} })).unwrap();
180
- assert!(update.palette.is_none());
221
+ assert_eq!(update.palette, OptionalUpdate::Missing);
181
222
 
182
223
  let update: WorkspaceConfigUpdate = serde_json::from_value(json!({
183
224
  "panels": {},
@@ -189,7 +230,11 @@ mod tests {
189
230
  }))
190
231
  .unwrap();
191
232
 
192
- let valid = validate_palette(update.palette.unwrap()).unwrap();
233
+ let OptionalUpdate::Update(palette) = update.palette else {
234
+ panic!("palette missing");
235
+ };
236
+
237
+ let valid = validate_palette(palette).unwrap();
193
238
  assert_eq!(
194
239
  valid.get("--psp-user--gradient-1").unwrap(),
195
240
  "linear-gradient(to right, #000000 0%, #ffffff 100%)"