@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
|
@@ -28,17 +28,13 @@ pub(crate) enum RestoreMode {
|
|
|
28
28
|
Fresh,
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/// Where a failed restore's error goes.
|
|
32
|
-
/// commits it to the session — the visible error UI and errored session
|
|
33
|
-
/// state. `Suppress` (the agent's `set_view_config` tool) returns it ONLY
|
|
34
|
-
/// to the caller: the model receives the error as a tool result and
|
|
35
|
-
/// self-corrects, so the transient failure is noise to the human user —
|
|
36
|
-
/// and the errored session state would otherwise BLOCK the corrected
|
|
37
|
-
/// retry, since error recovery below requires a `table` field the model's
|
|
38
|
-
/// patches don't carry.
|
|
31
|
+
/// Where a failed restore's error goes.
|
|
39
32
|
#[derive(Clone, Copy)]
|
|
40
33
|
pub(crate) enum RestoreErrors {
|
|
34
|
+
// Raise errors in the UI.
|
|
41
35
|
Publish,
|
|
36
|
+
|
|
37
|
+
// Report only in the API.
|
|
42
38
|
Suppress,
|
|
43
39
|
}
|
|
44
40
|
|
|
@@ -61,8 +57,8 @@ pub(crate) async fn bind_table_task(
|
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
/// Apply a [`ViewerConfigUpdate`] to a single panel and re-draw — the one
|
|
64
|
-
/// pipeline shared by `restorePanel` (an existing panel),
|
|
65
|
-
///
|
|
60
|
+
/// pipeline shared by `restorePanel` (an existing panel), `restoreWorkspace`,
|
|
61
|
+
/// and `addPanel` (both fresh panels).
|
|
66
62
|
pub(crate) async fn restore_panel(
|
|
67
63
|
session: &Session,
|
|
68
64
|
renderer: &Renderer,
|
|
@@ -76,7 +72,11 @@ pub(crate) async fn restore_panel(
|
|
|
76
72
|
let fresh = matches!(mode, RestoreMode::Fresh);
|
|
77
73
|
match &update.theme {
|
|
78
74
|
OptionalUpdate::Update(theme) => renderer.set_theme_stamped(Some(theme.clone())),
|
|
79
|
-
|
|
75
|
+
// `SetDefault` resolves to a CONCRETE registry default here, rather
|
|
76
|
+
// than clearing the panel's theme — nothing downstream re-resolves.
|
|
77
|
+
OptionalUpdate::SetDefault => {
|
|
78
|
+
renderer.set_theme_stamped(presentation.get_default_theme_name().await)
|
|
79
|
+
},
|
|
80
80
|
OptionalUpdate::Missing => {},
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -154,8 +154,6 @@ pub(crate) async fn restore_panel(
|
|
|
154
154
|
|
|
155
155
|
if fresh {
|
|
156
156
|
renderer.resize().await.unwrap_or_log();
|
|
157
|
-
} else if renderer.needs_restyle() {
|
|
158
|
-
renderer.restyle_all().await?;
|
|
159
157
|
}
|
|
160
158
|
|
|
161
159
|
Ok(())
|
|
@@ -34,7 +34,9 @@ pub fn set_edit_mode(session: &Session, renderer: &Renderer, mode: &str) {
|
|
|
34
34
|
serde_json::Value::String(mode.to_owned()),
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
-
let changed = renderer
|
|
37
|
+
let changed = renderer
|
|
38
|
+
.update_plugin_config(&view_config, OptionalUpdate::Update(map))
|
|
39
|
+
.unwrap_or_default();
|
|
38
40
|
clone!(session, renderer);
|
|
39
41
|
ApiFuture::spawn(async move {
|
|
40
42
|
if changed {
|
|
@@ -46,8 +46,11 @@ pub fn sync_update_panels(
|
|
|
46
46
|
panels,
|
|
47
47
|
global_filters,
|
|
48
48
|
masters,
|
|
49
|
+
palette,
|
|
49
50
|
} = update.into_serde_ext()?;
|
|
50
51
|
|
|
52
|
+
let palette = validate_palette(palette.unwrap_or_default())
|
|
53
|
+
.map_err(|e| ApiError::from(JsValue::from_str(&e)))?;
|
|
51
54
|
let old_ids = this.workspace.panel_ids();
|
|
52
55
|
|
|
53
56
|
// Phase 1 — models only, NO renders and NO draws
|
|
@@ -92,6 +95,8 @@ pub fn sync_update_panels(
|
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
98
|
+
this.presentation.set_palette(palette)?;
|
|
99
|
+
|
|
95
100
|
// Phase 2 — stage the remapped layout tree on the Workspace
|
|
96
101
|
if let Some(layout) = layout {
|
|
97
102
|
this.workspace
|
|
@@ -113,13 +118,17 @@ pub fn sync_update_panels(
|
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
if let Some(app) = this.root.borrow().as_ref() {
|
|
121
|
+
// Silent (`announce: false`): each restored panel's own view-config
|
|
122
|
+
// commit dispatch announces the config, settings field included.
|
|
116
123
|
app.send_message(PerspectiveViewerMsg::ToggleSettingsInit(
|
|
117
124
|
Some(SettingsUpdate::Update(sidebar_open)),
|
|
125
|
+
false,
|
|
118
126
|
None,
|
|
119
127
|
));
|
|
120
128
|
}
|
|
121
129
|
|
|
122
130
|
let masters = masters
|
|
131
|
+
.unwrap_or_default()
|
|
123
132
|
.into_iter()
|
|
124
133
|
.filter_map(|saved| match id_map.get(&saved) {
|
|
125
134
|
Some(fresh) => Some(PanelId::from(fresh.as_str())),
|
|
@@ -131,6 +140,7 @@ pub fn sync_update_panels(
|
|
|
131
140
|
.collect::<Vec<_>>();
|
|
132
141
|
|
|
133
142
|
this.workspace.set_masters(masters);
|
|
134
|
-
this.workspace
|
|
143
|
+
this.workspace
|
|
144
|
+
.set_global_filters(global_filters.unwrap_or_default());
|
|
135
145
|
Ok((contents, eject_tasks))
|
|
136
146
|
}
|
|
@@ -19,20 +19,21 @@ use crate::presentation::Presentation;
|
|
|
19
19
|
use crate::renderer::Renderer;
|
|
20
20
|
use crate::workspace::Workspace;
|
|
21
21
|
|
|
22
|
-
///
|
|
23
|
-
///
|
|
24
|
-
///
|
|
25
|
-
///
|
|
26
|
-
pub(crate) async fn
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
) -> Option<String> {
|
|
30
|
-
let default = presentation.get_default_theme_name().await;
|
|
31
|
-
for panel in workspace.panels() {
|
|
32
|
-
panel.renderer.set_default_theme(default.clone());
|
|
22
|
+
/// Give `renderer` the concrete registry default IF it has none yet — the
|
|
23
|
+
/// cold-boot case, where the panel was created before the registry first
|
|
24
|
+
/// parsed and `active_theme_name_sync` had nothing to resolve. Only ever
|
|
25
|
+
/// FILLS IN, never overwrites, so it cannot repaint a themed panel.
|
|
26
|
+
pub(crate) async fn seed_panel_theme(presentation: &Presentation, renderer: &Renderer) {
|
|
27
|
+
if renderer.theme().is_none() {
|
|
28
|
+
renderer.set_theme(presentation.get_default_theme_name().await);
|
|
33
29
|
}
|
|
30
|
+
}
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
/// [`seed_panel_theme`] for every panel.
|
|
33
|
+
pub(crate) async fn seed_default_themes(presentation: &Presentation, workspace: &Workspace) {
|
|
34
|
+
for panel in workspace.panels() {
|
|
35
|
+
seed_panel_theme(presentation, &panel.renderer).await;
|
|
36
|
+
}
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/// Apply a theme change and restyle the affected panel's view.
|
|
@@ -59,14 +60,17 @@ pub fn update_theme(
|
|
|
59
60
|
workspace: &Workspace,
|
|
60
61
|
theme: Option<String>,
|
|
61
62
|
) {
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
|
|
63
|
+
// A NAMED theme needs no registry, so it stamps SYNCHRONOUSLY — no await
|
|
64
|
+
// separates the caller's config commit from the attribute the document
|
|
65
|
+
// cascade styles. Only "reset to default" has to await the registry, and
|
|
66
|
+
// it records the resolved NAME, never an empty theme.
|
|
67
|
+
if let Some(name) = &theme {
|
|
68
|
+
renderer.set_theme_stamped(Some(name.clone()));
|
|
69
|
+
}
|
|
67
70
|
|
|
68
71
|
let presentation = presentation.clone();
|
|
69
72
|
let workspace = workspace.clone();
|
|
73
|
+
let renderer = renderer.clone();
|
|
70
74
|
ApiFuture::spawn(async move {
|
|
71
75
|
match theme {
|
|
72
76
|
Some(name) => {
|
|
@@ -74,10 +78,10 @@ pub fn update_theme(
|
|
|
74
78
|
},
|
|
75
79
|
None => {
|
|
76
80
|
presentation.reset_theme().await?;
|
|
81
|
+
renderer.set_theme_stamped(presentation.get_default_theme_name().await);
|
|
77
82
|
},
|
|
78
83
|
}
|
|
79
84
|
|
|
80
|
-
seed_default_themes(&presentation, &workspace).await;
|
|
81
85
|
let panels = workspace.panels();
|
|
82
86
|
join_all(panels.iter().map(|panel| async move {
|
|
83
87
|
if panel.renderer.needs_restyle() {
|
|
@@ -90,6 +94,7 @@ pub fn update_theme(
|
|
|
90
94
|
.into_iter()
|
|
91
95
|
.collect::<ApiResult<Vec<_>>>()?;
|
|
92
96
|
|
|
97
|
+
presentation.publish_theme_config().await?;
|
|
93
98
|
Ok(())
|
|
94
99
|
});
|
|
95
100
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
use web_sys::Element;
|
|
14
|
+
|
|
15
|
+
/// The computed value of custom property `name` on `elem`, trimmed, or
|
|
16
|
+
/// `None` when undefined/empty.
|
|
17
|
+
pub fn read_custom_property(elem: &Element, name: &str) -> Option<String> {
|
|
18
|
+
let value = web_sys::window()?
|
|
19
|
+
.get_computed_style(elem)
|
|
20
|
+
.ok()??
|
|
21
|
+
.get_property_value(name)
|
|
22
|
+
.ok()?;
|
|
23
|
+
|
|
24
|
+
let value = value.trim();
|
|
25
|
+
(!value.is_empty()).then(|| value.to_owned())
|
|
26
|
+
}
|
package/src/rust/utils/mod.rs
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
mod browser;
|
|
20
20
|
mod completion;
|
|
21
|
+
mod css_vars;
|
|
21
22
|
mod custom_element;
|
|
22
23
|
mod datetime;
|
|
23
24
|
mod debounce;
|
|
@@ -35,6 +36,7 @@ mod tests;
|
|
|
35
36
|
|
|
36
37
|
pub use browser::*;
|
|
37
38
|
pub use completion::*;
|
|
39
|
+
pub use css_vars::*;
|
|
38
40
|
pub use custom_element::*;
|
|
39
41
|
pub use datetime::*;
|
|
40
42
|
pub use debounce::*;
|
package/src/rust/utils/spawn.rs
CHANGED
|
@@ -23,7 +23,7 @@ use perspective_js::utils::*;
|
|
|
23
23
|
/// (invariant I6); use this only at event-listener leaves where no caller
|
|
24
24
|
/// exists.
|
|
25
25
|
pub fn spawn_owned(tag: &'static str, fut: impl Future<Output = ApiResult<()>> + 'static) {
|
|
26
|
-
ApiFuture::
|
|
26
|
+
ApiFuture::spawn_named(tag, async move {
|
|
27
27
|
if let Err(e) = fut.await.ignore_view_delete() {
|
|
28
28
|
tracing::error!("[{}] unhandled task error: {}", tag, e);
|
|
29
29
|
}
|