@perspective-dev/viewer 4.4.1 → 4.5.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.
- package/dist/cdn/perspective-viewer.js +1 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- 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/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.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/esm/bootstrap.d.ts +2 -1
- package/dist/esm/column-format.d.ts +51 -0
- package/dist/esm/extensions.d.ts +2 -0
- package/dist/esm/perspective-viewer.d.ts +3 -1
- package/dist/esm/perspective-viewer.inline.js +1 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +1 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/perspective-viewer.worker.d.ts +2 -0
- package/dist/esm/plugin.d.ts +16 -72
- package/dist/esm/ts-rs/ColumnSelectMode.d.ts +1 -0
- package/dist/esm/ts-rs/PluginStaticConfig.d.ts +77 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +6 -3
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
- package/dist/wasm/perspective-viewer.d.ts +77 -18
- package/dist/wasm/perspective-viewer.js +302 -148
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +20 -15
- package/package.json +24 -2
- package/src/css/column-selector.css +3 -2
- package/src/css/column-settings-panel.css +44 -9
- package/src/css/column-style.css +35 -2
- package/src/css/containers/scroll-panel.css +2 -1
- package/src/css/containers/tabs.css +8 -52
- package/src/css/dom/checkbox.css +2 -6
- package/src/css/form/code-editor.css +1 -0
- package/src/css/form/debug.css +3 -10
- package/src/css/plugin-selector.css +33 -0
- package/src/css/plugin-settings-panel.css +99 -0
- package/src/css/viewer.css +143 -3
- package/src/rust/components/column_dropdown.rs +3 -1
- package/src/rust/components/column_selector/active_column.rs +16 -19
- package/src/rust/components/column_selector/config_selector.rs +20 -20
- package/src/rust/components/column_selector/filter_column.rs +14 -14
- package/src/rust/components/column_selector/inactive_column.rs +10 -15
- package/src/rust/components/column_selector/pivot_column.rs +7 -7
- package/src/rust/components/column_selector/sort_column.rs +7 -7
- package/src/rust/components/column_selector.rs +55 -37
- package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +15 -7
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +395 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +15 -6
- package/src/rust/components/column_settings_sidebar/style_tab.rs +267 -136
- package/src/rust/components/column_settings_sidebar.rs +44 -49
- package/src/rust/components/containers/dragdrop_list.rs +32 -5
- package/src/rust/components/containers/mod.rs +0 -1
- package/src/rust/components/containers/scroll_panel.rs +21 -7
- package/src/rust/components/containers/sidebar.rs +8 -6
- package/src/rust/components/containers/split_panel.rs +3 -3
- package/src/rust/components/containers/tab_list.rs +3 -9
- package/src/rust/components/copy_dropdown.rs +2 -3
- package/src/rust/components/datetime_column_style.rs +19 -81
- package/src/rust/components/editable_header.rs +17 -3
- package/src/rust/components/export_dropdown.rs +2 -3
- package/src/rust/components/expression_editor.rs +29 -17
- package/src/rust/components/filter_dropdown.rs +2 -1
- package/src/rust/components/form/color_range_selector.rs +14 -7
- package/src/rust/components/form/debug.rs +47 -37
- package/src/rust/components/main_panel.rs +24 -65
- package/src/rust/components/mod.rs +2 -1
- package/src/rust/components/number_series_style.rs +161 -0
- package/src/rust/components/plugin_tab.rs +221 -0
- package/src/rust/components/settings_panel.rs +181 -59
- package/src/rust/components/status_bar.rs +141 -174
- package/src/rust/components/status_indicator.rs +15 -22
- package/src/rust/components/string_column_style.rs +20 -82
- package/src/rust/components/style_controls/number_string_format.rs +14 -30
- package/src/rust/components/viewer.rs +169 -132
- package/src/rust/config/column_config_schema.rs +195 -0
- package/src/rust/config/columns_config.rs +4 -97
- package/src/rust/config/datetime_column_style.rs +0 -5
- package/src/rust/config/mod.rs +8 -2
- package/src/rust/config/number_series_style.rs +79 -0
- package/src/rust/config/plugin_static_config.rs +144 -0
- package/src/rust/config/string_column_style.rs +0 -5
- package/src/rust/config/viewer_config.rs +5 -6
- package/src/rust/custom_elements/copy_dropdown.rs +30 -18
- package/src/rust/custom_elements/debug_plugin.rs +1 -3
- package/src/rust/custom_elements/export_dropdown.rs +26 -18
- package/src/rust/custom_elements/viewer.rs +62 -73
- package/src/rust/custom_events.rs +181 -224
- package/src/rust/js/plugin.rs +45 -117
- package/src/rust/lib.rs +34 -5
- package/src/rust/presentation/drag_helpers.rs +206 -0
- package/src/rust/presentation/props.rs +8 -0
- package/src/rust/presentation.rs +256 -41
- package/src/rust/{tasks → queries}/column_locator.rs +17 -73
- package/src/rust/queries/column_values.rs +59 -0
- package/src/rust/{tasks → queries}/columns_iter_set.rs +11 -18
- package/src/rust/queries/exports.rs +96 -0
- package/src/rust/queries/fetch_column_stats.rs +94 -0
- package/src/rust/queries/get_viewer_config.rs +54 -0
- package/src/rust/queries/mod.rs +44 -0
- package/src/rust/queries/plugin_column_styles.rs +101 -0
- package/src/rust/{engines.rs → queries/validate_expression.rs} +26 -15
- package/src/rust/renderer/activate.rs +1 -0
- package/src/rust/renderer/limits.rs +9 -4
- package/src/rust/renderer/plugin_store.rs +12 -0
- package/src/rust/renderer/props.rs +28 -3
- package/src/rust/renderer/registry.rs +40 -15
- package/src/rust/renderer.rs +703 -60
- package/src/rust/session/column_defaults_update.rs +20 -28
- package/src/rust/session/drag_drop_update.rs +10 -10
- package/src/rust/session/metadata.rs +31 -16
- package/src/rust/session/props.rs +15 -6
- package/src/rust/session/view_subscription.rs +10 -0
- package/src/rust/session.rs +109 -147
- package/src/rust/tasks/copy_export.rs +178 -158
- package/src/rust/tasks/{structural.rs → dismiss_render_warning.rs} +20 -40
- package/src/rust/tasks/edit_expression.rs +68 -88
- package/src/rust/tasks/eject.rs +25 -22
- package/src/rust/tasks/intersection_observer.rs +8 -21
- package/src/rust/tasks/mod.rs +19 -21
- package/src/rust/tasks/reset_all.rs +98 -0
- package/src/rust/tasks/resize_observer.rs +11 -33
- package/src/rust/tasks/restore_and_render.rs +128 -90
- package/src/rust/tasks/{get_viewer_config.rs → send_column_config.rs} +39 -35
- package/src/rust/tasks/send_plugin_config.rs +33 -33
- package/src/rust/tasks/update_and_render.rs +75 -49
- package/src/rust/{components/containers/trap_door_panel.rs → tasks/update_theme.rs} +34 -33
- package/src/rust/tasks/validate_expression.rs +61 -0
- package/src/rust/utils/browser/selection.rs +4 -4
- package/src/rust/utils/mod.rs +0 -63
- package/src/svg/checkbox-checked-icon.svg +1 -1
- package/src/svg/checkbox-unchecked-icon.svg +1 -1
- package/src/svg/mega-menu-icons-density.svg +23 -0
- package/src/svg/mega-menu-icons-map-density.svg +24 -0
- package/src/svg/mega-menu-icons-map-line.svg +19 -0
- package/src/themes/botanical.css +27 -53
- package/src/themes/defaults.css +24 -36
- package/src/themes/dracula.css +36 -54
- package/src/themes/gruvbox-dark.css +39 -59
- package/src/themes/gruvbox.css +16 -28
- package/src/themes/icons.css +5 -0
- package/src/themes/intl/de.css +43 -6
- package/src/themes/intl/es.css +43 -6
- package/src/themes/intl/fr.css +43 -6
- package/src/themes/intl/ja.css +43 -6
- package/src/themes/intl/pt.css +43 -6
- package/src/themes/intl/zh.css +43 -6
- package/src/themes/intl.css +38 -4
- package/src/themes/monokai.css +45 -61
- package/src/themes/phosphor.css +20 -29
- package/src/themes/pro-dark.css +25 -34
- package/src/themes/solarized-dark.css +21 -36
- package/src/themes/solarized.css +13 -23
- package/src/themes/vaporwave.css +40 -74
- package/src/ts/bootstrap.ts +14 -3
- package/src/ts/column-format.ts +162 -0
- package/src/ts/extensions.ts +4 -0
- package/src/ts/perspective-viewer.ts +9 -1
- package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
- package/src/ts/plugin.ts +25 -101
- package/src/ts/ts-rs/{FormatUnit.ts → ColumnSelectMode.ts} +1 -1
- package/src/ts/ts-rs/PluginStaticConfig.ts +78 -0
- package/src/ts/ts-rs/ViewerConfig.ts +1 -2
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -3
- package/dist/esm/ts-rs/ColumnConfigValues.d.ts +0 -31
- package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +0 -1
- package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +0 -15
- package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +0 -18
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/DatetimeFormatType.d.ts +0 -6
- package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
- package/dist/esm/ts-rs/FormatUnit.d.ts +0 -1
- package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +0 -1
- package/dist/esm/ts-rs/NumberForegroundMode.d.ts +0 -1
- package/dist/esm/ts-rs/PluginConfig.d.ts +0 -2
- package/dist/esm/ts-rs/RoundingMode.d.ts +0 -1
- package/dist/esm/ts-rs/RoundingPriority.d.ts +0 -1
- package/dist/esm/ts-rs/SignDisplay.d.ts +0 -1
- package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +0 -1
- package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +0 -6
- package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +0 -1
- package/dist/esm/ts-rs/UseGrouping.d.ts +0 -1
- package/src/rust/components/number_column_style.rs +0 -491
- package/src/rust/config/number_column_style.rs +0 -136
- package/src/rust/dragdrop.rs +0 -481
- package/src/rust/tasks/plugin_column_styles.rs +0 -98
- package/src/ts/ts-rs/ColumnConfigValues.ts +0 -14
- package/src/ts/ts-rs/CustomDatetimeFormat.ts +0 -3
- package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +0 -5
- package/src/ts/ts-rs/CustomNumberFormatConfig.ts +0 -8
- package/src/ts/ts-rs/DatetimeColorMode.ts +0 -3
- package/src/ts/ts-rs/DatetimeFormatType.ts +0 -8
- package/src/ts/ts-rs/FormatMode.ts +0 -3
- package/src/ts/ts-rs/NumberBackgroundMode.ts +0 -3
- package/src/ts/ts-rs/NumberForegroundMode.ts +0 -3
- package/src/ts/ts-rs/PluginConfig.ts +0 -4
- package/src/ts/ts-rs/RoundingMode.ts +0 -3
- package/src/ts/ts-rs/RoundingPriority.ts +0 -3
- package/src/ts/ts-rs/SignDisplay.ts +0 -3
- package/src/ts/ts-rs/SimpleDatetimeFormat.ts +0 -3
- package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +0 -4
- package/src/ts/ts-rs/StringColorMode.ts +0 -3
- package/src/ts/ts-rs/TrailingZeroDisplay.ts +0 -3
- package/src/ts/ts-rs/UseGrouping.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline4.js +0 -0
- /package/src/rust/{tasks → config}/export_method.rs +0 -0
- /package/src/rust/{tasks → queries}/export_app.rs +0 -0
- /package/src/rust/{tasks → queries}/is_invalid_drop.rs +0 -0
|
@@ -19,7 +19,6 @@ use crate::js::*;
|
|
|
19
19
|
use crate::presentation::Presentation;
|
|
20
20
|
use crate::renderer::*;
|
|
21
21
|
use crate::session::Session;
|
|
22
|
-
use crate::tasks::*;
|
|
23
22
|
use crate::utils::*;
|
|
24
23
|
use crate::*;
|
|
25
24
|
|
|
@@ -77,30 +76,18 @@ struct IntersectionObserverState {
|
|
|
77
76
|
presentation: Presentation,
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
impl HasPresentation for IntersectionObserverState {
|
|
81
|
-
fn presentation(&self) -> &Presentation {
|
|
82
|
-
&self.presentation
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
impl HasRenderer for IntersectionObserverState {
|
|
87
|
-
fn renderer(&self) -> &Renderer {
|
|
88
|
-
&self.renderer
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
impl HasSession for IntersectionObserverState {
|
|
93
|
-
fn session(&self) -> &Session {
|
|
94
|
-
&self.session
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
79
|
impl IntersectionObserverState {
|
|
99
80
|
async fn set_pause(self, intersect: bool) -> ApiResult<()> {
|
|
100
81
|
if intersect {
|
|
101
82
|
if self.session.set_pause(false) {
|
|
102
|
-
|
|
103
|
-
.
|
|
83
|
+
super::restore_and_render(
|
|
84
|
+
&self.session,
|
|
85
|
+
&self.renderer,
|
|
86
|
+
&self.presentation,
|
|
87
|
+
ViewerConfigUpdate::default(),
|
|
88
|
+
async move { Ok(()) },
|
|
89
|
+
)
|
|
90
|
+
.await?;
|
|
104
91
|
}
|
|
105
92
|
} else {
|
|
106
93
|
self.session.set_pause(true);
|
package/src/rust/tasks/mod.rs
CHANGED
|
@@ -10,43 +10,41 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
//!
|
|
14
|
-
//! `Renderer`, `Presentation`, and `DragDrop` singletons.
|
|
13
|
+
//! State-mutating async business logic dispatched from user actions.
|
|
15
14
|
//!
|
|
16
|
-
//!
|
|
17
|
-
//!
|
|
18
|
-
//! `
|
|
19
|
-
//!
|
|
15
|
+
//! Every function in this module ends in side effects on one or more of
|
|
16
|
+
//! [`Session`], [`Renderer`], [`Presentation`] — applying a
|
|
17
|
+
//! `ViewConfigUpdate`, drawing the active plugin, mutating expressions, etc.
|
|
18
|
+
//! Read-only async derivations belong in [`crate::queries`].
|
|
19
|
+
//!
|
|
20
|
+
//! [`Session`]: crate::session::Session
|
|
21
|
+
//! [`Renderer`]: crate::renderer::Renderer
|
|
22
|
+
//! [`Presentation`]: crate::presentation::Presentation
|
|
20
23
|
|
|
21
|
-
mod column_locator;
|
|
22
|
-
mod columns_iter_set;
|
|
23
24
|
mod copy_export;
|
|
25
|
+
mod dismiss_render_warning;
|
|
24
26
|
mod edit_expression;
|
|
25
27
|
mod eject;
|
|
26
|
-
mod export_app;
|
|
27
|
-
mod export_method;
|
|
28
|
-
mod get_viewer_config;
|
|
29
28
|
mod intersection_observer;
|
|
30
|
-
mod
|
|
31
|
-
mod plugin_column_styles;
|
|
29
|
+
mod reset_all;
|
|
32
30
|
mod resize_observer;
|
|
33
31
|
mod restore_and_render;
|
|
32
|
+
mod send_column_config;
|
|
34
33
|
mod send_plugin_config;
|
|
35
|
-
mod structural;
|
|
36
34
|
mod update_and_render;
|
|
35
|
+
mod update_theme;
|
|
36
|
+
mod validate_expression;
|
|
37
37
|
|
|
38
|
-
pub use self::column_locator::*;
|
|
39
|
-
pub use self::columns_iter_set::*;
|
|
40
38
|
pub use self::copy_export::*;
|
|
39
|
+
pub use self::dismiss_render_warning::*;
|
|
41
40
|
pub use self::edit_expression::*;
|
|
42
41
|
pub use self::eject::*;
|
|
43
|
-
pub use self::export_method::*;
|
|
44
|
-
pub use self::get_viewer_config::*;
|
|
45
42
|
pub use self::intersection_observer::*;
|
|
46
|
-
pub use self::
|
|
47
|
-
pub use self::plugin_column_styles::*;
|
|
43
|
+
pub use self::reset_all::*;
|
|
48
44
|
pub use self::resize_observer::*;
|
|
49
45
|
pub use self::restore_and_render::*;
|
|
46
|
+
pub use self::send_column_config::*;
|
|
50
47
|
pub use self::send_plugin_config::*;
|
|
51
|
-
pub use self::structural::*;
|
|
52
48
|
pub use self::update_and_render::*;
|
|
49
|
+
pub use self::update_theme::*;
|
|
50
|
+
pub use self::validate_expression::*;
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
//! Cross-engine reset orchestration: reset session config, optionally clear
|
|
14
|
+
//! presentation columns config / theme, then delegate to `restore_and_render`
|
|
15
|
+
//! to switch back to the default plugin and redraw.
|
|
16
|
+
|
|
17
|
+
use futures::channel::oneshot;
|
|
18
|
+
use perspective_client::clone;
|
|
19
|
+
use perspective_js::utils::ApiFuture;
|
|
20
|
+
|
|
21
|
+
use super::restore_and_render;
|
|
22
|
+
use crate::config::{
|
|
23
|
+
ColumnConfigUpdate, OptionalUpdate, PluginConfigUpdate, PluginUpdate, ViewerConfigUpdate,
|
|
24
|
+
};
|
|
25
|
+
use crate::presentation::Presentation;
|
|
26
|
+
use crate::renderer::Renderer;
|
|
27
|
+
use crate::session::{ResetOptions, Session};
|
|
28
|
+
|
|
29
|
+
/// Reset the viewer's `ViewerConfig` to the default.
|
|
30
|
+
///
|
|
31
|
+
/// - `all = false`: clears the view config but preserves expressions and
|
|
32
|
+
/// per-column style maps.
|
|
33
|
+
/// - `all = true`: also clears expressions, per-column styles, and theme.
|
|
34
|
+
///
|
|
35
|
+
/// Optionally signals `sender` once the reset+redraw round-trip completes,
|
|
36
|
+
/// then emits `renderer.reset_changed`.
|
|
37
|
+
///
|
|
38
|
+
/// Delegates plugin selection + draw to [`restore_and_render`], whose
|
|
39
|
+
/// two-pass restore guarantees the default plugin sees materialized
|
|
40
|
+
/// `columns_config` / `plugin_config` on its first draw — fixing a race
|
|
41
|
+
/// where the raw post-reset bucket would reach the plugin before
|
|
42
|
+
/// stats-dependent `include: true` defaults were resolved.
|
|
43
|
+
pub fn reset_all(
|
|
44
|
+
session: &Session,
|
|
45
|
+
renderer: &Renderer,
|
|
46
|
+
presentation: &Presentation,
|
|
47
|
+
all: bool,
|
|
48
|
+
sender: Option<oneshot::Sender<()>>,
|
|
49
|
+
) {
|
|
50
|
+
presentation.set_open_column_settings(None);
|
|
51
|
+
clone!(session, renderer, presentation);
|
|
52
|
+
ApiFuture::spawn(async move {
|
|
53
|
+
session
|
|
54
|
+
.reset(ResetOptions {
|
|
55
|
+
config: true,
|
|
56
|
+
expressions: all,
|
|
57
|
+
..ResetOptions::default()
|
|
58
|
+
})
|
|
59
|
+
.await?;
|
|
60
|
+
|
|
61
|
+
presentation.reset_available_themes(None).await;
|
|
62
|
+
if all {
|
|
63
|
+
presentation.reset_theme().await?;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// For `all = true`, route the bucket clears through `restore_and_render`'s
|
|
67
|
+
// `update_*` paths as `SetDefault`. This guarantees the materialized
|
|
68
|
+
// restore fires even when the user is already on the default plugin
|
|
69
|
+
// (no plugin_swap signal), since `SetDefault` reports the bucket as
|
|
70
|
+
// `changed` when it was non-empty. The per-plugin bucket model means
|
|
71
|
+
// only the (post-swap) default plugin's bucket is cleared; other
|
|
72
|
+
// plugins' buckets persist with their per-plugin state.
|
|
73
|
+
let (columns_config, plugin_config) = if all {
|
|
74
|
+
(
|
|
75
|
+
ColumnConfigUpdate::SetDefault,
|
|
76
|
+
PluginConfigUpdate::SetDefault,
|
|
77
|
+
)
|
|
78
|
+
} else {
|
|
79
|
+
(OptionalUpdate::Missing, OptionalUpdate::Missing)
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
let update = ViewerConfigUpdate {
|
|
83
|
+
plugin: PluginUpdate::SetDefault,
|
|
84
|
+
plugin_config,
|
|
85
|
+
columns_config,
|
|
86
|
+
..Default::default()
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
restore_and_render(&session, &renderer, &presentation, update, async { Ok(()) }).await?;
|
|
90
|
+
|
|
91
|
+
if let Some(sender) = sender {
|
|
92
|
+
sender.send(()).unwrap();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
renderer.reset_changed.emit(());
|
|
96
|
+
Ok(())
|
|
97
|
+
})
|
|
98
|
+
}
|
|
@@ -22,7 +22,6 @@ use crate::presentation::Presentation;
|
|
|
22
22
|
use crate::renderer::*;
|
|
23
23
|
use crate::root::Root;
|
|
24
24
|
use crate::session::{Session, TableLoadState};
|
|
25
|
-
use crate::tasks::*;
|
|
26
25
|
use crate::utils::*;
|
|
27
26
|
|
|
28
27
|
pub struct ResizeObserverHandle {
|
|
@@ -83,32 +82,6 @@ struct ResizeObserverState {
|
|
|
83
82
|
on_resize: Callback<()>,
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
impl HasRenderer for ResizeObserverState {
|
|
87
|
-
fn renderer(&self) -> &Renderer {
|
|
88
|
-
&self.renderer
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
impl HasSession for ResizeObserverState {
|
|
93
|
-
fn session(&self) -> &Session {
|
|
94
|
-
&self.session
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
impl HasPresentation for ResizeObserverState {
|
|
99
|
-
fn presentation(&self) -> &'_ crate::presentation::Presentation {
|
|
100
|
-
&self.presentation
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
impl StateProvider for ResizeObserverState {
|
|
105
|
-
type State = ResizeObserverState;
|
|
106
|
-
|
|
107
|
-
fn clone_state(&self) -> Self::State {
|
|
108
|
-
self.clone()
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
85
|
impl ResizeObserverState {
|
|
113
86
|
fn on_resize(&mut self, entries: &js_sys::Array) {
|
|
114
87
|
let is_visible = self
|
|
@@ -124,16 +97,16 @@ impl ResizeObserverState {
|
|
|
124
97
|
let content_height = content.height().floor() as i32;
|
|
125
98
|
let resized = self.width != content_width || self.height != content_height;
|
|
126
99
|
if resized && is_visible {
|
|
127
|
-
let state = self.
|
|
100
|
+
let state = self.clone();
|
|
128
101
|
clone!(self.on_resize);
|
|
129
102
|
ApiFuture::spawn_throttled(async move {
|
|
130
103
|
let needs_render = state
|
|
131
|
-
.renderer
|
|
104
|
+
.renderer
|
|
132
105
|
.clone()
|
|
133
106
|
.with_lock(async {
|
|
134
|
-
Ok(!state.renderer
|
|
107
|
+
Ok(!state.renderer.is_plugin_activated()?
|
|
135
108
|
&& matches!(
|
|
136
|
-
state.session
|
|
109
|
+
state.session.has_table(),
|
|
137
110
|
Some(TableLoadState::Loaded)
|
|
138
111
|
))
|
|
139
112
|
})
|
|
@@ -141,9 +114,14 @@ impl ResizeObserverState {
|
|
|
141
114
|
|
|
142
115
|
if needs_render {
|
|
143
116
|
state.presentation.reset_attached();
|
|
144
|
-
|
|
117
|
+
super::update_and_render(
|
|
118
|
+
&state.session,
|
|
119
|
+
&state.renderer,
|
|
120
|
+
Default::default(),
|
|
121
|
+
)?
|
|
122
|
+
.await?;
|
|
145
123
|
} else {
|
|
146
|
-
state.renderer
|
|
124
|
+
state.renderer.resize().await?;
|
|
147
125
|
}
|
|
148
126
|
|
|
149
127
|
on_resize.emit(());
|
|
@@ -10,110 +10,148 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
+
//! Apply a full [`ViewerConfigUpdate`] (settings, theme, title, plugin,
|
|
14
|
+
//! plugin_config, columns_config, view_config) and re-draw.
|
|
15
|
+
|
|
13
16
|
use futures::Future;
|
|
17
|
+
use perspective_client::clone;
|
|
14
18
|
|
|
15
|
-
use super::structural::*;
|
|
16
19
|
use crate::config::{OptionalUpdate, ViewerConfigUpdate};
|
|
17
|
-
use crate::
|
|
20
|
+
use crate::presentation::Presentation;
|
|
21
|
+
use crate::renderer::Renderer;
|
|
22
|
+
use crate::session::Session;
|
|
18
23
|
use crate::*;
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
/// Apply a full [`ViewerConfigUpdate`] (theme, title, plugin selection,
|
|
26
|
+
/// plugin config, columns config, view config) to the engines and re-draw.
|
|
27
|
+
/// Returns an [`ApiFuture<()>`] which resolves when the draw completes.
|
|
28
|
+
pub fn restore_and_render(
|
|
29
|
+
session: &Session,
|
|
30
|
+
renderer: &Renderer,
|
|
31
|
+
presentation: &Presentation,
|
|
32
|
+
ViewerConfigUpdate {
|
|
33
|
+
plugin,
|
|
34
|
+
plugin_config,
|
|
35
|
+
columns_config,
|
|
36
|
+
settings,
|
|
37
|
+
theme: theme_name,
|
|
38
|
+
title,
|
|
39
|
+
mut view_config,
|
|
40
|
+
..
|
|
41
|
+
}: ViewerConfigUpdate,
|
|
42
|
+
task: impl Future<Output = Result<(), ApiError>> + 'static,
|
|
43
|
+
) -> ApiFuture<()> {
|
|
44
|
+
clone!(session, renderer, presentation);
|
|
45
|
+
ApiFuture::new(async move {
|
|
46
|
+
if let OptionalUpdate::Update(x) = settings {
|
|
47
|
+
presentation.set_settings_attribute(x);
|
|
48
|
+
presentation.set_settings_before_open(x);
|
|
49
|
+
}
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
if let OptionalUpdate::Update(title) = title {
|
|
52
|
+
session.set_title(Some(title));
|
|
53
|
+
} else if matches!(title, OptionalUpdate::SetDefault) {
|
|
54
|
+
session.set_title(None);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let needs_restyle = match theme_name {
|
|
58
|
+
OptionalUpdate::SetDefault => {
|
|
59
|
+
let current_name = presentation.get_selected_theme_name().await;
|
|
60
|
+
if current_name.is_some() {
|
|
61
|
+
presentation.set_theme_name(None).await?;
|
|
62
|
+
true
|
|
63
|
+
} else {
|
|
64
|
+
false
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
OptionalUpdate::Update(x) => {
|
|
68
|
+
let current_name = presentation.get_selected_theme_name().await;
|
|
69
|
+
if current_name.is_some() && current_name.as_ref().unwrap() != &x {
|
|
70
|
+
presentation.set_theme_name(Some(&x)).await?;
|
|
71
|
+
true
|
|
72
|
+
} else {
|
|
73
|
+
false
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
_ => false,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if let Some(metadata) = renderer.get_next_plugin_metadata(&plugin) {
|
|
80
|
+
session.set_update_column_defaults(&mut view_config, &metadata);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
session.update_view_config(view_config)?;
|
|
84
|
+
let draw_task = renderer.draw(async {
|
|
85
|
+
task.await?;
|
|
86
|
+
let plugin_swapped = renderer.apply_pending_plugin()?;
|
|
87
|
+
let plugin = renderer.get_active_plugin()?;
|
|
48
88
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if current_name.is_some() {
|
|
53
|
-
presentation.set_theme_name(None).await?;
|
|
54
|
-
true
|
|
55
|
-
} else {
|
|
56
|
-
false
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
OptionalUpdate::Update(x) => {
|
|
60
|
-
let current_name = presentation.get_selected_theme_name().await;
|
|
61
|
-
if current_name.is_some() && current_name.as_ref().unwrap() != &x {
|
|
62
|
-
presentation.set_theme_name(Some(&x)).await?;
|
|
63
|
-
true
|
|
64
|
-
} else {
|
|
65
|
-
false
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
_ => false,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
if let Some(metadata) = renderer.get_next_plugin_metadata(&plugin) {
|
|
72
|
-
session.set_update_column_defaults(&mut view_config, &metadata);
|
|
89
|
+
// The previous call which acquired the lock errored, so skip this render
|
|
90
|
+
if let Some(error) = session.get_error() {
|
|
91
|
+
return Err(error);
|
|
73
92
|
}
|
|
74
93
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
// Validate + create the view BEFORE applying
|
|
95
|
+
// columns_config / plugin_config updates, so the
|
|
96
|
+
// strip-on-write and materialize passes see fresh
|
|
97
|
+
// `expression_schema` and `view_schema`, and the
|
|
98
|
+
// materialize warm step can call `View::get_min_max`
|
|
99
|
+
// against a view that knows about any new expression
|
|
100
|
+
// columns. Previously this happened after the strip,
|
|
101
|
+
// which silently dropped any `columns_config` entry
|
|
102
|
+
// keyed by a new expression column.
|
|
103
|
+
let view = session.validate().await?.create_view().await?;
|
|
85
104
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
// Apply incoming updates into the now-active plugin's
|
|
106
|
+
// bucket on `Renderer`. Per-plugin storage means no
|
|
107
|
+
// schema filter is needed before restore — foreign keys
|
|
108
|
+
// cannot appear in the bucket by construction. The
|
|
109
|
+
// renderer methods also strip schema-default entries so
|
|
110
|
+
// restored maps containing default values produce an
|
|
111
|
+
// empty bucket (correct: bucket-empty ⇒ reads-default).
|
|
112
|
+
let view_config_snapshot = session.get_view_config().clone();
|
|
113
|
+
let plugin_config_changed =
|
|
114
|
+
renderer.update_plugin_config(&view_config_snapshot, plugin_config);
|
|
115
|
+
let columns_config_changed =
|
|
116
|
+
renderer.update_columns_configs(&view_config_snapshot, &session, columns_config);
|
|
117
|
+
let changed = plugin_config_changed || columns_config_changed;
|
|
89
118
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
119
|
+
// Force a materialized restore when the plugin just
|
|
120
|
+
// swapped — `commit_plugin_idx` already restored from the
|
|
121
|
+
// raw bucket, but the materialized restore is needed for
|
|
122
|
+
// schema-revealed `include: true` defaults to reach the
|
|
123
|
+
// plugin before its first draw.
|
|
124
|
+
if changed || plugin_swapped {
|
|
125
|
+
let plugin_config_snapshot = renderer.get_plugin_config();
|
|
126
|
+
let plugin_update =
|
|
127
|
+
wasm_bindgen::JsValue::from_serde_ext(&plugin_config_snapshot).unwrap();
|
|
128
|
+
let columns_config = renderer
|
|
129
|
+
.all_columns_configs_materialized(&view_config_snapshot, &session)
|
|
130
|
+
.await;
|
|
131
|
+
plugin.restore(&plugin_update, Some(&columns_config))?;
|
|
132
|
+
if plugin_config_changed {
|
|
133
|
+
renderer.plugin_config_changed.emit(plugin_config_snapshot);
|
|
93
134
|
}
|
|
135
|
+
}
|
|
94
136
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
});
|
|
137
|
+
if !presentation.is_visible() {
|
|
138
|
+
Ok(None)
|
|
139
|
+
} else {
|
|
140
|
+
Ok(view)
|
|
141
|
+
}
|
|
142
|
+
});
|
|
102
143
|
|
|
103
|
-
|
|
144
|
+
draw_task.await?;
|
|
104
145
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
146
|
+
// TODO this should be part of the API for `draw()` above, such that
|
|
147
|
+
// the plugin need not render twice when a theme is provided.
|
|
148
|
+
if needs_restyle
|
|
149
|
+
&& presentation.is_visible()
|
|
150
|
+
&& let Some(view) = session.get_view()
|
|
151
|
+
{
|
|
152
|
+
renderer.restyle_all(&view).await?;
|
|
153
|
+
}
|
|
113
154
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
155
|
+
Ok(())
|
|
156
|
+
})
|
|
117
157
|
}
|
|
118
|
-
|
|
119
|
-
impl<T: HasRenderer + HasSession + HasPresentation> RestoreAndRender for T {}
|
|
@@ -10,41 +10,45 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use
|
|
14
|
-
use
|
|
15
|
-
use crate::*;
|
|
13
|
+
use perspective_client::clone;
|
|
14
|
+
use perspective_js::utils::*;
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
use crate::config::ColumnConfigFieldUpdate;
|
|
17
|
+
use crate::renderer::Renderer;
|
|
18
|
+
use crate::session::Session;
|
|
19
|
+
|
|
20
|
+
/// Apply a [`ColumnConfigFieldUpdate`] from a column-style sidebar
|
|
21
|
+
/// control to the active plugin's per-column config bucket on
|
|
22
|
+
/// [`Renderer`], then re-`restore` the active plugin with the
|
|
23
|
+
/// updated maps and trigger a render.
|
|
19
24
|
///
|
|
20
|
-
///
|
|
21
|
-
/// `
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
let theme = self.presentation().get_selected_theme_name().await;
|
|
33
|
-
let title = self.session().get_title();
|
|
34
|
-
let table = self.session().get_table().map(|x| x.get_name().to_owned());
|
|
35
|
-
let columns_config = self.presentation().all_columns_configs();
|
|
36
|
-
Ok(ViewerConfig {
|
|
37
|
-
version,
|
|
38
|
-
plugin,
|
|
39
|
-
title,
|
|
40
|
-
plugin_config,
|
|
41
|
-
columns_config,
|
|
42
|
-
settings,
|
|
43
|
-
table,
|
|
44
|
-
view_config,
|
|
45
|
-
theme,
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
}
|
|
25
|
+
/// Plugin-level (non-column) field updates go through
|
|
26
|
+
/// [`super::send_plugin_config`] instead.
|
|
27
|
+
pub fn send_column_config(
|
|
28
|
+
session: &Session,
|
|
29
|
+
renderer: &Renderer,
|
|
30
|
+
column_name: &str,
|
|
31
|
+
update: ColumnConfigFieldUpdate,
|
|
32
|
+
) {
|
|
33
|
+
// Apply the renderer write synchronously so the StyleTab's
|
|
34
|
+
// revision-bump re-render path sees the new state immediately.
|
|
35
|
+
let view_config = session.get_view_config().clone();
|
|
36
|
+
renderer.update_columns_config_field(&view_config, session, column_name.to_string(), update);
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
clone!(session, renderer);
|
|
39
|
+
ApiFuture::spawn(async move {
|
|
40
|
+
let view_config_snapshot = session.get_view_config().clone();
|
|
41
|
+
let columns_configs = renderer
|
|
42
|
+
.all_columns_configs_materialized(&view_config_snapshot, &session)
|
|
43
|
+
.await;
|
|
44
|
+
let plugin_token =
|
|
45
|
+
wasm_bindgen::JsValue::from_serde_ext(&renderer.get_plugin_config()).unwrap();
|
|
46
|
+
renderer
|
|
47
|
+
.get_active_plugin()?
|
|
48
|
+
.restore(&plugin_token, Some(&columns_configs))?;
|
|
49
|
+
|
|
50
|
+
renderer.update(session.get_view()).await?;
|
|
51
|
+
renderer.column_style_changed.emit(columns_configs);
|
|
52
|
+
Ok(())
|
|
53
|
+
})
|
|
54
|
+
}
|