@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
|
@@ -10,249 +10,206 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
//! Wire engine PubSub fanout to JavaScript `CustomEvent` dispatch on the host
|
|
14
|
+
//! element. [`wire_custom_events`] is the single subscription site; every
|
|
15
|
+
//! `perspective-*` `CustomEvent` originates from a PubSub fire on `Session`,
|
|
16
|
+
//! `Renderer`, or `Presentation`.
|
|
16
17
|
|
|
17
18
|
use perspective_client::{ViewWindow, clone};
|
|
18
19
|
use perspective_js::json;
|
|
20
|
+
use perspective_js::utils::{ApiResult, JsValueSerdeExt};
|
|
19
21
|
use wasm_bindgen::prelude::*;
|
|
20
22
|
use web_sys::*;
|
|
21
|
-
use yew::html::ImplicitClone;
|
|
22
23
|
|
|
23
|
-
use crate::config::*;
|
|
24
24
|
use crate::js::JsPerspectiveViewerPlugin;
|
|
25
25
|
use crate::presentation::Presentation;
|
|
26
|
-
use crate::
|
|
26
|
+
use crate::queries::get_viewer_config;
|
|
27
|
+
use crate::renderer::{ColumnConfigMap, Renderer};
|
|
27
28
|
use crate::session::Session;
|
|
28
|
-
use crate::
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
impl PartialEq for CustomEvents {
|
|
42
|
-
fn eq(&self, other: &Self) -> bool {
|
|
43
|
-
Rc::ptr_eq(&self.0, &other.0)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
#[derive(Clone)]
|
|
48
|
-
struct CustomEventsDataRc(Rc<CustomEventsData>);
|
|
49
|
-
|
|
50
|
-
impl Deref for CustomEventsDataRc {
|
|
51
|
-
type Target = CustomEventsData;
|
|
52
|
-
|
|
53
|
-
fn deref(&self) -> &CustomEventsData {
|
|
54
|
-
&self.0
|
|
55
|
-
}
|
|
29
|
+
use crate::utils::{AddListener, Subscription};
|
|
30
|
+
|
|
31
|
+
/// Dispatch a JS `CustomEvent` named `perspective-{name}` on `elem`.
|
|
32
|
+
fn dispatch_event<T: Into<JsValue>>(elem: &HtmlElement, name: &str, event: T) -> ApiResult<()> {
|
|
33
|
+
let event_init = web_sys::CustomEventInit::new();
|
|
34
|
+
event_init.set_detail(&event.into());
|
|
35
|
+
let event = web_sys::CustomEvent::new_with_event_init_dict(
|
|
36
|
+
format!("perspective-{}", name).as_str(),
|
|
37
|
+
&event_init,
|
|
38
|
+
)?;
|
|
39
|
+
|
|
40
|
+
elem.dispatch_event(&event)?;
|
|
41
|
+
Ok(())
|
|
56
42
|
}
|
|
57
43
|
|
|
58
|
-
|
|
59
|
-
elem: HtmlElement,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
fn dispatch_column_settings_open_changed(
|
|
45
|
+
elem: &HtmlElement,
|
|
46
|
+
open: bool,
|
|
47
|
+
column_name: Option<String>,
|
|
48
|
+
) {
|
|
49
|
+
let event_init = web_sys::CustomEventInit::new();
|
|
50
|
+
event_init.set_detail(&JsValue::from(
|
|
51
|
+
json!({"open": open, "column_name": column_name}),
|
|
52
|
+
));
|
|
53
|
+
let event = web_sys::CustomEvent::new_with_event_init_dict(
|
|
54
|
+
"perspective-toggle-column-settings",
|
|
55
|
+
&event_init,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
elem.dispatch_event(&event.unwrap()).unwrap();
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
impl HasRenderer for CustomEventsData {
|
|
73
|
-
fn renderer(&self) -> &Renderer {
|
|
74
|
-
&self.renderer
|
|
75
|
-
}
|
|
76
|
-
}
|
|
61
|
+
fn dispatch_plugin_changed(elem: &HtmlElement, plugin: &JsPerspectiveViewerPlugin) {
|
|
62
|
+
let event_init = web_sys::CustomEventInit::new();
|
|
63
|
+
event_init.set_detail(plugin);
|
|
64
|
+
let event =
|
|
65
|
+
web_sys::CustomEvent::new_with_event_init_dict("perspective-plugin-update", &event_init);
|
|
77
66
|
|
|
78
|
-
|
|
79
|
-
fn session(&self) -> &Session {
|
|
80
|
-
&self.session
|
|
81
|
-
}
|
|
67
|
+
elem.dispatch_event(&event.unwrap()).unwrap();
|
|
82
68
|
}
|
|
83
69
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
clone!(data);
|
|
114
|
-
move |open: bool| {
|
|
115
|
-
data.dispatch_event("toggle-settings-before", open).unwrap();
|
|
116
|
-
// data.clone().dispatch_config_update();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
let column_settings_sub = presentation.column_settings_open_changed.add_listener({
|
|
121
|
-
clone!(data);
|
|
122
|
-
move |(open, column_name)| {
|
|
123
|
-
data.dispatch_column_settings_open_changed(open, column_name);
|
|
124
|
-
// column_settings is ethereal; do not change the config
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
let plugin_sub = renderer.plugin_changed.add_listener({
|
|
129
|
-
clone!(data);
|
|
130
|
-
move |plugin| {
|
|
131
|
-
data.dispatch_plugin_changed(&plugin);
|
|
132
|
-
data.clone().dispatch_config_update();
|
|
133
|
-
}
|
|
134
|
-
});
|
|
70
|
+
/// Per-element memoized config-change dispatcher. Reads/writes the dedup
|
|
71
|
+
/// cell on `presentation.last_dispatched_config` so each viewer instance
|
|
72
|
+
/// has its own cache — without this, a second viewer reloading the same
|
|
73
|
+
/// table the first viewer used would have its initial `config-update`
|
|
74
|
+
/// suppressed.
|
|
75
|
+
fn dispatch_config_update(
|
|
76
|
+
elem: &HtmlElement,
|
|
77
|
+
session: &Session,
|
|
78
|
+
renderer: &Renderer,
|
|
79
|
+
presentation: &Presentation,
|
|
80
|
+
) {
|
|
81
|
+
clone!(session, renderer, presentation);
|
|
82
|
+
let elem = elem.clone();
|
|
83
|
+
perspective_js::utils::ApiFuture::spawn(async move {
|
|
84
|
+
let viewer_config = get_viewer_config(&session, &renderer, &presentation).await?;
|
|
85
|
+
if viewer_config.view_config != Default::default()
|
|
86
|
+
&& Some(&viewer_config) != presentation.last_dispatched_config.borrow().as_ref()
|
|
87
|
+
{
|
|
88
|
+
let json_config = JsValue::from_serde_ext(&viewer_config)?;
|
|
89
|
+
let event_init = web_sys::CustomEventInit::new();
|
|
90
|
+
event_init.set_detail(&json_config);
|
|
91
|
+
let event = web_sys::CustomEvent::new_with_event_init_dict(
|
|
92
|
+
"perspective-config-update",
|
|
93
|
+
&event_init,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
*presentation.last_dispatched_config.borrow_mut() = Some(viewer_config);
|
|
97
|
+
elem.dispatch_event(&event.unwrap()).unwrap();
|
|
98
|
+
}
|
|
135
99
|
|
|
136
|
-
let view_sub = session.view_created.add_listener({
|
|
137
|
-
clone!(data);
|
|
138
|
-
move |_| data.clone().dispatch_config_update()
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
let title_sub = session.title_changed.add_listener({
|
|
142
|
-
clone!(data);
|
|
143
|
-
move |_| data.clone().dispatch_config_update()
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
let unload_sub = session.table_unloaded.add_listener({
|
|
147
|
-
clone!(data);
|
|
148
|
-
move |x: bool| {
|
|
149
|
-
if !x {
|
|
150
|
-
data.clone()
|
|
151
|
-
.dispatch_event("table-delete-before", JsValue::UNDEFINED)
|
|
152
|
-
.unwrap();
|
|
153
|
-
} else {
|
|
154
|
-
data.clone()
|
|
155
|
-
.dispatch_event("table-delete", JsValue::UNDEFINED)
|
|
156
|
-
.unwrap()
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
Self(Rc::new((data, [
|
|
162
|
-
theme_sub,
|
|
163
|
-
before_settings_sub,
|
|
164
|
-
settings_sub,
|
|
165
|
-
column_settings_sub,
|
|
166
|
-
plugin_sub,
|
|
167
|
-
view_sub,
|
|
168
|
-
title_sub,
|
|
169
|
-
unload_sub,
|
|
170
|
-
])))
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
pub fn dispatch_column_style_changed(&self, config: &JsValue) -> ApiResult<()> {
|
|
174
|
-
self.dispatch_event("column-style-change", config)?;
|
|
175
|
-
self.0.0.clone().dispatch_config_update();
|
|
176
100
|
Ok(())
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
pub fn dispatch_select(&self, view_window: Option<&ViewWindow>) -> ApiResult<()> {
|
|
180
|
-
self.dispatch_event("select", &serde_wasm_bindgen::to_value(&view_window)?)?;
|
|
181
|
-
self.0.0.clone().dispatch_config_update();
|
|
182
|
-
Ok(())
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
pub fn dispatch_event<T>(&self, name: &str, event: T) -> ApiResult<()>
|
|
186
|
-
where
|
|
187
|
-
T: Into<JsValue>,
|
|
188
|
-
{
|
|
189
|
-
self.0.0.dispatch_event(name, event)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
pub fn dispatch_raw_event(&self, event: &web_sys::CustomEvent) -> ApiResult<bool> {
|
|
193
|
-
self.0.0.elem.dispatch_event(event).map_err(|e| e.into())
|
|
194
|
-
}
|
|
101
|
+
});
|
|
195
102
|
}
|
|
196
103
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
104
|
+
/// Wire PubSub channels on `session`, `renderer`, and `presentation` to the
|
|
105
|
+
/// `perspective-*` `CustomEvent` set on `elem`. The returned
|
|
106
|
+
/// `Vec<Subscription>` must be kept alive for the lifetime of the element;
|
|
107
|
+
/// dropping it detaches all listeners.
|
|
108
|
+
pub fn wire_custom_events(
|
|
109
|
+
elem: &HtmlElement,
|
|
110
|
+
session: &Session,
|
|
111
|
+
renderer: &Renderer,
|
|
112
|
+
presentation: &Presentation,
|
|
113
|
+
) -> Vec<Subscription> {
|
|
114
|
+
let theme_sub = presentation.theme_config_updated.add_listener({
|
|
115
|
+
clone!(elem, session, renderer, presentation);
|
|
116
|
+
move |_| dispatch_config_update(&elem, &session, &renderer, &presentation)
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
let settings_sub = presentation.settings_open_changed.add_listener({
|
|
120
|
+
clone!(elem, session, renderer, presentation);
|
|
121
|
+
move |open: bool| {
|
|
122
|
+
dispatch_event(&elem, "toggle-settings", open).unwrap();
|
|
123
|
+
dispatch_config_update(&elem, &session, &renderer, &presentation);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
let before_settings_sub = presentation.settings_before_open_changed.add_listener({
|
|
128
|
+
clone!(elem);
|
|
129
|
+
move |open: bool| {
|
|
130
|
+
dispatch_event(&elem, "toggle-settings-before", open).unwrap();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
let column_settings_sub = presentation.column_settings_open_changed.add_listener({
|
|
135
|
+
clone!(elem);
|
|
136
|
+
move |(open, column_name)| {
|
|
137
|
+
dispatch_column_settings_open_changed(&elem, open, column_name);
|
|
138
|
+
// column_settings is ethereal; do not change the config
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
let plugin_sub = renderer.plugin_changed.add_listener({
|
|
143
|
+
clone!(elem, session, renderer, presentation);
|
|
144
|
+
move |plugin| {
|
|
145
|
+
dispatch_plugin_changed(&elem, &plugin);
|
|
146
|
+
dispatch_config_update(&elem, &session, &renderer, &presentation);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
let view_sub = session.view_created.add_listener({
|
|
151
|
+
clone!(elem, session, renderer, presentation);
|
|
152
|
+
move |_| dispatch_config_update(&elem, &session, &renderer, &presentation)
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
let title_sub = session.title_changed.add_listener({
|
|
156
|
+
clone!(elem, session, renderer, presentation);
|
|
157
|
+
move |_| dispatch_config_update(&elem, &session, &renderer, &presentation)
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
let unload_sub = session.table_unloaded.add_listener({
|
|
161
|
+
clone!(elem);
|
|
162
|
+
move |x: bool| {
|
|
163
|
+
if !x {
|
|
164
|
+
dispatch_event(&elem, "table-delete-before", JsValue::UNDEFINED).unwrap();
|
|
165
|
+
} else {
|
|
166
|
+
dispatch_event(&elem, "table-delete", JsValue::UNDEFINED).unwrap()
|
|
253
167
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
let select_sub = renderer.selection_changed.add_listener({
|
|
172
|
+
clone!(elem, session, renderer, presentation);
|
|
173
|
+
move |window: Option<ViewWindow>| {
|
|
174
|
+
let detail = JsValue::from_serde_ext(&window).unwrap();
|
|
175
|
+
dispatch_event(&elem, "select", &detail).unwrap();
|
|
176
|
+
dispatch_config_update(&elem, &session, &renderer, &presentation);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
let column_style_sub = renderer.column_style_changed.add_listener({
|
|
181
|
+
clone!(elem, session, renderer, presentation);
|
|
182
|
+
move |cfg: ColumnConfigMap| {
|
|
183
|
+
let detail = JsValue::from_serde_ext(&cfg).unwrap();
|
|
184
|
+
dispatch_event(&elem, "column-style-change", &detail).unwrap();
|
|
185
|
+
dispatch_config_update(&elem, &session, &renderer, &presentation);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
let status_click_sub = session.status_indicator_clicked.add_listener({
|
|
190
|
+
clone!(elem);
|
|
191
|
+
move |_| dispatch_event(&elem, "status-indicator-click", JsValue::UNDEFINED).unwrap()
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
let statusbar_ptr_sub = presentation.statusbar_pointer_event.add_listener({
|
|
195
|
+
clone!(elem);
|
|
196
|
+
move |event: PointerEvent| {
|
|
197
|
+
dispatch_event(&elem, &format!("statusbar-{}", event.type_()), &event).unwrap();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
vec![
|
|
202
|
+
theme_sub,
|
|
203
|
+
before_settings_sub,
|
|
204
|
+
settings_sub,
|
|
205
|
+
column_settings_sub,
|
|
206
|
+
plugin_sub,
|
|
207
|
+
view_sub,
|
|
208
|
+
title_sub,
|
|
209
|
+
unload_sub,
|
|
210
|
+
select_sub,
|
|
211
|
+
column_style_sub,
|
|
212
|
+
status_click_sub,
|
|
213
|
+
statusbar_ptr_sub,
|
|
214
|
+
]
|
|
258
215
|
}
|
package/src/rust/js/plugin.rs
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use
|
|
13
|
+
use perspective_js::JsViewWindow;
|
|
14
14
|
use perspective_js::utils::*;
|
|
15
|
-
use serde::*;
|
|
16
15
|
use wasm_bindgen::prelude::*;
|
|
17
16
|
|
|
18
|
-
use crate::
|
|
17
|
+
use crate::config::PluginStaticConfig;
|
|
18
|
+
use crate::renderer::ColumnConfigMap;
|
|
19
19
|
|
|
20
20
|
/// Perspective FFI
|
|
21
21
|
#[wasm_bindgen]
|
|
@@ -25,55 +25,31 @@ extern "C" {
|
|
|
25
25
|
#[derive(Clone)]
|
|
26
26
|
pub type JsPerspectiveViewer;
|
|
27
27
|
|
|
28
|
-
#[wasm_bindgen(method)]
|
|
29
|
-
pub fn get_model(this: &JsPerspectiveViewer) -> JsValue;
|
|
30
|
-
|
|
31
28
|
#[derive(Clone)]
|
|
32
29
|
pub type JsPerspectiveViewerPlugin;
|
|
33
30
|
|
|
34
|
-
#[
|
|
35
|
-
pub
|
|
36
|
-
|
|
37
|
-
#[wasm_bindgen(method, getter)]
|
|
38
|
-
pub fn category(this: &JsPerspectiveViewerPlugin) -> Option<String>;
|
|
39
|
-
|
|
40
|
-
#[wasm_bindgen(method, getter)]
|
|
41
|
-
pub fn max_columns(this: &JsPerspectiveViewerPlugin) -> Option<usize>;
|
|
42
|
-
|
|
43
|
-
#[wasm_bindgen(method, getter)]
|
|
44
|
-
pub fn max_cells(this: &JsPerspectiveViewerPlugin) -> Option<usize>;
|
|
45
|
-
|
|
46
|
-
// TODO This can be an internal property
|
|
47
|
-
#[wasm_bindgen(method, getter)]
|
|
48
|
-
pub fn render_warning(this: &JsPerspectiveViewerPlugin) -> Option<bool>;
|
|
49
|
-
|
|
50
|
-
#[wasm_bindgen(method, setter)]
|
|
51
|
-
pub fn set_render_warning(this: &JsPerspectiveViewerPlugin, val: bool);
|
|
52
|
-
|
|
53
|
-
#[wasm_bindgen(method, getter)]
|
|
54
|
-
pub fn select_mode(this: &JsPerspectiveViewerPlugin) -> JsValue;
|
|
55
|
-
|
|
56
|
-
#[wasm_bindgen(method, getter)]
|
|
57
|
-
pub fn min_config_columns(this: &JsPerspectiveViewerPlugin) -> Option<usize>;
|
|
58
|
-
|
|
59
|
-
#[wasm_bindgen(method, getter)]
|
|
60
|
-
pub fn config_column_names(this: &JsPerspectiveViewerPlugin) -> Option<js_sys::Array>;
|
|
61
|
-
|
|
62
|
-
#[wasm_bindgen(method, getter)]
|
|
63
|
-
pub fn priority(this: &JsPerspectiveViewerPlugin) -> Option<i32>;
|
|
64
|
-
|
|
65
|
-
#[wasm_bindgen(method, getter)]
|
|
66
|
-
pub fn group_rollups(this: &JsPerspectiveViewerPlugin) -> Option<js_sys::Array>;
|
|
31
|
+
#[derive(Clone)]
|
|
32
|
+
pub type JsPluginStaticConfig;
|
|
67
33
|
|
|
68
|
-
///
|
|
69
|
-
|
|
70
|
-
|
|
34
|
+
/// The static configuration of the plugin which defines the basic
|
|
35
|
+
/// integration with `perspective-viewer`. Called once per plugin at
|
|
36
|
+
/// registration time and cached — the result must be stable for
|
|
37
|
+
/// the lifetime of the application.
|
|
38
|
+
#[wasm_bindgen(method)]
|
|
39
|
+
pub fn get_static_config(this: &JsPerspectiveViewerPlugin) -> JsPluginStaticConfig;
|
|
71
40
|
|
|
72
|
-
|
|
73
|
-
|
|
41
|
+
/// Returns the per-column schema describing which controls to render
|
|
42
|
+
/// in the sidebar Style tab and the keys each control owns in the
|
|
43
|
+
/// column's persisted config map. `column_stats` carries cached
|
|
44
|
+
/// per-column numeric stats (currently `{ abs_max?: number }`);
|
|
45
|
+
/// fields are populated lazily and may be missing on the first
|
|
46
|
+
/// call — the view re-renders and re-queries the schema once the
|
|
47
|
+
/// async fetch resolves.
|
|
48
|
+
#[wasm_bindgen(method, catch, js_name = column_config_schema)]
|
|
49
|
+
pub fn _column_config_schema(this: &JsPerspectiveViewerPlugin, view_type: &str, group: Option<&str>, column_name: &str, current_value: &JsValue, view_config: &JsValue, column_stats: &JsValue) -> ApiResult<JsValue>;
|
|
74
50
|
|
|
75
|
-
#[wasm_bindgen(method, catch)]
|
|
76
|
-
pub fn
|
|
51
|
+
#[wasm_bindgen(method, catch, js_name = plugin_config_schema)]
|
|
52
|
+
pub fn _plugin_config_schema(this: &JsPerspectiveViewerPlugin, view_config: &JsValue) -> ApiResult<JsValue>;
|
|
77
53
|
|
|
78
54
|
#[wasm_bindgen(method, js_name=restore, catch)]
|
|
79
55
|
pub fn _restore(this: &JsPerspectiveViewerPlugin, token: &JsValue, columns_config: &JsValue) -> ApiResult<()>;
|
|
@@ -81,11 +57,17 @@ extern "C" {
|
|
|
81
57
|
#[wasm_bindgen(method)]
|
|
82
58
|
pub fn delete(this: &JsPerspectiveViewerPlugin);
|
|
83
59
|
|
|
60
|
+
#[wasm_bindgen(method)]
|
|
61
|
+
pub fn restyle(
|
|
62
|
+
this: &JsPerspectiveViewerPlugin,
|
|
63
|
+
);
|
|
64
|
+
|
|
84
65
|
#[wasm_bindgen(method, catch)]
|
|
85
|
-
pub async fn
|
|
66
|
+
pub async fn render(
|
|
86
67
|
this: &JsPerspectiveViewerPlugin,
|
|
87
|
-
view: perspective_js::View
|
|
88
|
-
|
|
68
|
+
view: perspective_js::View,
|
|
69
|
+
viewport: Option<JsViewWindow>,
|
|
70
|
+
) -> ApiResult<web_sys::Blob>;
|
|
89
71
|
|
|
90
72
|
#[wasm_bindgen(method, catch)]
|
|
91
73
|
pub async fn draw(
|
|
@@ -113,7 +95,21 @@ extern "C" {
|
|
|
113
95
|
|
|
114
96
|
}
|
|
115
97
|
|
|
98
|
+
impl From<JsPluginStaticConfig> for PluginStaticConfig {
|
|
99
|
+
fn from(value: JsPluginStaticConfig) -> Self {
|
|
100
|
+
value.into_serde_ext().expect("Invalid plugin config")
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
116
104
|
impl JsPerspectiveViewerPlugin {
|
|
105
|
+
/// Read and deserialize the plugin's static config. Should only
|
|
106
|
+
/// be called once per plugin (at registration time); cache the
|
|
107
|
+
/// result and read fields off the cached value rather than
|
|
108
|
+
/// reaching back through the FFI.
|
|
109
|
+
pub fn read_static_config(&self) -> PluginStaticConfig {
|
|
110
|
+
self.get_static_config().into()
|
|
111
|
+
}
|
|
112
|
+
|
|
117
113
|
pub fn restore(
|
|
118
114
|
&self,
|
|
119
115
|
token: &JsValue,
|
|
@@ -123,71 +119,3 @@ impl JsPerspectiveViewerPlugin {
|
|
|
123
119
|
self._restore(token, &columns_config)
|
|
124
120
|
}
|
|
125
121
|
}
|
|
126
|
-
|
|
127
|
-
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
|
|
128
|
-
#[serde(rename_all = "camelCase")]
|
|
129
|
-
pub enum ColumnSelectMode {
|
|
130
|
-
#[default]
|
|
131
|
-
Toggle,
|
|
132
|
-
Select,
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
impl ColumnSelectMode {
|
|
136
|
-
pub fn css(&self) -> yew::Classes {
|
|
137
|
-
match self {
|
|
138
|
-
Self::Toggle => yew::classes!("toggle-mode", "is_column_active"),
|
|
139
|
-
Self::Select => yew::classes!("select-mode", "is_column_active"),
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
#[derive(Clone, Debug, Default, PartialEq)]
|
|
145
|
-
pub struct ViewConfigRequirements {
|
|
146
|
-
pub min: Option<usize>,
|
|
147
|
-
pub names: Option<Vec<String>>,
|
|
148
|
-
pub mode: ColumnSelectMode,
|
|
149
|
-
pub max_columns: Option<usize>,
|
|
150
|
-
pub max_cells: Option<usize>,
|
|
151
|
-
pub name: String,
|
|
152
|
-
pub render_warning: bool,
|
|
153
|
-
group_rollups: Option<Vec<GroupRollupMode>>,
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
impl ViewConfigRequirements {
|
|
157
|
-
pub fn is_swap(&self, index: usize) -> bool {
|
|
158
|
-
self.names
|
|
159
|
-
.as_ref()
|
|
160
|
-
.map(|x| index < x.len() - 1)
|
|
161
|
-
.unwrap_or(false)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
pub fn get_group_rollups(&self, rollup_features: &[GroupRollupMode]) -> Vec<GroupRollupMode> {
|
|
165
|
-
self.group_rollups
|
|
166
|
-
.clone()
|
|
167
|
-
.map(|x| {
|
|
168
|
-
x.into_iter()
|
|
169
|
-
.filter(|y| rollup_features.is_empty() || rollup_features.contains(y))
|
|
170
|
-
.collect()
|
|
171
|
-
})
|
|
172
|
-
.unwrap_or_default()
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
impl JsPerspectiveViewerPlugin {
|
|
177
|
-
pub fn get_requirements(&self) -> ApiResult<ViewConfigRequirements> {
|
|
178
|
-
Ok(ViewConfigRequirements {
|
|
179
|
-
min: self.min_config_columns(),
|
|
180
|
-
mode: self.select_mode().into_serde_ext()?,
|
|
181
|
-
names: self
|
|
182
|
-
.config_column_names()
|
|
183
|
-
.map(|x| x.into_serde_ext().unwrap()),
|
|
184
|
-
max_columns: self.max_columns(),
|
|
185
|
-
max_cells: self.max_cells(),
|
|
186
|
-
name: self.name(),
|
|
187
|
-
render_warning: self.render_warning().unwrap_or(true),
|
|
188
|
-
group_rollups: self
|
|
189
|
-
.group_rollups()
|
|
190
|
-
.map(|x| x.into_serde_ext::<Vec<GroupRollupMode>>().unwrap()),
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
}
|