@perspective-dev/viewer 4.2.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +2 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/botanical.css +1 -0
- 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/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 +32 -1
- 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/ts-rs/GroupRollupMode.d.ts +1 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +2 -0
- package/dist/wasm/perspective-viewer.d.ts +57 -53
- package/dist/wasm/perspective-viewer.js +197 -164
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +17 -18
- package/package.json +9 -6
- 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} +161 -159
- package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +69 -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/css/config-selector.css +441 -0
- 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} +156 -144
- 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 +374 -185
- 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 +21 -10
- package/src/rust/components/column_selector/sort_column.rs +23 -13
- package/src/rust/components/column_selector.rs +189 -100
- 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 +29 -7
- package/src/rust/components/containers/scroll_panel.rs +8 -1
- package/src/rust/components/containers/select.rs +3 -3
- package/src/rust/components/containers/sidebar_close_button.rs +1 -1
- package/src/rust/components/containers/split_panel.rs +3 -2
- 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 +22 -7
- package/src/rust/components/plugin_selector.rs +34 -92
- 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 -111
- 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 -39
- package/src/rust/custom_elements/copy_dropdown.rs +102 -21
- 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 +99 -35
- 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 +20 -1
- package/src/rust/lib.rs +5 -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/registry.rs +8 -1
- package/src/rust/renderer.rs +83 -9
- package/src/rust/session/column_defaults_update.rs +18 -0
- package/src/rust/session/metadata.rs +23 -2
- package/src/rust/session/props.rs +178 -0
- package/src/rust/session/replace_expression_update.rs +1 -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 +22 -4
- 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}/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/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 +139 -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 +124 -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/pro-dark.css +158 -0
- package/src/themes/{themes.less → pro.css} +17 -20
- package/src/themes/solarized-dark.css +135 -0
- package/src/themes/solarized.css +95 -0
- package/src/themes/themes.css +22 -0
- package/src/themes/vaporwave.css +256 -0
- package/src/ts/extensions.ts +73 -2
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/ts-rs/GroupRollupMode.ts +3 -0
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -1
- package/tsconfig.json +1 -0
- package/dist/css/variables.css +0 -0
- package/src/less/column-dropdown.less +0 -95
- package/src/less/config-selector.less +0 -363
- 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/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-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/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}/restore_and_render.rs +0 -0
- /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
|
@@ -13,24 +13,91 @@
|
|
|
13
13
|
use std::cell::RefCell;
|
|
14
14
|
use std::rc::Rc;
|
|
15
15
|
|
|
16
|
-
use
|
|
16
|
+
use perspective_js::utils::global;
|
|
17
17
|
use wasm_bindgen::prelude::*;
|
|
18
18
|
use wasm_bindgen_futures::spawn_local;
|
|
19
19
|
use web_sys::*;
|
|
20
|
-
use yew::*;
|
|
20
|
+
use yew::prelude::*;
|
|
21
21
|
|
|
22
|
-
use super::modal::*;
|
|
23
22
|
use super::viewer::PerspectiveViewerElement;
|
|
24
|
-
use crate::components::copy_dropdown::
|
|
23
|
+
use crate::components::copy_dropdown::CopyDropDownMenu;
|
|
24
|
+
use crate::components::portal::PortalModal;
|
|
25
|
+
use crate::components::style::StyleProvider;
|
|
25
26
|
use crate::js::*;
|
|
26
|
-
use crate::
|
|
27
|
+
use crate::renderer::*;
|
|
28
|
+
use crate::tasks::*;
|
|
27
29
|
use crate::utils::*;
|
|
30
|
+
use crate::*;
|
|
31
|
+
|
|
32
|
+
type TargetState = Rc<RefCell<Option<HtmlElement>>>;
|
|
33
|
+
|
|
34
|
+
#[derive(Properties, PartialEq)]
|
|
35
|
+
struct CopyDropDownWrapperProps {
|
|
36
|
+
renderer: Renderer,
|
|
37
|
+
callback: Callback<ExportFile>,
|
|
38
|
+
target: TargetState,
|
|
39
|
+
custom_element: HtmlElement,
|
|
40
|
+
#[prop_or_default]
|
|
41
|
+
theme: String,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
enum CopyDropDownWrapperMsg {
|
|
45
|
+
Open,
|
|
46
|
+
Close,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
struct CopyDropDownWrapper {
|
|
50
|
+
target: Option<HtmlElement>,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl Component for CopyDropDownWrapper {
|
|
54
|
+
type Message = CopyDropDownWrapperMsg;
|
|
55
|
+
type Properties = CopyDropDownWrapperProps;
|
|
56
|
+
|
|
57
|
+
fn create(_ctx: &Context<Self>) -> Self {
|
|
58
|
+
Self { target: None }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
62
|
+
match msg {
|
|
63
|
+
CopyDropDownWrapperMsg::Open => {
|
|
64
|
+
self.target = ctx.props().target.borrow().clone();
|
|
65
|
+
true
|
|
66
|
+
},
|
|
67
|
+
CopyDropDownWrapperMsg::Close => {
|
|
68
|
+
self.target = None;
|
|
69
|
+
true
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
75
|
+
let on_close = ctx.link().callback(|_| CopyDropDownWrapperMsg::Close);
|
|
76
|
+
html! {
|
|
77
|
+
<StyleProvider root={ctx.props().custom_element.clone()}>
|
|
78
|
+
<PortalModal
|
|
79
|
+
tag_name="perspective-copy-menu"
|
|
80
|
+
target={self.target.clone()}
|
|
81
|
+
own_focus=true
|
|
82
|
+
{on_close}
|
|
83
|
+
theme={ctx.props().theme.clone()}
|
|
84
|
+
>
|
|
85
|
+
<CopyDropDownMenu
|
|
86
|
+
renderer={ctx.props().renderer.clone()}
|
|
87
|
+
callback={ctx.props().callback.clone()}
|
|
88
|
+
/>
|
|
89
|
+
</PortalModal>
|
|
90
|
+
</StyleProvider>
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
28
94
|
|
|
29
95
|
#[wasm_bindgen]
|
|
30
96
|
#[derive(Clone)]
|
|
31
97
|
pub struct CopyDropDownMenuElement {
|
|
32
98
|
elem: HtmlElement,
|
|
33
|
-
|
|
99
|
+
target: TargetState,
|
|
100
|
+
root: Rc<RefCell<Option<AppHandle<CopyDropDownWrapper>>>>,
|
|
34
101
|
}
|
|
35
102
|
|
|
36
103
|
impl CustomElementMetadata for CopyDropDownMenuElement {
|
|
@@ -43,24 +110,25 @@ impl CopyDropDownMenuElement {
|
|
|
43
110
|
pub fn new(elem: HtmlElement) -> Self {
|
|
44
111
|
Self {
|
|
45
112
|
elem,
|
|
46
|
-
|
|
113
|
+
target: Default::default(),
|
|
114
|
+
root: Default::default(),
|
|
47
115
|
}
|
|
48
116
|
}
|
|
49
117
|
|
|
50
118
|
pub fn open(&self, target: HtmlElement) {
|
|
51
|
-
|
|
52
|
-
|
|
119
|
+
*self.target.borrow_mut() = Some(target);
|
|
120
|
+
if let Some(root) = self.root.borrow().as_ref() {
|
|
121
|
+
root.send_message(CopyDropDownWrapperMsg::Open);
|
|
53
122
|
}
|
|
54
123
|
}
|
|
55
124
|
|
|
56
125
|
pub fn hide(&self) -> ApiResult<()> {
|
|
57
|
-
let
|
|
58
|
-
|
|
126
|
+
if let Some(root) = self.root.borrow().as_ref() {
|
|
127
|
+
root.send_message(CopyDropDownWrapperMsg::Close);
|
|
128
|
+
}
|
|
129
|
+
Ok(())
|
|
59
130
|
}
|
|
60
131
|
|
|
61
|
-
/// Internal Only.
|
|
62
|
-
///
|
|
63
|
-
/// Set this custom element model's raw pointer.
|
|
64
132
|
pub fn __set_model(&self, parent: &PerspectiveViewerElement) {
|
|
65
133
|
self.set_config_model(parent)
|
|
66
134
|
}
|
|
@@ -91,30 +159,43 @@ impl CopyDropDownMenuElement {
|
|
|
91
159
|
{
|
|
92
160
|
let callback = Callback::from({
|
|
93
161
|
let model = model.clone_state();
|
|
94
|
-
let
|
|
162
|
+
let target = self.target.clone();
|
|
163
|
+
let root = self.root.clone();
|
|
95
164
|
move |x: ExportFile| {
|
|
96
165
|
let model = model.clone();
|
|
97
|
-
let
|
|
166
|
+
let target = target.clone();
|
|
167
|
+
let root = root.clone();
|
|
98
168
|
spawn_local(async move {
|
|
99
169
|
let mime = x.method.mimetype(x.is_chart);
|
|
100
170
|
let task = model.export_method_to_blob(x.method);
|
|
101
171
|
let result = copy_to_clipboard(task, mime).await;
|
|
102
172
|
crate::maybe_log!({
|
|
103
173
|
result?;
|
|
104
|
-
|
|
174
|
+
*target.borrow_mut() = None;
|
|
175
|
+
if let Some(root) = root.borrow().as_ref() {
|
|
176
|
+
root.send_message(CopyDropDownWrapperMsg::Close);
|
|
177
|
+
}
|
|
105
178
|
})
|
|
106
179
|
})
|
|
107
180
|
}
|
|
108
181
|
});
|
|
109
182
|
|
|
110
183
|
let renderer = model.renderer().clone();
|
|
111
|
-
let
|
|
184
|
+
let init = ShadowRootInit::new(ShadowRootMode::Open);
|
|
185
|
+
let shadow_root = self
|
|
186
|
+
.elem
|
|
187
|
+
.attach_shadow(&init)
|
|
188
|
+
.unwrap()
|
|
189
|
+
.unchecked_into::<Element>();
|
|
190
|
+
|
|
191
|
+
let props = yew::props!(CopyDropDownWrapperProps {
|
|
112
192
|
renderer,
|
|
113
193
|
callback,
|
|
114
|
-
|
|
194
|
+
target: self.target.clone(),
|
|
195
|
+
custom_element: self.elem.clone()
|
|
115
196
|
});
|
|
116
197
|
|
|
117
|
-
let
|
|
118
|
-
*self.
|
|
198
|
+
let handle = yew::Renderer::with_root_and_props(shadow_root, props).render();
|
|
199
|
+
*self.root.borrow_mut() = Some(handle);
|
|
119
200
|
}
|
|
120
201
|
}
|
|
@@ -17,20 +17,89 @@ use perspective_js::utils::global;
|
|
|
17
17
|
use wasm_bindgen::prelude::*;
|
|
18
18
|
use wasm_bindgen_futures::spawn_local;
|
|
19
19
|
use web_sys::*;
|
|
20
|
-
use yew::*;
|
|
20
|
+
use yew::prelude::*;
|
|
21
21
|
|
|
22
22
|
use super::viewer::PerspectiveViewerElement;
|
|
23
|
-
use crate::components::export_dropdown
|
|
24
|
-
use crate::
|
|
25
|
-
use crate::
|
|
23
|
+
use crate::components::export_dropdown::ExportDropDownMenu;
|
|
24
|
+
use crate::components::portal::PortalModal;
|
|
25
|
+
use crate::components::style::StyleProvider;
|
|
26
|
+
use crate::renderer::*;
|
|
27
|
+
use crate::session::*;
|
|
28
|
+
use crate::tasks::*;
|
|
26
29
|
use crate::utils::*;
|
|
27
30
|
use crate::*;
|
|
28
31
|
|
|
32
|
+
type TargetState = Rc<RefCell<Option<HtmlElement>>>;
|
|
33
|
+
|
|
34
|
+
#[derive(Properties, PartialEq)]
|
|
35
|
+
struct ExportDropDownWrapperProps {
|
|
36
|
+
renderer: Renderer,
|
|
37
|
+
session: Session,
|
|
38
|
+
callback: Callback<ExportFile>,
|
|
39
|
+
target: TargetState,
|
|
40
|
+
custom_element: HtmlElement,
|
|
41
|
+
#[prop_or_default]
|
|
42
|
+
theme: String,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
enum ExportDropDownWrapperMsg {
|
|
46
|
+
Open,
|
|
47
|
+
Close,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
struct ExportDropDownWrapper {
|
|
51
|
+
target: Option<HtmlElement>,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl Component for ExportDropDownWrapper {
|
|
55
|
+
type Message = ExportDropDownWrapperMsg;
|
|
56
|
+
type Properties = ExportDropDownWrapperProps;
|
|
57
|
+
|
|
58
|
+
fn create(_ctx: &Context<Self>) -> Self {
|
|
59
|
+
Self { target: None }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
63
|
+
match msg {
|
|
64
|
+
ExportDropDownWrapperMsg::Open => {
|
|
65
|
+
self.target = ctx.props().target.borrow().clone();
|
|
66
|
+
true
|
|
67
|
+
},
|
|
68
|
+
ExportDropDownWrapperMsg::Close => {
|
|
69
|
+
self.target = None;
|
|
70
|
+
true
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
76
|
+
let on_close = ctx.link().callback(|_| ExportDropDownWrapperMsg::Close);
|
|
77
|
+
html! {
|
|
78
|
+
<StyleProvider root={ctx.props().custom_element.clone()}>
|
|
79
|
+
<PortalModal
|
|
80
|
+
tag_name="perspective-export-menu"
|
|
81
|
+
target={self.target.clone()}
|
|
82
|
+
own_focus=true
|
|
83
|
+
{on_close}
|
|
84
|
+
theme={ctx.props().theme.clone()}
|
|
85
|
+
>
|
|
86
|
+
<ExportDropDownMenu
|
|
87
|
+
renderer={ctx.props().renderer.clone()}
|
|
88
|
+
session={ctx.props().session.clone()}
|
|
89
|
+
callback={ctx.props().callback.clone()}
|
|
90
|
+
/>
|
|
91
|
+
</PortalModal>
|
|
92
|
+
</StyleProvider>
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
29
97
|
#[wasm_bindgen]
|
|
30
98
|
#[derive(Clone)]
|
|
31
99
|
pub struct ExportDropDownMenuElement {
|
|
32
100
|
elem: HtmlElement,
|
|
33
|
-
|
|
101
|
+
target: TargetState,
|
|
102
|
+
root: Rc<RefCell<Option<AppHandle<ExportDropDownWrapper>>>>,
|
|
34
103
|
}
|
|
35
104
|
|
|
36
105
|
impl CustomElementMetadata for ExportDropDownMenuElement {
|
|
@@ -43,24 +112,25 @@ impl ExportDropDownMenuElement {
|
|
|
43
112
|
pub fn new(elem: HtmlElement) -> Self {
|
|
44
113
|
Self {
|
|
45
114
|
elem,
|
|
46
|
-
|
|
115
|
+
target: Default::default(),
|
|
116
|
+
root: Default::default(),
|
|
47
117
|
}
|
|
48
118
|
}
|
|
49
119
|
|
|
50
120
|
pub fn open(&self, target: HtmlElement) {
|
|
51
|
-
|
|
52
|
-
|
|
121
|
+
*self.target.borrow_mut() = Some(target);
|
|
122
|
+
if let Some(root) = self.root.borrow().as_ref() {
|
|
123
|
+
root.send_message(ExportDropDownWrapperMsg::Open);
|
|
53
124
|
}
|
|
54
125
|
}
|
|
55
126
|
|
|
56
127
|
pub fn hide(&self) -> ApiResult<()> {
|
|
57
|
-
let
|
|
58
|
-
|
|
128
|
+
if let Some(root) = self.root.borrow().as_ref() {
|
|
129
|
+
root.send_message(ExportDropDownWrapperMsg::Close);
|
|
130
|
+
}
|
|
131
|
+
Ok(())
|
|
59
132
|
}
|
|
60
133
|
|
|
61
|
-
/// Internal Only.
|
|
62
|
-
///
|
|
63
|
-
/// Set this custom element model's raw pointer.
|
|
64
134
|
pub fn __set_model(&self, parent: &PerspectiveViewerElement) {
|
|
65
135
|
self.set_config_model(parent)
|
|
66
136
|
}
|
|
@@ -91,15 +161,19 @@ impl ExportDropDownMenuElement {
|
|
|
91
161
|
{
|
|
92
162
|
let callback = Callback::from({
|
|
93
163
|
let model = model.clone_state();
|
|
94
|
-
let
|
|
164
|
+
let target = self.target.clone();
|
|
165
|
+
let root = self.root.clone();
|
|
95
166
|
move |x: ExportFile| {
|
|
96
167
|
if !x.name.is_empty() {
|
|
97
|
-
clone!(
|
|
168
|
+
clone!(target, root, model);
|
|
98
169
|
spawn_local(async move {
|
|
99
170
|
let val = model.export_method_to_blob(x.method).await.unwrap();
|
|
100
171
|
let is_chart = model.renderer().is_chart();
|
|
101
172
|
download(&x.as_filename(is_chart), &val).unwrap();
|
|
102
|
-
|
|
173
|
+
*target.borrow_mut() = None;
|
|
174
|
+
if let Some(root) = root.borrow().as_ref() {
|
|
175
|
+
root.send_message(ExportDropDownWrapperMsg::Close);
|
|
176
|
+
}
|
|
103
177
|
})
|
|
104
178
|
}
|
|
105
179
|
}
|
|
@@ -107,14 +181,22 @@ impl ExportDropDownMenuElement {
|
|
|
107
181
|
|
|
108
182
|
let renderer = model.renderer().clone();
|
|
109
183
|
let session = model.session().clone();
|
|
110
|
-
let
|
|
184
|
+
let init = ShadowRootInit::new(ShadowRootMode::Open);
|
|
185
|
+
let shadow_root = self
|
|
186
|
+
.elem
|
|
187
|
+
.attach_shadow(&init)
|
|
188
|
+
.unwrap()
|
|
189
|
+
.unchecked_into::<Element>();
|
|
190
|
+
|
|
191
|
+
let props = yew::props!(ExportDropDownWrapperProps {
|
|
111
192
|
renderer,
|
|
112
193
|
session,
|
|
113
194
|
callback,
|
|
114
|
-
|
|
195
|
+
target: self.target.clone(),
|
|
196
|
+
custom_element: self.elem.clone(),
|
|
115
197
|
});
|
|
116
198
|
|
|
117
|
-
let
|
|
118
|
-
*self.
|
|
199
|
+
let handle = yew::Renderer::with_root_and_props(shadow_root, props).render();
|
|
200
|
+
*self.root.borrow_mut() = Some(handle);
|
|
119
201
|
}
|
|
120
202
|
}
|
|
@@ -13,15 +13,8 @@
|
|
|
13
13
|
//! Each file in `custom_elements` exports a single struct which will be the
|
|
14
14
|
//! public [`wasm_bindgen`] API to a JavaScript Custom Element.
|
|
15
15
|
|
|
16
|
-
mod column_dropdown;
|
|
17
16
|
pub mod copy_dropdown;
|
|
18
17
|
pub mod debug_plugin;
|
|
19
18
|
pub mod export_dropdown;
|
|
20
|
-
mod filter_dropdown;
|
|
21
|
-
mod function_dropdown;
|
|
22
19
|
pub mod modal;
|
|
23
20
|
pub mod viewer;
|
|
24
|
-
|
|
25
|
-
pub use self::column_dropdown::*;
|
|
26
|
-
pub use self::filter_dropdown::*;
|
|
27
|
-
pub use self::function_dropdown::*;
|
|
@@ -56,81 +56,6 @@ where
|
|
|
56
56
|
on_blur: Option<Callback<()>>,
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
/// Anchor point enum, `ModalCornerTargetCorner`
|
|
60
|
-
#[derive(Clone, Copy, Debug, Default)]
|
|
61
|
-
enum ModalAnchor {
|
|
62
|
-
BottomRightTopLeft,
|
|
63
|
-
BottomRightBottomLeft,
|
|
64
|
-
BottomRightTopRight,
|
|
65
|
-
BottomLeftTopLeft,
|
|
66
|
-
TopRightTopLeft,
|
|
67
|
-
TopRightBottomRight,
|
|
68
|
-
|
|
69
|
-
#[default]
|
|
70
|
-
TopLeftBottomLeft,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
impl ModalAnchor {
|
|
74
|
-
const fn is_rev_vert(&self) -> bool {
|
|
75
|
-
matches!(
|
|
76
|
-
self,
|
|
77
|
-
Self::BottomLeftTopLeft
|
|
78
|
-
| Self::BottomRightBottomLeft
|
|
79
|
-
| Self::BottomRightTopLeft
|
|
80
|
-
| Self::BottomRightTopRight
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/// Given the bounds of the target element as previous computed, as well as the
|
|
86
|
-
/// browser's viewport and the bounds of the already-connected
|
|
87
|
-
/// `<perspectuve-style-menu>` element itself, determine a new (top, left)
|
|
88
|
-
/// coordinates that keeps the element on-screen.
|
|
89
|
-
fn calc_relative_position(
|
|
90
|
-
elem: &HtmlElement,
|
|
91
|
-
_top: f64,
|
|
92
|
-
left: f64,
|
|
93
|
-
height: f64,
|
|
94
|
-
width: f64,
|
|
95
|
-
) -> ModalAnchor {
|
|
96
|
-
let window = global::window();
|
|
97
|
-
let rect = elem.get_bounding_client_rect();
|
|
98
|
-
let inner_width = window.inner_width().unwrap().as_f64().unwrap();
|
|
99
|
-
let inner_height = window.inner_height().unwrap().as_f64().unwrap();
|
|
100
|
-
let rect_top = rect.top();
|
|
101
|
-
let rect_height = rect.height();
|
|
102
|
-
let rect_width = rect.width();
|
|
103
|
-
let rect_left = rect.left();
|
|
104
|
-
|
|
105
|
-
let elem_over_y = inner_height < rect_top + rect_height;
|
|
106
|
-
let elem_over_x = inner_width < rect_left + rect_width;
|
|
107
|
-
let target_over_x = inner_width < rect_left + width;
|
|
108
|
-
let target_over_y = inner_height < rect_top + height;
|
|
109
|
-
|
|
110
|
-
// modal/target
|
|
111
|
-
match (elem_over_y, elem_over_x, target_over_x, target_over_y) {
|
|
112
|
-
(true, _, true, true) => ModalAnchor::BottomRightTopLeft,
|
|
113
|
-
(true, _, true, false) => ModalAnchor::BottomRightBottomLeft,
|
|
114
|
-
(true, true, false, _) => {
|
|
115
|
-
if left + width - rect_width > 0.0 {
|
|
116
|
-
ModalAnchor::BottomRightTopRight
|
|
117
|
-
} else {
|
|
118
|
-
ModalAnchor::BottomLeftTopLeft
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
(true, false, false, _) => ModalAnchor::BottomLeftTopLeft,
|
|
122
|
-
(false, true, true, _) => ModalAnchor::TopRightTopLeft,
|
|
123
|
-
(false, true, false, _) => {
|
|
124
|
-
if left + width - rect_width > 0.0 {
|
|
125
|
-
ModalAnchor::TopRightBottomRight
|
|
126
|
-
} else {
|
|
127
|
-
ModalAnchor::TopLeftBottomLeft
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
_ => ModalAnchor::TopLeftBottomLeft,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
59
|
impl<T> ModalElement<T>
|
|
135
60
|
where
|
|
136
61
|
T: Component,
|
|
@@ -172,31 +97,10 @@ where
|
|
|
172
97
|
}
|
|
173
98
|
}
|
|
174
99
|
|
|
175
|
-
fn
|
|
176
|
-
let
|
|
177
|
-
let
|
|
178
|
-
|
|
179
|
-
let width = rect.width();
|
|
180
|
-
let top = rect.top();
|
|
181
|
-
let left = rect.left();
|
|
182
|
-
|
|
183
|
-
let self_rect = self.custom_element.get_bounding_client_rect();
|
|
184
|
-
let rect_height = self_rect.height();
|
|
185
|
-
let rect_width = self_rect.width();
|
|
186
|
-
|
|
187
|
-
match self.anchor.get() {
|
|
188
|
-
ModalAnchor::BottomRightTopLeft => (top - rect_height, left - rect_width + 1.0),
|
|
189
|
-
ModalAnchor::BottomRightBottomLeft => {
|
|
190
|
-
(top - rect_height + height, left - rect_width + 1.0)
|
|
191
|
-
},
|
|
192
|
-
ModalAnchor::BottomRightTopRight => {
|
|
193
|
-
(top - rect_height + 1.0, left + width - rect_width)
|
|
194
|
-
},
|
|
195
|
-
ModalAnchor::BottomLeftTopLeft => (top - rect_height + 1.0, left),
|
|
196
|
-
ModalAnchor::TopRightTopLeft => (top, left - rect_width + 1.0),
|
|
197
|
-
ModalAnchor::TopRightBottomRight => (top + height - 1.0, left + width - rect_width),
|
|
198
|
-
ModalAnchor::TopLeftBottomLeft => ((top + height - 1.0), left),
|
|
199
|
-
}
|
|
100
|
+
fn calc_anchor_pos(&self, target: &HtmlElement) -> (f64, f64) {
|
|
101
|
+
let target_rect = target.get_bounding_client_rect();
|
|
102
|
+
let modal_rect = self.custom_element.get_bounding_client_rect();
|
|
103
|
+
calc_anchor_position(self.anchor.get(), &target_rect, &modal_rect)
|
|
200
104
|
}
|
|
201
105
|
|
|
202
106
|
async fn open_within_viewport(&self, target: HtmlElement) -> ApiResult<()> {
|
|
@@ -229,7 +133,7 @@ where
|
|
|
229
133
|
width,
|
|
230
134
|
));
|
|
231
135
|
|
|
232
|
-
let (top, left) = self.
|
|
136
|
+
let (top, left) = self.calc_anchor_pos(&target);
|
|
233
137
|
let msg = ModalMsg::SetPos {
|
|
234
138
|
top,
|
|
235
139
|
left,
|
|
@@ -310,7 +214,7 @@ where
|
|
|
310
214
|
let target = target.clone();
|
|
311
215
|
let anchor = self.anchor.clone();
|
|
312
216
|
*self.resize_sub.borrow_mut() = Some(resize.add_listener(move |()| {
|
|
313
|
-
let (top, left) = this.
|
|
217
|
+
let (top, left) = this.calc_anchor_pos(&target);
|
|
314
218
|
let msg = ModalMsg::SetPos {
|
|
315
219
|
top,
|
|
316
220
|
left,
|
|
@@ -382,7 +286,7 @@ where
|
|
|
382
286
|
fn get_theme(elem: &HtmlElement) -> Option<String> {
|
|
383
287
|
let styles = global::window().get_computed_style(elem).unwrap().unwrap();
|
|
384
288
|
styles
|
|
385
|
-
.get_property_value("--theme-name")
|
|
289
|
+
.get_property_value("--psp-theme-name")
|
|
386
290
|
.ok()
|
|
387
291
|
.and_then(|x| {
|
|
388
292
|
let trimmed = x.trim();
|