@perspective-dev/viewer 4.3.0 → 4.4.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 +2 -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 -0
- 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/extensions.d.ts +4 -0
- package/dist/esm/perspective-viewer.d.ts +1 -0
- package/dist/esm/perspective-viewer.inline.js +2 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +2 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +9 -9
- package/dist/esm/ts-rs/NumberForegroundMode.d.ts +1 -1
- package/dist/esm/ts-rs/ViewerConfig.d.ts +36 -0
- package/dist/wasm/perspective-viewer.d.ts +68 -59
- package/dist/wasm/perspective-viewer.js +216 -171
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +19 -20
- package/package.json +7 -5
- package/src/{less/aggregate-selector.less → css/aggregate-selector.css} +23 -20
- package/src/css/column-dropdown.css +109 -0
- package/src/{less/column-selector.less → css/column-selector.css} +160 -158
- package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +70 -59
- package/src/{less/column-style.less → css/column-style.css} +52 -66
- package/src/{less/column-symbol-attributes.less → css/column-symbol-attributes.css} +15 -14
- package/src/{less/config-selector.less → css/config-selector.css} +151 -135
- package/src/{less/containers/dropdown-menu.less → css/containers/dropdown-menu.css} +20 -19
- package/src/{less/containers/pairs-list.less → css/containers/pairs-list.css} +13 -12
- package/src/{themes/variables.less → css/containers/scroll-panel.css} +25 -22
- package/src/{less/containers/split-panel.less → css/containers/split-panel.css} +15 -14
- package/src/{less/containers/tabs.less → css/containers/tabs.css} +17 -19
- package/src/css/dom/checkbox.css +102 -0
- package/src/css/dom/scrollbar.css +35 -0
- package/src/{less/dom/select.less → css/dom/select.css} +17 -18
- package/src/{less/empty-column.less → css/empty-column.css} +19 -18
- package/src/{less/expression-editor.less → css/expression-editor.css} +19 -18
- package/src/{less/filter-dropdown.less → css/filter-dropdown.css} +12 -11
- package/src/{less/filter-item.less → css/filter-item.css} +16 -15
- package/src/{less/form/code-editor.less → css/form/code-editor.css} +26 -30
- package/src/{less/form/debug.less → css/form/debug.css} +19 -18
- package/src/{less/function-dropdown.less → css/function-dropdown.css} +12 -11
- package/src/css/plugin-selector.css +261 -0
- package/src/{less/render-warning.less → css/render-warning.css} +18 -17
- package/src/{less/status-bar.less → css/status-bar.css} +157 -145
- package/src/css/type-icon.css +116 -0
- package/src/{less/viewer.less → css/viewer.css} +112 -146
- package/src/rust/components/column_dropdown.rs +229 -119
- package/src/rust/components/column_selector/active_column.rs +81 -62
- package/src/rust/components/column_selector/add_expression_button.rs +1 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +25 -15
- package/src/rust/components/column_selector/config_selector.rs +315 -199
- package/src/rust/components/column_selector/empty_column.rs +2 -2
- package/src/rust/components/column_selector/expr_edit_button.rs +8 -2
- package/src/rust/components/column_selector/filter_column.rs +37 -26
- package/src/rust/components/column_selector/inactive_column.rs +41 -29
- package/src/rust/components/column_selector/invalid_column.rs +7 -18
- package/src/rust/components/column_selector/pivot_column.rs +11 -5
- package/src/rust/components/column_selector/sort_column.rs +23 -13
- package/src/rust/components/column_selector.rs +163 -84
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +2 -3
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +7 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +153 -112
- package/src/rust/components/column_settings_sidebar.rs +91 -53
- package/src/rust/components/containers/dragdrop_list.rs +2 -1
- package/src/rust/components/containers/sidebar_close_button.rs +1 -1
- package/src/rust/components/containers/split_panel.rs +1 -0
- package/src/rust/components/containers/tab_list.rs +1 -1
- package/src/rust/components/copy_dropdown.rs +7 -28
- package/src/rust/components/datetime_column_style/custom.rs +2 -2
- package/src/rust/components/datetime_column_style/simple.rs +2 -2
- package/src/rust/components/datetime_column_style.rs +4 -2
- package/src/rust/components/editable_header.rs +7 -4
- package/src/rust/components/empty_row.rs +1 -1
- package/src/rust/components/export_dropdown.rs +4 -30
- package/src/rust/components/expression_editor.rs +19 -10
- package/src/rust/components/filter_dropdown.rs +246 -102
- package/src/rust/components/font_loader.rs +11 -28
- package/src/rust/components/form/code_editor.rs +17 -2
- package/src/rust/components/form/color_range_selector.rs +19 -6
- package/src/rust/components/form/debug.rs +30 -13
- package/src/rust/components/function_dropdown.rs +186 -113
- package/src/rust/components/main_panel.rs +71 -89
- package/src/rust/components/mod.rs +1 -1
- package/src/rust/components/modal.rs +7 -1
- package/src/rust/components/number_column_style.rs +30 -7
- package/src/rust/components/plugin_selector.rs +34 -102
- package/src/rust/components/portal.rs +274 -0
- package/src/rust/components/render_warning.rs +72 -123
- package/src/rust/components/settings_panel.rs +115 -11
- package/src/rust/components/status_bar.rs +222 -98
- package/src/rust/components/status_bar_counter.rs +8 -20
- package/src/rust/components/status_indicator.rs +64 -114
- package/src/rust/components/string_column_style.rs +2 -2
- package/src/rust/components/style/style_cache.rs +5 -1
- package/src/rust/components/viewer.rs +391 -40
- package/src/rust/config/number_column_style.rs +5 -1
- package/src/rust/config/viewer_config.rs +2 -2
- package/src/rust/custom_elements/copy_dropdown.rs +102 -21
- package/src/rust/custom_elements/debug_plugin.rs +4 -4
- package/src/rust/custom_elements/export_dropdown.rs +102 -20
- package/src/rust/custom_elements/mod.rs +0 -7
- package/src/rust/custom_elements/modal.rs +7 -103
- package/src/rust/custom_elements/viewer.rs +114 -39
- package/src/rust/custom_events.rs +23 -2
- package/src/rust/dragdrop.rs +149 -10
- package/src/{less/containers/scroll-panel.less → rust/engines.rs} +15 -13
- package/src/rust/js/plugin.rs +1 -1
- package/src/rust/lib.rs +10 -4
- package/src/rust/presentation/props.rs +39 -0
- package/src/rust/presentation/sheets.rs +3 -3
- package/src/rust/presentation.rs +44 -8
- package/src/rust/renderer/limits.rs +32 -3
- package/src/{less/dom/scrollbar.less → rust/renderer/props.rs} +18 -19
- package/src/rust/renderer.rs +93 -14
- package/src/rust/session/column_defaults_update.rs +1 -1
- package/src/rust/session/metadata.rs +23 -2
- package/src/rust/session/props.rs +178 -0
- package/src/rust/session.rs +124 -117
- package/src/rust/tasks/column_locator.rs +133 -0
- package/src/rust/{model → tasks}/columns_iter_set.rs +14 -23
- package/src/rust/{model → tasks}/edit_expression.rs +34 -10
- package/src/rust/{model → tasks}/eject.rs +2 -2
- package/src/rust/{model → tasks}/get_viewer_config.rs +0 -11
- package/src/rust/{model → tasks}/intersection_observer.rs +19 -3
- package/src/{less/containers/radio-list.less → rust/tasks/is_invalid_drop.rs} +21 -14
- package/src/rust/tasks/mod.rs +52 -0
- package/src/rust/{model → tasks}/plugin_column_styles.rs +69 -46
- package/src/rust/{model → tasks}/resize_observer.rs +39 -6
- package/src/rust/{model → tasks}/restore_and_render.rs +4 -3
- package/src/rust/{model → tasks}/send_plugin_config.rs +1 -1
- package/src/rust/tasks/structural.rs +53 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/modal_position.rs +110 -0
- package/src/rust/utils/ptr_eq_rc.rs +74 -0
- package/src/rust/utils/pubsub.rs +11 -1
- package/src/svg/bg-pattern.png +0 -0
- package/src/svg/close-icon.svg +1 -1
- package/src/svg/datagrid-select-row-tree.svg +13 -0
- package/src/svg/expression.svg +1 -1
- package/src/svg/mega-menu-icons-candlestick.svg +1 -1
- package/src/svg/mega-menu-icons-datagrid.svg +1 -2
- package/src/svg/mega-menu-icons-heatmap.svg +1 -1
- package/src/svg/mega-menu-icons-map-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-ohlc.svg +1 -1
- package/src/svg/mega-menu-icons-sunburst.svg +1 -1
- package/src/svg/mega-menu-icons-treemap.svg +1 -1
- package/src/svg/mega-menu-icons-x-bar.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-y-area.svg +1 -1
- package/src/svg/mega-menu-icons-y-bar.svg +1 -1
- package/src/svg/mega-menu-icons-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-y-scatter.svg +1 -1
- package/src/svg/radio-hover.svg +1 -1
- package/src/svg/radio-off.svg +1 -1
- package/src/svg/radio-on.svg +1 -1
- package/src/themes/botanical.css +157 -0
- package/src/themes/defaults.css +157 -0
- package/src/themes/dracula.css +233 -0
- package/src/themes/gruvbox-dark.css +255 -0
- package/src/themes/gruvbox.css +134 -0
- package/src/themes/icons.css +107 -0
- package/src/themes/intl/de.css +102 -0
- package/src/themes/intl/es.css +102 -0
- package/src/themes/intl/fr.css +102 -0
- package/src/themes/intl/ja.css +102 -0
- package/src/themes/intl/pt.css +102 -0
- package/src/themes/intl/zh.css +102 -0
- package/src/themes/intl.css +102 -0
- package/src/themes/monokai.css +233 -0
- package/src/themes/phosphor.css +184 -0
- package/src/themes/pro-dark.css +158 -0
- package/src/themes/{themes.less → pro.css} +17 -21
- package/src/themes/solarized-dark.css +135 -0
- package/src/themes/solarized.css +95 -0
- package/src/themes/themes.css +23 -0
- package/src/themes/vaporwave.css +256 -0
- package/src/ts/extensions.ts +8 -1
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/plugin.ts +9 -9
- package/src/ts/ts-rs/NumberForegroundMode.ts +1 -1
- package/src/ts/ts-rs/ViewerConfig.ts +15 -0
- package/dist/css/variables.css +0 -0
- package/src/less/column-dropdown.less +0 -95
- package/src/less/dom/checkbox.less +0 -100
- package/src/less/plugin-selector.less +0 -183
- package/src/less/type-icon.less +0 -68
- package/src/rust/components/error_message.rs +0 -56
- package/src/rust/custom_elements/column_dropdown.rs +0 -123
- package/src/rust/custom_elements/filter_dropdown.rs +0 -179
- package/src/rust/custom_elements/function_dropdown.rs +0 -115
- package/src/rust/model/column_locator.rs +0 -82
- package/src/rust/model/is_invalid_drop.rs +0 -36
- package/src/rust/model/mod.rs +0 -100
- package/src/rust/model/reset_all.rs +0 -38
- package/src/rust/model/structural.rs +0 -244
- package/src/themes/botanical.less +0 -142
- package/src/themes/dracula.less +0 -101
- package/src/themes/gruvbox-dark.less +0 -116
- package/src/themes/gruvbox.less +0 -152
- package/src/themes/icons.less +0 -130
- package/src/themes/intl/de.less +0 -102
- package/src/themes/intl/es.less +0 -102
- package/src/themes/intl/fr.less +0 -102
- package/src/themes/intl/ja.less +0 -102
- package/src/themes/intl/pt.less +0 -102
- package/src/themes/intl/zh.less +0 -102
- package/src/themes/intl.less +0 -102
- package/src/themes/monokai.less +0 -107
- package/src/themes/pro-dark.less +0 -147
- package/src/themes/pro.less +0 -186
- package/src/themes/solarized-dark.less +0 -78
- package/src/themes/solarized.less +0 -102
- package/src/themes/vaporwave.less +0 -145
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline4.js +0 -0
- /package/src/rust/{model → tasks}/copy_export.rs +0 -0
- /package/src/rust/{model → tasks}/export_app.rs +0 -0
- /package/src/rust/{model → tasks}/export_method.rs +0 -0
- /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
|
@@ -25,16 +25,17 @@ use crate::components::column_settings_sidebar::ColumnSettingsPanel;
|
|
|
25
25
|
use crate::components::main_panel::MainPanel;
|
|
26
26
|
use crate::components::settings_panel::SettingsPanel;
|
|
27
27
|
use crate::config::*;
|
|
28
|
+
use crate::css;
|
|
28
29
|
use crate::custom_events::CustomEvents;
|
|
29
|
-
use crate::dragdrop
|
|
30
|
-
use crate::
|
|
31
|
-
use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation};
|
|
32
|
-
use crate::renderer
|
|
33
|
-
use crate::session
|
|
30
|
+
use crate::dragdrop::{DragDropProps, *};
|
|
31
|
+
use crate::js::JsPerspectiveViewerPlugin;
|
|
32
|
+
use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation, PresentationProps};
|
|
33
|
+
use crate::renderer::{RendererProps, *};
|
|
34
|
+
use crate::session::{SessionProps, *};
|
|
35
|
+
use crate::tasks::*;
|
|
34
36
|
use crate::utils::*;
|
|
35
|
-
use crate::{PerspectiveProperties, css};
|
|
36
37
|
|
|
37
|
-
#[derive(Clone, Properties
|
|
38
|
+
#[derive(Clone, Properties)]
|
|
38
39
|
pub struct PerspectiveViewerProps {
|
|
39
40
|
/// The light DOM element this component will render to.
|
|
40
41
|
pub elem: web_sys::HtmlElement,
|
|
@@ -53,9 +54,41 @@ impl PartialEq for PerspectiveViewerProps {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
impl PerspectiveViewerProps {
|
|
57
|
-
fn
|
|
58
|
-
self.
|
|
57
|
+
impl HasCustomEvents for PerspectiveViewerProps {
|
|
58
|
+
fn custom_events(&self) -> &CustomEvents {
|
|
59
|
+
&self.custom_events
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl HasDragDrop for PerspectiveViewerProps {
|
|
64
|
+
fn dragdrop(&self) -> &DragDrop {
|
|
65
|
+
&self.dragdrop
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
impl HasPresentation for PerspectiveViewerProps {
|
|
70
|
+
fn presentation(&self) -> &Presentation {
|
|
71
|
+
&self.presentation
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
impl HasRenderer for PerspectiveViewerProps {
|
|
76
|
+
fn renderer(&self) -> &Renderer {
|
|
77
|
+
&self.renderer
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
impl HasSession for PerspectiveViewerProps {
|
|
82
|
+
fn session(&self) -> &Session {
|
|
83
|
+
&self.session
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
impl StateProvider for PerspectiveViewerProps {
|
|
88
|
+
type State = PerspectiveViewerProps;
|
|
89
|
+
|
|
90
|
+
fn clone_state(&self) -> Self::State {
|
|
91
|
+
self.clone()
|
|
59
92
|
}
|
|
60
93
|
}
|
|
61
94
|
|
|
@@ -75,12 +108,34 @@ pub enum PerspectiveViewerMsg {
|
|
|
75
108
|
ToggleDebug,
|
|
76
109
|
ToggleSettingsComplete(SettingsUpdate, Sender<()>),
|
|
77
110
|
ToggleSettingsInit(Option<SettingsUpdate>, Option<Sender<ApiResult<JsValue>>>),
|
|
111
|
+
UpdateSession(Box<SessionProps>),
|
|
112
|
+
UpdateRenderer(Box<RendererProps>),
|
|
113
|
+
UpdatePresentation(Box<PresentationProps>),
|
|
114
|
+
|
|
115
|
+
/// Update only `is_settings_open` in the presentation snapshot without
|
|
116
|
+
/// touching `available_themes` (which requires async data).
|
|
117
|
+
UpdateSettingsOpen(bool),
|
|
118
|
+
UpdateIsWorkspace(bool),
|
|
119
|
+
|
|
120
|
+
/// Update only `open_column_settings` in the presentation snapshot.
|
|
121
|
+
UpdateColumnSettings(Box<crate::presentation::OpenColumnSettings>),
|
|
122
|
+
UpdateDragDrop(Box<DragDropProps>),
|
|
123
|
+
|
|
124
|
+
/// Update only stats-related fields of `session_props` without touching
|
|
125
|
+
/// `config`. This prevents `stats_changed` events (e.g. from `reset()`)
|
|
126
|
+
/// from propagating a freshly-cleared config to the column selector.
|
|
127
|
+
UpdateSessionStats(Option<ViewStats>, Option<TableLoadState>),
|
|
128
|
+
|
|
129
|
+
/// Increment/decrement the in-flight render counter threaded to
|
|
130
|
+
/// `StatusIndicator` so it can show the "updating" spinner.
|
|
131
|
+
IncrementUpdateCount,
|
|
132
|
+
DecrementUpdateCount,
|
|
78
133
|
}
|
|
79
134
|
|
|
80
135
|
use PerspectiveViewerMsg::*;
|
|
81
136
|
|
|
82
137
|
pub struct PerspectiveViewer {
|
|
83
|
-
_subscriptions:
|
|
138
|
+
_subscriptions: Vec<Subscription>,
|
|
84
139
|
column_settings_panel_width_override: Option<i32>,
|
|
85
140
|
debug_open: bool,
|
|
86
141
|
fonts: FontLoaderProps,
|
|
@@ -89,6 +144,18 @@ pub struct PerspectiveViewer {
|
|
|
89
144
|
on_resize: Rc<PubSub<()>>,
|
|
90
145
|
settings_open: bool,
|
|
91
146
|
settings_panel_width_override: Option<i32>,
|
|
147
|
+
|
|
148
|
+
/// Value-semantic state snapshots (Step 4 scaffold).
|
|
149
|
+
/// Populated by `UpdateSession` / `UpdateRenderer` / `UpdatePresentation` /
|
|
150
|
+
/// `UpdateDragDrop` messages dispatched from async engine tasks.
|
|
151
|
+
session_props: SessionProps,
|
|
152
|
+
renderer_props: RendererProps,
|
|
153
|
+
presentation_props: PresentationProps,
|
|
154
|
+
dragdrop_props: DragDropProps,
|
|
155
|
+
|
|
156
|
+
/// Counts in-flight renders (incremented on `view_config_changed`,
|
|
157
|
+
/// decremented on `view_created`). Threaded to `StatusIndicator`.
|
|
158
|
+
update_count: u32,
|
|
92
159
|
}
|
|
93
160
|
|
|
94
161
|
impl Component for PerspectiveViewer {
|
|
@@ -98,36 +165,38 @@ impl Component for PerspectiveViewer {
|
|
|
98
165
|
fn create(ctx: &Context<Self>) -> Self {
|
|
99
166
|
let elem = ctx.props().elem.clone();
|
|
100
167
|
let fonts = FontLoaderProps::new(&elem, ctx.link().callback(|()| PreloadFontsUpdate));
|
|
168
|
+
inject_engine_callbacks(ctx);
|
|
169
|
+
let subscriptions = create_subscriptions(ctx);
|
|
170
|
+
let session_props = ctx.props().session.to_props();
|
|
171
|
+
let renderer_props = ctx.props().renderer.to_props(None);
|
|
172
|
+
let presentation_props = ctx.props().presentation.to_props(PtrEqRc::new(vec![]));
|
|
101
173
|
|
|
102
|
-
|
|
103
|
-
let props = ctx.props().clone();
|
|
104
|
-
let callback = ctx.link().batch_callback(move |(update, _)| {
|
|
105
|
-
if update {
|
|
106
|
-
vec![]
|
|
107
|
-
} else {
|
|
108
|
-
let locator = props.get_current_column_locator();
|
|
109
|
-
vec![OpenColumnSettings {
|
|
110
|
-
locator,
|
|
111
|
-
sender: None,
|
|
112
|
-
toggle: false,
|
|
113
|
-
}]
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
ctx.props()
|
|
118
|
-
.renderer
|
|
119
|
-
.render_limits_changed
|
|
120
|
-
.add_listener(callback)
|
|
121
|
-
};
|
|
122
|
-
|
|
174
|
+
// Memoized callback for column settings drawer
|
|
123
175
|
let on_close_column_settings = ctx.link().callback(|_| OpenColumnSettings {
|
|
124
176
|
locator: None,
|
|
125
177
|
sender: None,
|
|
126
178
|
toggle: false,
|
|
127
179
|
});
|
|
128
180
|
|
|
181
|
+
// Kick off an initial async theme fetch so that `available_themes` is
|
|
182
|
+
// populated even if `theme_config_updated` fires before the PubSub
|
|
183
|
+
// subscription is registered.
|
|
184
|
+
{
|
|
185
|
+
let presentation = ctx.props().presentation.clone();
|
|
186
|
+
let cb = ctx.link().callback(move |themes: PtrEqRc<Vec<String>>| {
|
|
187
|
+
UpdatePresentation(Box::new(presentation.to_props(themes)))
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
let presentation = ctx.props().presentation.clone();
|
|
191
|
+
ApiFuture::spawn(async move {
|
|
192
|
+
let themes = presentation.get_available_themes().await?;
|
|
193
|
+
cb.emit(themes);
|
|
194
|
+
Ok(())
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
129
198
|
Self {
|
|
130
|
-
_subscriptions:
|
|
199
|
+
_subscriptions: subscriptions,
|
|
131
200
|
column_settings_panel_width_override: None,
|
|
132
201
|
debug_open: false,
|
|
133
202
|
fonts,
|
|
@@ -136,6 +205,11 @@ impl Component for PerspectiveViewer {
|
|
|
136
205
|
on_resize: Default::default(),
|
|
137
206
|
settings_open: false,
|
|
138
207
|
settings_panel_width_override: None,
|
|
208
|
+
session_props,
|
|
209
|
+
renderer_props,
|
|
210
|
+
presentation_props,
|
|
211
|
+
dragdrop_props: DragDropProps::default(),
|
|
212
|
+
update_count: 0,
|
|
139
213
|
}
|
|
140
214
|
}
|
|
141
215
|
|
|
@@ -220,7 +294,6 @@ impl Component for PerspectiveViewer {
|
|
|
220
294
|
ToggleSettingsComplete(_, resolve)
|
|
221
295
|
if matches!(self.fonts.get_status(), FontLoaderStatus::Finished) =>
|
|
222
296
|
{
|
|
223
|
-
ctx.props().presentation.set_open_column_settings(None);
|
|
224
297
|
if let Err(e) = resolve.send(()) {
|
|
225
298
|
tracing::error!("toggle settings failed {:?}", e);
|
|
226
299
|
}
|
|
@@ -250,7 +323,7 @@ impl Component for PerspectiveViewer {
|
|
|
250
323
|
} else {
|
|
251
324
|
locator.as_ref().and_then(|x| {
|
|
252
325
|
x.name().map(|x| {
|
|
253
|
-
if
|
|
326
|
+
if self.session_props.is_column_active(x) {
|
|
254
327
|
ColumnSettingsTab::Style
|
|
255
328
|
} else {
|
|
256
329
|
ColumnSettingsTab::Attributes
|
|
@@ -303,6 +376,56 @@ impl Component for PerspectiveViewer {
|
|
|
303
376
|
|
|
304
377
|
true
|
|
305
378
|
},
|
|
379
|
+
UpdateSession(props) => {
|
|
380
|
+
let changed = *props != self.session_props;
|
|
381
|
+
self.session_props = *props;
|
|
382
|
+
changed
|
|
383
|
+
},
|
|
384
|
+
UpdateSessionStats(stats, has_table) => {
|
|
385
|
+
let changed =
|
|
386
|
+
stats != self.session_props.stats || has_table != self.session_props.has_table;
|
|
387
|
+
self.session_props.stats = stats;
|
|
388
|
+
self.session_props.has_table = has_table;
|
|
389
|
+
changed
|
|
390
|
+
},
|
|
391
|
+
UpdateRenderer(props) => {
|
|
392
|
+
let changed = *props != self.renderer_props;
|
|
393
|
+
self.renderer_props = *props;
|
|
394
|
+
changed
|
|
395
|
+
},
|
|
396
|
+
UpdatePresentation(props) => {
|
|
397
|
+
let changed = *props != self.presentation_props;
|
|
398
|
+
self.presentation_props = *props;
|
|
399
|
+
changed
|
|
400
|
+
},
|
|
401
|
+
UpdateSettingsOpen(open) => {
|
|
402
|
+
let changed = open != self.presentation_props.is_settings_open;
|
|
403
|
+
self.presentation_props.is_settings_open = open;
|
|
404
|
+
changed
|
|
405
|
+
},
|
|
406
|
+
UpdateIsWorkspace(is_workspace) => {
|
|
407
|
+
let changed = is_workspace != self.presentation_props.is_workspace;
|
|
408
|
+
self.presentation_props.is_workspace = is_workspace;
|
|
409
|
+
changed
|
|
410
|
+
},
|
|
411
|
+
UpdateColumnSettings(ocs) => {
|
|
412
|
+
let changed = *ocs != self.presentation_props.open_column_settings;
|
|
413
|
+
self.presentation_props.open_column_settings = *ocs;
|
|
414
|
+
changed
|
|
415
|
+
},
|
|
416
|
+
UpdateDragDrop(props) => {
|
|
417
|
+
let changed = *props != self.dragdrop_props;
|
|
418
|
+
self.dragdrop_props = *props;
|
|
419
|
+
changed
|
|
420
|
+
},
|
|
421
|
+
IncrementUpdateCount => {
|
|
422
|
+
self.update_count = self.update_count.saturating_add(1);
|
|
423
|
+
true
|
|
424
|
+
},
|
|
425
|
+
DecrementUpdateCount => {
|
|
426
|
+
self.update_count = self.update_count.saturating_sub(1);
|
|
427
|
+
true
|
|
428
|
+
},
|
|
306
429
|
}
|
|
307
430
|
}
|
|
308
431
|
|
|
@@ -334,13 +457,15 @@ impl Component for PerspectiveViewer {
|
|
|
334
457
|
..
|
|
335
458
|
} = ctx.props();
|
|
336
459
|
|
|
337
|
-
let is_settings_open = self.settings_open
|
|
460
|
+
let is_settings_open = self.settings_open
|
|
461
|
+
&& matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
|
|
462
|
+
|
|
338
463
|
let mut class = classes!();
|
|
339
464
|
if !is_settings_open {
|
|
340
465
|
class.push("settings-closed");
|
|
341
466
|
}
|
|
342
467
|
|
|
343
|
-
if
|
|
468
|
+
if self.session_props.title.is_some() {
|
|
344
469
|
class.push("titled");
|
|
345
470
|
}
|
|
346
471
|
|
|
@@ -360,8 +485,28 @@ impl Component for PerspectiveViewer {
|
|
|
360
485
|
|
|
361
486
|
let on_close_settings = ctx.link().callback(|()| ToggleSettingsInit(None, None));
|
|
362
487
|
let on_debug = ctx.link().callback(|_| ToggleDebug);
|
|
363
|
-
let selected_column =
|
|
364
|
-
|
|
488
|
+
let selected_column = get_current_column_locator(
|
|
489
|
+
&self.presentation_props.open_column_settings,
|
|
490
|
+
&ctx.props().renderer,
|
|
491
|
+
&self.session_props.config,
|
|
492
|
+
&self.session_props.metadata,
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
let selected_tab = self.presentation_props.open_column_settings.tab;
|
|
496
|
+
let plugin_name = self.renderer_props.plugin_name.clone();
|
|
497
|
+
let available_plugins = self.renderer_props.available_plugins.clone();
|
|
498
|
+
let has_table = self.session_props.has_table.clone();
|
|
499
|
+
let named_column_count = self
|
|
500
|
+
.renderer_props
|
|
501
|
+
.requirements
|
|
502
|
+
.names
|
|
503
|
+
.as_ref()
|
|
504
|
+
.map(|n| n.len())
|
|
505
|
+
.unwrap_or(0);
|
|
506
|
+
|
|
507
|
+
let view_config = self.session_props.config.clone();
|
|
508
|
+
let drag_column = self.dragdrop_props.column.clone();
|
|
509
|
+
let metadata = self.session_props.metadata.clone();
|
|
365
510
|
let settings_panel = html! {
|
|
366
511
|
if is_settings_open {
|
|
367
512
|
<SettingsPanel
|
|
@@ -370,6 +515,15 @@ impl Component for PerspectiveViewer {
|
|
|
370
515
|
on_select_column={on_open_expr_panel}
|
|
371
516
|
is_debug={self.debug_open}
|
|
372
517
|
{on_debug}
|
|
518
|
+
{plugin_name}
|
|
519
|
+
{available_plugins}
|
|
520
|
+
{has_table}
|
|
521
|
+
{named_column_count}
|
|
522
|
+
{view_config}
|
|
523
|
+
{drag_column}
|
|
524
|
+
metadata={metadata.clone()}
|
|
525
|
+
open_column_settings={self.presentation_props.open_column_settings.clone()}
|
|
526
|
+
selected_theme={self.presentation_props.selected_theme.clone()}
|
|
373
527
|
{dragdrop}
|
|
374
528
|
{presentation}
|
|
375
529
|
{renderer}
|
|
@@ -395,6 +549,10 @@ impl Component for PerspectiveViewer {
|
|
|
395
549
|
on_close={self.on_close_column_settings.clone()}
|
|
396
550
|
width_override={self.column_settings_panel_width_override}
|
|
397
551
|
{on_select_tab}
|
|
552
|
+
plugin_name={self.renderer_props.plugin_name.clone()}
|
|
553
|
+
{metadata}
|
|
554
|
+
view_config={self.session_props.config.clone()}
|
|
555
|
+
selected_theme={self.presentation_props.selected_theme.clone()}
|
|
398
556
|
{custom_events}
|
|
399
557
|
{presentation}
|
|
400
558
|
{renderer}
|
|
@@ -405,8 +563,38 @@ impl Component for PerspectiveViewer {
|
|
|
405
563
|
}
|
|
406
564
|
};
|
|
407
565
|
|
|
566
|
+
let on_reset = ctx.link().callback(|all| Reset(all, None));
|
|
567
|
+
let render_limits = self.renderer_props.render_limits;
|
|
568
|
+
let has_table = self.session_props.has_table.clone();
|
|
569
|
+
let is_errored = self.session_props.error.is_some();
|
|
570
|
+
let stats = self.session_props.stats.clone();
|
|
571
|
+
let update_count = self.update_count;
|
|
572
|
+
let error = self.session_props.error.clone();
|
|
573
|
+
let is_settings_open = self.settings_open
|
|
574
|
+
&& matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
|
|
575
|
+
let title = self.session_props.title.clone();
|
|
576
|
+
let selected_theme = self.presentation_props.selected_theme.clone();
|
|
577
|
+
let available_themes = self.presentation_props.available_themes.clone();
|
|
408
578
|
let main_panel = html! {
|
|
409
|
-
<MainPanel
|
|
579
|
+
<MainPanel
|
|
580
|
+
{on_settings}
|
|
581
|
+
{on_reset}
|
|
582
|
+
{render_limits}
|
|
583
|
+
{has_table}
|
|
584
|
+
{is_errored}
|
|
585
|
+
{stats}
|
|
586
|
+
{update_count}
|
|
587
|
+
{error}
|
|
588
|
+
{is_settings_open}
|
|
589
|
+
{title}
|
|
590
|
+
{selected_theme}
|
|
591
|
+
{available_themes}
|
|
592
|
+
is_workspace={self.presentation_props.is_workspace}
|
|
593
|
+
{custom_events}
|
|
594
|
+
{presentation}
|
|
595
|
+
{renderer}
|
|
596
|
+
{session}
|
|
597
|
+
/>
|
|
410
598
|
};
|
|
411
599
|
|
|
412
600
|
let debug_panel = html! {
|
|
@@ -523,3 +711,166 @@ impl PerspectiveViewer {
|
|
|
523
711
|
};
|
|
524
712
|
}
|
|
525
713
|
}
|
|
714
|
+
|
|
715
|
+
/// Subscribe to PubSub events that still have non-root subscribers and
|
|
716
|
+
/// therefore cannot yet be replaced with direct callbacks.
|
|
717
|
+
fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
|
|
718
|
+
let session_props_sub = {
|
|
719
|
+
let session = ctx.props().session.clone();
|
|
720
|
+
let cb = ctx
|
|
721
|
+
.link()
|
|
722
|
+
.callback(move |_: ()| UpdateSession(Box::new(session.to_props())));
|
|
723
|
+
|
|
724
|
+
let s = &ctx.props().session;
|
|
725
|
+
let sub1 = s.table_loaded.add_notify_listener(&cb);
|
|
726
|
+
let sub2 = s.table_unloaded.add_notify_listener(&cb);
|
|
727
|
+
let sub3 = s.view_created.add_notify_listener(&cb);
|
|
728
|
+
let sub4 = s.view_config_changed.add_notify_listener(&cb);
|
|
729
|
+
let sub5 = s.title_changed.add_notify_listener(&cb);
|
|
730
|
+
let sub6 = s
|
|
731
|
+
.view_config_changed
|
|
732
|
+
.add_listener(ctx.link().callback(|_| IncrementUpdateCount));
|
|
733
|
+
|
|
734
|
+
let sub7 = s
|
|
735
|
+
.view_created
|
|
736
|
+
.add_listener(ctx.link().callback(|_| DecrementUpdateCount));
|
|
737
|
+
|
|
738
|
+
vec![sub1, sub2, sub3, sub4, sub5, sub6, sub7]
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
let renderer_props_sub = {
|
|
742
|
+
let renderer = ctx.props().renderer.clone();
|
|
743
|
+
let cb_plugin = ctx.link().callback({
|
|
744
|
+
move |_: JsPerspectiveViewerPlugin| UpdateRenderer(Box::new(renderer.to_props(None)))
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
let sub1 = ctx.props().renderer.plugin_changed.add_listener(cb_plugin);
|
|
748
|
+
vec![sub1]
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
let presentation_props_sub = {
|
|
752
|
+
let presentation = ctx.props().presentation.clone();
|
|
753
|
+
let cb_settings = ctx.link().callback(UpdateSettingsOpen);
|
|
754
|
+
let cb_theme = {
|
|
755
|
+
let pres = presentation.clone();
|
|
756
|
+
ctx.link()
|
|
757
|
+
.callback(move |(themes, _): (PtrEqRc<Vec<String>>, _)| {
|
|
758
|
+
UpdatePresentation(Box::new(pres.to_props(themes)))
|
|
759
|
+
})
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
let cb_column_settings = {
|
|
763
|
+
let pres = presentation.clone();
|
|
764
|
+
ctx.link().callback(move |_: (bool, Option<String>)| {
|
|
765
|
+
UpdateColumnSettings(Box::new(pres.get_open_column_settings()))
|
|
766
|
+
})
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
let sub1 = presentation.settings_open_changed.add_listener(cb_settings);
|
|
770
|
+
let sub2 = presentation.theme_config_updated.add_listener(cb_theme);
|
|
771
|
+
let sub3 = presentation
|
|
772
|
+
.column_settings_open_changed
|
|
773
|
+
.add_listener(cb_column_settings);
|
|
774
|
+
|
|
775
|
+
vec![sub1, sub2, sub3]
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
let dragdrop_props_sub = {
|
|
779
|
+
let cb_clear = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
|
|
780
|
+
let sub1 = ctx
|
|
781
|
+
.props()
|
|
782
|
+
.dragdrop
|
|
783
|
+
.drop_received
|
|
784
|
+
.add_notify_listener(&cb_clear);
|
|
785
|
+
|
|
786
|
+
vec![sub1]
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
let mut subscriptions = Vec::new();
|
|
790
|
+
subscriptions.extend(session_props_sub);
|
|
791
|
+
subscriptions.extend(renderer_props_sub);
|
|
792
|
+
subscriptions.extend(presentation_props_sub);
|
|
793
|
+
subscriptions.extend(dragdrop_props_sub);
|
|
794
|
+
subscriptions
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/// Inject direct callbacks into the engine handles, replacing PubSub fields
|
|
798
|
+
/// that were exclusively consumed by the root component.
|
|
799
|
+
fn inject_engine_callbacks(ctx: &Context<PerspectiveViewer>) {
|
|
800
|
+
// Session: on_stats_changed
|
|
801
|
+
{
|
|
802
|
+
let session = ctx.props().session.clone();
|
|
803
|
+
let cb = ctx.link().callback(move |_: ()| {
|
|
804
|
+
UpdateSessionStats(session.get_table_stats(), session.has_table())
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
*ctx.props().session.on_stats_changed.borrow_mut() = Some(cb);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Session: on_table_errored
|
|
811
|
+
{
|
|
812
|
+
let session = ctx.props().session.clone();
|
|
813
|
+
let cb = ctx
|
|
814
|
+
.link()
|
|
815
|
+
.callback(move |_: ()| UpdateSession(Box::new(session.to_props())));
|
|
816
|
+
|
|
817
|
+
*ctx.props().session.on_table_errored.borrow_mut() = Some(cb);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Renderer: on_render_limits_changed (combines UpdateRenderer + column
|
|
821
|
+
// locator recheck that were previously two separate PubSub subscriptions).
|
|
822
|
+
{
|
|
823
|
+
clone!(
|
|
824
|
+
ctx.props().presentation,
|
|
825
|
+
ctx.props().renderer,
|
|
826
|
+
ctx.props().session
|
|
827
|
+
);
|
|
828
|
+
|
|
829
|
+
let cb = ctx.link().batch_callback(move |limits: RenderLimits| {
|
|
830
|
+
let mut msgs = vec![UpdateRenderer(Box::new(renderer.to_props(Some(limits))))];
|
|
831
|
+
if !limits.is_update {
|
|
832
|
+
let locator = get_current_column_locator(
|
|
833
|
+
&presentation.get_open_column_settings(),
|
|
834
|
+
&renderer,
|
|
835
|
+
&session.get_view_config(),
|
|
836
|
+
&session.metadata(),
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
msgs.push(OpenColumnSettings {
|
|
840
|
+
locator,
|
|
841
|
+
sender: None,
|
|
842
|
+
toggle: false,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
msgs
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
*ctx.props().renderer.on_render_limits_changed.borrow_mut() = Some(cb);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// Presentation: on_is_workspace_changed
|
|
853
|
+
{
|
|
854
|
+
let cb = ctx.link().callback(UpdateIsWorkspace);
|
|
855
|
+
*ctx.props()
|
|
856
|
+
.presentation
|
|
857
|
+
.on_is_workspace_changed
|
|
858
|
+
.borrow_mut() = Some(cb);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// DragDrop: on_dragstart
|
|
862
|
+
{
|
|
863
|
+
let dragdrop = ctx.props().dragdrop.clone();
|
|
864
|
+
let cb = ctx
|
|
865
|
+
.link()
|
|
866
|
+
.callback(move |_: DragEffect| UpdateDragDrop(Box::new(dragdrop.to_props())));
|
|
867
|
+
|
|
868
|
+
*ctx.props().dragdrop.on_dragstart.borrow_mut() = Some(cb);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// DragDrop: on_dragend
|
|
872
|
+
{
|
|
873
|
+
let cb = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
|
|
874
|
+
*ctx.props().dragdrop.on_dragend.borrow_mut() = Some(cb);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
@@ -29,6 +29,9 @@ pub enum NumberForegroundMode {
|
|
|
29
29
|
|
|
30
30
|
#[serde(rename = "bar")]
|
|
31
31
|
Bar,
|
|
32
|
+
|
|
33
|
+
#[serde(rename = "label-bar")]
|
|
34
|
+
LabelBar,
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
impl FromStr for NumberForegroundMode {
|
|
@@ -38,6 +41,7 @@ impl FromStr for NumberForegroundMode {
|
|
|
38
41
|
match s {
|
|
39
42
|
"color" => Ok(Self::Color),
|
|
40
43
|
"bar" => Ok(Self::Bar),
|
|
44
|
+
"label-bar" => Ok(Self::LabelBar),
|
|
41
45
|
x => Err(format!("Unknown NumberForegroundMode::{x}")),
|
|
42
46
|
}
|
|
43
47
|
}
|
|
@@ -53,7 +57,7 @@ impl NumberForegroundMode {
|
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
pub fn needs_gradient(&self) -> bool {
|
|
56
|
-
*self == Self::Bar
|
|
60
|
+
*self == Self::Bar || *self == Self::LabelBar
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -26,9 +26,9 @@ use crate::presentation::ColumnConfigMap;
|
|
|
26
26
|
|
|
27
27
|
/// The state of an entire `custom_elements::PerspectiveViewerElement` component
|
|
28
28
|
/// and its `Plugin`.
|
|
29
|
-
#[derive(Debug, Default, Serialize, PartialEq)]
|
|
29
|
+
#[derive(Debug, Default, Serialize, PartialEq, TS)]
|
|
30
30
|
#[serde(deny_unknown_fields)]
|
|
31
|
-
pub struct ViewerConfig<V = String> {
|
|
31
|
+
pub struct ViewerConfig<V: TS = String> {
|
|
32
32
|
pub version: V,
|
|
33
33
|
pub columns_config: ColumnConfigMap,
|
|
34
34
|
pub plugin: String,
|