@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.
Files changed (227) hide show
  1. package/dist/cdn/perspective-viewer.js +20 -1
  2. package/dist/cdn/perspective-viewer.js.map +4 -4
  3. package/dist/css/botanical.css +1 -1
  4. package/dist/css/dracula.css +1 -1
  5. package/dist/css/gruvbox-dark.css +1 -1
  6. package/dist/css/gruvbox.css +1 -1
  7. package/dist/css/icons.css +1 -1
  8. package/dist/css/intl/de.css +1 -1
  9. package/dist/css/intl/es.css +1 -1
  10. package/dist/css/intl/fr.css +1 -1
  11. package/dist/css/intl/ja.css +1 -1
  12. package/dist/css/intl/pt.css +1 -1
  13. package/dist/css/intl/zh.css +1 -1
  14. package/dist/css/intl.css +1 -1
  15. package/dist/css/monokai.css +1 -1
  16. package/dist/css/phosphor.css +1 -1
  17. package/dist/css/pro-dark.css +1 -1
  18. package/dist/css/pro.css +1 -1
  19. package/dist/css/solarized-dark.css +1 -1
  20. package/dist/css/solarized.css +1 -1
  21. package/dist/css/themes.css +1 -1
  22. package/dist/css/vaporwave.css +1 -1
  23. package/dist/esm/extensions.d.ts +22 -3
  24. package/dist/esm/perspective-viewer.d.ts +9 -0
  25. package/dist/esm/perspective-viewer.inline.js +20 -1
  26. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  27. package/dist/esm/perspective-viewer.js +20 -1
  28. package/dist/esm/perspective-viewer.js.map +4 -4
  29. package/dist/esm/plugin.d.ts +71 -5
  30. package/dist/esm/ts-rs/ClientOptions.d.ts +7 -0
  31. package/dist/esm/ts-rs/ExportMethod.d.ts +1 -0
  32. package/dist/esm/ts-rs/ExportOptions.d.ts +9 -0
  33. package/dist/esm/ts-rs/GetClientOptions.d.ts +8 -0
  34. package/dist/esm/ts-rs/GetTableOptions.d.ts +8 -0
  35. package/dist/esm/ts-rs/Layout.d.ts +11 -0
  36. package/dist/esm/ts-rs/Orientation.d.ts +4 -0
  37. package/dist/esm/ts-rs/PanelOptions.d.ts +7 -0
  38. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +41 -0
  39. package/dist/esm/ts-rs/SplitLayout.d.ts +7 -0
  40. package/dist/esm/ts-rs/TabLayout.d.ts +10 -0
  41. package/dist/esm/ts-rs/ViewerConfig.d.ts +8 -2
  42. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +9 -0
  43. package/dist/esm/ts-rs/WindowAggregate.d.ts +1 -0
  44. package/dist/esm/ts-rs/WindowSort.d.ts +7 -0
  45. package/dist/esm/ts-rs/WindowSortDir.d.ts +6 -0
  46. package/dist/esm/ts-rs/WindowSpec.d.ts +46 -0
  47. package/dist/esm/ts-rs/Windows.d.ts +10 -0
  48. package/dist/esm/ts-rs/WorkspaceConfig.d.ts +40 -0
  49. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +28 -0
  50. package/dist/wasm/perspective-viewer.d.ts +299 -78
  51. package/dist/wasm/perspective-viewer.js +544 -186
  52. package/dist/wasm/perspective-viewer.wasm +0 -0
  53. package/dist/wasm/perspective-viewer.wasm.d.ts +34 -26
  54. package/dist/wasm/snippets/perspective-viewer-8a8c7d5d696b43ae/inline0.js +6 -0
  55. package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline3.js → perspective-viewer-8a8c7d5d696b43ae/inline4.js} +5 -0
  56. package/package.json +3 -2
  57. package/src/css/_context_menu.css +14 -0
  58. package/src/css/column-selector.css +1 -0
  59. package/src/css/column-settings-panel.css +68 -3
  60. package/src/css/column-style.css +4 -3
  61. package/src/css/config-selector.css +22 -1
  62. package/src/css/containers/context-menu.css +107 -0
  63. package/src/css/containers/tabs.css +2 -2
  64. package/src/css/panel-tab.css +193 -0
  65. package/src/css/plugin-selector.css +7 -10
  66. package/src/css/status-bar.css +75 -81
  67. package/src/css/viewer.css +188 -70
  68. package/src/rust/components/column_dropdown.rs +40 -30
  69. package/src/rust/components/column_selector/active_column.rs +28 -45
  70. package/src/rust/components/column_selector/aggregate_selector.rs +4 -7
  71. package/src/rust/components/column_selector/column_selector_column_row.rs +73 -0
  72. package/src/rust/components/column_selector/config_selector.rs +40 -82
  73. package/src/rust/components/column_selector/expr_edit_button.rs +7 -1
  74. package/src/rust/components/column_selector/filter_column.rs +5 -15
  75. package/src/rust/components/column_selector/inactive_column.rs +11 -9
  76. package/src/rust/components/column_selector/sort_column.rs +3 -6
  77. package/src/rust/components/column_selector.rs +25 -14
  78. package/src/rust/components/column_settings_sidebar/style_tab.rs +2 -1
  79. package/src/rust/components/column_settings_sidebar/window_tab.rs +34 -0
  80. package/src/rust/components/column_settings_sidebar.rs +163 -16
  81. package/src/rust/components/containers/dragdrop_list.rs +73 -3
  82. package/src/rust/components/containers/sidebar.rs +99 -22
  83. package/src/rust/components/containers/split_panel.rs +181 -62
  84. package/src/rust/components/context_menu.rs +130 -0
  85. package/src/rust/components/editable_header.rs +2 -0
  86. package/src/rust/components/form/debug.rs +3 -0
  87. package/src/rust/components/global_filter_bar.rs +76 -0
  88. package/src/rust/components/main_panel/frame_theme.rs +186 -0
  89. package/src/rust/components/main_panel/msg.rs +62 -0
  90. package/src/rust/components/main_panel/presize.rs +220 -0
  91. package/src/rust/components/main_panel/reconcile.rs +224 -0
  92. package/src/rust/components/main_panel/render.rs +385 -0
  93. package/src/rust/components/main_panel/update.rs +184 -0
  94. package/src/rust/components/main_panel.rs +316 -71
  95. package/src/rust/components/mod.rs +5 -0
  96. package/src/rust/components/panel_menu.rs +493 -0
  97. package/src/rust/components/panel_tab.rs +510 -0
  98. package/src/rust/components/plugin_tab.rs +1 -1
  99. package/src/rust/components/portal.rs +7 -0
  100. package/src/rust/components/settings_panel.rs +13 -5
  101. package/src/rust/components/status_bar.rs +110 -178
  102. package/src/rust/components/status_indicator.rs +6 -9
  103. package/src/rust/components/style/mod.rs +5 -0
  104. package/src/rust/components/style/style_provider.rs +2 -0
  105. package/src/rust/components/viewer/filters.rs +133 -0
  106. package/src/rust/components/viewer/msg.rs +182 -0
  107. package/src/rust/components/viewer/panels.rs +326 -0
  108. package/src/rust/components/viewer/render.rs +255 -0
  109. package/src/rust/components/viewer/settings.rs +434 -0
  110. package/src/rust/components/viewer/snapshots.rs +134 -0
  111. package/src/rust/components/viewer/wiring.rs +505 -0
  112. package/src/rust/components/viewer.rs +245 -756
  113. package/src/rust/components/window_editor.rs +1013 -0
  114. package/src/rust/config/export_method.rs +1 -1
  115. package/src/rust/config/mod.rs +4 -0
  116. package/src/rust/config/options.rs +71 -0
  117. package/src/rust/config/viewer_config.rs +24 -2
  118. package/src/rust/config/workspace_config.rs +92 -0
  119. package/src/rust/custom_elements/copy_dropdown.rs +3 -1
  120. package/src/rust/custom_elements/debug_plugin.rs +20 -1
  121. package/src/rust/custom_elements/export_dropdown.rs +3 -1
  122. package/src/rust/custom_elements/viewer.rs +1015 -286
  123. package/src/rust/custom_events.rs +212 -61
  124. package/src/rust/js/mod.rs +2 -0
  125. package/src/rust/js/plugin.rs +297 -10
  126. package/src/rust/js/regular_layout.rs +258 -0
  127. package/src/rust/lib.rs +24 -2
  128. package/src/rust/presentation/column_locator.rs +16 -1
  129. package/src/rust/presentation.rs +66 -33
  130. package/src/rust/queries/columns_iter_set.rs +7 -1
  131. package/src/rust/queries/get_viewer_config.rs +29 -11
  132. package/src/rust/queries/plugin_column_styles.rs +2 -2
  133. package/src/rust/renderer/activate.rs +41 -14
  134. package/src/rust/renderer/dispatch.rs +463 -0
  135. package/src/rust/renderer/plugin_config.rs +495 -0
  136. package/src/rust/renderer/registry.rs +18 -6
  137. package/src/rust/renderer/render_timer.rs +29 -10
  138. package/src/rust/renderer.rs +384 -838
  139. package/src/rust/session/column_defaults_update.rs +26 -8
  140. package/src/rust/session/drag_drop_update.rs +18 -0
  141. package/src/rust/session/metadata.rs +66 -9
  142. package/src/rust/session/replace_expression_update.rs +1 -0
  143. package/src/rust/session/view_subscription.rs +30 -15
  144. package/src/rust/session.rs +755 -264
  145. package/src/rust/tasks/apply_global_filters.rs +89 -0
  146. package/src/rust/tasks/auto_pause.rs +171 -0
  147. package/src/rust/tasks/copy_export.rs +29 -19
  148. package/src/rust/tasks/create_panel.rs +243 -0
  149. package/src/rust/tasks/dismiss_render_warning.rs +3 -1
  150. package/src/rust/tasks/edit_expression.rs +4 -4
  151. package/src/rust/tasks/edit_window.rs +155 -0
  152. package/src/rust/tasks/eject.rs +64 -23
  153. package/src/rust/tasks/mod.rs +30 -4
  154. package/src/rust/tasks/pipeline.rs +411 -0
  155. package/src/rust/tasks/presize_panels.rs +324 -0
  156. package/src/rust/tasks/reset_all.rs +22 -12
  157. package/src/rust/tasks/resize_observer.rs +124 -87
  158. package/src/rust/tasks/restore_and_render.rs +80 -86
  159. package/src/rust/tasks/restore_panel.rs +145 -0
  160. package/src/rust/tasks/send_column_config.rs +5 -2
  161. package/src/rust/tasks/send_plugin_config.rs +5 -2
  162. package/src/rust/tasks/set_edit_mode.rs +59 -0
  163. package/src/rust/tasks/sync_update_panels.rs +152 -0
  164. package/src/rust/tasks/table_lifecycle.rs +158 -0
  165. package/src/rust/tasks/update_theme.rs +56 -12
  166. package/src/rust/utils/browser/dragdrop.rs +12 -0
  167. package/src/rust/utils/browser/tests/debounce.rs +49 -0
  168. package/src/rust/utils/completion.rs +56 -0
  169. package/src/rust/utils/custom_element.rs +5 -0
  170. package/src/rust/utils/debounce.rs +189 -17
  171. package/src/rust/utils/mod.rs +6 -0
  172. package/src/rust/utils/pending_effects.rs +62 -0
  173. package/src/rust/utils/spawn.rs +33 -0
  174. package/src/rust/utils/weak_scope.rs +0 -10
  175. package/src/rust/workspace.rs +846 -0
  176. package/src/svg/active-indicator.svg +3 -0
  177. package/src/svg/pin-icon.svg +5 -0
  178. package/src/themes/botanical.css +5 -2
  179. package/src/themes/defaults.css +54 -2
  180. package/src/themes/dracula.css +6 -3
  181. package/src/themes/gruvbox-dark.css +5 -2
  182. package/src/themes/gruvbox.css +5 -2
  183. package/src/themes/icons.css +5 -2
  184. package/src/themes/intl/de.css +7 -0
  185. package/src/themes/intl/es.css +7 -0
  186. package/src/themes/intl/fr.css +7 -0
  187. package/src/themes/intl/ja.css +7 -0
  188. package/src/themes/intl/pt.css +7 -0
  189. package/src/themes/intl/zh.css +7 -0
  190. package/src/themes/intl.css +10 -1
  191. package/src/themes/monokai.css +5 -2
  192. package/src/themes/phosphor.css +5 -2
  193. package/src/themes/pro-dark.css +5 -2
  194. package/src/themes/pro.css +2 -1
  195. package/src/themes/solarized-dark.css +5 -2
  196. package/src/themes/solarized.css +5 -2
  197. package/src/themes/vaporwave.css +5 -2
  198. package/src/ts/bootstrap.ts +8 -7
  199. package/src/ts/extensions.ts +30 -2
  200. package/src/ts/perspective-viewer.ts +10 -0
  201. package/src/ts/plugin.ts +72 -5
  202. package/src/ts/ts-rs/ClientOptions.ts +7 -0
  203. package/src/ts/ts-rs/ExportMethod.ts +3 -0
  204. package/src/ts/ts-rs/ExportOptions.ts +8 -0
  205. package/src/ts/ts-rs/GetClientOptions.ts +7 -0
  206. package/src/ts/ts-rs/GetTableOptions.ts +7 -0
  207. package/src/ts/ts-rs/Layout.ts +9 -0
  208. package/src/ts/ts-rs/Orientation.ts +6 -0
  209. package/src/ts/ts-rs/PanelOptions.ts +7 -0
  210. package/src/ts/ts-rs/PanelViewerConfig.ts +16 -0
  211. package/src/ts/ts-rs/SplitLayout.ts +5 -0
  212. package/src/ts/ts-rs/TabLayout.ts +11 -0
  213. package/src/ts/ts-rs/ViewerConfig.ts +7 -2
  214. package/src/ts/ts-rs/ViewerConfigUpdate.ts +9 -0
  215. package/src/ts/ts-rs/WindowAggregate.ts +3 -0
  216. package/src/ts/ts-rs/WindowSort.ts +9 -0
  217. package/src/ts/ts-rs/WindowSortDir.ts +8 -0
  218. package/src/ts/ts-rs/WindowSpec.ts +46 -0
  219. package/src/ts/ts-rs/Windows.ts +10 -0
  220. package/src/ts/ts-rs/WorkspaceConfig.ts +36 -0
  221. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +24 -0
  222. package/src/rust/tasks/intersection_observer.rs +0 -98
  223. package/src/rust/tasks/update_and_render.rs +0 -110
  224. /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline0.js → perspective-viewer-8a8c7d5d696b43ae/inline1.js} +0 -0
  225. /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline1.js → perspective-viewer-8a8c7d5d696b43ae/inline2.js} +0 -0
  226. /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline2.js → perspective-viewer-8a8c7d5d696b43ae/inline3.js} +0 -0
  227. /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline4.js → perspective-viewer-8a8c7d5d696b43ae/inline5.js} +0 -0
@@ -0,0 +1,155 @@
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 perspective_client::clone;
14
+ use perspective_client::config::{Filter, ViewConfigUpdate, WindowSpec};
15
+
16
+ use super::apply_and_render;
17
+ use crate::presentation::{ColumnLocator, ColumnSettingsTab, OpenColumnSettings, Presentation};
18
+ use crate::renderer::Renderer;
19
+ use crate::session::Session;
20
+ use crate::*;
21
+
22
+ fn reopen(presentation: &Presentation, name: String) {
23
+ presentation.set_open_column_settings(Some(OpenColumnSettings {
24
+ locator: Some(ColumnLocator::Window(name)),
25
+ tab: Some(ColumnSettingsTab::Window),
26
+ }));
27
+ }
28
+
29
+ /// Insert `spec` into the session's windows as `name` (replacing any spec
30
+ /// under the same key) and re-render. After the render completes, opens the
31
+ /// column-settings drawer on the new window column.
32
+ pub fn save_window(
33
+ session: &Session,
34
+ renderer: &Renderer,
35
+ presentation: &Presentation,
36
+ name: String,
37
+ spec: WindowSpec,
38
+ ) -> ApiResult<()> {
39
+ let presentation = presentation.clone();
40
+ let task = {
41
+ let mut windows = session.get_view_config().windows.clone();
42
+ windows.insert(name.clone(), spec);
43
+ apply_and_render(session, renderer, ViewConfigUpdate {
44
+ windows: Some(windows),
45
+ ..Default::default()
46
+ })
47
+ }?;
48
+
49
+ ApiFuture::spawn(async move {
50
+ task.await?;
51
+ reopen(&presentation, name);
52
+ Ok(())
53
+ });
54
+
55
+ Ok(())
56
+ }
57
+
58
+ /// Replace the window at `old_name` with `spec` and re-render. A rename
59
+ /// rewrites every config reference to the old name - `columns`, `group_by`,
60
+ /// `split_by`, `sort`, `filter` and the `aggregates` key - so usage follows
61
+ /// the column, as expression renames do.
62
+ pub fn update_window(
63
+ session: &Session,
64
+ renderer: &Renderer,
65
+ presentation: &Presentation,
66
+ old_name: String,
67
+ new_name: String,
68
+ spec: WindowSpec,
69
+ ) {
70
+ clone!(session, renderer, presentation);
71
+ ApiFuture::spawn(async move {
72
+ let update = {
73
+ let config = session.get_view_config().clone();
74
+ let mut windows = config.windows.clone();
75
+ windows.remove(&old_name);
76
+ windows.insert(new_name.clone(), spec);
77
+
78
+ let rename = |col: &String| -> String {
79
+ if col == &old_name {
80
+ new_name.clone()
81
+ } else {
82
+ col.clone()
83
+ }
84
+ };
85
+
86
+ let mut update = ViewConfigUpdate {
87
+ windows: Some(windows),
88
+ ..Default::default()
89
+ };
90
+
91
+ if old_name != new_name {
92
+ update.columns = Some(
93
+ config
94
+ .columns
95
+ .iter()
96
+ .map(|col| col.as_ref().map(&rename))
97
+ .collect(),
98
+ );
99
+ update.group_by = Some(config.group_by.iter().map(&rename).collect());
100
+ update.split_by = Some(config.split_by.iter().map(&rename).collect());
101
+ update.sort = Some(
102
+ config
103
+ .sort
104
+ .iter()
105
+ .map(|sort| {
106
+ let mut sort = sort.clone();
107
+ sort.0 = rename(&sort.0);
108
+ sort
109
+ })
110
+ .collect(),
111
+ );
112
+ update.filter = Some(
113
+ config
114
+ .filter
115
+ .iter()
116
+ .map(|filter| {
117
+ if filter.column() == old_name {
118
+ Filter::new(new_name.as_str(), filter.op(), filter.term().clone())
119
+ } else {
120
+ filter.clone()
121
+ }
122
+ })
123
+ .collect(),
124
+ );
125
+ update.aggregates = Some(
126
+ config
127
+ .aggregates
128
+ .iter()
129
+ .map(|(col, agg)| (rename(col), agg.clone()))
130
+ .collect(),
131
+ );
132
+ }
133
+
134
+ update
135
+ };
136
+
137
+ apply_and_render(&session, &renderer, update)?.await?;
138
+ reopen(&presentation, new_name);
139
+ Ok(())
140
+ });
141
+ }
142
+
143
+ /// Remove the window named `name` from the session and re-render.
144
+ pub fn delete_window(session: &Session, renderer: &Renderer, name: &str) -> ApiResult<()> {
145
+ let mut windows = session.get_view_config().windows.clone();
146
+ windows.remove(name);
147
+ let config = ViewConfigUpdate {
148
+ windows: Some(windows),
149
+ ..ViewConfigUpdate::default()
150
+ };
151
+
152
+ let task = apply_and_render(session, renderer, config)?;
153
+ ApiFuture::spawn(task);
154
+ Ok(())
155
+ }
@@ -10,35 +10,76 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
+ use futures::future::join_all;
13
14
  use perspective_client::clone;
15
+ use perspective_js::utils::{ApiError, ApiResult};
14
16
  use yew::Component;
15
17
 
16
18
  use crate::ApiFuture;
17
- use crate::renderer::Renderer;
18
19
  use crate::root::Root;
19
- use crate::session::{ResetOptions, Session, TableIntermediateState};
20
+ use crate::session::{ResetOptions, TableIntermediateState};
21
+ use crate::workspace::Workspace;
20
22
 
21
- /// Tear down the entire viewer: emit `table_unloaded`, lock the renderer
22
- /// while it's destroyed, drop the Yew root, and reset the session to its
23
- /// ejected state.
24
- pub fn delete_all<T: Component>(
25
- session: &Session,
26
- renderer: &Renderer,
27
- root: &Root<T>,
28
- ) -> ApiFuture<()> {
29
- session.table_unloaded.emit(false);
30
- clone!(session, renderer, root);
31
- ApiFuture::new(renderer.clone().with_lock(async move {
32
- renderer.delete()?;
33
- root.borrow_mut().take().ok_or("Already deleted")?.destroy();
34
- session
35
- .reset(ResetOptions {
36
- config: true,
37
- expressions: true,
38
- table: Some(TableIntermediateState::Ejected),
39
- ..ResetOptions::default()
23
+ /// Tear down the entire viewer: dispose EVERY panel's engines (emit
24
+ /// `table_unloaded`, destroy the renderer under its own draw lock, eject the
25
+ /// session), then drop the Yew root once. Fans out over all panels — not just
26
+ /// the seed — so panels added via `addPanel` or a whole-element `restore` don't
27
+ /// leak their `View`/`Table` + plugin when the element is deleted or ejected.
28
+ pub fn delete_all<T: Component>(workspace: &Workspace, root: &Root<T>) -> ApiFuture<()> {
29
+ clone!(workspace, root);
30
+ ApiFuture::new(async move {
31
+ let panels = workspace
32
+ .take_reserved()
33
+ .into_iter()
34
+ .chain(
35
+ workspace
36
+ .panel_ids()
37
+ .into_iter()
38
+ .filter_map(|id| workspace.panel(&id)),
39
+ )
40
+ .collect::<Vec<_>>();
41
+
42
+ // Each panel owns its own `Renderer`/draw lock, so dispose them
43
+ // concurrently. `renderer.delete()` must hold the draw lock (it runs
44
+ // `plugin.delete()` synchronously), hence the per-panel `with_lock`.
45
+ // BEST-EFFORT teardown: attempt EVERY panel and ALWAYS destroy the
46
+ // Yew root, then report the first error. Aborting on the first
47
+ // failed panel (the previous behavior) leaked the root and every
48
+ // remaining panel's `View`/plugin.
49
+ let results = join_all(panels.iter().map(|panel| {
50
+ clone!(panel.session, panel.renderer);
51
+ session.table_unloaded.emit(false);
52
+ let was_errored = session.is_errored();
53
+ renderer.clone().with_lock(async move {
54
+ renderer.delete()?;
55
+ let reset = session
56
+ .reset(ResetOptions {
57
+ config: true,
58
+ expressions: true,
59
+ table: Some(TableIntermediateState::Ejected),
60
+ ..ResetOptions::default()
61
+ })
62
+ .await;
63
+
64
+ match reset {
65
+ Err(_) if was_errored => Ok(()),
66
+ other => other,
67
+ }
40
68
  })
41
- .await?;
69
+ }))
70
+ .await;
71
+
72
+ // Drop the Yew root once, after every panel's teardown was
73
+ // attempted — UNCONDITIONALLY, before error propagation, so a failed
74
+ // panel can't leak it.
75
+ let root_result = root
76
+ .borrow_mut()
77
+ .take()
78
+ .ok_or_else(|| ApiError::from("Already deleted"))
79
+ .map(|x| x.destroy());
80
+
81
+ results.into_iter().collect::<ApiResult<Vec<_>>>()?;
82
+ root_result?;
42
83
  Ok(())
43
- }))
84
+ })
44
85
  }
@@ -21,30 +21,56 @@
21
21
  //! [`Renderer`]: crate::renderer::Renderer
22
22
  //! [`Presentation`]: crate::presentation::Presentation
23
23
 
24
+ mod apply_global_filters;
25
+ mod auto_pause;
24
26
  mod copy_export;
27
+ mod create_panel;
25
28
  mod dismiss_render_warning;
26
29
  mod edit_expression;
30
+ mod edit_window;
27
31
  mod eject;
28
- mod intersection_observer;
32
+ mod pipeline;
33
+ mod presize_panels;
29
34
  mod reset_all;
30
35
  mod resize_observer;
31
36
  mod restore_and_render;
37
+ mod restore_panel;
32
38
  mod send_column_config;
33
39
  mod send_plugin_config;
34
- mod update_and_render;
40
+ mod set_edit_mode;
41
+ mod sync_update_panels;
42
+ mod table_lifecycle;
35
43
  mod update_theme;
36
44
  mod validate_expression;
37
45
 
46
+ /// How long staged work (a hidden first draw, a presize sweep) may withhold
47
+ /// a layout transition before it is released anyway — the progressive-reveal
48
+ /// fallback for slow (e.g. remote) tables.
49
+ pub(crate) const STAGING_DEADLINE_MS: i32 = 500;
50
+
51
+ /// Fallback panel chrome `(width, height)` px (margin + border + titlebar)
52
+ /// when no frame is available to measure live (see
53
+ /// [`presize_panels::plugin_chrome`]).
54
+ pub(crate) const CHROME_FALLBACK: (f64, f64) = (8.0, 33.0);
55
+
56
+ pub use self::apply_global_filters::*;
57
+ pub use self::auto_pause::*;
38
58
  pub use self::copy_export::*;
59
+ pub(crate) use self::create_panel::*;
39
60
  pub use self::dismiss_render_warning::*;
40
61
  pub use self::edit_expression::*;
62
+ pub use self::edit_window::*;
41
63
  pub use self::eject::*;
42
- pub use self::intersection_observer::*;
64
+ pub use self::pipeline::*;
65
+ pub use self::presize_panels::*;
43
66
  pub use self::reset_all::*;
44
67
  pub use self::resize_observer::*;
45
68
  pub use self::restore_and_render::*;
69
+ pub(crate) use self::restore_panel::*;
46
70
  pub use self::send_column_config::*;
47
71
  pub use self::send_plugin_config::*;
48
- pub use self::update_and_render::*;
72
+ pub use self::set_edit_mode::*;
73
+ pub(crate) use self::sync_update_panels::*;
74
+ pub(crate) use self::table_lifecycle::*;
49
75
  pub use self::update_theme::*;
50
76
  pub use self::validate_expression::*;