@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
|
@@ -23,19 +23,8 @@ use yew::virtual_dom::VChild;
|
|
|
23
23
|
|
|
24
24
|
use super::scroll_panel_item::ScrollPanelItem;
|
|
25
25
|
use crate::components::style::LocalStyle;
|
|
26
|
+
use crate::css;
|
|
26
27
|
use crate::utils::*;
|
|
27
|
-
use crate::*;
|
|
28
|
-
|
|
29
|
-
pub struct ScrollPanel {
|
|
30
|
-
viewport_ref: NodeRef,
|
|
31
|
-
viewport_height: f64,
|
|
32
|
-
viewport_width: f64,
|
|
33
|
-
content_window: Option<ContentWindow>,
|
|
34
|
-
needs_rerender: bool,
|
|
35
|
-
total_height: f64,
|
|
36
|
-
_dimensions_reset_sub: Option<Subscription>,
|
|
37
|
-
_resize_sub: Option<Subscription>,
|
|
38
|
-
}
|
|
39
28
|
|
|
40
29
|
#[derive(Properties)]
|
|
41
30
|
pub struct ScrollPanelProps {
|
|
@@ -96,71 +85,15 @@ pub enum ScrollPanelMsg {
|
|
|
96
85
|
ChildrenChanged,
|
|
97
86
|
}
|
|
98
87
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
self.viewport(ctx).cast::<Element>().unwrap()
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
#[derive(PartialEq)]
|
|
113
|
-
struct ContentWindow {
|
|
114
|
-
scroll_top: f64,
|
|
115
|
-
start_y: f64,
|
|
116
|
-
visible_range: Range<usize>,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
impl ScrollPanel {
|
|
120
|
-
fn calculate_window_content(&mut self, ctx: &Context<Self>) -> bool {
|
|
121
|
-
let viewport = self.viewport_elem(ctx);
|
|
122
|
-
let scroll_top = viewport.scroll_top() as f64;
|
|
123
|
-
let mut start_node = 0;
|
|
124
|
-
let mut start_y = 0_f64;
|
|
125
|
-
let mut offset = 0_f64;
|
|
126
|
-
let end_node = ctx
|
|
127
|
-
.props()
|
|
128
|
-
.children
|
|
129
|
-
.iter()
|
|
130
|
-
.enumerate()
|
|
131
|
-
.find_or_last(|(i, x)| {
|
|
132
|
-
if offset + x.props.get_size() < scroll_top {
|
|
133
|
-
start_node = *i + 1;
|
|
134
|
-
start_y = offset + x.props.get_size();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
offset += x.props.get_size();
|
|
138
|
-
offset > scroll_top + self.viewport_height
|
|
139
|
-
})
|
|
140
|
-
.map(|x| x.0)
|
|
141
|
-
.unwrap_or_default();
|
|
142
|
-
|
|
143
|
-
// Why is this `end_node + 2`, I can see you asking yourself? `end_node` is the
|
|
144
|
-
// index of the last visible child, but [`Range`] is an open interval so we must
|
|
145
|
-
// increment by 1. The next rendered element is always occluded by the parent
|
|
146
|
-
// container, it may seem unnecessary to render it, however not doing so causing
|
|
147
|
-
// scroll glitching in Chrome:
|
|
148
|
-
// * When the first pixel of the `end_node + 1` child is scrolled into view, the
|
|
149
|
-
// container element it is embedded in will expand past the end of the scroll
|
|
150
|
-
// container.
|
|
151
|
-
// * Chrome detects this and helpfully scrolls this new element into view,
|
|
152
|
-
// re-triggering the on scroll callback.
|
|
153
|
-
let visible_range = start_node..min!(ctx.props().children.len(), end_node + 2);
|
|
154
|
-
let content_window = Some(ContentWindow {
|
|
155
|
-
scroll_top,
|
|
156
|
-
start_y,
|
|
157
|
-
visible_range,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
let re_render = self.content_window != content_window;
|
|
161
|
-
self.content_window = content_window;
|
|
162
|
-
re_render
|
|
163
|
-
}
|
|
88
|
+
pub struct ScrollPanel {
|
|
89
|
+
viewport_ref: NodeRef,
|
|
90
|
+
viewport_height: f64,
|
|
91
|
+
viewport_width: f64,
|
|
92
|
+
content_window: Option<ContentWindow>,
|
|
93
|
+
needs_rerender: bool,
|
|
94
|
+
total_height: f64,
|
|
95
|
+
_dimensions_reset_sub: Option<Subscription>,
|
|
96
|
+
_resize_sub: Option<Subscription>,
|
|
164
97
|
}
|
|
165
98
|
|
|
166
99
|
impl Component for ScrollPanel {
|
|
@@ -211,12 +144,12 @@ impl Component for ScrollPanel {
|
|
|
211
144
|
let viewport = self.viewport_elem(ctx);
|
|
212
145
|
let rect = viewport.get_bounding_client_rect();
|
|
213
146
|
let viewport_height = rect.height() - 8.0;
|
|
214
|
-
let viewport_width =
|
|
147
|
+
let viewport_width = self.viewport_width.max(rect.width() - 6.0);
|
|
215
148
|
let re_render = self.viewport_height != viewport_height
|
|
216
149
|
|| self.viewport_width != viewport_width;
|
|
217
150
|
|
|
218
151
|
self.viewport_height = rect.height() - 8.0;
|
|
219
|
-
self.viewport_width =
|
|
152
|
+
self.viewport_width = self.viewport_width.max(rect.width() - 6.0);
|
|
220
153
|
re_render
|
|
221
154
|
},
|
|
222
155
|
ScrollPanelMsg::CalculateWindowContent => self.calculate_window_content(ctx),
|
|
@@ -254,7 +187,7 @@ impl Component for ScrollPanel {
|
|
|
254
187
|
),
|
|
255
188
|
};
|
|
256
189
|
|
|
257
|
-
let width_style = format!("width:{}px",
|
|
190
|
+
let width_style = format!("width:{}px", self.viewport_width.max(0.0));
|
|
258
191
|
let items = if !windowed_items.is_empty() {
|
|
259
192
|
let onscroll = ctx.link().batch_callback(|_| {
|
|
260
193
|
vec![
|
|
@@ -309,3 +242,70 @@ impl Component for ScrollPanel {
|
|
|
309
242
|
]);
|
|
310
243
|
}
|
|
311
244
|
}
|
|
245
|
+
|
|
246
|
+
impl ScrollPanel {
|
|
247
|
+
fn viewport<'a, 'b: 'a, 'c: 'a>(&'b self, ctx: &'c Context<Self>) -> &'a NodeRef {
|
|
248
|
+
ctx.props()
|
|
249
|
+
.viewport_ref
|
|
250
|
+
.as_ref()
|
|
251
|
+
.unwrap_or(&self.viewport_ref)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
fn viewport_elem(&self, ctx: &Context<Self>) -> Element {
|
|
255
|
+
self.viewport(ctx).cast::<Element>().unwrap()
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
#[derive(PartialEq)]
|
|
260
|
+
struct ContentWindow {
|
|
261
|
+
scroll_top: f64,
|
|
262
|
+
start_y: f64,
|
|
263
|
+
visible_range: Range<usize>,
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
impl ScrollPanel {
|
|
267
|
+
fn calculate_window_content(&mut self, ctx: &Context<Self>) -> bool {
|
|
268
|
+
let viewport = self.viewport_elem(ctx);
|
|
269
|
+
let scroll_top = viewport.scroll_top() as f64;
|
|
270
|
+
let mut start_node = 0;
|
|
271
|
+
let mut start_y = 0_f64;
|
|
272
|
+
let mut offset = 0_f64;
|
|
273
|
+
let end_node = ctx
|
|
274
|
+
.props()
|
|
275
|
+
.children
|
|
276
|
+
.iter()
|
|
277
|
+
.enumerate()
|
|
278
|
+
.find_or_last(|(i, x)| {
|
|
279
|
+
if offset + x.props.get_size() < scroll_top {
|
|
280
|
+
start_node = *i + 1;
|
|
281
|
+
start_y = offset + x.props.get_size();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
offset += x.props.get_size();
|
|
285
|
+
offset > scroll_top + self.viewport_height
|
|
286
|
+
})
|
|
287
|
+
.map(|x| x.0)
|
|
288
|
+
.unwrap_or_default();
|
|
289
|
+
|
|
290
|
+
// Why is this `end_node + 2`, I can see you asking yourself? `end_node` is the
|
|
291
|
+
// index of the last visible child, but [`Range`] is an open interval so we must
|
|
292
|
+
// increment by 1. The next rendered element is always occluded by the parent
|
|
293
|
+
// container, it may seem unnecessary to render it, however not doing so causing
|
|
294
|
+
// scroll glitching in Chrome:
|
|
295
|
+
// * When the first pixel of the `end_node + 1` child is scrolled into view, the
|
|
296
|
+
// container element it is embedded in will expand past the end of the scroll
|
|
297
|
+
// container.
|
|
298
|
+
// * Chrome detects this and helpfully scrolls this new element into view,
|
|
299
|
+
// re-triggering the on scroll callback.
|
|
300
|
+
let visible_range = start_node..ctx.props().children.len().min(end_node + 2);
|
|
301
|
+
let content_window = Some(ContentWindow {
|
|
302
|
+
scroll_top,
|
|
303
|
+
start_y,
|
|
304
|
+
visible_range,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
let re_render = self.content_window != content_window;
|
|
308
|
+
self.content_window = content_window;
|
|
309
|
+
re_render
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -13,88 +13,88 @@
|
|
|
13
13
|
// Forked from https://github.com/AircastDev/yew-virtual-scroller (Apache 2.0)
|
|
14
14
|
// Adds support for Yew 0.19, auto-width and a simplified message structure.
|
|
15
15
|
|
|
16
|
-
#[cfg(debug_assertions)]
|
|
17
16
|
use std::cell::Cell;
|
|
18
|
-
#[cfg(debug_assertions)]
|
|
19
17
|
use std::rc::Rc;
|
|
20
18
|
|
|
21
19
|
use yew::prelude::*;
|
|
22
20
|
|
|
23
21
|
#[derive(PartialEq, Properties)]
|
|
24
22
|
pub struct ScrollPanelItemProps {
|
|
23
|
+
pub children: Children,
|
|
24
|
+
|
|
25
25
|
/// The expected size of this component in pixels. Calculating this value
|
|
26
26
|
/// ahead of time makes it easier to implement a high-performance virtual
|
|
27
27
|
/// renderer without resorting to weird tricks, _but_ checking that this
|
|
28
28
|
/// hint is correct is nearly as expensive. So, we only generate the
|
|
29
29
|
/// validation code in debug builds.
|
|
30
30
|
pub size_hint: f64,
|
|
31
|
-
pub children: Children,
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
/// Should we measure the child sizes or just rely on the hint? This
|
|
33
|
+
/// option may be enabled during debugging to validation render optimization
|
|
34
|
+
/// via [`Self::size_hint`], but will faile tests due to the extra DOM
|
|
35
|
+
/// structure it emits.
|
|
36
|
+
#[prop_or_default]
|
|
37
|
+
pub is_debug_mode: bool,
|
|
38
|
+
|
|
39
|
+
/// Communicate the panel size to virtual parent
|
|
34
40
|
#[prop_or_default]
|
|
35
41
|
measured_size: Rc<Cell<Option<f64>>>,
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
impl ScrollPanelItemProps {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
pub fn get_size(&self) -> f64 {
|
|
46
|
-
self.size_hint
|
|
45
|
+
pub(crate) fn get_size(&self) -> f64 {
|
|
46
|
+
if self.is_debug_mode {
|
|
47
|
+
self.measured_size.get().unwrap_or(self.size_hint)
|
|
48
|
+
} else {
|
|
49
|
+
self.size_hint
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
#[cfg(debug_assertions)]
|
|
51
54
|
pub struct ScrollPanelItem {
|
|
52
55
|
node: NodeRef,
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
#[cfg(not(debug_assertions))]
|
|
56
|
-
pub struct ScrollPanelItem {}
|
|
57
|
-
|
|
58
58
|
impl Component for ScrollPanelItem {
|
|
59
59
|
type Message = ();
|
|
60
60
|
type Properties = ScrollPanelItemProps;
|
|
61
61
|
|
|
62
|
-
#[cfg(debug_assertions)]
|
|
63
62
|
fn create(ctx: &Context<Self>) -> Self {
|
|
64
|
-
ctx.props().
|
|
63
|
+
if ctx.props().is_debug_mode {
|
|
64
|
+
ctx.props().measured_size.set(Some(ctx.props().size_hint));
|
|
65
|
+
}
|
|
66
|
+
|
|
65
67
|
Self {
|
|
66
68
|
node: NodeRef::default(),
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
#[cfg(not(debug_assertions))]
|
|
71
|
-
fn create(_ctx: &Context<Self>) -> Self {
|
|
72
|
-
Self {}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
#[cfg(debug_assertions)]
|
|
76
72
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
77
73
|
html! {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
if ctx.props().is_debug_mode {
|
|
75
|
+
<div class="debug-size-wrapper" style="display: flow-root" ref={self.node.clone()}>
|
|
76
|
+
for child in ctx.props().children.iter() {
|
|
77
|
+
{ child }
|
|
78
|
+
}
|
|
79
|
+
</div>
|
|
80
|
+
} else {
|
|
81
|
+
for child in ctx.props().children.iter() {
|
|
82
|
+
{ child }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
#[cfg(not(debug_assertions))]
|
|
85
|
-
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
86
|
-
html! { { for ctx.props().children.iter() } }
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
#[cfg(debug_assertions)]
|
|
90
88
|
fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
|
|
91
|
-
ctx.props().
|
|
89
|
+
if ctx.props().is_debug_mode {
|
|
90
|
+
ctx.props().measured_size.set(Some(ctx.props().size_hint));
|
|
91
|
+
}
|
|
92
|
+
|
|
92
93
|
true
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
#[cfg(debug_assertions)]
|
|
96
96
|
fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
|
|
97
|
-
if first_render {
|
|
97
|
+
if first_render && ctx.props().is_debug_mode {
|
|
98
98
|
let elem = self.node.cast::<web_sys::HtmlElement>().unwrap();
|
|
99
99
|
let new_height = elem.get_bounding_client_rect().height();
|
|
100
100
|
if ctx.props().measured_size.get() != Some(new_height) {
|
|
@@ -17,26 +17,6 @@ use std::rc::Rc;
|
|
|
17
17
|
use wasm_bindgen::JsCast;
|
|
18
18
|
use yew::prelude::*;
|
|
19
19
|
|
|
20
|
-
#[derive(Clone, Eq, PartialEq)]
|
|
21
|
-
pub enum SelectItem<T> {
|
|
22
|
-
Option(T),
|
|
23
|
-
OptGroup(Cow<'static, str>, Vec<T>),
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
impl<T: Display> SelectItem<T> {
|
|
27
|
-
pub fn name<'a>(&self) -> Cow<'a, str> {
|
|
28
|
-
match self {
|
|
29
|
-
Self::Option(x) => format!("{x}").into(),
|
|
30
|
-
Self::OptGroup(x, _) => x.clone(),
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
pub enum SelectMsg {
|
|
36
|
-
SelectedChanged(i32),
|
|
37
|
-
KeyboardInput(bool, i32, String),
|
|
38
|
-
}
|
|
39
|
-
|
|
40
20
|
#[derive(Properties)]
|
|
41
21
|
pub struct SelectProps<T>
|
|
42
22
|
where
|
|
@@ -71,6 +51,11 @@ where
|
|
|
71
51
|
}
|
|
72
52
|
}
|
|
73
53
|
|
|
54
|
+
pub enum SelectMsg {
|
|
55
|
+
SelectedChanged(i32),
|
|
56
|
+
KeyboardInput(bool, i32, String),
|
|
57
|
+
}
|
|
58
|
+
|
|
74
59
|
/// A `<select>` HTML elements, lifted to support parameterization over a set of
|
|
75
60
|
/// values of a type `T`.
|
|
76
61
|
pub struct Select<T>
|
|
@@ -81,23 +66,6 @@ where
|
|
|
81
66
|
selected: T,
|
|
82
67
|
}
|
|
83
68
|
|
|
84
|
-
fn find_nth<T>(mut count: i32, items: &[SelectItem<T>]) -> Option<&T> {
|
|
85
|
-
for ref item in items.iter() {
|
|
86
|
-
match item {
|
|
87
|
-
SelectItem::Option(_) if count > 0 => {
|
|
88
|
-
count -= 1;
|
|
89
|
-
},
|
|
90
|
-
SelectItem::OptGroup(_, items) if count >= items.len() as i32 => {
|
|
91
|
-
count -= items.len() as i32;
|
|
92
|
-
},
|
|
93
|
-
SelectItem::OptGroup(_, items) => return items.get(count as usize),
|
|
94
|
-
SelectItem::Option(x) => return Some(x),
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
None
|
|
99
|
-
}
|
|
100
|
-
|
|
101
69
|
impl<T> Component for Select<T>
|
|
102
70
|
where
|
|
103
71
|
T: Clone + Display + PartialEq + 'static,
|
|
@@ -132,12 +100,12 @@ where
|
|
|
132
100
|
ctx.props().on_select.emit(self.selected.clone());
|
|
133
101
|
return true;
|
|
134
102
|
}
|
|
135
|
-
} else if code.as_str() == "ArrowDown"
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
103
|
+
} else if code.as_str() == "ArrowDown" {
|
|
104
|
+
if let Some(x) = find_nth(idx + 1, &ctx.props().values) {
|
|
105
|
+
self.selected = x.clone();
|
|
106
|
+
ctx.props().on_select.emit(self.selected.clone());
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
141
109
|
}
|
|
142
110
|
}
|
|
143
111
|
|
|
@@ -259,7 +227,9 @@ where
|
|
|
259
227
|
|
|
260
228
|
html! {
|
|
261
229
|
if is_group_selected && ctx.props().label.is_some() {
|
|
262
|
-
<label>
|
|
230
|
+
<label>
|
|
231
|
+
{ ctx.props().label.as_ref().map(|x| x.to_string()).unwrap_or_default() }
|
|
232
|
+
</label>
|
|
263
233
|
<div class={wrapper_class} data-value={value.clone()}>{ select }</div>
|
|
264
234
|
} else {
|
|
265
235
|
<div class={wrapper_class} data-value={value}>{ select }</div>
|
|
@@ -267,3 +237,35 @@ where
|
|
|
267
237
|
}
|
|
268
238
|
}
|
|
269
239
|
}
|
|
240
|
+
|
|
241
|
+
#[derive(Clone, Eq, PartialEq)]
|
|
242
|
+
pub enum SelectItem<T> {
|
|
243
|
+
Option(T),
|
|
244
|
+
OptGroup(Cow<'static, str>, Vec<T>),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
impl<T: Display> SelectItem<T> {
|
|
248
|
+
pub fn name<'a>(&self) -> Cow<'a, str> {
|
|
249
|
+
match self {
|
|
250
|
+
Self::Option(x) => format!("{x}").into(),
|
|
251
|
+
Self::OptGroup(x, _) => x.clone(),
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
fn find_nth<T>(mut count: i32, items: &[SelectItem<T>]) -> Option<&T> {
|
|
257
|
+
for ref item in items.iter() {
|
|
258
|
+
match item {
|
|
259
|
+
SelectItem::Option(_) if count > 0 => {
|
|
260
|
+
count -= 1;
|
|
261
|
+
},
|
|
262
|
+
SelectItem::OptGroup(_, items) if count >= items.len() as i32 => {
|
|
263
|
+
count -= items.len() as i32;
|
|
264
|
+
},
|
|
265
|
+
SelectItem::OptGroup(_, items) => return items.get(count as usize),
|
|
266
|
+
SelectItem::Option(x) => return Some(x),
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
None
|
|
271
|
+
}
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
use perspective_client::clone;
|
|
14
14
|
use web_sys::Element;
|
|
15
15
|
use yew::{
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Callback, Children, Html, Properties, function_component, html, use_effect_with, use_node_ref,
|
|
17
|
+
use_state_eq,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
use crate::components::containers::sidebar_close_button::SidebarCloseButton;
|
|
20
21
|
use crate::components::editable_header::{EditableHeader, EditableHeaderProps};
|
|
21
22
|
|
|
22
23
|
#[derive(PartialEq, Clone, Properties)]
|
|
@@ -70,20 +71,3 @@ pub fn Sidebar(p: &SidebarProps) -> Html {
|
|
|
70
71
|
</div>
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
|
-
|
|
74
|
-
#[derive(PartialEq, Clone, Properties)]
|
|
75
|
-
pub struct SidebarCloseButtonProps {
|
|
76
|
-
pub on_close_sidebar: Callback<()>,
|
|
77
|
-
pub id: AttrValue,
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
#[function_component]
|
|
81
|
-
pub fn SidebarCloseButton(p: &SidebarCloseButtonProps) -> Html {
|
|
82
|
-
let onclick = yew::use_callback(p.on_close_sidebar.clone(), |_, cb| cb.emit(()));
|
|
83
|
-
let id = &p.id;
|
|
84
|
-
html! {
|
|
85
|
-
<div {onclick} {id} class="sidebar_close_button">
|
|
86
|
-
<div class="sidebar_close_button_inner" />
|
|
87
|
-
</div>
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -10,15 +10,21 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use
|
|
13
|
+
use yew::{AttrValue, Callback, Html, Properties, function_component, html};
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
#[derive(Serialize, Deserialize)]
|
|
20
|
-
pub struct SymbolConfig {
|
|
21
|
-
pub symbols: HashMap<String, String>,
|
|
15
|
+
#[derive(PartialEq, Clone, Properties)]
|
|
16
|
+
pub struct SidebarCloseButtonProps {
|
|
17
|
+
pub on_close_sidebar: Callback<()>,
|
|
18
|
+
pub id: AttrValue,
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
#[function_component]
|
|
22
|
+
pub fn SidebarCloseButton(p: &SidebarCloseButtonProps) -> Html {
|
|
23
|
+
let onclick = yew::use_callback(p.on_close_sidebar.clone(), |_, cb| cb.emit(()));
|
|
24
|
+
let id = &p.id;
|
|
25
|
+
html! {
|
|
26
|
+
<div {onclick} {id} class="sidebar_close_button">
|
|
27
|
+
<div class="sidebar_close_button_inner" />
|
|
28
|
+
</div>
|
|
29
|
+
}
|
|
30
|
+
}
|