@perspective-dev/viewer 4.5.2 → 5.1.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 +20 -1
- 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 -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 +22 -3
- package/dist/esm/perspective-viewer.d.ts +9 -0
- package/dist/esm/perspective-viewer.inline.js +20 -1
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +20 -1
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +71 -5
- package/dist/esm/ts-rs/ClientOptions.d.ts +7 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -0
- package/dist/esm/ts-rs/ExportOptions.d.ts +9 -0
- package/dist/esm/ts-rs/GetClientOptions.d.ts +8 -0
- package/dist/esm/ts-rs/GetTableOptions.d.ts +8 -0
- package/dist/esm/ts-rs/Layout.d.ts +11 -0
- package/dist/esm/ts-rs/Orientation.d.ts +4 -0
- package/dist/esm/ts-rs/PanelOptions.d.ts +7 -0
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +41 -0
- package/dist/esm/ts-rs/SplitLayout.d.ts +7 -0
- package/dist/esm/ts-rs/TabLayout.d.ts +10 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +8 -2
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +9 -0
- package/dist/esm/ts-rs/WindowAggregate.d.ts +1 -0
- package/dist/esm/ts-rs/WindowSort.d.ts +7 -0
- package/dist/esm/ts-rs/WindowSortDir.d.ts +6 -0
- package/dist/esm/ts-rs/WindowSpec.d.ts +46 -0
- package/dist/esm/ts-rs/Windows.d.ts +10 -0
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +40 -0
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +28 -0
- package/dist/wasm/perspective-viewer.d.ts +299 -78
- package/dist/wasm/perspective-viewer.js +544 -186
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +34 -26
- package/dist/wasm/snippets/perspective-viewer-8a8c7d5d696b43ae/inline0.js +6 -0
- package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline3.js → perspective-viewer-8a8c7d5d696b43ae/inline4.js} +5 -0
- package/package.json +3 -2
- package/src/css/_context_menu.css +14 -0
- package/src/css/column-selector.css +1 -0
- package/src/css/column-settings-panel.css +68 -3
- package/src/css/column-style.css +4 -3
- package/src/css/config-selector.css +22 -1
- package/src/css/containers/context-menu.css +107 -0
- package/src/css/containers/tabs.css +2 -2
- package/src/css/panel-tab.css +193 -0
- package/src/css/plugin-selector.css +7 -10
- package/src/css/status-bar.css +75 -81
- package/src/css/viewer.css +188 -70
- package/src/rust/components/column_dropdown.rs +40 -30
- package/src/rust/components/column_selector/active_column.rs +28 -45
- package/src/rust/components/column_selector/aggregate_selector.rs +4 -7
- package/src/rust/components/column_selector/column_selector_column_row.rs +73 -0
- package/src/rust/components/column_selector/config_selector.rs +40 -82
- package/src/rust/components/column_selector/expr_edit_button.rs +7 -1
- package/src/rust/components/column_selector/filter_column.rs +5 -15
- package/src/rust/components/column_selector/inactive_column.rs +11 -9
- package/src/rust/components/column_selector/sort_column.rs +3 -6
- package/src/rust/components/column_selector.rs +25 -14
- package/src/rust/components/column_settings_sidebar/style_tab.rs +2 -1
- package/src/rust/components/column_settings_sidebar/window_tab.rs +34 -0
- package/src/rust/components/column_settings_sidebar.rs +163 -16
- package/src/rust/components/containers/dragdrop_list.rs +73 -3
- package/src/rust/components/containers/sidebar.rs +99 -22
- package/src/rust/components/containers/split_panel.rs +181 -62
- package/src/rust/components/context_menu.rs +130 -0
- package/src/rust/components/editable_header.rs +2 -0
- package/src/rust/components/form/debug.rs +3 -0
- package/src/rust/components/global_filter_bar.rs +76 -0
- package/src/rust/components/main_panel/frame_theme.rs +186 -0
- package/src/rust/components/main_panel/msg.rs +62 -0
- package/src/rust/components/main_panel/presize.rs +220 -0
- package/src/rust/components/main_panel/reconcile.rs +224 -0
- package/src/rust/components/main_panel/render.rs +385 -0
- package/src/rust/components/main_panel/update.rs +184 -0
- package/src/rust/components/main_panel.rs +316 -71
- package/src/rust/components/mod.rs +5 -0
- package/src/rust/components/panel_menu.rs +493 -0
- package/src/rust/components/panel_tab.rs +510 -0
- package/src/rust/components/plugin_tab.rs +1 -1
- package/src/rust/components/portal.rs +7 -0
- package/src/rust/components/settings_panel.rs +13 -5
- package/src/rust/components/status_bar.rs +110 -178
- package/src/rust/components/status_indicator.rs +6 -9
- package/src/rust/components/style/mod.rs +5 -0
- package/src/rust/components/style/style_provider.rs +2 -0
- package/src/rust/components/viewer/filters.rs +133 -0
- package/src/rust/components/viewer/msg.rs +182 -0
- package/src/rust/components/viewer/panels.rs +326 -0
- package/src/rust/components/viewer/render.rs +255 -0
- package/src/rust/components/viewer/settings.rs +434 -0
- package/src/rust/components/viewer/snapshots.rs +134 -0
- package/src/rust/components/viewer/wiring.rs +505 -0
- package/src/rust/components/viewer.rs +245 -756
- package/src/rust/components/window_editor.rs +1013 -0
- package/src/rust/config/export_method.rs +1 -1
- package/src/rust/config/mod.rs +4 -0
- package/src/rust/config/options.rs +71 -0
- package/src/rust/config/viewer_config.rs +24 -2
- package/src/rust/config/workspace_config.rs +92 -0
- package/src/rust/custom_elements/copy_dropdown.rs +3 -1
- package/src/rust/custom_elements/debug_plugin.rs +20 -1
- package/src/rust/custom_elements/export_dropdown.rs +3 -1
- package/src/rust/custom_elements/viewer.rs +1015 -286
- package/src/rust/custom_events.rs +212 -61
- package/src/rust/js/mod.rs +2 -0
- package/src/rust/js/plugin.rs +297 -10
- package/src/rust/js/regular_layout.rs +258 -0
- package/src/rust/lib.rs +24 -2
- package/src/rust/presentation/column_locator.rs +16 -1
- package/src/rust/presentation.rs +66 -33
- package/src/rust/queries/columns_iter_set.rs +7 -1
- package/src/rust/queries/get_viewer_config.rs +29 -11
- package/src/rust/queries/plugin_column_styles.rs +2 -2
- package/src/rust/renderer/activate.rs +41 -14
- package/src/rust/renderer/dispatch.rs +463 -0
- package/src/rust/renderer/plugin_config.rs +495 -0
- package/src/rust/renderer/registry.rs +18 -6
- package/src/rust/renderer/render_timer.rs +29 -10
- package/src/rust/renderer.rs +384 -838
- package/src/rust/session/column_defaults_update.rs +26 -8
- package/src/rust/session/drag_drop_update.rs +18 -0
- package/src/rust/session/metadata.rs +66 -9
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session/view_subscription.rs +30 -15
- package/src/rust/session.rs +755 -264
- package/src/rust/tasks/apply_global_filters.rs +89 -0
- package/src/rust/tasks/auto_pause.rs +171 -0
- package/src/rust/tasks/copy_export.rs +29 -19
- package/src/rust/tasks/create_panel.rs +243 -0
- package/src/rust/tasks/dismiss_render_warning.rs +3 -1
- package/src/rust/tasks/edit_expression.rs +4 -4
- package/src/rust/tasks/edit_window.rs +155 -0
- package/src/rust/tasks/eject.rs +64 -23
- package/src/rust/tasks/mod.rs +30 -4
- package/src/rust/tasks/pipeline.rs +411 -0
- package/src/rust/tasks/presize_panels.rs +324 -0
- package/src/rust/tasks/reset_all.rs +22 -12
- package/src/rust/tasks/resize_observer.rs +124 -87
- package/src/rust/tasks/restore_and_render.rs +80 -86
- package/src/rust/tasks/restore_panel.rs +145 -0
- package/src/rust/tasks/send_column_config.rs +5 -2
- package/src/rust/tasks/send_plugin_config.rs +5 -2
- package/src/rust/tasks/set_edit_mode.rs +59 -0
- package/src/rust/tasks/sync_update_panels.rs +152 -0
- package/src/rust/tasks/table_lifecycle.rs +158 -0
- package/src/rust/tasks/update_theme.rs +56 -12
- package/src/rust/utils/browser/dragdrop.rs +12 -0
- package/src/rust/utils/browser/tests/debounce.rs +49 -0
- package/src/rust/utils/completion.rs +56 -0
- package/src/rust/utils/custom_element.rs +5 -0
- package/src/rust/utils/debounce.rs +189 -17
- package/src/rust/utils/mod.rs +6 -0
- package/src/rust/utils/pending_effects.rs +62 -0
- package/src/rust/utils/spawn.rs +33 -0
- package/src/rust/utils/weak_scope.rs +0 -10
- package/src/rust/workspace.rs +846 -0
- package/src/svg/active-indicator.svg +3 -0
- package/src/svg/pin-icon.svg +5 -0
- package/src/themes/botanical.css +5 -2
- package/src/themes/defaults.css +54 -2
- package/src/themes/dracula.css +6 -3
- package/src/themes/gruvbox-dark.css +5 -2
- package/src/themes/gruvbox.css +5 -2
- package/src/themes/icons.css +5 -2
- package/src/themes/intl/de.css +7 -0
- package/src/themes/intl/es.css +7 -0
- package/src/themes/intl/fr.css +7 -0
- package/src/themes/intl/ja.css +7 -0
- package/src/themes/intl/pt.css +7 -0
- package/src/themes/intl/zh.css +7 -0
- package/src/themes/intl.css +10 -1
- package/src/themes/monokai.css +5 -2
- package/src/themes/phosphor.css +5 -2
- package/src/themes/pro-dark.css +5 -2
- package/src/themes/pro.css +2 -1
- package/src/themes/solarized-dark.css +5 -2
- package/src/themes/solarized.css +5 -2
- package/src/themes/vaporwave.css +5 -2
- package/src/ts/bootstrap.ts +8 -7
- package/src/ts/extensions.ts +30 -2
- package/src/ts/perspective-viewer.ts +10 -0
- package/src/ts/plugin.ts +72 -5
- package/src/ts/ts-rs/ClientOptions.ts +7 -0
- package/src/ts/ts-rs/ExportMethod.ts +3 -0
- package/src/ts/ts-rs/ExportOptions.ts +8 -0
- package/src/ts/ts-rs/GetClientOptions.ts +7 -0
- package/src/ts/ts-rs/GetTableOptions.ts +7 -0
- package/src/ts/ts-rs/Layout.ts +9 -0
- package/src/ts/ts-rs/Orientation.ts +6 -0
- package/src/ts/ts-rs/PanelOptions.ts +7 -0
- package/src/ts/ts-rs/PanelViewerConfig.ts +16 -0
- package/src/ts/ts-rs/SplitLayout.ts +5 -0
- package/src/ts/ts-rs/TabLayout.ts +11 -0
- package/src/ts/ts-rs/ViewerConfig.ts +7 -2
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +9 -0
- package/src/ts/ts-rs/WindowAggregate.ts +3 -0
- package/src/ts/ts-rs/WindowSort.ts +9 -0
- package/src/ts/ts-rs/WindowSortDir.ts +8 -0
- package/src/ts/ts-rs/WindowSpec.ts +46 -0
- package/src/ts/ts-rs/Windows.ts +10 -0
- package/src/ts/ts-rs/WorkspaceConfig.ts +36 -0
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +24 -0
- package/src/rust/tasks/intersection_observer.rs +0 -98
- package/src/rust/tasks/update_and_render.rs +0 -110
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline0.js → perspective-viewer-8a8c7d5d696b43ae/inline1.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline1.js → perspective-viewer-8a8c7d5d696b43ae/inline2.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline2.js → perspective-viewer-8a8c7d5d696b43ae/inline3.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline4.js → perspective-viewer-8a8c7d5d696b43ae/inline5.js} +0 -0
package/src/ts/plugin.ts
CHANGED
|
@@ -28,6 +28,36 @@ import { PluginStaticConfig } from "./ts-rs/PluginStaticConfig.js";
|
|
|
28
28
|
* level (if packaged as a library), or during application init to ensure global
|
|
29
29
|
* availability of a plugin.
|
|
30
30
|
*
|
|
31
|
+
* ## Dispatch contract
|
|
32
|
+
*
|
|
33
|
+
* The host dispatches each method for exactly one reason, and never
|
|
34
|
+
* defensively — implementations may rely on these meanings:
|
|
35
|
+
*
|
|
36
|
+
* - `draw(view)` — `view` is NEW to this plugin: a new engine `View` was
|
|
37
|
+
* constructed, or this plugin was freshly selected and owes its first
|
|
38
|
+
* render. Safe to reset zoom/scroll/selection state.
|
|
39
|
+
* - `update(view)` — same `View`, but a plugin-visible input genuinely
|
|
40
|
+
* changed: new data (`View.on_update`), an effective view-config delta
|
|
41
|
+
* without a rebuild, a *changed* plugin/columns config just delivered
|
|
42
|
+
* via `restore()`, changed CSS just applied via `restyle()`, a
|
|
43
|
+
* render-limits change, or an explicit public `viewer.restore()` call
|
|
44
|
+
* (the no-op-restore refresh affordance). Host-internal operations that
|
|
45
|
+
* change none of these dispatch nothing.
|
|
46
|
+
* - `resize(view)` — geometry or visibility changed (including panel
|
|
47
|
+
* activation); repaint from retained state, no data or CSS re-read.
|
|
48
|
+
* - `restyle()` — the effective theme genuinely changed; when a
|
|
49
|
+
* `draw`/`update` is part of the same operation, `restyle()` is called
|
|
50
|
+
* immediately BEFORE it, so one render pass paints in the new theme.
|
|
51
|
+
* - `restore()`/`save()` — state transfer only. Plugins must NOT render
|
|
52
|
+
* from `restore()` (a changed restore is always followed by exactly one
|
|
53
|
+
* `update`) and must NOT call host APIs from inside it — a
|
|
54
|
+
* `restore()` echo re-enters the host's public surface and forces
|
|
55
|
+
* a redundant render (the classic double-render-on-load bug).
|
|
56
|
+
*
|
|
57
|
+
* Rendering methods (`draw`, `update`, `resize`, `render`, `clear`) and
|
|
58
|
+
* `delete` are serialized per element — the host never overlaps them, and
|
|
59
|
+
* each call runs to completion before the next begins.
|
|
60
|
+
*
|
|
31
61
|
* @example
|
|
32
62
|
* ```javascript
|
|
33
63
|
* const BasePlugin = customElements.get("perspective-viewer-plugin");
|
|
@@ -68,6 +98,14 @@ export interface IPerspectiveViewerPlugin {
|
|
|
68
98
|
* provision to cancel a render in progress per se, calling a method on
|
|
69
99
|
* a `View` which has been deleted will throw an exception.
|
|
70
100
|
*
|
|
101
|
+
* The host invokes `draw` ONLY when `view` is NEW to this plugin — a
|
|
102
|
+
* new engine `View` was constructed for a config change, or this plugin
|
|
103
|
+
* element was freshly selected and owes its first render of the bound
|
|
104
|
+
* `View` — so implementations may treat it as "new data shape" and
|
|
105
|
+
* reset zoom/scroll/selection-domain state. Repaints of the same
|
|
106
|
+
* `View` arrive as `update()` (data or style refresh) or `resize()`
|
|
107
|
+
* (geometry/chrome), never `draw()`.
|
|
108
|
+
*
|
|
71
109
|
* @example
|
|
72
110
|
* ```
|
|
73
111
|
* async draw(view: perspective.View): Promise<void> {
|
|
@@ -79,9 +117,9 @@ export interface IPerspectiveViewerPlugin {
|
|
|
79
117
|
draw(view: View): Promise<void>;
|
|
80
118
|
|
|
81
119
|
/**
|
|
82
|
-
* Draw under the assumption that the `
|
|
83
|
-
*
|
|
84
|
-
* dispatch to `draw()`.
|
|
120
|
+
* Draw under the assumption that the `View` has not changed since the
|
|
121
|
+
* previous call to `draw()`, but some plugin-visible input has.
|
|
122
|
+
* Defaults to dispatch to `draw()`.
|
|
85
123
|
*
|
|
86
124
|
* @example
|
|
87
125
|
* ```javascript
|
|
@@ -109,21 +147,50 @@ export interface IPerspectiveViewerPlugin {
|
|
|
109
147
|
|
|
110
148
|
/**
|
|
111
149
|
* Like `update()`, but for when the dimensions of the plugin have changed
|
|
112
|
-
* and the underlying data has not
|
|
150
|
+
* and the underlying data has not — a repaint from retained state,
|
|
151
|
+
* invoked ONLY when geometry or visibility changed: box resizes,
|
|
152
|
+
* presize sweeps, and the panel-ACTIVATION chrome nudge (multi-panel),
|
|
153
|
+
* so implementations should repaint activation-dependent chrome here
|
|
154
|
+
* and no-op while hidden (`offsetParent == null`).
|
|
113
155
|
*/
|
|
114
156
|
resize(view: View): Promise<void>;
|
|
115
157
|
|
|
116
158
|
/**
|
|
117
159
|
* Notify the plugin that the style environment has changed. Useful for
|
|
118
|
-
* plugins which read CSS styles via `window.getComputedStyle()
|
|
160
|
+
* plugins which read CSS styles via `window.getComputedStyle()` — this
|
|
161
|
+
* is the ONLY point at which a plugin is expected to (re-)read them
|
|
162
|
+
* (besides its first `draw()`), so implementations may cache computed
|
|
163
|
+
* styles between `restyle()` calls.
|
|
119
164
|
*/
|
|
120
165
|
restyle(): void;
|
|
121
166
|
|
|
122
167
|
/**
|
|
123
168
|
* Restore this plugin to a state previously returned by `save()`.
|
|
169
|
+
*
|
|
170
|
+
* State transfer ONLY — implementations must not render from
|
|
171
|
+
* `restore()` (the host follows a restore that genuinely changed
|
|
172
|
+
* plugin state with exactly one `update()` in the same serialized
|
|
173
|
+
* sequence), and must not call host `<perspective-viewer>` APIs from
|
|
174
|
+
* inside it: an echoed `restore()` re-enters the host's public
|
|
175
|
+
* surface where it is indistinguishable from a user call and forces a
|
|
176
|
+
* redundant render. Host API calls to persist plugin state belong to
|
|
177
|
+
* genuine user-gesture handlers (e.g. a toolbar click), never to the
|
|
178
|
+
* `restore()` delivery path.
|
|
124
179
|
*/
|
|
125
180
|
restore(config: any): void;
|
|
126
181
|
|
|
182
|
+
/**
|
|
183
|
+
* OPTIONAL — clear any visible user selection state (highlighted rows,
|
|
184
|
+
* pinned tooltips) WITHOUT emitting selection events. The host
|
|
185
|
+
* `<perspective-viewer>` invokes this when an element-level global
|
|
186
|
+
* filter contributed by this plugin's selection is removed from the
|
|
187
|
+
* global filter bar, so the selection visual can't outlive the filter
|
|
188
|
+
* it produced. Called under the host's per-panel render serialization
|
|
189
|
+
* (like `draw`), so implementations may redraw. Plugins without a
|
|
190
|
+
* selection UI may omit it.
|
|
191
|
+
*/
|
|
192
|
+
deselect?(): Promise<void>;
|
|
193
|
+
|
|
127
194
|
/**
|
|
128
195
|
* Free any resources acquired by this plugin and prepare to be deleted.
|
|
129
196
|
*/
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `eject` argument: the loaded client to remove by name; the active
|
|
5
|
+
* panel's client when omitted.
|
|
6
|
+
*/
|
|
7
|
+
export type ClientOptions = { client?: string, };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
export type ExportMethod = "csv" | "csv-all" | "csv-selected" | "json" | "json-all" | "json-selected" | "ndjson" | "ndjson-all" | "ndjson-selected" | "html" | "plugin" | "arrow" | "arrow-selected" | "arrow-all" | "json-config";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { ExportMethod } from "./ExportMethod.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `download` / `export` / `copy` argument: the `ExportMethod` and target
|
|
6
|
+
* panel.
|
|
7
|
+
*/
|
|
8
|
+
export type ExportOptions = { method?: ExportMethod, panel?: string, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `getClient` argument: whether to `wait` for a `Client`, and the target
|
|
5
|
+
* panel.
|
|
6
|
+
*/
|
|
7
|
+
export type GetClientOptions = { wait?: boolean, panel?: string, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `getTable` argument: whether to `wait` for a `Table`, and the target
|
|
5
|
+
* panel.
|
|
6
|
+
*/
|
|
7
|
+
export type GetTableOptions = { wait?: boolean, panel?: string, };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { SplitLayout } from "./SplitLayout.js";
|
|
3
|
+
import type { TabLayout } from "./TabLayout.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A serde mirror of `regular-layout`'s serialized layout tree, as returned by
|
|
7
|
+
* [`RegularLayout::save`] and accepted by [`RegularLayout::restore`].
|
|
8
|
+
*/
|
|
9
|
+
export type Layout = { "type": "split-layout" } & SplitLayout | { "type": "tab-layout" } & TabLayout;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Selects the target panel of a panel-scoped `<perspective-viewer>` method;
|
|
5
|
+
* the active panel when `panel` is omitted.
|
|
6
|
+
*/
|
|
7
|
+
export type PanelOptions = { panel?: string, };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { Aggregate } from "./Aggregate.js";
|
|
3
|
+
import type { Expressions } from "./Expressions.js";
|
|
4
|
+
import type { Filter } from "./Filter.js";
|
|
5
|
+
import type { FilterReducer } from "./FilterReducer.js";
|
|
6
|
+
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
|
+
import type { Sort } from "./Sort.js";
|
|
8
|
+
import type { Windows } from "./Windows.js";
|
|
9
|
+
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The per-panel state of a [`ViewerConfig`] — everything except the
|
|
13
|
+
* element-level `settings` flag. This is the `panels` entry type of the
|
|
14
|
+
* whole-element config format.
|
|
15
|
+
*/
|
|
16
|
+
export type PanelViewerConfig<V = string> = { version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, windows?: Windows, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { Layout } from "./Layout.js";
|
|
3
|
+
import type { Orientation } from "./Orientation.js";
|
|
4
|
+
|
|
5
|
+
export type SplitLayout = { children: Array<Layout>, sizes: Array<number>, orientation: Orientation, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
export type TabLayout = {
|
|
4
|
+
/**
|
|
5
|
+
* Panel ids (slot names) in this stack.
|
|
6
|
+
*/
|
|
7
|
+
tabs: Array<string>,
|
|
8
|
+
/**
|
|
9
|
+
* Index of the selected tab within `tabs`.
|
|
10
|
+
*/
|
|
11
|
+
selected?: number, };
|
|
@@ -5,10 +5,15 @@ import type { Filter } from "./Filter.js";
|
|
|
5
5
|
import type { FilterReducer } from "./FilterReducer.js";
|
|
6
6
|
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
7
|
import type { Sort } from "./Sort.js";
|
|
8
|
+
import type { Windows } from "./Windows.js";
|
|
8
9
|
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The state of an entire `custom_elements::PerspectiveViewerElement` component
|
|
12
|
-
* and its `Plugin
|
|
13
|
+
* and its `Plugin`: the element-level `settings` flag plus the per-panel
|
|
14
|
+
* [`PanelViewerConfig`]. The split exists so the whole-element config format
|
|
15
|
+
* can serialize panel entries *without* a `settings` key (it is element-level
|
|
16
|
+
* state there, carried by the top-level `active` field instead), while the
|
|
17
|
+
* single-panel format flattens back to the legacy shape.
|
|
13
18
|
*/
|
|
14
|
-
export type ViewerConfig<V = string> = { version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue },
|
|
19
|
+
export type ViewerConfig<V = string> = { settings: boolean, version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, windows?: Windows, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
@@ -6,6 +6,7 @@ import type { FilterReducer } from "./FilterReducer.js";
|
|
|
6
6
|
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
7
|
import type { OptionalUpdate } from "./OptionalUpdate.js";
|
|
8
8
|
import type { Sort } from "./Sort.js";
|
|
9
|
+
import type { Windows } from "./Windows.js";
|
|
9
10
|
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
10
11
|
|
|
11
12
|
export type ViewerConfigUpdate = { version?: OptionalUpdate<string>, plugin?: OptionalUpdate<string>, title?: OptionalUpdate<string>, table?: OptionalUpdate<string>, theme?: OptionalUpdate<string>, settings?: OptionalUpdate<boolean>, plugin_config?: OptionalUpdate<{ [key in string]?: JsonValue }>, columns_config?: OptionalUpdate<{ [key in string]?: { [key in string]?: JsonValue } }>,
|
|
@@ -74,6 +75,14 @@ sort?: Array<Sort>,
|
|
|
74
75
|
* panel.
|
|
75
76
|
*/
|
|
76
77
|
expressions?: Expressions,
|
|
78
|
+
/**
|
|
79
|
+
* The `windows` property declares ordered, partitioned rolling
|
|
80
|
+
* computations (moving aggregates, cumulative sums) as _new_ columns
|
|
81
|
+
* keyed by output alias (`{"name": {...spec}}`, symmetric with
|
|
82
|
+
* `expressions`), analogous to SQL window functions. See
|
|
83
|
+
* [`crate::config::WindowSpec`].
|
|
84
|
+
*/
|
|
85
|
+
windows?: Windows,
|
|
77
86
|
/**
|
|
78
87
|
* Aggregates perform a calculation over an entire column, and are
|
|
79
88
|
* displayed when one or more [Group By](#group-by) are applied to the
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowSortDir } from "./WindowSortDir.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `Table` column which orders each partition, with its direction -
|
|
6
|
+
* serialized as a two-element array (`["ts", "desc"]`), symmetric with the
|
|
7
|
+
* `ViewConfig`'s `sort` field.
|
|
8
|
+
*/
|
|
9
|
+
export type WindowSort = [string, WindowSortDir];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A window's order direction. A dedicated two-variant enum rather than
|
|
5
|
+
* [`crate::config::SortDir`] - the column-sort extras (`col asc`, `abs`,
|
|
6
|
+
* `none`) are meaningless inside a window frame and unrepresentable here.
|
|
7
|
+
*/
|
|
8
|
+
export type WindowSortDir = "asc" | "desc";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowAggregate } from "./WindowAggregate.js";
|
|
3
|
+
import type { WindowSort } from "./WindowSort.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The serialized form of [`WindowSpec`].
|
|
7
|
+
*/
|
|
8
|
+
export type WindowSpec = {
|
|
9
|
+
/**
|
|
10
|
+
* The input column - either a real `Table` column or an expression
|
|
11
|
+
* alias from the same `ViewConfig`.
|
|
12
|
+
*/
|
|
13
|
+
column: string, aggregate: WindowAggregate,
|
|
14
|
+
/**
|
|
15
|
+
* Columns whose distinct value tuples partition the rows; empty
|
|
16
|
+
* partitions the whole `Table` as one group.
|
|
17
|
+
*/
|
|
18
|
+
partition_by?: Array<string>,
|
|
19
|
+
/**
|
|
20
|
+
* The `Table` column which orders each partition, and the direction.
|
|
21
|
+
*/
|
|
22
|
+
order_by?: WindowSort | null,
|
|
23
|
+
/**
|
|
24
|
+
* A frame of the `rows` preceding each row, plus the row itself.
|
|
25
|
+
* Mutually exclusive with `range` and `cumulative`.
|
|
26
|
+
*/
|
|
27
|
+
rows?: number | null,
|
|
28
|
+
/**
|
|
29
|
+
* A frame of the rows whose `order_by` value lies within `range` of
|
|
30
|
+
* each row's, requiring a numeric or temporal `order_by`. Mutually
|
|
31
|
+
* exclusive with `rows` and `cumulative`.
|
|
32
|
+
*/
|
|
33
|
+
range?: number | null,
|
|
34
|
+
/**
|
|
35
|
+
* `true` frames all rows from the partition start through each row.
|
|
36
|
+
* Default can be omitted.
|
|
37
|
+
*/
|
|
38
|
+
cumulative?: boolean | null,
|
|
39
|
+
/**
|
|
40
|
+
* Row offset for `lag`/`lead` (default 1).
|
|
41
|
+
*/
|
|
42
|
+
offset?: number | null,
|
|
43
|
+
/**
|
|
44
|
+
* Smoothing factor in `(0, 1]` for `ema`.
|
|
45
|
+
*/
|
|
46
|
+
alpha?: number | null, };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowSpec } from "./WindowSpec.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The window columns of a `ViewConfig`, keyed by output column alias -
|
|
6
|
+
* symmetric with `expressions` (`{"name": {...spec}}`). An alias must not
|
|
7
|
+
* collide with a `Table` column, expression alias, or another window's
|
|
8
|
+
* key.
|
|
9
|
+
*/
|
|
10
|
+
export type Windows = { [key in string]?: WindowSpec };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { Filter } from "./Filter.js";
|
|
3
|
+
import type { Layout } from "./Layout.js";
|
|
4
|
+
import type { PanelViewerConfig } from "./PanelViewerConfig.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The whole-element config format (`{version, active?, layout, panels}`) —
|
|
8
|
+
* the multi-panel counterpart of the single-panel [`ViewerConfig`] — as
|
|
9
|
+
* emitted by [`PerspectiveViewerElement::save`].
|
|
10
|
+
*
|
|
11
|
+
* - `panels` entries are [`PanelViewerConfig`]s: per-panel state only, no
|
|
12
|
+
* `settings` key (element-level state).
|
|
13
|
+
* - `active` names the panel targeted by the *open* settings sidebar; it is
|
|
14
|
+
* omitted when the sidebar is closed.
|
|
15
|
+
*/
|
|
16
|
+
export type WorkspaceConfig = { version: string, active?: string, layout: Layout | null,
|
|
17
|
+
/**
|
|
18
|
+
* `BTreeMap` (not `HashMap`) so `save()` serializes panels in a
|
|
19
|
+
* DETERMINISTIC (sorted) key order — a fresh `HashMap` per call
|
|
20
|
+
* iterates in a per-instance random order, which made consecutive
|
|
21
|
+
* `save()` outputs byte-unstable.
|
|
22
|
+
*/
|
|
23
|
+
panels: { [key in string]?: PanelViewerConfig<string> },
|
|
24
|
+
/**
|
|
25
|
+
* The element-level global (master/detail cross-) filters. A transient
|
|
26
|
+
* overlay on every detail panel's view — persisted here, never in a
|
|
27
|
+
* per-panel entry. Omitted when empty.
|
|
28
|
+
*/
|
|
29
|
+
global_filters?: Array<Filter>,
|
|
30
|
+
/**
|
|
31
|
+
* The MASTER (filter-source) panels' ids, referencing `panels` keys.
|
|
32
|
+
* Roles are layout state (like the panel arrangement), so they persist;
|
|
33
|
+
* which master contributed which clause does not — restored
|
|
34
|
+
* `global_filters` are one unattributed bucket. Omitted when empty.
|
|
35
|
+
*/
|
|
36
|
+
masters?: Array<string>, };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { Filter } from "./Filter.js";
|
|
3
|
+
import type { Layout } from "./Layout.js";
|
|
4
|
+
import type { ViewerConfigUpdate } from "./ViewerConfigUpdate.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The parse target of a whole-element config in
|
|
8
|
+
* [`PerspectiveViewerElement::restore`]. Mirrors [`WorkspaceConfig`],
|
|
9
|
+
* but `panels` entries are full [`ViewerConfigUpdate`]s so a stray per-panel
|
|
10
|
+
* `settings` can be detected (warned, then ignored — `create_panel` strips
|
|
11
|
+
* it).
|
|
12
|
+
*/
|
|
13
|
+
export type WorkspaceConfigUpdate = { active?: string, layout?: Layout, panels: { [key in string]?: ViewerConfigUpdate },
|
|
14
|
+
/**
|
|
15
|
+
* The element-level global (master/detail cross-) filters to re-apply as
|
|
16
|
+
* a transient overlay on every DETAIL panel. Restored as one
|
|
17
|
+
* unattributed bucket: the next selection on any master replaces it.
|
|
18
|
+
*/
|
|
19
|
+
global_filters?: Array<Filter>,
|
|
20
|
+
/**
|
|
21
|
+
* The master (filter-source) panels, by saved `panels` key. An id not in
|
|
22
|
+
* `panels` warns and is dropped.
|
|
23
|
+
*/
|
|
24
|
+
masters?: Array<string>, };
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
-
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
-
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
-
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
-
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
-
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
-
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
-
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
-
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
-
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
-
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
-
|
|
13
|
-
use wasm_bindgen::JsCast;
|
|
14
|
-
use wasm_bindgen::prelude::*;
|
|
15
|
-
use web_sys::*;
|
|
16
|
-
|
|
17
|
-
use crate::config::ViewerConfigUpdate;
|
|
18
|
-
use crate::js::*;
|
|
19
|
-
use crate::presentation::Presentation;
|
|
20
|
-
use crate::renderer::*;
|
|
21
|
-
use crate::session::Session;
|
|
22
|
-
use crate::utils::*;
|
|
23
|
-
use crate::*;
|
|
24
|
-
|
|
25
|
-
pub struct IntersectionObserverHandle {
|
|
26
|
-
elem: HtmlElement,
|
|
27
|
-
observer: IntersectionObserver,
|
|
28
|
-
_callback: Closure<dyn FnMut(js_sys::Array)>,
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
impl IntersectionObserverHandle {
|
|
32
|
-
pub fn new(
|
|
33
|
-
elem: &HtmlElement,
|
|
34
|
-
presentation: &Presentation,
|
|
35
|
-
session: &Session,
|
|
36
|
-
renderer: &Renderer,
|
|
37
|
-
) -> Self {
|
|
38
|
-
clone!(session, renderer, presentation);
|
|
39
|
-
let _callback = Closure::new(move |xs: js_sys::Array| {
|
|
40
|
-
// https://stackoverflow.com/questions/53862160/intersectionobserver-multiple-entries
|
|
41
|
-
let intersect = xs
|
|
42
|
-
.pop()
|
|
43
|
-
.unchecked_into::<IntersectionObserverEntry>()
|
|
44
|
-
.is_intersecting();
|
|
45
|
-
|
|
46
|
-
clone!(session, renderer, presentation);
|
|
47
|
-
let state = IntersectionObserverState {
|
|
48
|
-
presentation,
|
|
49
|
-
session,
|
|
50
|
-
renderer,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
ApiFuture::spawn(state.set_pause(intersect));
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
let func = _callback.as_ref().unchecked_ref::<js_sys::Function>();
|
|
57
|
-
let observer = IntersectionObserver::new(func);
|
|
58
|
-
observer.observe(elem);
|
|
59
|
-
Self {
|
|
60
|
-
elem: elem.clone(),
|
|
61
|
-
_callback,
|
|
62
|
-
observer,
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
impl Drop for IntersectionObserverHandle {
|
|
68
|
-
fn drop(&mut self) {
|
|
69
|
-
self.observer.unobserve(&self.elem);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
struct IntersectionObserverState {
|
|
74
|
-
session: Session,
|
|
75
|
-
renderer: Renderer,
|
|
76
|
-
presentation: Presentation,
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
impl IntersectionObserverState {
|
|
80
|
-
async fn set_pause(self, intersect: bool) -> ApiResult<()> {
|
|
81
|
-
if intersect {
|
|
82
|
-
if self.session.set_pause(false) {
|
|
83
|
-
super::restore_and_render(
|
|
84
|
-
&self.session,
|
|
85
|
-
&self.renderer,
|
|
86
|
-
&self.presentation,
|
|
87
|
-
ViewerConfigUpdate::default(),
|
|
88
|
-
async move { Ok(()) },
|
|
89
|
-
)
|
|
90
|
-
.await?;
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
self.session.set_pause(true);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
Ok(())
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
-
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
-
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
-
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
-
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
-
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
-
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
-
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
-
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
-
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
-
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
-
|
|
13
|
-
//! Apply a [`ViewConfigUpdate`] to the active [`Session`], validate it, then
|
|
14
|
-
//! draw with the active [`Renderer`]. The companion `*_callback` helpers
|
|
15
|
-
//! return [`yew::Callback`]s suitable for wiring as Yew child-component
|
|
16
|
-
//! props.
|
|
17
|
-
|
|
18
|
-
use perspective_client::config::ViewConfigUpdate;
|
|
19
|
-
use yew::prelude::*;
|
|
20
|
-
|
|
21
|
-
use crate::renderer::Renderer;
|
|
22
|
-
use crate::session::Session;
|
|
23
|
-
use crate::utils::*;
|
|
24
|
-
use crate::*;
|
|
25
|
-
|
|
26
|
-
/// Create a [`Callback`] that renders from the current `View` and `Plugin`.
|
|
27
|
-
pub fn render_callback(session: &Session, renderer: &Renderer) -> Callback<()> {
|
|
28
|
-
clone!(session, renderer);
|
|
29
|
-
Callback::from(move |_| {
|
|
30
|
-
clone!(session, renderer);
|
|
31
|
-
ApiFuture::spawn(async move {
|
|
32
|
-
renderer.draw(async { Ok(session.get_view()) }).await?;
|
|
33
|
-
Ok(())
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/// Create a [`Callback`] that resizes from the current `View` and `Plugin`.
|
|
39
|
-
pub fn resize_callback(session: &Session, renderer: &Renderer) -> Callback<()> {
|
|
40
|
-
clone!(session, renderer);
|
|
41
|
-
Callback::from(move |_| {
|
|
42
|
-
clone!(renderer, session);
|
|
43
|
-
ApiFuture::spawn(async move {
|
|
44
|
-
if !renderer.is_plugin_activated()? {
|
|
45
|
-
update_and_render_inner(session, renderer).await?
|
|
46
|
-
} else {
|
|
47
|
-
renderer.resize().await?;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
Ok(())
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/// Apply a `ViewConfigUpdate` to the current `View` and render.
|
|
56
|
-
pub fn update_and_render(
|
|
57
|
-
session: &Session,
|
|
58
|
-
renderer: &Renderer,
|
|
59
|
-
update: ViewConfigUpdate,
|
|
60
|
-
) -> ApiResult<ApiFuture<()>> {
|
|
61
|
-
session.update_view_config(update)?;
|
|
62
|
-
clone!(session, renderer);
|
|
63
|
-
Ok(ApiFuture::new(update_and_render_inner(session, renderer)))
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/// Re-render the current `View` and `Plugin` without applying a new
|
|
67
|
-
/// `ViewConfigUpdate`.
|
|
68
|
-
pub fn just_render(session: &Session, renderer: &Renderer) -> ApiResult<ApiFuture<()>> {
|
|
69
|
-
clone!(session, renderer);
|
|
70
|
-
Ok(ApiFuture::new(update_and_render_inner(session, renderer)))
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
#[tracing::instrument(level = "debug", skip(session, renderer))]
|
|
74
|
-
async fn update_and_render_inner(session: Session, renderer: Renderer) -> ApiResult<()> {
|
|
75
|
-
// The previous call which acquired the lock errored, so skip this render
|
|
76
|
-
if session.get_error().is_some() {
|
|
77
|
-
return Ok(());
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let plugin_swapped = renderer.apply_pending_plugin()?;
|
|
81
|
-
|
|
82
|
-
// Validate + create the view BEFORE the plugin-swap materialize
|
|
83
|
-
// so the schema query sees fresh `expression_schema` /
|
|
84
|
-
// `view_schema` and `resolve_abs_max` has a bound view that
|
|
85
|
-
// knows about any new expression columns.
|
|
86
|
-
let view = session.validate().await?.create_view().await?;
|
|
87
|
-
|
|
88
|
-
if plugin_swapped {
|
|
89
|
-
// `commit_plugin_idx` already restored the new plugin from its
|
|
90
|
-
// raw bucket; re-run with the materialized snapshot so any
|
|
91
|
-
// `include: true` schema defaults (e.g. Datagrid's
|
|
92
|
-
// `fg_gradient` when `number_fg_mode = "bar"`) make it into
|
|
93
|
-
// the plugin's state before the first draw. The Session is in
|
|
94
|
-
// scope here but not at `commit_plugin_idx`'s call sites in
|
|
95
|
-
// the column-selector tree, so we do the second restore at
|
|
96
|
-
// the caller instead of plumbing `&Session` through every
|
|
97
|
-
// `apply_pending_plugin` site.
|
|
98
|
-
let view_config_snapshot = session.get_view_config().clone();
|
|
99
|
-
let plugin_token = wasm_bindgen::JsValue::from_serde_ext(&renderer.get_plugin_config())
|
|
100
|
-
.unwrap_or(wasm_bindgen::JsValue::NULL);
|
|
101
|
-
let columns_config = renderer
|
|
102
|
-
.all_columns_configs_materialized(&view_config_snapshot, &session)
|
|
103
|
-
.await;
|
|
104
|
-
renderer
|
|
105
|
-
.get_active_plugin()?
|
|
106
|
-
.restore(&plugin_token, Some(&columns_config))?;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
renderer.draw(async { Ok(view) }).await
|
|
110
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|