@perspective-dev/viewer 4.3.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +2 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/phosphor.css +1 -0
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/esm/extensions.d.ts +4 -0
- package/dist/esm/perspective-viewer.d.ts +1 -0
- package/dist/esm/perspective-viewer.inline.js +2 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +2 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +9 -9
- package/dist/esm/ts-rs/NumberForegroundMode.d.ts +1 -1
- package/dist/esm/ts-rs/ViewerConfig.d.ts +36 -0
- package/dist/wasm/perspective-viewer.d.ts +68 -59
- package/dist/wasm/perspective-viewer.js +216 -171
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +19 -20
- package/package.json +7 -5
- package/src/{less/aggregate-selector.less → css/aggregate-selector.css} +23 -20
- package/src/css/column-dropdown.css +109 -0
- package/src/{less/column-selector.less → css/column-selector.css} +160 -158
- package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +70 -59
- package/src/{less/column-style.less → css/column-style.css} +52 -66
- package/src/{less/column-symbol-attributes.less → css/column-symbol-attributes.css} +15 -14
- package/src/{less/config-selector.less → css/config-selector.css} +151 -135
- package/src/{less/containers/dropdown-menu.less → css/containers/dropdown-menu.css} +20 -19
- package/src/{less/containers/pairs-list.less → css/containers/pairs-list.css} +13 -12
- package/src/{themes/variables.less → css/containers/scroll-panel.css} +25 -22
- package/src/{less/containers/split-panel.less → css/containers/split-panel.css} +15 -14
- package/src/{less/containers/tabs.less → css/containers/tabs.css} +17 -19
- package/src/css/dom/checkbox.css +102 -0
- package/src/css/dom/scrollbar.css +35 -0
- package/src/{less/dom/select.less → css/dom/select.css} +17 -18
- package/src/{less/empty-column.less → css/empty-column.css} +19 -18
- package/src/{less/expression-editor.less → css/expression-editor.css} +19 -18
- package/src/{less/filter-dropdown.less → css/filter-dropdown.css} +12 -11
- package/src/{less/filter-item.less → css/filter-item.css} +16 -15
- package/src/{less/form/code-editor.less → css/form/code-editor.css} +26 -30
- package/src/{less/form/debug.less → css/form/debug.css} +19 -18
- package/src/{less/function-dropdown.less → css/function-dropdown.css} +12 -11
- package/src/css/plugin-selector.css +261 -0
- package/src/{less/render-warning.less → css/render-warning.css} +18 -17
- package/src/{less/status-bar.less → css/status-bar.css} +157 -145
- package/src/css/type-icon.css +116 -0
- package/src/{less/viewer.less → css/viewer.css} +112 -146
- package/src/rust/components/column_dropdown.rs +229 -119
- package/src/rust/components/column_selector/active_column.rs +81 -62
- package/src/rust/components/column_selector/add_expression_button.rs +1 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +25 -15
- package/src/rust/components/column_selector/config_selector.rs +315 -199
- package/src/rust/components/column_selector/empty_column.rs +2 -2
- package/src/rust/components/column_selector/expr_edit_button.rs +8 -2
- package/src/rust/components/column_selector/filter_column.rs +37 -26
- package/src/rust/components/column_selector/inactive_column.rs +41 -29
- package/src/rust/components/column_selector/invalid_column.rs +7 -18
- package/src/rust/components/column_selector/pivot_column.rs +11 -5
- package/src/rust/components/column_selector/sort_column.rs +23 -13
- package/src/rust/components/column_selector.rs +163 -84
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +2 -3
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +7 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +153 -112
- package/src/rust/components/column_settings_sidebar.rs +91 -53
- package/src/rust/components/containers/dragdrop_list.rs +2 -1
- package/src/rust/components/containers/sidebar_close_button.rs +1 -1
- package/src/rust/components/containers/split_panel.rs +1 -0
- package/src/rust/components/containers/tab_list.rs +1 -1
- package/src/rust/components/copy_dropdown.rs +7 -28
- package/src/rust/components/datetime_column_style/custom.rs +2 -2
- package/src/rust/components/datetime_column_style/simple.rs +2 -2
- package/src/rust/components/datetime_column_style.rs +4 -2
- package/src/rust/components/editable_header.rs +7 -4
- package/src/rust/components/empty_row.rs +1 -1
- package/src/rust/components/export_dropdown.rs +4 -30
- package/src/rust/components/expression_editor.rs +19 -10
- package/src/rust/components/filter_dropdown.rs +246 -102
- package/src/rust/components/font_loader.rs +11 -28
- package/src/rust/components/form/code_editor.rs +17 -2
- package/src/rust/components/form/color_range_selector.rs +19 -6
- package/src/rust/components/form/debug.rs +30 -13
- package/src/rust/components/function_dropdown.rs +186 -113
- package/src/rust/components/main_panel.rs +71 -89
- package/src/rust/components/mod.rs +1 -1
- package/src/rust/components/modal.rs +7 -1
- package/src/rust/components/number_column_style.rs +30 -7
- package/src/rust/components/plugin_selector.rs +34 -102
- package/src/rust/components/portal.rs +274 -0
- package/src/rust/components/render_warning.rs +72 -123
- package/src/rust/components/settings_panel.rs +115 -11
- package/src/rust/components/status_bar.rs +222 -98
- package/src/rust/components/status_bar_counter.rs +8 -20
- package/src/rust/components/status_indicator.rs +64 -114
- package/src/rust/components/string_column_style.rs +2 -2
- package/src/rust/components/style/style_cache.rs +5 -1
- package/src/rust/components/viewer.rs +391 -40
- package/src/rust/config/number_column_style.rs +5 -1
- package/src/rust/config/viewer_config.rs +2 -2
- package/src/rust/custom_elements/copy_dropdown.rs +102 -21
- package/src/rust/custom_elements/debug_plugin.rs +4 -4
- package/src/rust/custom_elements/export_dropdown.rs +102 -20
- package/src/rust/custom_elements/mod.rs +0 -7
- package/src/rust/custom_elements/modal.rs +7 -103
- package/src/rust/custom_elements/viewer.rs +114 -39
- package/src/rust/custom_events.rs +23 -2
- package/src/rust/dragdrop.rs +149 -10
- package/src/{less/containers/scroll-panel.less → rust/engines.rs} +15 -13
- package/src/rust/js/plugin.rs +1 -1
- package/src/rust/lib.rs +10 -4
- package/src/rust/presentation/props.rs +39 -0
- package/src/rust/presentation/sheets.rs +3 -3
- package/src/rust/presentation.rs +44 -8
- package/src/rust/renderer/limits.rs +32 -3
- package/src/{less/dom/scrollbar.less → rust/renderer/props.rs} +18 -19
- package/src/rust/renderer.rs +93 -14
- package/src/rust/session/column_defaults_update.rs +1 -1
- package/src/rust/session/metadata.rs +23 -2
- package/src/rust/session/props.rs +178 -0
- package/src/rust/session.rs +124 -117
- package/src/rust/tasks/column_locator.rs +133 -0
- package/src/rust/{model → tasks}/columns_iter_set.rs +14 -23
- package/src/rust/{model → tasks}/edit_expression.rs +34 -10
- package/src/rust/{model → tasks}/eject.rs +2 -2
- package/src/rust/{model → tasks}/get_viewer_config.rs +0 -11
- package/src/rust/{model → tasks}/intersection_observer.rs +19 -3
- package/src/{less/containers/radio-list.less → rust/tasks/is_invalid_drop.rs} +21 -14
- package/src/rust/tasks/mod.rs +52 -0
- package/src/rust/{model → tasks}/plugin_column_styles.rs +69 -46
- package/src/rust/{model → tasks}/resize_observer.rs +39 -6
- package/src/rust/{model → tasks}/restore_and_render.rs +4 -3
- package/src/rust/{model → tasks}/send_plugin_config.rs +1 -1
- package/src/rust/tasks/structural.rs +53 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/modal_position.rs +110 -0
- package/src/rust/utils/ptr_eq_rc.rs +74 -0
- package/src/rust/utils/pubsub.rs +11 -1
- package/src/svg/bg-pattern.png +0 -0
- package/src/svg/close-icon.svg +1 -1
- package/src/svg/datagrid-select-row-tree.svg +13 -0
- package/src/svg/expression.svg +1 -1
- package/src/svg/mega-menu-icons-candlestick.svg +1 -1
- package/src/svg/mega-menu-icons-datagrid.svg +1 -2
- package/src/svg/mega-menu-icons-heatmap.svg +1 -1
- package/src/svg/mega-menu-icons-map-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-ohlc.svg +1 -1
- package/src/svg/mega-menu-icons-sunburst.svg +1 -1
- package/src/svg/mega-menu-icons-treemap.svg +1 -1
- package/src/svg/mega-menu-icons-x-bar.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-y-area.svg +1 -1
- package/src/svg/mega-menu-icons-y-bar.svg +1 -1
- package/src/svg/mega-menu-icons-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-y-scatter.svg +1 -1
- package/src/svg/radio-hover.svg +1 -1
- package/src/svg/radio-off.svg +1 -1
- package/src/svg/radio-on.svg +1 -1
- package/src/themes/botanical.css +157 -0
- package/src/themes/defaults.css +157 -0
- package/src/themes/dracula.css +233 -0
- package/src/themes/gruvbox-dark.css +255 -0
- package/src/themes/gruvbox.css +134 -0
- package/src/themes/icons.css +107 -0
- package/src/themes/intl/de.css +102 -0
- package/src/themes/intl/es.css +102 -0
- package/src/themes/intl/fr.css +102 -0
- package/src/themes/intl/ja.css +102 -0
- package/src/themes/intl/pt.css +102 -0
- package/src/themes/intl/zh.css +102 -0
- package/src/themes/intl.css +102 -0
- package/src/themes/monokai.css +233 -0
- package/src/themes/phosphor.css +184 -0
- package/src/themes/pro-dark.css +158 -0
- package/src/themes/{themes.less → pro.css} +17 -21
- package/src/themes/solarized-dark.css +135 -0
- package/src/themes/solarized.css +95 -0
- package/src/themes/themes.css +23 -0
- package/src/themes/vaporwave.css +256 -0
- package/src/ts/extensions.ts +8 -1
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/plugin.ts +9 -9
- package/src/ts/ts-rs/NumberForegroundMode.ts +1 -1
- package/src/ts/ts-rs/ViewerConfig.ts +15 -0
- package/dist/css/variables.css +0 -0
- package/src/less/column-dropdown.less +0 -95
- package/src/less/dom/checkbox.less +0 -100
- package/src/less/plugin-selector.less +0 -183
- package/src/less/type-icon.less +0 -68
- package/src/rust/components/error_message.rs +0 -56
- package/src/rust/custom_elements/column_dropdown.rs +0 -123
- package/src/rust/custom_elements/filter_dropdown.rs +0 -179
- package/src/rust/custom_elements/function_dropdown.rs +0 -115
- package/src/rust/model/column_locator.rs +0 -82
- package/src/rust/model/is_invalid_drop.rs +0 -36
- package/src/rust/model/mod.rs +0 -100
- package/src/rust/model/reset_all.rs +0 -38
- package/src/rust/model/structural.rs +0 -244
- package/src/themes/botanical.less +0 -142
- package/src/themes/dracula.less +0 -101
- package/src/themes/gruvbox-dark.less +0 -116
- package/src/themes/gruvbox.less +0 -152
- package/src/themes/icons.less +0 -130
- package/src/themes/intl/de.less +0 -102
- package/src/themes/intl/es.less +0 -102
- package/src/themes/intl/fr.less +0 -102
- package/src/themes/intl/ja.less +0 -102
- package/src/themes/intl/pt.less +0 -102
- package/src/themes/intl/zh.less +0 -102
- package/src/themes/intl.less +0 -102
- package/src/themes/monokai.less +0 -107
- package/src/themes/pro-dark.less +0 -147
- package/src/themes/pro.less +0 -186
- package/src/themes/solarized-dark.less +0 -78
- package/src/themes/solarized.less +0 -102
- package/src/themes/vaporwave.less +0 -145
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-d924246f0b4a3dce}/inline4.js +0 -0
- /package/src/rust/{model → tasks}/copy_export.rs +0 -0
- /package/src/rust/{model → tasks}/export_app.rs +0 -0
- /package/src/rust/{model → tasks}/export_method.rs +0 -0
- /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
|
@@ -47,35 +47,18 @@ impl PartialEq for FontLoaderProps {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
fn update(&mut self, _ctx: &Context<Self>, _msg: ()) -> bool {
|
|
63
|
-
false
|
|
64
|
-
}
|
|
50
|
+
#[function_component(FontLoader)]
|
|
51
|
+
pub fn font_loader(props: &FontLoaderProps) -> Html {
|
|
52
|
+
if matches!(props.get_status(), FontLoaderStatus::Finished) {
|
|
53
|
+
html! {}
|
|
54
|
+
} else {
|
|
55
|
+
let inner = props
|
|
56
|
+
.get_fonts()
|
|
57
|
+
.iter()
|
|
58
|
+
.map(font_test_html)
|
|
59
|
+
.collect::<Html>();
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
if matches!(ctx.props().get_status(), FontLoaderStatus::Finished) {
|
|
68
|
-
html! {}
|
|
69
|
-
} else {
|
|
70
|
-
let inner = ctx
|
|
71
|
-
.props()
|
|
72
|
-
.get_fonts()
|
|
73
|
-
.iter()
|
|
74
|
-
.map(font_test_html)
|
|
75
|
-
.collect::<Html>();
|
|
76
|
-
|
|
77
|
-
html! { <><style>{ ":host{opacity:0!important;}" }</style>{ inner }</> }
|
|
78
|
-
}
|
|
61
|
+
html! { <><style>{ ":host{opacity:0!important;}" }</style>{ inner }</> }
|
|
79
62
|
}
|
|
80
63
|
}
|
|
81
64
|
|
|
@@ -18,9 +18,9 @@ use web_sys::*;
|
|
|
18
18
|
use yew::prelude::*;
|
|
19
19
|
|
|
20
20
|
use crate::components::form::highlight::highlight;
|
|
21
|
+
use crate::components::function_dropdown::{FunctionDropDownElement, FunctionDropDownPortal};
|
|
21
22
|
use crate::components::style::LocalStyle;
|
|
22
23
|
use crate::css;
|
|
23
|
-
use crate::custom_elements::FunctionDropDownElement;
|
|
24
24
|
use crate::exprtk::{Cursor, tokenize};
|
|
25
25
|
use crate::utils::*;
|
|
26
26
|
|
|
@@ -45,6 +45,10 @@ pub struct CodeEditorProps {
|
|
|
45
45
|
|
|
46
46
|
#[prop_or_default]
|
|
47
47
|
pub error: Option<ExprValidationError>,
|
|
48
|
+
|
|
49
|
+
/// Selected theme name, threaded for PortalModal consumers.
|
|
50
|
+
#[prop_or_default]
|
|
51
|
+
pub theme: String,
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
/// A syntax-highlighted text editor component.
|
|
@@ -128,6 +132,8 @@ pub fn code_editor(props: &CodeEditorProps) -> Html {
|
|
|
128
132
|
|deps| scroll_sync(&deps.0, &deps.1, &deps.2),
|
|
129
133
|
);
|
|
130
134
|
|
|
135
|
+
let portal_dropdown = filter_dropdown.clone();
|
|
136
|
+
|
|
131
137
|
// Blur if this element is not in the tree
|
|
132
138
|
use_effect_with(filter_dropdown.clone(), |filter_dropdown| {
|
|
133
139
|
clone!(filter_dropdown);
|
|
@@ -160,7 +166,11 @@ pub fn code_editor(props: &CodeEditorProps) -> Html {
|
|
|
160
166
|
))
|
|
161
167
|
.collect::<Html>();
|
|
162
168
|
|
|
163
|
-
let class = if props.wordwrap {
|
|
169
|
+
let class = if props.wordwrap {
|
|
170
|
+
"wordwrap scrollable"
|
|
171
|
+
} else {
|
|
172
|
+
"scrollable"
|
|
173
|
+
};
|
|
164
174
|
clone!(props.disabled);
|
|
165
175
|
html! {
|
|
166
176
|
<>
|
|
@@ -171,6 +181,7 @@ pub fn code_editor(props: &CodeEditorProps) -> Html {
|
|
|
171
181
|
<textarea
|
|
172
182
|
{disabled}
|
|
173
183
|
id="textarea_editable"
|
|
184
|
+
class="scrollable"
|
|
174
185
|
ref={textarea_ref}
|
|
175
186
|
spellcheck="false"
|
|
176
187
|
{oninput}
|
|
@@ -191,6 +202,10 @@ pub fn code_editor(props: &CodeEditorProps) -> Html {
|
|
|
191
202
|
</pre>
|
|
192
203
|
</div>
|
|
193
204
|
</div>
|
|
205
|
+
<FunctionDropDownPortal
|
|
206
|
+
element={(*portal_dropdown).clone()}
|
|
207
|
+
theme={props.theme.clone()}
|
|
208
|
+
/>
|
|
194
209
|
</>
|
|
195
210
|
}
|
|
196
211
|
}
|
|
@@ -106,12 +106,25 @@ pub fn color_chooser_component(props: &ColorRangeProps) -> Html {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
fn infer_fg(color: &str) -> &'static str {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
if color.len() >= 7 {
|
|
110
|
+
let r = i32::from_str_radix(&color[1..3], 16).unwrap_or(255) as f64;
|
|
111
|
+
let g = i32::from_str_radix(&color[3..5], 16).unwrap_or(0) as f64;
|
|
112
|
+
let b = i32::from_str_radix(&color[5..7], 16).unwrap_or(0) as f64;
|
|
113
|
+
if (r * r * 0.299 + g * g * 0.587 + b * b * 0.114).sqrt() > 130.0 {
|
|
114
|
+
"--sign--color:var(--psp--color)"
|
|
115
|
+
} else {
|
|
116
|
+
"--sign--color:var(--psp--background-color)"
|
|
117
|
+
}
|
|
118
|
+
} else if color.len() == 4 {
|
|
119
|
+
let r = i32::from_str_radix(&color[1..2], 16).unwrap_or(15) as f64;
|
|
120
|
+
let g = i32::from_str_radix(&color[2..3], 16).unwrap_or(0) as f64;
|
|
121
|
+
let b = i32::from_str_radix(&color[3..4], 16).unwrap_or(0) as f64;
|
|
122
|
+
if (r * r * 0.299 + g * g * 0.587 + b * b * 0.114).sqrt() > 8.0 {
|
|
123
|
+
"--sign--color:var(--psp--color)"
|
|
124
|
+
} else {
|
|
125
|
+
"--sign--color:var(--psp--background-color)"
|
|
126
|
+
}
|
|
114
127
|
} else {
|
|
115
|
-
"--sign--color
|
|
128
|
+
"--sign--color:var(--psp--color)"
|
|
116
129
|
}
|
|
117
130
|
}
|
|
@@ -20,21 +20,39 @@ use yew::prelude::*;
|
|
|
20
20
|
use crate::components::containers::trap_door_panel::TrapDoorPanel;
|
|
21
21
|
use crate::components::form::code_editor::CodeEditor;
|
|
22
22
|
use crate::components::style::LocalStyle;
|
|
23
|
+
use crate::css;
|
|
23
24
|
use crate::js::{MimeType, copy_to_clipboard, paste_from_clipboard};
|
|
24
|
-
use crate::model::*;
|
|
25
25
|
use crate::presentation::*;
|
|
26
26
|
use crate::renderer::*;
|
|
27
27
|
use crate::session::*;
|
|
28
|
+
use crate::tasks::*;
|
|
28
29
|
use crate::utils::*;
|
|
29
|
-
use crate::{PerspectiveProperties, css};
|
|
30
30
|
|
|
31
|
-
#[derive(PartialEq, Properties
|
|
31
|
+
#[derive(Clone, PartialEq, Properties)]
|
|
32
32
|
pub struct DebugPanelProps {
|
|
33
33
|
pub presentation: Presentation,
|
|
34
34
|
pub renderer: Renderer,
|
|
35
35
|
pub session: Session,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
impl HasPresentation for DebugPanelProps {
|
|
39
|
+
fn presentation(&self) -> &Presentation {
|
|
40
|
+
&self.presentation
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl HasRenderer for DebugPanelProps {
|
|
45
|
+
fn renderer(&self) -> &Renderer {
|
|
46
|
+
&self.renderer
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
impl HasSession for DebugPanelProps {
|
|
51
|
+
fn session(&self) -> &Session {
|
|
52
|
+
&self.session
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
38
56
|
#[function_component(DebugPanel)]
|
|
39
57
|
pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
40
58
|
let expr = use_state_eq(|| Rc::new("".to_string()));
|
|
@@ -42,7 +60,7 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
42
60
|
let select_all = use_memo((), |()| PubSub::default());
|
|
43
61
|
let modified = use_state_eq(|| false);
|
|
44
62
|
|
|
45
|
-
use_effect_with((expr.setter(), props.
|
|
63
|
+
use_effect_with((expr.setter(), props.clone()), {
|
|
46
64
|
clone!(error, modified);
|
|
47
65
|
move |(text, state)| {
|
|
48
66
|
state.set_text(text.clone());
|
|
@@ -57,7 +75,7 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
57
75
|
));
|
|
58
76
|
|
|
59
77
|
let sub2 = state
|
|
60
|
-
.renderer
|
|
78
|
+
.renderer
|
|
61
79
|
.reset_changed
|
|
62
80
|
.add_listener(state.reset_callback(
|
|
63
81
|
text.clone(),
|
|
@@ -66,7 +84,7 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
66
84
|
));
|
|
67
85
|
|
|
68
86
|
let sub3 = state
|
|
69
|
-
.session
|
|
87
|
+
.session
|
|
70
88
|
.view_config_changed
|
|
71
89
|
.add_listener(state.reset_callback(
|
|
72
90
|
text.clone(),
|
|
@@ -90,7 +108,7 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
90
108
|
}
|
|
91
109
|
});
|
|
92
110
|
|
|
93
|
-
let onsave = use_callback((expr.clone(), error.clone(), props.
|
|
111
|
+
let onsave = use_callback((expr.clone(), error.clone(), props.clone()), {
|
|
94
112
|
clone!(modified);
|
|
95
113
|
move |_, (text, error, props)| props.on_save(text, error, &modified)
|
|
96
114
|
});
|
|
@@ -111,12 +129,12 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
111
129
|
},
|
|
112
130
|
);
|
|
113
131
|
|
|
114
|
-
let onapply = use_callback((expr.clone(), error.clone(), props.
|
|
132
|
+
let onapply = use_callback((expr.clone(), error.clone(), props.clone()), {
|
|
115
133
|
clone!(modified);
|
|
116
134
|
move |_, (text, error, props)| props.on_save(text, error, &modified)
|
|
117
135
|
});
|
|
118
136
|
|
|
119
|
-
let onreset = use_callback((expr.setter(), error.clone(), props.
|
|
137
|
+
let onreset = use_callback((expr.setter(), error.clone(), props.clone()), {
|
|
120
138
|
clone!(modified);
|
|
121
139
|
move |_, (text, error, props)| {
|
|
122
140
|
props.set_text(text.clone());
|
|
@@ -125,7 +143,7 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
125
143
|
}
|
|
126
144
|
});
|
|
127
145
|
|
|
128
|
-
let onpaste = use_callback((expr.clone(), error.clone(), props.
|
|
146
|
+
let onpaste = use_callback((expr.clone(), error.clone(), props.clone()), {
|
|
129
147
|
clone!(modified);
|
|
130
148
|
move |_, (text, error, props)| {
|
|
131
149
|
clone!(text, error, props, modified);
|
|
@@ -181,12 +199,11 @@ pub fn debug_panel(props: &DebugPanelProps) -> Html {
|
|
|
181
199
|
}
|
|
182
200
|
}
|
|
183
201
|
|
|
184
|
-
impl
|
|
202
|
+
impl DebugPanelProps {
|
|
185
203
|
fn set_text(&self, setter: UseStateSetter<Rc<String>>) {
|
|
186
204
|
let props = self.clone();
|
|
187
205
|
ApiFuture::spawn(async move {
|
|
188
|
-
let
|
|
189
|
-
let config = task.await?;
|
|
206
|
+
let config = props.get_viewer_config().await?;
|
|
190
207
|
let json = JsValue::from_serde_ext(&config)?;
|
|
191
208
|
let js_string =
|
|
192
209
|
js_sys::JSON::stringify_with_replacer_and_space(&json, &JsValue::NULL, &2.into())?;
|
|
@@ -10,142 +10,215 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use
|
|
13
|
+
use std::cell::RefCell;
|
|
14
|
+
use std::rc::Rc;
|
|
15
|
+
|
|
16
|
+
use perspective_client::config::{COMPLETIONS, CompletionItemSuggestion};
|
|
17
|
+
use perspective_js::utils::ApiResult;
|
|
14
18
|
use web_sys::*;
|
|
19
|
+
use yew::html::ImplicitClone;
|
|
15
20
|
use yew::prelude::*;
|
|
16
21
|
|
|
17
|
-
use super::
|
|
18
|
-
use crate::utils
|
|
22
|
+
use super::portal::PortalModal;
|
|
23
|
+
use crate::utils::*;
|
|
19
24
|
|
|
20
25
|
static CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/css/function-dropdown.css"));
|
|
21
26
|
|
|
22
|
-
#[derive(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
#[derive(Default)]
|
|
28
|
+
struct FunctionDropDownState {
|
|
29
|
+
values: Vec<CompletionItemSuggestion>,
|
|
30
|
+
selected: usize,
|
|
31
|
+
on_select: Option<Callback<CompletionItemSuggestion>>,
|
|
32
|
+
target: Option<HtmlElement>,
|
|
26
33
|
}
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
#[derive(Clone, Default)]
|
|
36
|
+
pub struct FunctionDropDownElement {
|
|
37
|
+
state: Rc<RefCell<FunctionDropDownState>>,
|
|
38
|
+
notify: Rc<PubSub<()>>,
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ItemUp,
|
|
39
|
-
ItemSelect,
|
|
41
|
+
impl PartialEq for FunctionDropDownElement {
|
|
42
|
+
fn eq(&self, other: &Self) -> bool {
|
|
43
|
+
Rc::ptr_eq(&self.state, &other.state)
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
values: Option<Vec<CompletionItemSuggestion>>,
|
|
44
|
-
selected: usize,
|
|
45
|
-
on_select: Option<Callback<CompletionItemSuggestion>>,
|
|
46
|
-
}
|
|
47
|
+
impl ImplicitClone for FunctionDropDownElement {}
|
|
47
48
|
|
|
48
|
-
impl
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
impl FunctionDropDownElement {
|
|
50
|
+
pub fn reautocomplete(&self) {
|
|
51
|
+
self.notify.emit(());
|
|
52
|
+
}
|
|
51
53
|
|
|
52
|
-
fn
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
pub fn autocomplete(
|
|
55
|
+
&self,
|
|
56
|
+
input: String,
|
|
57
|
+
target: HtmlElement,
|
|
58
|
+
callback: Callback<CompletionItemSuggestion>,
|
|
59
|
+
) -> ApiResult<()> {
|
|
60
|
+
let values = filter_values(&input);
|
|
61
|
+
if values.is_empty() {
|
|
62
|
+
self.hide()?;
|
|
63
|
+
} else {
|
|
64
|
+
let mut s = self.state.borrow_mut();
|
|
65
|
+
s.values = values;
|
|
66
|
+
s.selected = 0;
|
|
67
|
+
s.on_select = Some(callback);
|
|
68
|
+
s.target = Some(target);
|
|
69
|
+
drop(s);
|
|
70
|
+
self.notify.emit(());
|
|
58
71
|
}
|
|
72
|
+
|
|
73
|
+
Ok(())
|
|
59
74
|
}
|
|
60
75
|
|
|
61
|
-
fn
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
FunctionDropDownMsg::SetValues(values) => {
|
|
68
|
-
self.values = Some(values);
|
|
69
|
-
self.selected = 0;
|
|
70
|
-
true
|
|
71
|
-
},
|
|
72
|
-
FunctionDropDownMsg::ItemSelect => {
|
|
73
|
-
if let Some(ref values) = self.values {
|
|
74
|
-
match values.get(self.selected) {
|
|
75
|
-
None => {
|
|
76
|
-
console::error_1(&"Selected out-of-bounds".into());
|
|
77
|
-
false
|
|
78
|
-
},
|
|
79
|
-
Some(x) => {
|
|
80
|
-
self.on_select.as_ref().unwrap().emit(*x);
|
|
81
|
-
false
|
|
82
|
-
},
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
console::error_1(&"No Values".into());
|
|
86
|
-
false
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
FunctionDropDownMsg::ItemDown => {
|
|
90
|
-
self.selected += 1;
|
|
91
|
-
if let Some(ref values) = self.values
|
|
92
|
-
&& self.selected >= values.len()
|
|
93
|
-
{
|
|
94
|
-
self.selected = 0;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
true
|
|
98
|
-
},
|
|
99
|
-
FunctionDropDownMsg::ItemUp => {
|
|
100
|
-
if let Some(ref values) = self.values
|
|
101
|
-
&& self.selected < 1
|
|
102
|
-
{
|
|
103
|
-
self.selected = values.len();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
self.selected -= 1;
|
|
107
|
-
true
|
|
108
|
-
},
|
|
76
|
+
pub fn item_select(&self) {
|
|
77
|
+
let state = self.state.borrow();
|
|
78
|
+
if let Some(value) = state.values.get(state.selected)
|
|
79
|
+
&& let Some(ref cb) = state.on_select
|
|
80
|
+
{
|
|
81
|
+
cb.emit(*value);
|
|
109
82
|
}
|
|
110
83
|
}
|
|
111
84
|
|
|
112
|
-
fn
|
|
113
|
-
|
|
85
|
+
pub fn item_down(&self) {
|
|
86
|
+
let mut state = self.state.borrow_mut();
|
|
87
|
+
state.selected += 1;
|
|
88
|
+
if state.selected >= state.values.len() {
|
|
89
|
+
state.selected = 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
drop(state);
|
|
93
|
+
self.notify.emit(());
|
|
114
94
|
}
|
|
115
95
|
|
|
116
|
-
fn
|
|
117
|
-
let
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
96
|
+
pub fn item_up(&self) {
|
|
97
|
+
let mut state = self.state.borrow_mut();
|
|
98
|
+
if state.selected < 1 {
|
|
99
|
+
state.selected = state.values.len();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
state.selected -= 1;
|
|
103
|
+
drop(state);
|
|
104
|
+
self.notify.emit(());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
pub fn hide(&self) -> ApiResult<()> {
|
|
108
|
+
self.state.borrow_mut().target = None;
|
|
109
|
+
self.notify.emit(());
|
|
110
|
+
Ok(())
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[derive(Properties, PartialEq)]
|
|
115
|
+
pub struct FunctionDropDownPortalProps {
|
|
116
|
+
pub element: FunctionDropDownElement,
|
|
117
|
+
pub theme: String,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
pub struct FunctionDropDownPortal {
|
|
121
|
+
_sub: Subscription,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
impl Component for FunctionDropDownPortal {
|
|
125
|
+
type Message = ();
|
|
126
|
+
type Properties = FunctionDropDownPortalProps;
|
|
127
|
+
|
|
128
|
+
fn create(ctx: &Context<Self>) -> Self {
|
|
129
|
+
let link = ctx.link().clone();
|
|
130
|
+
let sub = ctx
|
|
131
|
+
.props()
|
|
132
|
+
.element
|
|
133
|
+
.notify
|
|
134
|
+
.add_listener(move |()| link.send_message(()));
|
|
135
|
+
Self { _sub: sub }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fn update(&mut self, _ctx: &Context<Self>, _msg: ()) -> bool {
|
|
139
|
+
true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
143
|
+
let state = ctx.props().element.state.borrow();
|
|
144
|
+
let target = state.target.clone();
|
|
145
|
+
let on_close = {
|
|
146
|
+
let element = ctx.props().element.clone();
|
|
147
|
+
Callback::from(move |()| {
|
|
148
|
+
let _ = element.hide();
|
|
149
|
+
})
|
|
147
150
|
};
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
if target.is_some() {
|
|
153
|
+
let values = state.values.clone();
|
|
154
|
+
let selected = state.selected;
|
|
155
|
+
let on_select = state.on_select.clone();
|
|
156
|
+
drop(state);
|
|
157
|
+
|
|
158
|
+
html! {
|
|
159
|
+
<PortalModal
|
|
160
|
+
tag_name="perspective-dropdown"
|
|
161
|
+
{target}
|
|
162
|
+
own_focus=false
|
|
163
|
+
{on_close}
|
|
164
|
+
theme={ctx.props().theme.clone()}
|
|
165
|
+
>
|
|
166
|
+
<FunctionDropDownView {values} {selected} {on_select} />
|
|
167
|
+
</PortalModal>
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
html! {}
|
|
171
|
+
}
|
|
150
172
|
}
|
|
151
173
|
}
|
|
174
|
+
|
|
175
|
+
#[derive(Properties, PartialEq)]
|
|
176
|
+
struct FunctionDropDownViewProps {
|
|
177
|
+
values: Vec<CompletionItemSuggestion>,
|
|
178
|
+
selected: usize,
|
|
179
|
+
on_select: Option<Callback<CompletionItemSuggestion>>,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#[function_component]
|
|
183
|
+
fn FunctionDropDownView(props: &FunctionDropDownViewProps) -> Html {
|
|
184
|
+
let body = html! {
|
|
185
|
+
if !props.values.is_empty() {
|
|
186
|
+
{ for props.values
|
|
187
|
+
.iter()
|
|
188
|
+
.enumerate()
|
|
189
|
+
.map(|(idx, value)| {
|
|
190
|
+
let click = props.on_select.as_ref().unwrap().reform({
|
|
191
|
+
let value = *value;
|
|
192
|
+
move |_: MouseEvent| value
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
html! {
|
|
196
|
+
if idx == props.selected {
|
|
197
|
+
<div onmousedown={click} class="selected">
|
|
198
|
+
<span style="font-weight:500">{ value.label }</span>
|
|
199
|
+
<br/>
|
|
200
|
+
<span style="padding-left:12px">{ value.documentation }</span>
|
|
201
|
+
</div>
|
|
202
|
+
} else {
|
|
203
|
+
<div onmousedown={click}>
|
|
204
|
+
<span style="font-weight:500">{ value.label }</span>
|
|
205
|
+
<br/>
|
|
206
|
+
<span style="padding-left:12px">{ value.documentation }</span>
|
|
207
|
+
</div>
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}) }
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
html! { <><style>{ CSS }</style>{ body }</> }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
fn filter_values(input: &str) -> Vec<CompletionItemSuggestion> {
|
|
218
|
+
let input = input.to_lowercase();
|
|
219
|
+
COMPLETIONS
|
|
220
|
+
.iter()
|
|
221
|
+
.filter(|x| x.label.to_lowercase().starts_with(&input))
|
|
222
|
+
.cloned()
|
|
223
|
+
.collect::<Vec<_>>()
|
|
224
|
+
}
|