@perspective-dev/viewer 4.0.1 → 4.1.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/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/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 +23 -2
- package/dist/esm/perspective-viewer.d.ts +2 -7
- 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 +1 -1
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +1 -0
- package/dist/wasm/perspective-viewer.d.ts +218 -46
- package/dist/wasm/perspective-viewer.js +1242 -753
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +38 -19
- package/package.json +1 -1
- package/src/less/containers/scroll-panel.less +0 -1
- package/src/less/plugin-selector.less +15 -5
- package/src/less/status-bar.less +75 -27
- package/src/less/viewer.less +140 -58
- package/src/rust/components/column_dropdown.rs +21 -21
- package/src/rust/components/column_selector/active_column.rs +131 -120
- package/src/rust/components/column_selector/add_expression_button.rs +5 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +8 -4
- package/src/rust/components/column_selector/config_selector.rs +170 -161
- package/src/rust/components/column_selector/empty_column.rs +16 -11
- package/src/rust/components/column_selector/{expression_toolbar.rs → expr_edit_button.rs} +7 -0
- package/src/rust/components/column_selector/filter_column.rs +195 -194
- package/src/rust/components/column_selector/inactive_column.rs +82 -67
- package/src/rust/components/column_selector/pivot_column.rs +16 -11
- package/src/rust/components/column_selector/sort_column.rs +9 -7
- package/src/rust/components/column_selector.rs +42 -37
- package/src/rust/components/column_settings_sidebar/save_settings.rs +3 -1
- package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +58 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +6 -6
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +2 -94
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +111 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +3 -3
- package/src/rust/components/column_settings_sidebar/style_tab.rs +23 -83
- package/src/rust/components/{column_settings_sidebar/sidebar.rs → column_settings_sidebar.rs} +198 -171
- package/src/rust/components/containers/dragdrop_list.rs +20 -20
- package/src/rust/components/containers/dropdown_menu.rs +4 -6
- package/src/rust/components/containers/mod.rs +1 -4
- package/src/rust/components/containers/scroll_panel.rs +80 -80
- package/src/rust/components/containers/scroll_panel_item.rs +36 -36
- package/src/rust/components/containers/select.rs +46 -44
- package/src/rust/components/containers/sidebar.rs +3 -19
- package/src/rust/components/{column_settings_sidebar/style_tab/symbol/symbol_config.rs → containers/sidebar_close_button.rs} +15 -9
- package/src/rust/components/containers/split_panel.rs +212 -200
- package/src/rust/components/containers/tab_list.rs +11 -11
- package/src/rust/components/copy_dropdown.rs +22 -25
- package/src/rust/components/datetime_column_style/custom.rs +19 -19
- package/src/rust/components/datetime_column_style/simple.rs +13 -14
- package/src/rust/components/datetime_column_style.rs +75 -76
- package/src/rust/components/editable_header.rs +18 -14
- package/src/rust/components/empty_row.rs +5 -5
- package/src/rust/components/export_dropdown.rs +42 -42
- package/src/rust/components/expression_editor.rs +25 -19
- package/src/rust/components/filter_dropdown.rs +22 -22
- package/src/rust/components/font_loader.rs +11 -9
- package/src/rust/components/form/code_editor.rs +106 -105
- package/src/rust/components/form/color_range_selector.rs +14 -12
- package/src/rust/components/form/color_selector.rs +3 -1
- package/src/rust/components/form/debug.rs +95 -94
- package/src/rust/components/form/highlight.rs +5 -3
- package/src/rust/components/form/mod.rs +3 -2
- package/src/rust/components/form/optional_field.rs +2 -2
- package/src/rust/components/form/{select_field.rs → select_enum_field.rs} +1 -46
- package/src/rust/components/form/select_value_field.rs +64 -0
- package/src/rust/components/function_dropdown.rs +21 -21
- package/src/rust/components/main_panel.rs +219 -0
- package/src/rust/components/mod.rs +6 -6
- package/src/rust/components/modal.rs +42 -42
- package/src/rust/components/number_column_style.rs +34 -88
- package/src/rust/components/plugin_selector.rs +22 -25
- package/src/rust/components/render_warning.rs +9 -6
- package/src/rust/components/settings_panel.rs +82 -0
- package/src/rust/components/status_bar.rs +250 -146
- package/src/rust/components/status_bar_counter.rs +26 -119
- package/src/rust/components/status_indicator.rs +95 -79
- package/src/rust/components/string_column_style.rs +45 -45
- package/src/rust/components/style/style_provider.rs +1 -15
- package/src/rust/components/style_controls/number_string_format/digits_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format/misc_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format.rs +45 -46
- package/src/rust/components/type_icon.rs +14 -11
- package/src/rust/components/viewer.rs +241 -384
- package/src/rust/config/columns_config.rs +2 -2
- package/src/rust/config/datetime_column_style.rs +1 -6
- package/src/rust/config/mod.rs +1 -0
- package/src/rust/config/number_column_style.rs +0 -6
- package/src/rust/config/number_string_format.rs +27 -4
- package/src/rust/config/viewer_config.rs +27 -167
- package/src/rust/custom_elements/copy_dropdown.rs +14 -6
- package/src/rust/custom_elements/export_dropdown.rs +15 -7
- package/src/rust/custom_elements/filter_dropdown.rs +4 -4
- package/src/rust/custom_elements/mod.rs +3 -0
- package/src/rust/custom_elements/viewer.rs +367 -169
- package/src/rust/custom_events.rs +55 -32
- package/src/rust/dragdrop.rs +4 -24
- package/src/rust/exprtk/cursor.rs +10 -1
- package/src/rust/exprtk/mod.rs +2 -0
- package/src/rust/exprtk/tokenize.rs +20 -3
- package/src/rust/js/clipboard.rs +2 -2
- package/src/rust/js/mimetype.rs +2 -7
- package/src/rust/js/mod.rs +0 -1
- package/src/rust/js/plugin.rs +7 -0
- package/src/rust/lib.rs +18 -5
- package/src/rust/model/column_locator.rs +82 -0
- package/src/rust/model/columns_iter_set.rs +1 -0
- package/src/rust/model/copy_export.rs +50 -14
- package/src/rust/model/edit_expression.rs +2 -5
- package/src/rust/model/eject.rs +41 -0
- package/src/rust/model/get_viewer_config.rs +4 -28
- package/src/rust/model/intersection_observer.rs +20 -8
- package/src/rust/model/mod.rs +11 -4
- package/src/rust/model/plugin_column_styles.rs +0 -31
- package/src/rust/model/reset_all.rs +38 -0
- package/src/rust/model/resize_observer.rs +34 -7
- package/src/rust/model/restore_and_render.rs +12 -7
- package/src/rust/{utils/scope.rs → model/send_plugin_config.rs} +32 -35
- package/src/rust/model/structural.rs +194 -23
- package/src/rust/model/update_and_render.rs +14 -4
- package/src/rust/{model/create_col.rs → presentation/column_locator.rs} +73 -42
- package/src/rust/{utils/wasm_abi.rs → presentation/sheets.rs} +54 -40
- package/src/rust/presentation.rs +60 -119
- package/src/rust/renderer/activate.rs +20 -5
- package/src/rust/renderer/limits.rs +0 -149
- package/src/rust/renderer/render_timer.rs +1 -1
- package/src/rust/renderer.rs +34 -18
- package/src/rust/root.rs +50 -0
- package/src/rust/session/column_defaults_update.rs +4 -4
- package/src/rust/session/drag_drop_update.rs +1 -1
- package/src/rust/session/metadata.rs +3 -17
- package/src/rust/session/replace_expression_update.rs +1 -2
- package/src/rust/session.rs +162 -82
- package/src/rust/utils/browser/blob.rs +16 -2
- package/src/rust/utils/browser/download.rs +1 -0
- package/src/rust/{components/column_settings_sidebar/mod.rs → utils/browser/dragdrop.rs} +14 -5
- package/src/rust/utils/browser/mod.rs +8 -4
- package/src/rust/utils/browser/selection.rs +5 -0
- package/src/rust/utils/custom_element.rs +28 -13
- package/src/rust/utils/datetime.rs +5 -0
- package/src/rust/utils/debounce.rs +7 -1
- package/src/rust/utils/hooks/use_async_callback.rs +7 -17
- package/src/rust/utils/mod.rs +28 -40
- package/src/rust/utils/number_format.rs +6 -5
- package/src/rust/utils/pubsub.rs +15 -10
- package/src/rust/utils/weak_scope.rs +11 -1
- package/src/svg/bookmark-icon.svg +4 -0
- package/src/svg/drag-handle copy.svg +10 -0
- package/src/svg/drawer-tab-hover.svg +5 -7
- package/src/svg/drawer-tab-invert-hover.svg +4 -8
- package/src/svg/drawer-tab-invert.svg +4 -7
- package/src/svg/drawer-tab.svg +4 -6
- package/src/svg/status_ok.svg +24 -24
- package/src/ts/extensions.ts +51 -3
- package/src/ts/perspective-viewer.ts +2 -14
- package/src/ts/plugin.ts +1 -1
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/column_style.rs +0 -177
- package/src/rust/components/containers/tests/mod.rs +0 -11
- package/src/rust/components/containers/tests/split_panel.rs +0 -91
- package/src/rust/js/testing.rs +0 -149
- package/src/rust/utils/tee.rs +0 -88
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline4.js +0 -0
- /package/src/rust/components/{style_controls.rs → style_controls/mod.rs} +0 -0
- /package/src/rust/{components/containers → config}/kvpair.rs +0 -0
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
use std::collections::HashMap;
|
|
14
14
|
|
|
15
15
|
use serde::{Deserialize, Serialize};
|
|
16
|
-
use serde_with::skip_serializing_none;
|
|
17
16
|
use ts_rs::TS;
|
|
18
17
|
|
|
19
18
|
use super::{
|
|
@@ -28,7 +27,6 @@ fn is_zero(x: &u32) -> bool {
|
|
|
28
27
|
|
|
29
28
|
/// The value de/serialized and stored in the viewer config.
|
|
30
29
|
/// Also passed to the plugin via `plugin.save()`.
|
|
31
|
-
#[skip_serializing_none]
|
|
32
30
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TS)]
|
|
33
31
|
pub struct ColumnConfigValues {
|
|
34
32
|
#[serde(default)]
|
|
@@ -130,3 +128,5 @@ pub struct KeyValueOpts {
|
|
|
130
128
|
pub keys: KvPairKeys,
|
|
131
129
|
pub values: Vec<String>,
|
|
132
130
|
}
|
|
131
|
+
|
|
132
|
+
pub type SymbolKVPair = super::kvpair::KVPair<Option<String>, String>;
|
|
@@ -24,8 +24,6 @@ pub use simple::*;
|
|
|
24
24
|
pub use simple_format::*;
|
|
25
25
|
use ts_rs::TS;
|
|
26
26
|
|
|
27
|
-
use crate::*;
|
|
28
|
-
|
|
29
27
|
/// `Simple` case has all default-able keys and must be last!
|
|
30
28
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TS)]
|
|
31
29
|
// #[serde(tag = "format", content = "date_format")]
|
|
@@ -65,6 +63,7 @@ impl DatetimeFormatType {
|
|
|
65
63
|
/// A model for the JSON serialized style configuration for a column of type
|
|
66
64
|
/// `datetime`.
|
|
67
65
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TS)]
|
|
66
|
+
// #[derive(WasmDescribe!, FromWasmAbi!)]
|
|
68
67
|
pub struct DatetimeColumnStyleConfig {
|
|
69
68
|
#[serde(default)]
|
|
70
69
|
#[serde(skip_serializing_if = "DatetimeFormatType::is_simple")]
|
|
@@ -94,11 +93,7 @@ impl Default for DatetimeColumnStyleConfig {
|
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
derive_wasm_abi!(DatetimeColumnStyleConfig, FromWasmAbi, IntoWasmAbi);
|
|
98
|
-
|
|
99
96
|
#[derive(Clone, Default, Deserialize, Eq, PartialEq, Serialize, Debug)]
|
|
100
97
|
pub struct DatetimeColumnStyleDefaultConfig {
|
|
101
98
|
pub color: String,
|
|
102
99
|
}
|
|
103
|
-
|
|
104
|
-
derive_wasm_abi!(DatetimeColumnStyleDefaultConfig, FromWasmAbi);
|
package/src/rust/config/mod.rs
CHANGED
|
@@ -16,8 +16,6 @@ use serde::{Deserialize, Serialize};
|
|
|
16
16
|
use strum::{Display, EnumIter};
|
|
17
17
|
use ts_rs::TS;
|
|
18
18
|
|
|
19
|
-
use crate::*;
|
|
20
|
-
|
|
21
19
|
#[derive(
|
|
22
20
|
Clone, Copy, Debug, Default, Deserialize, Display, EnumIter, Eq, PartialEq, Serialize, TS,
|
|
23
21
|
)]
|
|
@@ -116,8 +114,6 @@ pub struct NumberColumnStyleConfig {
|
|
|
116
114
|
pub bg_gradient: Option<f64>,
|
|
117
115
|
}
|
|
118
116
|
|
|
119
|
-
derive_wasm_abi!(NumberColumnStyleConfig, FromWasmAbi, IntoWasmAbi);
|
|
120
|
-
|
|
121
117
|
/// Exactly like a `ColumnStyleConfig`, except without `Option<>` fields.
|
|
122
118
|
///
|
|
123
119
|
/// Necessary because this struct represents the default values we should use in
|
|
@@ -134,5 +130,3 @@ pub struct NumberColumnStyleDefaultConfig {
|
|
|
134
130
|
pub number_fg_mode: NumberForegroundMode,
|
|
135
131
|
pub number_bg_mode: NumberBackgroundMode,
|
|
136
132
|
}
|
|
137
|
-
|
|
138
|
-
derive_wasm_abi!(NumberColumnStyleDefaultConfig, FromWasmAbi);
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
mod enums;
|
|
14
14
|
pub use enums::*;
|
|
15
15
|
use serde::{Deserialize, Serialize};
|
|
16
|
-
use serde_with::skip_serializing_none;
|
|
17
16
|
use strum::{Display, EnumIter};
|
|
18
17
|
use ts_rs::TS;
|
|
19
18
|
|
|
@@ -45,13 +44,16 @@ pub enum CurrencySign {
|
|
|
45
44
|
Accounting,
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
#[skip_serializing_none]
|
|
49
47
|
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Clone, TS)]
|
|
50
48
|
#[serde(rename_all = "camelCase")]
|
|
51
49
|
pub struct CurrencyNumberFormatStyle {
|
|
52
50
|
#[serde(default)]
|
|
53
51
|
pub currency: CurrencyCode,
|
|
52
|
+
|
|
53
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
54
54
|
pub currency_display: Option<CurrencyDisplay>,
|
|
55
|
+
|
|
56
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
55
57
|
pub currency_sign: Option<CurrencySign>,
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -64,12 +66,13 @@ pub enum UnitDisplay {
|
|
|
64
66
|
Long,
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
#[skip_serializing_none]
|
|
68
69
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, TS)]
|
|
69
70
|
#[serde(rename_all = "camelCase")]
|
|
70
71
|
pub struct UnitNumberFormatStyle {
|
|
71
72
|
#[serde(default)]
|
|
72
73
|
pub unit: Unit,
|
|
74
|
+
|
|
75
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
73
76
|
pub unit_display: Option<UnitDisplay>,
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -166,7 +169,6 @@ pub enum SignDisplay {
|
|
|
166
169
|
Never,
|
|
167
170
|
}
|
|
168
171
|
|
|
169
|
-
#[skip_serializing_none]
|
|
170
172
|
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Clone, TS)]
|
|
171
173
|
#[serde(rename_all = "camelCase")]
|
|
172
174
|
pub struct CustomNumberFormatConfig {
|
|
@@ -178,24 +180,45 @@ pub struct CustomNumberFormatConfig {
|
|
|
178
180
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#minimumintegerdigits
|
|
179
181
|
// these min/max props can all be specified but it results in possible conflicts
|
|
180
182
|
// may consider making them distinct options
|
|
183
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
181
184
|
pub minimum_integer_digits: Option<f64>,
|
|
185
|
+
|
|
186
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
182
187
|
pub minimum_fraction_digits: Option<f64>,
|
|
188
|
+
|
|
189
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
183
190
|
pub maximum_fraction_digits: Option<f64>,
|
|
191
|
+
|
|
192
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
184
193
|
pub minimum_significant_digits: Option<f64>,
|
|
194
|
+
|
|
195
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
185
196
|
pub maximum_significant_digits: Option<f64>,
|
|
197
|
+
|
|
198
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
186
199
|
pub rounding_priority: Option<RoundingPriority>,
|
|
187
200
|
|
|
188
201
|
// specific values https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#roundingincrement
|
|
189
202
|
// Only available with automatic rounding priority
|
|
190
203
|
// Cannot be mixed with sigfig rounding. (Does this mean max/min sigfig must be unset?)
|
|
204
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
191
205
|
pub rounding_increment: Option<f64>,
|
|
206
|
+
|
|
207
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
192
208
|
pub rounding_mode: Option<RoundingMode>,
|
|
209
|
+
|
|
210
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
193
211
|
pub trailing_zero_display: Option<TrailingZeroDisplay>,
|
|
194
212
|
|
|
195
213
|
#[serde(flatten)]
|
|
196
214
|
#[ts(skip)]
|
|
215
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
197
216
|
pub _notation: Option<Notation>,
|
|
217
|
+
|
|
218
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
198
219
|
pub use_grouping: Option<UseGrouping>,
|
|
220
|
+
|
|
221
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
199
222
|
pub sign_display: Option<SignDisplay>,
|
|
200
223
|
}
|
|
201
224
|
|
|
@@ -11,55 +11,30 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
use std::collections::HashMap;
|
|
14
|
-
use std::io::{Read, Write};
|
|
15
14
|
use std::ops::Deref;
|
|
16
|
-
use std::str::FromStr;
|
|
17
15
|
use std::sync::LazyLock;
|
|
18
16
|
|
|
19
|
-
use flate2::Compression;
|
|
20
|
-
use flate2::read::ZlibDecoder;
|
|
21
|
-
use flate2::write::ZlibEncoder;
|
|
22
17
|
use perspective_client::config::*;
|
|
23
18
|
use perspective_js::utils::*;
|
|
24
19
|
use serde::{Deserialize, Deserializer, Serialize};
|
|
25
20
|
use serde_json::Value;
|
|
26
21
|
use ts_rs::TS;
|
|
27
|
-
use wasm_bindgen::JsCast;
|
|
28
22
|
use wasm_bindgen::prelude::*;
|
|
29
23
|
|
|
30
24
|
use super::ColumnConfigValues;
|
|
31
25
|
use crate::presentation::ColumnConfigMap;
|
|
32
26
|
|
|
33
|
-
pub enum ViewerConfigEncoding {
|
|
34
|
-
Json,
|
|
35
|
-
String,
|
|
36
|
-
ArrayBuffer,
|
|
37
|
-
JSONString,
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
impl FromStr for ViewerConfigEncoding {
|
|
41
|
-
type Err = JsValue;
|
|
42
|
-
|
|
43
|
-
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
44
|
-
match s {
|
|
45
|
-
"json" => Ok(Self::Json),
|
|
46
|
-
"string" => Ok(Self::String),
|
|
47
|
-
"arraybuffer" => Ok(Self::ArrayBuffer),
|
|
48
|
-
x => Err(format!("Unknown format \"{x}\"").into()),
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
27
|
/// The state of an entire `custom_elements::PerspectiveViewerElement` component
|
|
54
28
|
/// and its `Plugin`.
|
|
55
|
-
#[derive(Serialize, PartialEq)]
|
|
29
|
+
#[derive(Debug, Default, Serialize, PartialEq)]
|
|
56
30
|
#[serde(deny_unknown_fields)]
|
|
57
|
-
pub struct ViewerConfig {
|
|
58
|
-
pub version:
|
|
31
|
+
pub struct ViewerConfig<V = String> {
|
|
32
|
+
pub version: V,
|
|
33
|
+
pub columns_config: ColumnConfigMap,
|
|
59
34
|
pub plugin: String,
|
|
60
35
|
pub plugin_config: Value,
|
|
61
|
-
pub columns_config: ColumnConfigMap,
|
|
62
36
|
pub settings: bool,
|
|
37
|
+
pub table: Option<String>,
|
|
63
38
|
pub theme: Option<String>,
|
|
64
39
|
pub title: Option<String>,
|
|
65
40
|
|
|
@@ -67,30 +42,6 @@ pub struct ViewerConfig {
|
|
|
67
42
|
pub view_config: ViewConfig,
|
|
68
43
|
}
|
|
69
44
|
|
|
70
|
-
// `#[serde(flatten)]` makes messagepack 2x as big as they can no longer be
|
|
71
|
-
// struct fields, so make a tuple alternative for serialization in binary.
|
|
72
|
-
type ViewerConfigBinarySerialFormat<'a> = (
|
|
73
|
-
&'a String,
|
|
74
|
-
&'a ColumnConfigMap,
|
|
75
|
-
&'a String,
|
|
76
|
-
&'a Value,
|
|
77
|
-
bool,
|
|
78
|
-
&'a Option<String>,
|
|
79
|
-
&'a Option<String>,
|
|
80
|
-
&'a ViewConfig,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
type ViewerConfigBinaryDeserialFormat = (
|
|
84
|
-
VersionUpdate,
|
|
85
|
-
ColumnConfigUpdate,
|
|
86
|
-
PluginUpdate,
|
|
87
|
-
Option<Value>,
|
|
88
|
-
SettingsUpdate,
|
|
89
|
-
ThemeUpdate,
|
|
90
|
-
TitleUpdate,
|
|
91
|
-
ViewConfigUpdate,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
45
|
pub static API_VERSION: LazyLock<&'static str> = LazyLock::new(|| {
|
|
95
46
|
#[derive(Deserialize)]
|
|
96
47
|
struct Package {
|
|
@@ -102,76 +53,16 @@ pub static API_VERSION: LazyLock<&'static str> = LazyLock::new(|| {
|
|
|
102
53
|
});
|
|
103
54
|
|
|
104
55
|
impl ViewerConfig {
|
|
105
|
-
fn token(&self) -> ViewerConfigBinarySerialFormat<'_> {
|
|
106
|
-
(
|
|
107
|
-
&self.version,
|
|
108
|
-
&self.columns_config,
|
|
109
|
-
&self.plugin,
|
|
110
|
-
&self.plugin_config,
|
|
111
|
-
self.settings,
|
|
112
|
-
&self.theme,
|
|
113
|
-
&self.title,
|
|
114
|
-
&self.view_config,
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
56
|
/// Encode a `ViewerConfig` to a `JsValue` in a supported type.
|
|
119
|
-
pub fn encode(&self
|
|
120
|
-
|
|
121
|
-
Some(ViewerConfigEncoding::String) => {
|
|
122
|
-
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
|
123
|
-
let bytes = rmp_serde::to_vec_named(&self.token())?;
|
|
124
|
-
encoder.write_all(&bytes)?;
|
|
125
|
-
let encoded = encoder.finish()?;
|
|
126
|
-
Ok(JsValue::from(base64::encode(encoded)))
|
|
127
|
-
},
|
|
128
|
-
Some(ViewerConfigEncoding::ArrayBuffer) => {
|
|
129
|
-
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
|
130
|
-
let bytes = rmp_serde::to_vec_named(&self.token())?;
|
|
131
|
-
encoder.write_all(&bytes)?;
|
|
132
|
-
let encoded = encoder.finish()?;
|
|
133
|
-
let array = js_sys::Uint8Array::from(&encoded[..]);
|
|
134
|
-
let start = array.byte_offset();
|
|
135
|
-
let len = array.byte_length();
|
|
136
|
-
Ok(array
|
|
137
|
-
.buffer()
|
|
138
|
-
.slice_with_end(start, start + len)
|
|
139
|
-
.unchecked_into())
|
|
140
|
-
},
|
|
141
|
-
Some(ViewerConfigEncoding::JSONString) => {
|
|
142
|
-
Ok(JsValue::from(serde_json::to_string(self)?))
|
|
143
|
-
},
|
|
144
|
-
None | Some(ViewerConfigEncoding::Json) => Ok(JsValue::from_serde_ext(self)?),
|
|
145
|
-
}
|
|
57
|
+
pub fn encode(&self) -> ApiResult<JsValue> {
|
|
58
|
+
Ok(JsValue::from_serde_ext(self)?)
|
|
146
59
|
}
|
|
147
60
|
}
|
|
148
61
|
|
|
149
|
-
#[derive(Clone, TS, Deserialize)]
|
|
62
|
+
#[derive(Clone, Debug, TS, Deserialize, PartialEq, Serialize)]
|
|
150
63
|
#[serde(transparent)]
|
|
151
64
|
pub struct PluginConfig(serde_json::Value);
|
|
152
65
|
|
|
153
|
-
// impl Type for PluginConfig {
|
|
154
|
-
// fn inline(type_map: &mut specta::TypeMap, generics: specta::Generics) ->
|
|
155
|
-
// specta::DataType { specta::Map::from(());
|
|
156
|
-
// // specta::Map {
|
|
157
|
-
// // key_ty:
|
|
158
|
-
// // specta::DataType::Primitive(specta::PrimitiveType::String),
|
|
159
|
-
// // value_ty: specta::DataType::Any,
|
|
160
|
-
// // }
|
|
161
|
-
|
|
162
|
-
// // specta::DataType::Map(specta::Map { Box::new((
|
|
163
|
-
// // specta::DataType::Primitive(specta::PrimitiveType::String),
|
|
164
|
-
// // specta::DataType::Any,
|
|
165
|
-
// // )))
|
|
166
|
-
// }
|
|
167
|
-
// // fn inline(_type_map: &mut specta::TypeMap, _generics:
|
|
168
|
-
// &[specta::DataType]) -> // specta::DataType {
|
|
169
|
-
// specta::DataType::Map(Box::new(( //
|
|
170
|
-
// specta::DataType::Primitive(specta::PrimitiveType::String), //
|
|
171
|
-
// specta::DataType::Any, // )))
|
|
172
|
-
// // }
|
|
173
|
-
// }
|
|
174
|
-
|
|
175
66
|
impl Deref for PluginConfig {
|
|
176
67
|
type Target = Value;
|
|
177
68
|
|
|
@@ -180,8 +71,7 @@ impl Deref for PluginConfig {
|
|
|
180
71
|
}
|
|
181
72
|
}
|
|
182
73
|
|
|
183
|
-
#[derive(Clone, Deserialize, TS)]
|
|
184
|
-
// #[serde(deny_unknown_fields)]
|
|
74
|
+
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize, TS)]
|
|
185
75
|
pub struct ViewerConfigUpdate {
|
|
186
76
|
#[serde(default)]
|
|
187
77
|
#[ts(as = "Option<_>")]
|
|
@@ -198,6 +88,11 @@ pub struct ViewerConfigUpdate {
|
|
|
198
88
|
#[ts(optional)]
|
|
199
89
|
pub title: TitleUpdate,
|
|
200
90
|
|
|
91
|
+
#[serde(default)]
|
|
92
|
+
#[ts(as = "Option<_>")]
|
|
93
|
+
#[ts(optional)]
|
|
94
|
+
pub table: TableUpdate,
|
|
95
|
+
|
|
201
96
|
#[serde(default)]
|
|
202
97
|
#[ts(as = "Option<_>")]
|
|
203
98
|
#[ts(optional)]
|
|
@@ -223,44 +118,10 @@ pub struct ViewerConfigUpdate {
|
|
|
223
118
|
}
|
|
224
119
|
|
|
225
120
|
impl ViewerConfigUpdate {
|
|
226
|
-
fn from_token(
|
|
227
|
-
(version, columns_config, plugin, plugin_config, settings, theme, title, view_config): ViewerConfigBinaryDeserialFormat,
|
|
228
|
-
) -> ViewerConfigUpdate {
|
|
229
|
-
ViewerConfigUpdate {
|
|
230
|
-
version,
|
|
231
|
-
columns_config,
|
|
232
|
-
plugin,
|
|
233
|
-
plugin_config: plugin_config.map(PluginConfig),
|
|
234
|
-
settings,
|
|
235
|
-
theme,
|
|
236
|
-
title,
|
|
237
|
-
view_config,
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
121
|
/// Decode a `JsValue` into a `ViewerConfigUpdate` by auto-detecting format
|
|
242
122
|
/// from JavaScript type.
|
|
243
123
|
pub fn decode(update: &JsValue) -> ApiResult<Self> {
|
|
244
|
-
|
|
245
|
-
let js_str = update.as_string().into_apierror()?;
|
|
246
|
-
let bytes = base64::decode(js_str)?;
|
|
247
|
-
let mut decoder = ZlibDecoder::new(&*bytes);
|
|
248
|
-
let mut decoded = vec![];
|
|
249
|
-
decoder.read_to_end(&mut decoded)?;
|
|
250
|
-
let token = rmp_serde::from_slice(&decoded[..])?;
|
|
251
|
-
Ok(ViewerConfigUpdate::from_token(token))
|
|
252
|
-
} else if update.is_instance_of::<js_sys::ArrayBuffer>() {
|
|
253
|
-
let uint8array = js_sys::Uint8Array::new(update);
|
|
254
|
-
let mut slice = vec![0; uint8array.length() as usize];
|
|
255
|
-
uint8array.copy_to(&mut slice[..]);
|
|
256
|
-
let mut decoder = ZlibDecoder::new(&*slice);
|
|
257
|
-
let mut decoded = vec![];
|
|
258
|
-
decoder.read_to_end(&mut decoded)?;
|
|
259
|
-
let token = rmp_serde::from_slice(&decoded[..])?;
|
|
260
|
-
Ok(ViewerConfigUpdate::from_token(token))
|
|
261
|
-
} else {
|
|
262
|
-
Ok(update.into_serde_ext()?)
|
|
263
|
-
}
|
|
124
|
+
Ok(update.into_serde_ext()?)
|
|
264
125
|
}
|
|
265
126
|
|
|
266
127
|
pub fn migrate(&self) -> ApiResult<Self> {
|
|
@@ -269,7 +130,17 @@ impl ViewerConfigUpdate {
|
|
|
269
130
|
}
|
|
270
131
|
}
|
|
271
132
|
|
|
272
|
-
|
|
133
|
+
impl std::fmt::Display for ViewerConfigUpdate {
|
|
134
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
135
|
+
write!(
|
|
136
|
+
f,
|
|
137
|
+
"{}",
|
|
138
|
+
serde_json::to_string(self).map_err(|_| std::fmt::Error)?
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#[derive(Clone, Debug, Serialize, PartialEq, TS)]
|
|
273
144
|
#[serde(untagged)]
|
|
274
145
|
// #[ts(untagged)]
|
|
275
146
|
pub enum OptionalUpdate<T: Clone> {
|
|
@@ -285,22 +156,11 @@ pub enum OptionalUpdate<T: Clone> {
|
|
|
285
156
|
Update(T),
|
|
286
157
|
}
|
|
287
158
|
|
|
288
|
-
// #[derive(Clone, Debug, Serialize, TS)]
|
|
289
|
-
// #[serde(flatten)]
|
|
290
|
-
// pub struct OptionalUpdate<T: Clone> {
|
|
291
|
-
// #[ts(optional)]
|
|
292
|
-
// inner: Option<OptionalUpdateInner<T>>,
|
|
293
|
-
// }
|
|
294
|
-
|
|
295
|
-
// // #[ts(optional = nullable)]
|
|
296
|
-
|
|
297
|
-
// #[derive(Clone, Debug, Serialize, TS)]
|
|
298
|
-
// pub struct OptionalUpdateInner<T: Clone>(Option<T>);
|
|
299
|
-
|
|
300
159
|
pub type PluginUpdate = OptionalUpdate<String>;
|
|
301
160
|
pub type SettingsUpdate = OptionalUpdate<bool>;
|
|
302
161
|
pub type ThemeUpdate = OptionalUpdate<String>;
|
|
303
162
|
pub type TitleUpdate = OptionalUpdate<String>;
|
|
163
|
+
pub type TableUpdate = OptionalUpdate<String>;
|
|
304
164
|
pub type VersionUpdate = OptionalUpdate<String>;
|
|
305
165
|
pub type ColumnConfigUpdate = OptionalUpdate<HashMap<String, ColumnConfigValues>>;
|
|
306
166
|
|
|
@@ -61,7 +61,7 @@ impl CopyDropDownMenuElement {
|
|
|
61
61
|
/// Internal Only.
|
|
62
62
|
///
|
|
63
63
|
/// Set this custom element model's raw pointer.
|
|
64
|
-
pub fn
|
|
64
|
+
pub fn __set_model(&self, parent: &PerspectiveViewerElement) {
|
|
65
65
|
self.set_config_model(parent)
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,7 +69,11 @@ impl CopyDropDownMenuElement {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
impl CopyDropDownMenuElement {
|
|
72
|
-
pub fn new_from_model<A
|
|
72
|
+
pub fn new_from_model<A>(model: &A) -> Self
|
|
73
|
+
where
|
|
74
|
+
A: GetViewerConfigModel + StateProvider,
|
|
75
|
+
<A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
|
|
76
|
+
{
|
|
73
77
|
let dropdown = global::document()
|
|
74
78
|
.create_element("perspective-copy-menu")
|
|
75
79
|
.unwrap()
|
|
@@ -80,18 +84,22 @@ impl CopyDropDownMenuElement {
|
|
|
80
84
|
elem
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
pub fn set_config_model<A
|
|
87
|
+
pub fn set_config_model<A>(&self, model: &A)
|
|
88
|
+
where
|
|
89
|
+
A: GetViewerConfigModel + StateProvider,
|
|
90
|
+
<A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
|
|
91
|
+
{
|
|
84
92
|
let callback = Callback::from({
|
|
85
|
-
let model = model.
|
|
93
|
+
let model = model.clone_state();
|
|
86
94
|
let modal_rc = self.modal.clone();
|
|
87
95
|
move |x: ExportFile| {
|
|
88
96
|
let model = model.clone();
|
|
89
97
|
let modal = modal_rc.borrow().clone().unwrap();
|
|
90
98
|
spawn_local(async move {
|
|
91
99
|
let mime = x.method.mimetype(x.is_chart);
|
|
92
|
-
let task = model.
|
|
100
|
+
let task = model.export_method_to_blob(x.method);
|
|
93
101
|
let result = copy_to_clipboard(task, mime).await;
|
|
94
|
-
crate::
|
|
102
|
+
crate::maybe_log!({
|
|
95
103
|
result?;
|
|
96
104
|
modal.hide()?;
|
|
97
105
|
})
|
|
@@ -61,7 +61,7 @@ impl ExportDropDownMenuElement {
|
|
|
61
61
|
/// Internal Only.
|
|
62
62
|
///
|
|
63
63
|
/// Set this custom element model's raw pointer.
|
|
64
|
-
pub fn
|
|
64
|
+
pub fn __set_model(&self, parent: &PerspectiveViewerElement) {
|
|
65
65
|
self.set_config_model(parent)
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,7 +69,11 @@ impl ExportDropDownMenuElement {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
impl ExportDropDownMenuElement {
|
|
72
|
-
pub fn new_from_model<A
|
|
72
|
+
pub fn new_from_model<A>(model: &A) -> Self
|
|
73
|
+
where
|
|
74
|
+
A: GetViewerConfigModel + StateProvider,
|
|
75
|
+
<A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
|
|
76
|
+
{
|
|
73
77
|
let dropdown = global::document()
|
|
74
78
|
.create_element("perspective-export-menu")
|
|
75
79
|
.unwrap()
|
|
@@ -80,15 +84,19 @@ impl ExportDropDownMenuElement {
|
|
|
80
84
|
elem
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
fn set_config_model<A
|
|
87
|
+
fn set_config_model<A>(&self, model: &A)
|
|
88
|
+
where
|
|
89
|
+
A: GetViewerConfigModel + StateProvider,
|
|
90
|
+
<A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
|
|
91
|
+
{
|
|
84
92
|
let callback = Callback::from({
|
|
85
|
-
let model = model.
|
|
93
|
+
let model = model.clone_state();
|
|
86
94
|
let modal_rc = self.modal.clone();
|
|
87
95
|
move |x: ExportFile| {
|
|
88
96
|
if !x.name.is_empty() {
|
|
89
97
|
clone!(modal_rc, model);
|
|
90
98
|
spawn_local(async move {
|
|
91
|
-
let val = model.
|
|
99
|
+
let val = model.export_method_to_blob(x.method).await.unwrap();
|
|
92
100
|
let is_chart = model.renderer().is_chart();
|
|
93
101
|
download(&x.as_filename(is_chart), &val).unwrap();
|
|
94
102
|
modal_rc.borrow().clone().unwrap().hide().unwrap();
|
|
@@ -98,10 +106,10 @@ impl ExportDropDownMenuElement {
|
|
|
98
106
|
});
|
|
99
107
|
|
|
100
108
|
let renderer = model.renderer().clone();
|
|
101
|
-
let
|
|
109
|
+
let session = model.session().clone();
|
|
102
110
|
let props = props!(ExportDropDownMenuProps {
|
|
103
111
|
renderer,
|
|
104
|
-
|
|
112
|
+
session,
|
|
105
113
|
callback,
|
|
106
114
|
root: self.elem.clone()
|
|
107
115
|
});
|
|
@@ -93,10 +93,10 @@ impl FilterDropDownElement {
|
|
|
93
93
|
FilterDropDownMsg::SetValues(values),
|
|
94
94
|
]);
|
|
95
95
|
|
|
96
|
-
if let Some(x) = self.target.borrow().clone()
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
if let Some(x) = self.target.borrow().clone() {
|
|
97
|
+
if !self.modal.is_open() {
|
|
98
|
+
ApiFuture::spawn(self.modal.clone().open(x, None))
|
|
99
|
+
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
},
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
+
//! Each file in `custom_elements` exports a single struct which will be the
|
|
14
|
+
//! public [`wasm_bindgen`] API to a JavaScript Custom Element.
|
|
15
|
+
|
|
13
16
|
mod column_dropdown;
|
|
14
17
|
pub mod copy_dropdown;
|
|
15
18
|
pub mod debug_plugin;
|