@perspective-dev/viewer 4.3.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 -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/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/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/wasm/perspective-viewer.d.ts +57 -53
- package/dist/wasm/perspective-viewer.js +190 -165
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +17 -18
- 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} +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/{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} +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 +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 +22 -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 -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 +1 -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.rs +83 -9
- 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}/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 -21
- 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/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-68fef752754ffbc6}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → 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
|
@@ -27,6 +27,7 @@ use std::rc::Rc;
|
|
|
27
27
|
|
|
28
28
|
pub use empty_column::*;
|
|
29
29
|
pub use invalid_column::*;
|
|
30
|
+
use perspective_client::config::ViewConfig;
|
|
30
31
|
use perspective_js::utils::ApiFuture;
|
|
31
32
|
pub use pivot_column::*;
|
|
32
33
|
use web_sys::*;
|
|
@@ -39,17 +40,20 @@ use self::inactive_column::*;
|
|
|
39
40
|
use super::containers::scroll_panel::*;
|
|
40
41
|
use super::containers::split_panel::{Orientation, SplitPanel};
|
|
41
42
|
use super::style::LocalStyle;
|
|
43
|
+
use crate::components::column_dropdown::{ColumnDropDownElement, ColumnDropDownPortal};
|
|
42
44
|
use crate::components::containers::scroll_panel_item::ScrollPanelItem;
|
|
43
|
-
use crate::
|
|
45
|
+
use crate::css;
|
|
44
46
|
use crate::dragdrop::*;
|
|
45
|
-
use crate::model::*;
|
|
46
47
|
use crate::presentation::ColumnLocator;
|
|
47
48
|
use crate::renderer::*;
|
|
49
|
+
use crate::session::drag_drop_update::*;
|
|
48
50
|
use crate::session::*;
|
|
51
|
+
use crate::tasks::{
|
|
52
|
+
ActiveColumnState, ActiveColumnStateData, ColumnsIteratorSet, can_render_column_styles,
|
|
53
|
+
};
|
|
49
54
|
use crate::utils::*;
|
|
50
|
-
use crate::*;
|
|
51
55
|
|
|
52
|
-
#[derive(Properties
|
|
56
|
+
#[derive(Properties)]
|
|
53
57
|
pub struct ColumnSelectorProps {
|
|
54
58
|
/// Fires when the expression/config column is open.
|
|
55
59
|
pub on_open_expr_panel: Callback<ColumnLocator>,
|
|
@@ -57,30 +61,48 @@ pub struct ColumnSelectorProps {
|
|
|
57
61
|
/// This is passed to the add_expression_button for styling.
|
|
58
62
|
pub selected_column: Option<ColumnLocator>,
|
|
59
63
|
|
|
60
|
-
///
|
|
61
|
-
|
|
62
|
-
pub
|
|
64
|
+
/// Value props threaded from root's `SessionProps` / `RendererProps`.
|
|
65
|
+
pub has_table: Option<TableLoadState>,
|
|
66
|
+
pub named_column_count: usize,
|
|
67
|
+
pub view_config: PtrEqRc<ViewConfig>,
|
|
68
|
+
pub drag_column: Option<String>,
|
|
69
|
+
|
|
70
|
+
/// Cloned session metadata snapshot — threaded from `SessionProps`
|
|
71
|
+
/// so that metadata changes trigger re-renders via prop diffing.
|
|
72
|
+
pub metadata: SessionMetadataRc,
|
|
73
|
+
|
|
74
|
+
/// Selected theme name, threaded for PortalModal consumers.
|
|
75
|
+
pub selected_theme: Option<String>,
|
|
63
76
|
|
|
64
77
|
// State
|
|
65
78
|
pub session: Session,
|
|
66
79
|
pub renderer: Renderer,
|
|
67
80
|
pub dragdrop: DragDrop,
|
|
81
|
+
|
|
82
|
+
/// Fires when this component is resized via the UI.
|
|
83
|
+
#[prop_or_default]
|
|
84
|
+
pub on_resize: Option<Rc<PubSub<()>>>,
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
impl PartialEq for ColumnSelectorProps {
|
|
71
88
|
fn eq(&self, rhs: &Self) -> bool {
|
|
72
89
|
self.selected_column == rhs.selected_column
|
|
90
|
+
&& self.has_table == rhs.has_table
|
|
91
|
+
&& self.named_column_count == rhs.named_column_count
|
|
92
|
+
&& self.view_config == rhs.view_config
|
|
93
|
+
&& self.drag_column == rhs.drag_column
|
|
94
|
+
&& self.metadata == rhs.metadata
|
|
95
|
+
&& self.selected_theme == rhs.selected_theme
|
|
73
96
|
}
|
|
74
97
|
}
|
|
75
98
|
|
|
76
99
|
#[derive(Debug)]
|
|
77
100
|
pub enum ColumnSelectorMsg {
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
/// Triggers a plain re-render; used as `onselect`/`ondragenter` callbacks
|
|
102
|
+
/// from `ConfigSelector` after it mutates the view config.
|
|
103
|
+
Redraw,
|
|
80
104
|
HoverActiveIndex(Option<usize>),
|
|
81
105
|
SetWidth(f64),
|
|
82
|
-
Drag(DragEffect),
|
|
83
|
-
DragEnd,
|
|
84
106
|
Drop((String, DragTarget, DragEffect, usize)),
|
|
85
107
|
}
|
|
86
108
|
|
|
@@ -89,8 +111,7 @@ use ColumnSelectorMsg::*;
|
|
|
89
111
|
/// A `ColumnSelector` controls the `columns` field of the `ViewConfig`,
|
|
90
112
|
/// deriving its options from the table columns and `ViewConfig` expressions.
|
|
91
113
|
pub struct ColumnSelector {
|
|
92
|
-
_subscriptions: [Subscription;
|
|
93
|
-
named_row_count: usize,
|
|
114
|
+
_subscriptions: [Subscription; 1],
|
|
94
115
|
drag_container: DragDropContainer,
|
|
95
116
|
column_dropdown: ColumnDropDownElement,
|
|
96
117
|
viewport_width: f64,
|
|
@@ -103,44 +124,14 @@ impl Component for ColumnSelector {
|
|
|
103
124
|
|
|
104
125
|
fn create(ctx: &Context<Self>) -> Self {
|
|
105
126
|
let ColumnSelectorProps {
|
|
106
|
-
dragdrop,
|
|
107
|
-
renderer,
|
|
108
|
-
session,
|
|
109
|
-
..
|
|
127
|
+
dragdrop, session, ..
|
|
110
128
|
} = ctx.props();
|
|
111
|
-
let table_sub = {
|
|
112
|
-
let cb = ctx.link().callback(|_| ColumnSelectorMsg::TableLoaded);
|
|
113
|
-
session.table_loaded.add_listener(cb)
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
let view_sub = {
|
|
117
|
-
let cb = ctx.link().callback(|_| ColumnSelectorMsg::ViewCreated);
|
|
118
|
-
session.view_created.add_listener(cb)
|
|
119
|
-
};
|
|
120
129
|
|
|
121
130
|
let drop_sub = {
|
|
122
131
|
let cb = ctx.link().callback(ColumnSelectorMsg::Drop);
|
|
123
132
|
dragdrop.drop_received.add_listener(cb)
|
|
124
133
|
};
|
|
125
134
|
|
|
126
|
-
let drag_sub = {
|
|
127
|
-
let cb = ctx.link().callback(ColumnSelectorMsg::Drag);
|
|
128
|
-
dragdrop.dragstart_received.add_listener(cb)
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
let dragend_sub = {
|
|
132
|
-
let cb = ctx.link().callback(|_| ColumnSelectorMsg::DragEnd);
|
|
133
|
-
dragdrop.dragend_received.add_listener(cb)
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
let named = maybe! {
|
|
137
|
-
let plugin =
|
|
138
|
-
renderer.get_active_plugin().ok()?;
|
|
139
|
-
|
|
140
|
-
Some(plugin.config_column_names()?.length() as usize)
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
let named_row_count = named.unwrap_or_default();
|
|
144
135
|
let drag_container = DragDropContainer::new(|| {}, {
|
|
145
136
|
let link = ctx.link().clone();
|
|
146
137
|
move || link.send_message(ColumnSelectorMsg::HoverActiveIndex(None))
|
|
@@ -148,8 +139,7 @@ impl Component for ColumnSelector {
|
|
|
148
139
|
|
|
149
140
|
let column_dropdown = ColumnDropDownElement::new(session.clone());
|
|
150
141
|
Self {
|
|
151
|
-
_subscriptions: [
|
|
152
|
-
named_row_count,
|
|
142
|
+
_subscriptions: [drop_sub],
|
|
153
143
|
viewport_width: 0f64,
|
|
154
144
|
drag_container,
|
|
155
145
|
column_dropdown,
|
|
@@ -159,23 +149,11 @@ impl Component for ColumnSelector {
|
|
|
159
149
|
|
|
160
150
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
161
151
|
match msg {
|
|
162
|
-
|
|
163
|
-
Drag(_) | DragEnd | TableLoaded => true,
|
|
152
|
+
Redraw => true,
|
|
164
153
|
SetWidth(w) => {
|
|
165
154
|
self.viewport_width = w;
|
|
166
155
|
false
|
|
167
156
|
},
|
|
168
|
-
ViewCreated => {
|
|
169
|
-
let named = maybe! {
|
|
170
|
-
let plugin =
|
|
171
|
-
ctx.props().renderer.get_active_plugin().ok()?;
|
|
172
|
-
|
|
173
|
-
Some(plugin.config_column_names()?.length() as usize)
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
self.named_row_count = named.unwrap_or_default();
|
|
177
|
-
true
|
|
178
|
-
},
|
|
179
157
|
HoverActiveIndex(Some(to_index)) => ctx
|
|
180
158
|
.props()
|
|
181
159
|
.dragdrop
|
|
@@ -185,33 +163,77 @@ impl Component for ColumnSelector {
|
|
|
185
163
|
true
|
|
186
164
|
},
|
|
187
165
|
Drop((column, DragTarget::Active, DragEffect::Move(DragTarget::Active), index)) => {
|
|
188
|
-
|
|
189
|
-
let
|
|
166
|
+
let is_invalid = {
|
|
167
|
+
let config = &ctx.props().view_config;
|
|
168
|
+
let from_index = config
|
|
169
|
+
.columns
|
|
170
|
+
.iter()
|
|
171
|
+
.position(|x| x.as_ref() == Some(&column));
|
|
172
|
+
|
|
173
|
+
let min_cols = ctx.props().renderer.metadata().min;
|
|
174
|
+
let is_to_empty = !config
|
|
175
|
+
.columns
|
|
176
|
+
.get(index)
|
|
177
|
+
.map(|x| x.is_some())
|
|
178
|
+
.unwrap_or_default();
|
|
179
|
+
|
|
180
|
+
min_cols
|
|
181
|
+
.and_then(|x| from_index.map(|fi| fi < x))
|
|
182
|
+
.unwrap_or_default()
|
|
183
|
+
&& is_to_empty
|
|
184
|
+
};
|
|
185
|
+
if !is_invalid {
|
|
186
|
+
let col_type = ctx
|
|
187
|
+
.props()
|
|
188
|
+
.metadata
|
|
189
|
+
.get_column_table_type(column.as_str())
|
|
190
|
+
.unwrap();
|
|
191
|
+
|
|
192
|
+
let update = ctx.props().view_config.create_drag_drop_update(
|
|
190
193
|
column,
|
|
194
|
+
col_type,
|
|
191
195
|
index,
|
|
192
196
|
DragTarget::Active,
|
|
193
197
|
DragEffect::Move(DragTarget::Active),
|
|
194
198
|
&ctx.props().renderer.metadata(),
|
|
199
|
+
ctx.props().metadata.get_features().unwrap(),
|
|
195
200
|
);
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
let session = ctx.props().session.clone();
|
|
203
|
+
let renderer = ctx.props().renderer.clone();
|
|
204
|
+
if session.update_view_config(update).is_ok() {
|
|
205
|
+
ApiFuture::spawn(async move {
|
|
206
|
+
renderer.apply_pending_plugin()?;
|
|
207
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
208
|
+
});
|
|
199
209
|
}
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
true
|
|
203
213
|
},
|
|
204
214
|
Drop((column, DragTarget::Active, effect, index)) => {
|
|
205
|
-
let
|
|
215
|
+
let col_type = ctx
|
|
216
|
+
.props()
|
|
217
|
+
.metadata
|
|
218
|
+
.get_column_table_type(column.as_str())
|
|
219
|
+
.unwrap();
|
|
220
|
+
let update = ctx.props().view_config.create_drag_drop_update(
|
|
206
221
|
column,
|
|
222
|
+
col_type,
|
|
207
223
|
index,
|
|
208
224
|
DragTarget::Active,
|
|
209
225
|
effect,
|
|
210
226
|
&ctx.props().renderer.metadata(),
|
|
227
|
+
ctx.props().metadata.get_features().unwrap(),
|
|
211
228
|
);
|
|
212
229
|
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
let session = ctx.props().session.clone();
|
|
231
|
+
let renderer = ctx.props().renderer.clone();
|
|
232
|
+
if session.update_view_config(update).is_ok() {
|
|
233
|
+
ApiFuture::spawn(async move {
|
|
234
|
+
renderer.apply_pending_plugin()?;
|
|
235
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
236
|
+
});
|
|
215
237
|
}
|
|
216
238
|
|
|
217
239
|
true
|
|
@@ -228,10 +250,29 @@ impl Component for ColumnSelector {
|
|
|
228
250
|
dragdrop,
|
|
229
251
|
..
|
|
230
252
|
} = ctx.props();
|
|
231
|
-
let
|
|
253
|
+
let metadata = &ctx.props().metadata;
|
|
254
|
+
|
|
255
|
+
// When `config.columns` is empty but the table has columns (transient
|
|
256
|
+
// state during `load()` after `reset()` clears the config), fill in
|
|
257
|
+
// all table columns as active — matching `validate_view_config()`.
|
|
258
|
+
let prop_config = &ctx.props().view_config;
|
|
259
|
+
let config = if prop_config.columns.is_empty() {
|
|
260
|
+
if let Some(table_cols) = metadata.get_table_columns() {
|
|
261
|
+
ViewConfig {
|
|
262
|
+
columns: table_cols.iter().map(|c| Some(c.clone())).collect(),
|
|
263
|
+
..(**prop_config).clone()
|
|
264
|
+
}
|
|
265
|
+
.into()
|
|
266
|
+
} else {
|
|
267
|
+
prop_config.clone()
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
prop_config.clone()
|
|
271
|
+
};
|
|
272
|
+
|
|
232
273
|
let is_aggregated = config.is_aggregated();
|
|
233
|
-
let columns_iter =
|
|
234
|
-
let onselect = ctx.link().callback(|()|
|
|
274
|
+
let columns_iter = ColumnsIteratorSet::new(&config, metadata, renderer, dragdrop);
|
|
275
|
+
let onselect = ctx.link().callback(|()| Redraw);
|
|
235
276
|
let ondragenter = ctx.link().callback(HoverActiveIndex);
|
|
236
277
|
let ondragover = Callback::from(|_event: DragEvent| _event.prevent_default());
|
|
237
278
|
let ondrop = Callback::from({
|
|
@@ -244,8 +285,8 @@ impl Component for ColumnSelector {
|
|
|
244
285
|
move |_| dragdrop.notify_drag_end()
|
|
245
286
|
});
|
|
246
287
|
|
|
247
|
-
let mut active_classes = classes!();
|
|
248
|
-
if ctx.props().
|
|
288
|
+
let mut active_classes = classes!("scrollable");
|
|
289
|
+
if ctx.props().drag_column.is_some() {
|
|
249
290
|
active_classes.push("dragdrop-highlight");
|
|
250
291
|
};
|
|
251
292
|
|
|
@@ -258,8 +299,7 @@ impl Component for ColumnSelector {
|
|
|
258
299
|
+ config.split_by.len()
|
|
259
300
|
+ config.filter.len()
|
|
260
301
|
+ config.sort.len()) as f64,
|
|
261
|
-
|
|
262
|
-
.metadata()
|
|
302
|
+
metadata
|
|
263
303
|
.get_features()
|
|
264
304
|
.map(|x| {
|
|
265
305
|
let mut y = 0.0;
|
|
@@ -288,7 +328,11 @@ impl Component for ColumnSelector {
|
|
|
288
328
|
<ScrollPanelItem key="config_selector" {size_hint}>
|
|
289
329
|
<ConfigSelector
|
|
290
330
|
onselect={onselect.clone()}
|
|
291
|
-
ondragenter={ctx.link().callback(|()|
|
|
331
|
+
ondragenter={ctx.link().callback(|()| Redraw)}
|
|
332
|
+
view_config={ctx.props().view_config.clone()}
|
|
333
|
+
drag_column={ctx.props().drag_column.clone()}
|
|
334
|
+
metadata={metadata.clone()}
|
|
335
|
+
selected_theme={ctx.props().selected_theme.clone()}
|
|
292
336
|
{dragdrop}
|
|
293
337
|
{renderer}
|
|
294
338
|
{session}
|
|
@@ -296,11 +340,11 @@ impl Component for ColumnSelector {
|
|
|
296
340
|
</ScrollPanelItem>
|
|
297
341
|
};
|
|
298
342
|
|
|
299
|
-
let mut named_count =
|
|
343
|
+
let mut named_count = ctx.props().named_column_count;
|
|
300
344
|
let mut active_columns: Vec<_> = columns_iter
|
|
301
345
|
.active()
|
|
302
346
|
.enumerate()
|
|
303
|
-
.map(|(idx, name)| {
|
|
347
|
+
.map(|(idx, name): (usize, ActiveColumnState)| {
|
|
304
348
|
let ondragenter = ondragenter.reform(move |_| Some(idx));
|
|
305
349
|
let size_hint = if named_count > 0 { 50.0 } else { 28.0 };
|
|
306
350
|
named_count = named_count.saturating_sub(1);
|
|
@@ -315,6 +359,34 @@ impl Component for ColumnSelector {
|
|
|
315
359
|
Some(ColumnLocator::Table(x)) | Some(ColumnLocator::Expression(x))
|
|
316
360
|
if x == &key );
|
|
317
361
|
|
|
362
|
+
// Compute metadata-derived props here so that changes to
|
|
363
|
+
// session metadata propagate via prop diffing.
|
|
364
|
+
// For DragOver placeholders, resolve the type from the
|
|
365
|
+
// dragged column (since `get_name()` returns `None`).
|
|
366
|
+
let col_type = name
|
|
367
|
+
.get_name()
|
|
368
|
+
.and_then(|n| metadata.get_column_table_type(n))
|
|
369
|
+
.or_else(|| {
|
|
370
|
+
if matches!(name.state, ActiveColumnStateData::DragOver) {
|
|
371
|
+
dragdrop
|
|
372
|
+
.get_drag_column()
|
|
373
|
+
.and_then(|c| metadata.get_column_table_type(&c))
|
|
374
|
+
} else {
|
|
375
|
+
None
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
let is_expression = name
|
|
380
|
+
.get_name()
|
|
381
|
+
.map(|n| metadata.is_column_expression(n))
|
|
382
|
+
.unwrap_or(false);
|
|
383
|
+
|
|
384
|
+
let can_render_styles = name
|
|
385
|
+
.get_name()
|
|
386
|
+
.and_then(|n| can_render_column_styles(renderer, &config, metadata, n).ok())
|
|
387
|
+
.unwrap_or(false);
|
|
388
|
+
|
|
389
|
+
let show_edit_btn = is_expression || can_render_styles;
|
|
318
390
|
let on_open_expr_panel = &ctx.props().on_open_expr_panel;
|
|
319
391
|
html_nested! {
|
|
320
392
|
<ScrollPanelItem {key} {size_hint}>
|
|
@@ -323,6 +395,11 @@ impl Component for ColumnSelector {
|
|
|
323
395
|
{idx}
|
|
324
396
|
{is_aggregated}
|
|
325
397
|
{is_editing}
|
|
398
|
+
{is_expression}
|
|
399
|
+
{show_edit_btn}
|
|
400
|
+
{col_type}
|
|
401
|
+
view_config={config.clone()}
|
|
402
|
+
metadata={metadata.clone()}
|
|
326
403
|
{name}
|
|
327
404
|
{on_open_expr_panel}
|
|
328
405
|
{ondragenter}
|
|
@@ -344,6 +421,7 @@ impl Component for ColumnSelector {
|
|
|
344
421
|
.map(|(idx, vc)| {
|
|
345
422
|
let selected_column = ctx.props().selected_column.as_ref();
|
|
346
423
|
let is_editing = matches!(selected_column, Some(ColumnLocator::Expression(x)) if x.as_str() == vc.name);
|
|
424
|
+
let is_expression = metadata.is_column_expression(vc.name);
|
|
347
425
|
html_nested! {
|
|
348
426
|
<ScrollPanelItem key={vc.name} size_hint=28.0>
|
|
349
427
|
<InactiveColumn
|
|
@@ -351,6 +429,9 @@ impl Component for ColumnSelector {
|
|
|
351
429
|
visible={vc.is_visible}
|
|
352
430
|
name={vc.name.to_owned()}
|
|
353
431
|
{is_editing}
|
|
432
|
+
{is_expression}
|
|
433
|
+
view_config={config.clone()}
|
|
434
|
+
metadata={metadata.clone()}
|
|
354
435
|
onselect={&onselect}
|
|
355
436
|
ondragend={&ondragend}
|
|
356
437
|
on_open_expr_panel={&ctx.props().on_open_expr_panel}
|
|
@@ -365,14 +446,7 @@ impl Component for ColumnSelector {
|
|
|
365
446
|
|
|
366
447
|
let size = 28.0;
|
|
367
448
|
|
|
368
|
-
let add_column = if
|
|
369
|
-
.props()
|
|
370
|
-
.session
|
|
371
|
-
.metadata()
|
|
372
|
-
.get_features()
|
|
373
|
-
.unwrap()
|
|
374
|
-
.expressions
|
|
375
|
-
{
|
|
449
|
+
let add_column = if metadata.get_features().unwrap().expressions {
|
|
376
450
|
html_nested! {
|
|
377
451
|
<ScrollPanelItem key="__add_expression__" size_hint={size}>
|
|
378
452
|
<AddExpressionButton
|
|
@@ -417,6 +491,7 @@ impl Component for ColumnSelector {
|
|
|
417
491
|
<ScrollPanel
|
|
418
492
|
id="sub-columns"
|
|
419
493
|
key="__sub_columns__"
|
|
494
|
+
class={classes!("scrollable")}
|
|
420
495
|
on_resize={&ctx.props().on_resize}
|
|
421
496
|
on_dimensions_reset={&self.on_reset}
|
|
422
497
|
children={inactive_children}
|
|
@@ -435,6 +510,10 @@ impl Component for ColumnSelector {
|
|
|
435
510
|
>
|
|
436
511
|
{ for selected_columns }
|
|
437
512
|
</SplitPanel>
|
|
513
|
+
<ColumnDropDownPortal
|
|
514
|
+
element={self.column_dropdown.clone()}
|
|
515
|
+
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
516
|
+
/>
|
|
438
517
|
</>
|
|
439
518
|
}
|
|
440
519
|
}
|
|
@@ -18,8 +18,8 @@ use perspective_client::clone;
|
|
|
18
18
|
use yew::{Html, Properties, function_component, html};
|
|
19
19
|
|
|
20
20
|
use crate::components::empty_row::EmptyRow;
|
|
21
|
+
use crate::components::filter_dropdown::FilterDropDownElement;
|
|
21
22
|
use crate::config::SymbolKVPair;
|
|
22
|
-
use crate::custom_elements::FilterDropDownElement;
|
|
23
23
|
|
|
24
24
|
#[derive(Properties, PartialEq)]
|
|
25
25
|
pub struct RowSelectorProps {
|
|
@@ -16,10 +16,11 @@ use itertools::Itertools;
|
|
|
16
16
|
use yew::{Callback, Html, Properties, html};
|
|
17
17
|
|
|
18
18
|
use crate::components::column_settings_sidebar::style_tab::symbol::symbol_pairs_item::PairsListItem;
|
|
19
|
+
use crate::components::filter_dropdown::FilterDropDownElement;
|
|
19
20
|
use crate::components::style::LocalStyle;
|
|
20
21
|
use crate::config::SymbolKVPair;
|
|
21
22
|
use crate::css;
|
|
22
|
-
use crate::
|
|
23
|
+
use crate::utils::PtrEqRc;
|
|
23
24
|
|
|
24
25
|
#[derive(Properties, PartialEq)]
|
|
25
26
|
pub struct PairsListProps {
|
|
@@ -28,7 +29,7 @@ pub struct PairsListProps {
|
|
|
28
29
|
pub update_pairs: Callback<Vec<SymbolKVPair>>,
|
|
29
30
|
pub id: Option<String>,
|
|
30
31
|
pub row_dropdown: Rc<FilterDropDownElement>,
|
|
31
|
-
pub values:
|
|
32
|
+
pub values: PtrEqRc<Vec<String>>,
|
|
32
33
|
pub column_name: String,
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -16,8 +16,9 @@ use yew::{Callback, Html, Properties, html};
|
|
|
16
16
|
|
|
17
17
|
use crate::components::column_settings_sidebar::style_tab::symbol::row_selector::RowSelector;
|
|
18
18
|
use crate::components::column_settings_sidebar::style_tab::symbol::symbol_selector::SymbolSelector;
|
|
19
|
+
use crate::components::filter_dropdown::FilterDropDownElement;
|
|
19
20
|
use crate::config::SymbolKVPair;
|
|
20
|
-
use crate::
|
|
21
|
+
use crate::utils::PtrEqRc;
|
|
21
22
|
|
|
22
23
|
#[derive(Properties, PartialEq)]
|
|
23
24
|
pub struct PairsListItemProps {
|
|
@@ -26,7 +27,7 @@ pub struct PairsListItemProps {
|
|
|
26
27
|
pub pairs: Vec<SymbolKVPair>,
|
|
27
28
|
pub update_pairs: Callback<Vec<SymbolKVPair>>,
|
|
28
29
|
pub row_dropdown: Rc<FilterDropDownElement>,
|
|
29
|
-
pub values:
|
|
30
|
+
pub values: PtrEqRc<Vec<String>>,
|
|
30
31
|
pub focused: bool,
|
|
31
32
|
pub set_focused_index: Callback<Option<usize>>,
|
|
32
33
|
pub column_name: String,
|
|
@@ -10,18 +10,17 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use std::rc::Rc;
|
|
14
|
-
|
|
15
13
|
use itertools::Itertools;
|
|
16
14
|
use yew::{Callback, Html, Properties, function_component, html};
|
|
17
15
|
|
|
18
16
|
use crate::components::containers::select::{Select, SelectItem};
|
|
17
|
+
use crate::utils::PtrEqRc;
|
|
19
18
|
|
|
20
19
|
#[derive(Properties, PartialEq)]
|
|
21
20
|
pub struct SymbolSelectorProps {
|
|
22
21
|
pub index: usize,
|
|
23
22
|
pub selected_value: Option<String>,
|
|
24
|
-
pub values:
|
|
23
|
+
pub values: PtrEqRc<Vec<String>>,
|
|
25
24
|
pub callback: Callback<String>,
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -23,10 +23,10 @@ use itertools::Itertools;
|
|
|
23
23
|
use yew::{Callback, Html, Properties, html};
|
|
24
24
|
|
|
25
25
|
use crate::components::column_settings_sidebar::style_tab::symbol::symbol_pairs::PairsList;
|
|
26
|
+
use crate::components::filter_dropdown::{FilterDropDownElement, FilterDropDownPortal};
|
|
26
27
|
use crate::components::style::LocalStyle;
|
|
27
28
|
use crate::config::{ColumnConfigValueUpdate, KeyValueOpts, SymbolKVPair};
|
|
28
29
|
use crate::css;
|
|
29
|
-
use crate::custom_elements::FilterDropDownElement;
|
|
30
30
|
use crate::session::Session;
|
|
31
31
|
|
|
32
32
|
#[derive(Properties, PartialEq, Clone)]
|
|
@@ -36,6 +36,8 @@ pub struct SymbolAttrProps {
|
|
|
36
36
|
pub restored_config: Option<HashMap<String, String>>,
|
|
37
37
|
pub on_change: Callback<ColumnConfigValueUpdate>,
|
|
38
38
|
pub default_config: KeyValueOpts,
|
|
39
|
+
/// Selected theme name, threaded for PortalModal consumers.
|
|
40
|
+
pub selected_theme: Option<String>,
|
|
39
41
|
}
|
|
40
42
|
impl SymbolAttrProps {
|
|
41
43
|
pub fn next_default_symbol(&self, pairs_len: usize) -> String {
|
|
@@ -125,6 +127,10 @@ impl yew::Component for SymbolStyle {
|
|
|
125
127
|
values={Rc::new(ctx.props().default_config.values.clone())}
|
|
126
128
|
{update_pairs}
|
|
127
129
|
/>
|
|
130
|
+
<FilterDropDownPortal
|
|
131
|
+
element={(*self.row_dropdown).clone()}
|
|
132
|
+
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
133
|
+
/>
|
|
128
134
|
</>
|
|
129
135
|
}
|
|
130
136
|
}
|