@perspective-dev/viewer 5.2.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.
- package/dist/cdn/perspective-viewer.js +2 -2
- package/dist/cdn/perspective-viewer.js.map +2 -2
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/phosphor.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/docs/perspective-docs.json +1 -1
- package/dist/esm/perspective-viewer.d.ts +1 -0
- package/dist/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +2 -2
- package/dist/esm/perspective-viewer.js +4 -4
- package/dist/esm/perspective-viewer.js.map +2 -2
- package/dist/esm/plugin.d.ts +10 -0
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +1 -1
- package/dist/esm/ts-rs/SaveWorkspaceOptions.d.ts +10 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +1 -1
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +13 -3
- package/dist/wasm/perspective-viewer.d.ts +43 -36
- package/dist/wasm/perspective-viewer.js +194 -136
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +19 -17
- package/package.json +1 -1
- package/src/css/column-settings-panel.css +9 -5
- package/src/css/column-style.css +209 -31
- package/src/css/dom/select.css +2 -1
- package/src/css/form/code-editor.css +4 -4
- package/src/rust/agent/tools.rs +48 -17
- package/src/rust/components/column_selector/active_column.rs +2 -2
- package/src/rust/components/column_selector/add_expression_button.rs +3 -3
- package/src/rust/components/column_selector/aggregate_selector.rs +2 -3
- package/src/rust/components/column_selector/config_selector.rs +8 -0
- package/src/rust/components/column_selector/expr_edit_button.rs +4 -10
- package/src/rust/components/column_selector/inactive_column.rs +2 -2
- package/src/rust/components/column_selector.rs +48 -4
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +293 -126
- package/src/rust/components/column_settings_sidebar/style_tab.rs +262 -225
- package/src/rust/components/column_settings_sidebar.rs +88 -69
- package/src/rust/components/editable_header.rs +85 -144
- package/src/rust/components/expression_editor.rs +9 -16
- package/src/rust/components/form/code_editor.rs +16 -6
- package/src/rust/components/form/debug.rs +1 -0
- package/src/rust/components/form/mod.rs +3 -1
- package/src/rust/components/form/multi_stop_gradient_selector.rs +476 -0
- package/src/rust/components/form/named_value_picker.rs +86 -0
- package/src/rust/components/form/palette_selector.rs +440 -0
- package/src/rust/components/main_panel/msg.rs +2 -2
- package/src/rust/components/main_panel/reconcile.rs +4 -4
- package/src/rust/components/plugin_tab.rs +4 -28
- package/src/rust/components/settings_panel.rs +25 -20
- package/src/rust/components/viewer/msg.rs +46 -7
- package/src/rust/components/viewer/panels.rs +11 -9
- package/src/rust/components/viewer/render.rs +8 -3
- package/src/rust/components/viewer/settings.rs +163 -23
- package/src/rust/components/viewer/snapshots.rs +46 -21
- package/src/rust/components/viewer/wiring.rs +14 -25
- package/src/rust/components/viewer.rs +12 -8
- package/src/rust/config/column_config_schema.rs +100 -41
- package/src/rust/config/css_scale.rs +882 -0
- package/src/rust/config/mod.rs +2 -0
- package/src/rust/config/options.rs +10 -0
- package/src/rust/config/viewer_config.rs +49 -55
- package/src/rust/config/workspace_config.rs +132 -5
- package/src/rust/custom_elements/viewer.rs +214 -155
- package/src/rust/custom_events.rs +14 -1
- package/src/rust/js/regular_layout.rs +3 -3
- package/src/rust/lib.rs +2 -0
- package/src/rust/presentation/column_locator.rs +19 -5
- package/src/rust/presentation.rs +192 -36
- package/src/rust/queries/column_locator.rs +74 -44
- package/src/rust/queries/get_viewer_config.rs +0 -3
- package/src/rust/queries/mod.rs +2 -0
- package/src/rust/queries/palette_set.rs +82 -0
- package/src/rust/queries/plugin_column_styles.rs +6 -2
- package/src/rust/renderer/dispatch.rs +16 -4
- package/src/rust/renderer/plugin_config.rs +309 -47
- package/src/rust/renderer.rs +15 -42
- package/src/rust/session/column_defaults_update.rs +15 -8
- package/src/rust/session/metadata.rs +5 -1
- package/src/rust/session/props.rs +1 -0
- package/src/rust/session.rs +9 -6
- package/src/rust/tasks/create_panel.rs +44 -57
- package/src/rust/tasks/edit_expression.rs +19 -23
- package/src/rust/tasks/edit_window.rs +8 -10
- package/src/rust/tasks/eject.rs +4 -1
- package/src/rust/tasks/pipeline.rs +2 -2
- package/src/rust/tasks/presize_panels.rs +44 -5
- package/src/rust/tasks/reset_all.rs +4 -4
- package/src/rust/tasks/restore_and_render.rs +17 -44
- package/src/rust/tasks/restore_panel.rs +11 -13
- package/src/rust/tasks/set_edit_mode.rs +3 -1
- package/src/rust/tasks/sync_update_panels.rs +11 -1
- package/src/rust/tasks/update_theme.rs +23 -18
- package/src/rust/utils/css_vars.rs +26 -0
- package/src/rust/utils/mod.rs +2 -0
- package/src/rust/utils/spawn.rs +1 -1
- package/src/rust/workspace.rs +435 -272
- package/src/svg/lock.svg +7 -0
- package/src/themes/botanical.css +10 -0
- package/src/themes/defaults.css +12 -0
- package/src/themes/dracula.css +17 -0
- package/src/themes/gruvbox-dark.css +20 -0
- package/src/themes/gruvbox.css +10 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/monokai.css +22 -0
- package/src/themes/phosphor.css +5 -0
- package/src/themes/pro-dark.css +10 -0
- package/src/themes/solarized-dark.css +7 -0
- package/src/themes/solarized.css +7 -0
- package/src/themes/vaporwave.css +20 -0
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/plugin.ts +14 -0
- package/src/ts/ts-rs/PanelViewerConfig.ts +1 -1
- package/src/ts/ts-rs/SaveWorkspaceOptions.ts +11 -0
- package/src/ts/ts-rs/ViewerConfig.ts +1 -1
- package/src/ts/ts-rs/WorkspaceConfig.ts +8 -2
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +11 -3
- package/src/rust/components/form/color_range_selector.rs +0 -137
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-02e461f3d7062b26 → perspective-viewer-39c3c3b28e3cbd48}/inline5.js +0 -0
|
@@ -166,7 +166,7 @@ impl Component for PerspectiveViewer {
|
|
|
166
166
|
let renderer_props = active_renderer.to_props(None);
|
|
167
167
|
let presentation_props = ctx.props().presentation.to_props(PtrEqRc::new(vec![]));
|
|
168
168
|
let on_close_column_settings = ctx.link().callback(|_| OpenColumnSettings {
|
|
169
|
-
|
|
169
|
+
target: None,
|
|
170
170
|
sender: None,
|
|
171
171
|
toggle: false,
|
|
172
172
|
});
|
|
@@ -319,8 +319,8 @@ impl Component for PerspectiveViewer {
|
|
|
319
319
|
ClearGlobalFilters => self.on_clear_global_filters(ctx),
|
|
320
320
|
|
|
321
321
|
// Settings sidebar + divider pump + column settings (`settings.rs`)
|
|
322
|
-
ToggleSettingsInit(update, resolve) => {
|
|
323
|
-
self.on_toggle_settings_init(ctx, update, resolve)
|
|
322
|
+
ToggleSettingsInit(update, announce, resolve) => {
|
|
323
|
+
self.on_toggle_settings_init(ctx, update, announce, resolve)
|
|
324
324
|
},
|
|
325
325
|
ToggleSettingsComplete(update, resolve) => {
|
|
326
326
|
self.on_toggle_settings_complete(ctx, update, resolve)
|
|
@@ -333,25 +333,29 @@ impl Component for PerspectiveViewer {
|
|
|
333
333
|
SettingsPanelTabChanged(tab) => self.on_settings_panel_tab_changed(tab),
|
|
334
334
|
SettingsPanelAutoWidth(w) => self.on_settings_panel_auto_width(w),
|
|
335
335
|
OpenColumnSettings {
|
|
336
|
-
|
|
336
|
+
target,
|
|
337
337
|
sender,
|
|
338
338
|
toggle,
|
|
339
|
-
} => self.on_open_column_settings(ctx,
|
|
339
|
+
} => self.on_open_column_settings(ctx, target, sender, toggle),
|
|
340
340
|
ColumnSettingsPanelSizeUpdate(x) => self.on_column_settings_panel_size_update(x),
|
|
341
341
|
ColumnSettingsPanelAutoWidth(w) => self.on_column_settings_panel_auto_width(w),
|
|
342
|
-
ToggleColumnSettingsPin => self.on_toggle_column_settings_pin(),
|
|
342
|
+
ToggleColumnSettingsPin => self.on_toggle_column_settings_pin(ctx),
|
|
343
|
+
ToggleColumnSettingsPinComplete(resolve) => {
|
|
344
|
+
self.on_toggle_column_settings_pin_complete(resolve)
|
|
345
|
+
},
|
|
343
346
|
ColumnSettingsTabChanged(tab) => self.on_column_settings_tab_changed(ctx, tab),
|
|
344
347
|
ToggleDebug => self.on_toggle_debug(ctx),
|
|
345
348
|
|
|
346
349
|
// Value-semantic snapshot plumbing (`snapshots.rs`)
|
|
347
|
-
UpdateSession(props) => self.on_update_session(*props),
|
|
350
|
+
UpdateSession(props) => self.on_update_session(ctx, *props),
|
|
348
351
|
UpdateSessionStats(stats, has_table) => self.on_update_session_stats(stats, has_table),
|
|
349
352
|
UpdateGlobalFilters => self.on_update_global_filters(ctx),
|
|
350
353
|
UpdateRenderer(props) => self.on_update_renderer(*props),
|
|
351
354
|
UpdatePresentation(props) => self.on_update_presentation(ctx, *props),
|
|
352
355
|
UpdateSettingsOpen(open) => self.on_update_settings_open(open),
|
|
353
356
|
UpdateIsWorkspace(is_workspace) => self.on_update_is_workspace(is_workspace),
|
|
354
|
-
UpdateColumnSettings(ocs) => self.on_update_column_settings(*ocs),
|
|
357
|
+
UpdateColumnSettings(ocs) => self.on_update_column_settings(ctx, *ocs),
|
|
358
|
+
UpdateColumnSettingsCommit(resolve) => self.on_update_column_settings_commit(resolve),
|
|
355
359
|
UpdateDragDrop(props) => self.on_update_dragdrop(*props),
|
|
356
360
|
UpdateInFlight(count) => self.on_update_in_flight(count),
|
|
357
361
|
}
|
|
@@ -15,18 +15,12 @@ use std::collections::HashSet;
|
|
|
15
15
|
use serde::{Deserialize, Serialize};
|
|
16
16
|
use serde_json::Value;
|
|
17
17
|
|
|
18
|
-
use super::{KeyValueOpts, NumberSeriesStyleDefaultConfig};
|
|
18
|
+
use super::{CssKind, KeyValueOpts, NumberSeriesStyleDefaultConfig};
|
|
19
19
|
|
|
20
20
|
/// The full schema for one column at one point in time. Plugins may return
|
|
21
21
|
/// different schemas for the same column based on the column's current
|
|
22
22
|
/// stored value (e.g. to hide dependent fields), so this is re-queried on
|
|
23
23
|
/// every field update.
|
|
24
|
-
///
|
|
25
|
-
/// Each entry is a [`ControlSpec`]. Primitive variants carry their own
|
|
26
|
-
/// `key` (JSON storage key) inline; the sidebar UI label is supplied by
|
|
27
|
-
/// CSS via `--psp-label--<key>--content`. Composite variants render a
|
|
28
|
-
/// self-contained Yew component that supplies its own labels and owns a
|
|
29
|
-
/// fixed key namespace via [`ControlSpec::serialized_keys`].
|
|
30
24
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
|
31
25
|
pub struct ColumnConfigSchema {
|
|
32
26
|
pub fields: Vec<ControlSpec>,
|
|
@@ -93,33 +87,21 @@ pub enum ControlSpec {
|
|
|
93
87
|
key: String,
|
|
94
88
|
default: String,
|
|
95
89
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
ColorRange {
|
|
103
|
-
key_pos: String,
|
|
104
|
-
key_neg: String,
|
|
105
|
-
default_pos: String,
|
|
106
|
-
default_neg: String,
|
|
107
|
-
/// When `true`, the bar renders as a continuous gradient
|
|
108
|
-
/// (e.g. for `gradient` color modes); when `false`, the bar
|
|
109
|
-
/// renders as a hard pos/neg split. Currently only changes the
|
|
110
|
-
/// visual; pos/neg semantics are unchanged.
|
|
111
|
-
#[serde(default)]
|
|
112
|
-
is_gradient: bool,
|
|
90
|
+
Palette {
|
|
91
|
+
key: String,
|
|
92
|
+
default: String,
|
|
93
|
+
|
|
94
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
95
|
+
max: Option<usize>,
|
|
113
96
|
},
|
|
97
|
+
GradientStops {
|
|
98
|
+
key: String,
|
|
99
|
+
default: String,
|
|
114
100
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
/// styling.
|
|
101
|
+
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
|
102
|
+
discrete: bool,
|
|
103
|
+
},
|
|
119
104
|
DatetimeFormat,
|
|
120
|
-
/// Residual format-only widget for string columns — owns `format`
|
|
121
|
-
/// only. Pair with primitive `Enum` and `Color` fields for
|
|
122
|
-
/// `string_color_mode` + `color` to fully decompose string styling.
|
|
123
105
|
StringFormat,
|
|
124
106
|
NumberSeriesStyle {
|
|
125
107
|
default: NumberSeriesStyleDefaultConfig,
|
|
@@ -138,6 +120,90 @@ pub struct EnumVariant {
|
|
|
138
120
|
pub label: Option<String>,
|
|
139
121
|
}
|
|
140
122
|
|
|
123
|
+
/// One stop of a [`ControlSpec::GradientStops`] value in its in-memory
|
|
124
|
+
/// form: a `#rrggbb` color at `offset` ∈ `[0, 1]`.
|
|
125
|
+
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
|
126
|
+
pub struct GradientStopSpec {
|
|
127
|
+
pub color: String,
|
|
128
|
+
pub offset: f64,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// The [`ControlSpec::GradientStops`] canonical stop order: offsets
|
|
132
|
+
/// clamped to `[0, 1]` and rounded to 3 decimals, stops sorted stably
|
|
133
|
+
/// by offset.
|
|
134
|
+
pub fn canonicalize_gradient_stops(mut stops: Vec<GradientStopSpec>) -> Vec<GradientStopSpec> {
|
|
135
|
+
for stop in &mut stops {
|
|
136
|
+
stop.offset = (stop.offset.clamp(0.0, 1.0) * 1000.0).round() / 1000.0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
stops.sort_by(|a, b| {
|
|
140
|
+
a.offset
|
|
141
|
+
.partial_cmp(&b.offset)
|
|
142
|
+
.unwrap_or(std::cmp::Ordering::Equal)
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
stops
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/// Fit `stops` to a `discrete` field's fixed pair: an over-length value
|
|
149
|
+
/// keeps only its two end colors, pinned to `0`/`1`.
|
|
150
|
+
pub fn discrete_pair(stops: Vec<GradientStopSpec>) -> Vec<GradientStopSpec> {
|
|
151
|
+
let stops = canonicalize_gradient_stops(stops);
|
|
152
|
+
match (stops.first(), stops.last()) {
|
|
153
|
+
(Some(first), Some(last)) if stops.len() > 2 => vec![
|
|
154
|
+
GradientStopSpec {
|
|
155
|
+
color: first.color.clone(),
|
|
156
|
+
offset: 0.0,
|
|
157
|
+
},
|
|
158
|
+
GradientStopSpec {
|
|
159
|
+
color: last.color.clone(),
|
|
160
|
+
offset: 1.0,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
_ => stops,
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
impl ColumnConfigSchema {
|
|
168
|
+
/// Canonicalize every CSS-valued default at schema ingest, dropping
|
|
169
|
+
/// (and logging) fields whose default fails its kind's reader.
|
|
170
|
+
pub fn canonicalize_defaults(mut self) -> Self {
|
|
171
|
+
self.fields.retain_mut(|spec| {
|
|
172
|
+
let (kind, key, default) = match spec {
|
|
173
|
+
ControlSpec::Color { key, default } => (CssKind::Color, key, default),
|
|
174
|
+
ControlSpec::Palette { key, default, .. } => (CssKind::Palette, key, default),
|
|
175
|
+
ControlSpec::GradientStops { key, default, .. } => {
|
|
176
|
+
(CssKind::Gradient, key, default)
|
|
177
|
+
},
|
|
178
|
+
_ => return true,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
match kind.canonicalize(default) {
|
|
182
|
+
Ok(canonical) => {
|
|
183
|
+
*default = canonical;
|
|
184
|
+
true
|
|
185
|
+
},
|
|
186
|
+
Err(error) => {
|
|
187
|
+
tracing::error!("Dropping `{key}` — invalid schema default: {error}");
|
|
188
|
+
false
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
self
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// The CSS kind of the control owning `key`, if it is CSS-valued.
|
|
197
|
+
pub fn css_kind_of(&self, key: &str) -> Option<CssKind> {
|
|
198
|
+
self.fields.iter().find_map(|spec| match spec {
|
|
199
|
+
ControlSpec::Color { key: k, .. } if k == key => Some(CssKind::Color),
|
|
200
|
+
ControlSpec::Palette { key: k, .. } if k == key => Some(CssKind::Palette),
|
|
201
|
+
ControlSpec::GradientStops { key: k, .. } if k == key => Some(CssKind::Gradient),
|
|
202
|
+
_ => None,
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
141
207
|
impl ControlSpec {
|
|
142
208
|
/// Top-level JSON keys this control owns when its value is serialized
|
|
143
209
|
/// into a column's config map. For primitives this is just `[key]`;
|
|
@@ -152,14 +218,13 @@ impl ControlSpec {
|
|
|
152
218
|
ControlSpec::Symbols { .. } => vec!["symbols"],
|
|
153
219
|
ControlSpec::NumberFormat => vec!["number_format"],
|
|
154
220
|
ControlSpec::AggregateDepth => vec!["aggregate_depth"],
|
|
155
|
-
ControlSpec::ColorRange {
|
|
156
|
-
key_pos, key_neg, ..
|
|
157
|
-
} => vec![key_pos.as_str(), key_neg.as_str()],
|
|
158
221
|
ControlSpec::Enum { key, .. }
|
|
159
222
|
| ControlSpec::Bool { key, .. }
|
|
160
223
|
| ControlSpec::Number { key, .. }
|
|
161
224
|
| ControlSpec::String { key, .. }
|
|
162
|
-
| ControlSpec::Color { key, .. }
|
|
225
|
+
| ControlSpec::Color { key, .. }
|
|
226
|
+
| ControlSpec::Palette { key, .. }
|
|
227
|
+
| ControlSpec::GradientStops { key, .. } => vec![key.as_str()],
|
|
163
228
|
}
|
|
164
229
|
}
|
|
165
230
|
}
|
|
@@ -168,12 +233,6 @@ impl ControlSpec {
|
|
|
168
233
|
/// declares which top-level keys the update is allowed to write
|
|
169
234
|
/// (`keys` — equivalent to the field's [`ControlSpec::serialized_keys`])
|
|
170
235
|
/// and a partial new sub-state (`value`).
|
|
171
|
-
///
|
|
172
|
-
/// Apply semantics: keys in `keys` are *cleared* from the column's config
|
|
173
|
-
/// map, then keys present in `value` are *inserted*. Defaults are
|
|
174
|
-
/// pre-stripped by the caller (typically via `skip_serializing_if`), so
|
|
175
|
-
/// "no value set for key K" means the schema default applies and K is
|
|
176
|
-
/// not serialized.
|
|
177
236
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
178
237
|
pub struct ColumnConfigFieldUpdate {
|
|
179
238
|
pub keys: Vec<String>,
|