@perspective-dev/viewer 4.4.1 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/dist/cdn/perspective-viewer.js +1 -2
  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/bootstrap.d.ts +2 -1
  24. package/dist/esm/column-format.d.ts +51 -0
  25. package/dist/esm/extensions.d.ts +2 -0
  26. package/dist/esm/perspective-viewer.d.ts +3 -1
  27. package/dist/esm/perspective-viewer.inline.js +1 -2
  28. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  29. package/dist/esm/perspective-viewer.js +1 -2
  30. package/dist/esm/perspective-viewer.js.map +4 -4
  31. package/dist/esm/perspective-viewer.worker.d.ts +2 -0
  32. package/dist/esm/plugin.d.ts +16 -72
  33. package/dist/esm/ts-rs/ColumnSelectMode.d.ts +1 -0
  34. package/dist/esm/ts-rs/PluginStaticConfig.d.ts +77 -0
  35. package/dist/esm/ts-rs/ViewerConfig.d.ts +6 -3
  36. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
  37. package/dist/wasm/perspective-viewer.d.ts +77 -18
  38. package/dist/wasm/perspective-viewer.js +302 -148
  39. package/dist/wasm/perspective-viewer.wasm +0 -0
  40. package/dist/wasm/perspective-viewer.wasm.d.ts +20 -15
  41. package/package.json +24 -2
  42. package/src/css/column-selector.css +3 -2
  43. package/src/css/column-settings-panel.css +44 -9
  44. package/src/css/column-style.css +35 -2
  45. package/src/css/containers/scroll-panel.css +2 -1
  46. package/src/css/containers/tabs.css +8 -52
  47. package/src/css/dom/checkbox.css +2 -6
  48. package/src/css/form/code-editor.css +1 -0
  49. package/src/css/form/debug.css +3 -10
  50. package/src/css/plugin-selector.css +33 -0
  51. package/src/css/plugin-settings-panel.css +99 -0
  52. package/src/css/viewer.css +143 -3
  53. package/src/rust/components/column_dropdown.rs +3 -1
  54. package/src/rust/components/column_selector/active_column.rs +16 -19
  55. package/src/rust/components/column_selector/config_selector.rs +20 -20
  56. package/src/rust/components/column_selector/filter_column.rs +14 -14
  57. package/src/rust/components/column_selector/inactive_column.rs +10 -15
  58. package/src/rust/components/column_selector/pivot_column.rs +7 -7
  59. package/src/rust/components/column_selector/sort_column.rs +7 -7
  60. package/src/rust/components/column_selector.rs +55 -37
  61. package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +15 -7
  62. package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +395 -0
  63. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +15 -6
  64. package/src/rust/components/column_settings_sidebar/style_tab.rs +267 -136
  65. package/src/rust/components/column_settings_sidebar.rs +44 -49
  66. package/src/rust/components/containers/dragdrop_list.rs +32 -5
  67. package/src/rust/components/containers/mod.rs +0 -1
  68. package/src/rust/components/containers/scroll_panel.rs +21 -7
  69. package/src/rust/components/containers/sidebar.rs +8 -6
  70. package/src/rust/components/containers/split_panel.rs +3 -3
  71. package/src/rust/components/containers/tab_list.rs +3 -9
  72. package/src/rust/components/copy_dropdown.rs +2 -3
  73. package/src/rust/components/datetime_column_style.rs +19 -81
  74. package/src/rust/components/editable_header.rs +17 -3
  75. package/src/rust/components/export_dropdown.rs +2 -3
  76. package/src/rust/components/expression_editor.rs +29 -17
  77. package/src/rust/components/filter_dropdown.rs +2 -1
  78. package/src/rust/components/form/color_range_selector.rs +14 -7
  79. package/src/rust/components/form/debug.rs +47 -37
  80. package/src/rust/components/main_panel.rs +24 -65
  81. package/src/rust/components/mod.rs +2 -1
  82. package/src/rust/components/number_series_style.rs +161 -0
  83. package/src/rust/components/plugin_tab.rs +221 -0
  84. package/src/rust/components/settings_panel.rs +181 -59
  85. package/src/rust/components/status_bar.rs +141 -174
  86. package/src/rust/components/status_indicator.rs +15 -22
  87. package/src/rust/components/string_column_style.rs +20 -82
  88. package/src/rust/components/style_controls/number_string_format.rs +14 -30
  89. package/src/rust/components/viewer.rs +169 -132
  90. package/src/rust/config/column_config_schema.rs +195 -0
  91. package/src/rust/config/columns_config.rs +4 -97
  92. package/src/rust/config/datetime_column_style.rs +0 -5
  93. package/src/rust/config/mod.rs +8 -2
  94. package/src/rust/config/number_series_style.rs +79 -0
  95. package/src/rust/config/plugin_static_config.rs +144 -0
  96. package/src/rust/config/string_column_style.rs +0 -5
  97. package/src/rust/config/viewer_config.rs +5 -6
  98. package/src/rust/custom_elements/copy_dropdown.rs +30 -18
  99. package/src/rust/custom_elements/debug_plugin.rs +1 -3
  100. package/src/rust/custom_elements/export_dropdown.rs +26 -18
  101. package/src/rust/custom_elements/viewer.rs +62 -73
  102. package/src/rust/custom_events.rs +181 -224
  103. package/src/rust/js/plugin.rs +45 -117
  104. package/src/rust/lib.rs +34 -5
  105. package/src/rust/presentation/drag_helpers.rs +206 -0
  106. package/src/rust/presentation/props.rs +8 -0
  107. package/src/rust/presentation.rs +256 -41
  108. package/src/rust/{tasks → queries}/column_locator.rs +17 -73
  109. package/src/rust/queries/column_values.rs +59 -0
  110. package/src/rust/{tasks → queries}/columns_iter_set.rs +11 -18
  111. package/src/rust/queries/exports.rs +96 -0
  112. package/src/rust/queries/fetch_column_stats.rs +94 -0
  113. package/src/rust/queries/get_viewer_config.rs +54 -0
  114. package/src/rust/queries/mod.rs +44 -0
  115. package/src/rust/queries/plugin_column_styles.rs +101 -0
  116. package/src/rust/{engines.rs → queries/validate_expression.rs} +26 -15
  117. package/src/rust/renderer/activate.rs +1 -0
  118. package/src/rust/renderer/limits.rs +9 -4
  119. package/src/rust/renderer/plugin_store.rs +12 -0
  120. package/src/rust/renderer/props.rs +28 -3
  121. package/src/rust/renderer/registry.rs +40 -15
  122. package/src/rust/renderer.rs +703 -60
  123. package/src/rust/session/column_defaults_update.rs +20 -28
  124. package/src/rust/session/drag_drop_update.rs +10 -10
  125. package/src/rust/session/metadata.rs +31 -16
  126. package/src/rust/session/props.rs +15 -6
  127. package/src/rust/session/view_subscription.rs +10 -0
  128. package/src/rust/session.rs +109 -147
  129. package/src/rust/tasks/copy_export.rs +178 -158
  130. package/src/rust/tasks/{structural.rs → dismiss_render_warning.rs} +20 -40
  131. package/src/rust/tasks/edit_expression.rs +68 -88
  132. package/src/rust/tasks/eject.rs +25 -22
  133. package/src/rust/tasks/intersection_observer.rs +8 -21
  134. package/src/rust/tasks/mod.rs +19 -21
  135. package/src/rust/tasks/reset_all.rs +98 -0
  136. package/src/rust/tasks/resize_observer.rs +11 -33
  137. package/src/rust/tasks/restore_and_render.rs +128 -90
  138. package/src/rust/tasks/{get_viewer_config.rs → send_column_config.rs} +39 -35
  139. package/src/rust/tasks/send_plugin_config.rs +33 -33
  140. package/src/rust/tasks/update_and_render.rs +75 -49
  141. package/src/rust/{components/containers/trap_door_panel.rs → tasks/update_theme.rs} +34 -33
  142. package/src/rust/tasks/validate_expression.rs +61 -0
  143. package/src/rust/utils/browser/selection.rs +4 -4
  144. package/src/rust/utils/mod.rs +0 -63
  145. package/src/svg/checkbox-checked-icon.svg +1 -1
  146. package/src/svg/checkbox-unchecked-icon.svg +1 -1
  147. package/src/svg/mega-menu-icons-density.svg +23 -0
  148. package/src/svg/mega-menu-icons-map-density.svg +24 -0
  149. package/src/svg/mega-menu-icons-map-line.svg +19 -0
  150. package/src/themes/botanical.css +27 -53
  151. package/src/themes/defaults.css +24 -36
  152. package/src/themes/dracula.css +36 -54
  153. package/src/themes/gruvbox-dark.css +39 -59
  154. package/src/themes/gruvbox.css +16 -28
  155. package/src/themes/icons.css +5 -0
  156. package/src/themes/intl/de.css +43 -6
  157. package/src/themes/intl/es.css +43 -6
  158. package/src/themes/intl/fr.css +43 -6
  159. package/src/themes/intl/ja.css +43 -6
  160. package/src/themes/intl/pt.css +43 -6
  161. package/src/themes/intl/zh.css +43 -6
  162. package/src/themes/intl.css +38 -4
  163. package/src/themes/monokai.css +45 -61
  164. package/src/themes/phosphor.css +20 -29
  165. package/src/themes/pro-dark.css +25 -34
  166. package/src/themes/solarized-dark.css +21 -36
  167. package/src/themes/solarized.css +13 -23
  168. package/src/themes/vaporwave.css +40 -74
  169. package/src/ts/bootstrap.ts +14 -3
  170. package/src/ts/column-format.ts +162 -0
  171. package/src/ts/extensions.ts +4 -0
  172. package/src/ts/perspective-viewer.ts +9 -1
  173. package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
  174. package/src/ts/plugin.ts +25 -101
  175. package/src/ts/ts-rs/{FormatUnit.ts → ColumnSelectMode.ts} +1 -1
  176. package/src/ts/ts-rs/PluginStaticConfig.ts +78 -0
  177. package/src/ts/ts-rs/ViewerConfig.ts +1 -2
  178. package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -3
  179. package/dist/esm/ts-rs/ColumnConfigValues.d.ts +0 -31
  180. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +0 -1
  181. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +0 -15
  182. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +0 -18
  183. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
  184. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +0 -6
  185. package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
  186. package/dist/esm/ts-rs/FormatUnit.d.ts +0 -1
  187. package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +0 -1
  188. package/dist/esm/ts-rs/NumberForegroundMode.d.ts +0 -1
  189. package/dist/esm/ts-rs/PluginConfig.d.ts +0 -2
  190. package/dist/esm/ts-rs/RoundingMode.d.ts +0 -1
  191. package/dist/esm/ts-rs/RoundingPriority.d.ts +0 -1
  192. package/dist/esm/ts-rs/SignDisplay.d.ts +0 -1
  193. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +0 -1
  194. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +0 -6
  195. package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
  196. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +0 -1
  197. package/dist/esm/ts-rs/UseGrouping.d.ts +0 -1
  198. package/src/rust/components/number_column_style.rs +0 -491
  199. package/src/rust/config/number_column_style.rs +0 -136
  200. package/src/rust/dragdrop.rs +0 -481
  201. package/src/rust/tasks/plugin_column_styles.rs +0 -98
  202. package/src/ts/ts-rs/ColumnConfigValues.ts +0 -14
  203. package/src/ts/ts-rs/CustomDatetimeFormat.ts +0 -3
  204. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +0 -5
  205. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +0 -8
  206. package/src/ts/ts-rs/DatetimeColorMode.ts +0 -3
  207. package/src/ts/ts-rs/DatetimeFormatType.ts +0 -8
  208. package/src/ts/ts-rs/FormatMode.ts +0 -3
  209. package/src/ts/ts-rs/NumberBackgroundMode.ts +0 -3
  210. package/src/ts/ts-rs/NumberForegroundMode.ts +0 -3
  211. package/src/ts/ts-rs/PluginConfig.ts +0 -4
  212. package/src/ts/ts-rs/RoundingMode.ts +0 -3
  213. package/src/ts/ts-rs/RoundingPriority.ts +0 -3
  214. package/src/ts/ts-rs/SignDisplay.ts +0 -3
  215. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +0 -3
  216. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +0 -4
  217. package/src/ts/ts-rs/StringColorMode.ts +0 -3
  218. package/src/ts/ts-rs/TrailingZeroDisplay.ts +0 -3
  219. package/src/ts/ts-rs/UseGrouping.ts +0 -3
  220. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline0.js +0 -0
  221. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline1.js +0 -0
  222. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline2.js +0 -0
  223. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline3.js +0 -0
  224. /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-3cd58f0374935772}/inline4.js +0 -0
  225. /package/src/rust/{tasks → config}/export_method.rs +0 -0
  226. /package/src/rust/{tasks → queries}/export_app.rs +0 -0
  227. /package/src/rust/{tasks → queries}/is_invalid_drop.rs +0 -0
@@ -10,19 +10,30 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- //! Engine-handle types for the four major state singletons.
14
- //!
15
- //! These are the async-machinery halves of the engine/value split described in
16
- //! the props modules. They own JS object handles, draw locks, async
17
- //! subscriptions, and PubSub channels — i.e. anything that cannot be cheaply
18
- //! cloned into a plain `PartialEq` prop.
19
- //!
20
- //! **Current status (Step 3 of the migration):** Each `*Engine` type is a thin
21
- //! type alias for the existing `Rc<*Handle>` wrapper. They will be replaced
22
- //! with true struct types in later migration steps once the component tree has
23
- //! been updated to consume value-semantic props instead of the old handles.
13
+ use std::collections::HashMap;
24
14
 
25
- pub use crate::dragdrop::DragDrop as DragDropEngine;
26
- pub use crate::presentation::Presentation as PresentationEngine;
27
- pub use crate::renderer::Renderer as RendererEngine;
28
- pub use crate::session::Session as SessionEngine;
15
+ use perspective_client::ExprValidationError;
16
+ use perspective_client::config::ExpressionsDeserde;
17
+ use perspective_js::utils::ApiError;
18
+
19
+ use crate::session::Session;
20
+
21
+ /// Validate an expression string against the active table; returns the
22
+ /// per-expression error map entry (if any).
23
+ pub async fn validate_expr(
24
+ session: &Session,
25
+ expr: &str,
26
+ ) -> Result<Option<ExprValidationError>, ApiError> {
27
+ let table = session
28
+ .get_table()
29
+ .ok_or_else(|| ApiError::from("No table set"))?;
30
+ let errors = table
31
+ .validate_expressions(
32
+ ExpressionsDeserde::Map(HashMap::from_iter([("_".to_string(), expr.to_string())]))
33
+ .into(),
34
+ )
35
+ .await?
36
+ .errors;
37
+
38
+ Ok(errors.get("_").cloned())
39
+ }
@@ -36,6 +36,7 @@ pub async fn activate_plugin<T>(
36
36
  if html_plugin.parent_node().is_none() {
37
37
  html_plugin.style().set_property("opacity", "0")?;
38
38
  viewer.append_child(html_plugin)?;
39
+ plugin.restyle();
39
40
  }
40
41
 
41
42
  let result = task.await;
@@ -12,7 +12,7 @@
12
12
 
13
13
  use perspective_js::utils::ApiError;
14
14
 
15
- use crate::js::plugin::*;
15
+ use crate::config::PluginStaticConfig;
16
16
 
17
17
  /// The row/column limits computed for the current view and plugin
18
18
  /// configuration.
@@ -31,14 +31,19 @@ pub struct RenderLimits {
31
31
  pub max_rows: Option<usize>,
32
32
  }
33
33
 
34
+ /// Compute the row/column caps for `view` against the plugin's static
35
+ /// limits. `render_warning` is the renderer-state flag controlling
36
+ /// whether the warning is currently armed; when `false`, an oversized
37
+ /// view renders uncapped (the user has dismissed the warning).
34
38
  pub async fn get_row_and_col_limits(
35
39
  view: &perspective_client::View,
36
- plugin_metadata: &ViewConfigRequirements,
40
+ config: &PluginStaticConfig,
41
+ render_warning: bool,
37
42
  ) -> Result<RenderLimits, ApiError> {
38
43
  let dimensions = view.dimensions().await?;
39
44
  let num_cols = dimensions.num_view_columns as usize;
40
45
  let num_rows = dimensions.num_view_rows as usize;
41
- match (plugin_metadata.max_columns, plugin_metadata.render_warning) {
46
+ match (config.max_columns, render_warning) {
42
47
  (Some(_), false) => Ok(RenderLimits {
43
48
  is_update: false,
44
49
  num_cols,
@@ -60,7 +65,7 @@ pub async fn get_row_and_col_limits(
60
65
  }
61
66
  });
62
67
 
63
- let max_rows = plugin_metadata.max_cells.map(|max_cells| {
68
+ let max_rows = config.max_cells.map(|max_cells| {
64
69
  match max_cols {
65
70
  Some(max_cols) => max_cells as f64 / max_cols as f64,
66
71
  None => max_cells as f64 / num_cols as f64,
@@ -11,19 +11,23 @@
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
13
  use std::collections::HashMap;
14
+ use std::rc::Rc;
14
15
 
15
16
  use super::registry::*;
17
+ use crate::config::PluginStaticConfig;
16
18
  use crate::js::plugin::*;
17
19
 
18
20
  #[derive(Default)]
19
21
  pub struct PluginStore {
20
22
  plugins: Option<Vec<JsPerspectiveViewerPlugin>>,
23
+ plugin_configs: Option<Vec<Rc<PluginStaticConfig>>>,
21
24
  plugin_records: Option<HashMap<String, Vec<String>>>,
22
25
  }
23
26
 
24
27
  impl PluginStore {
25
28
  fn init_lazy(&mut self) {
26
29
  self.plugins = Some(PLUGIN_REGISTRY.create_plugins());
30
+ self.plugin_configs = Some(PLUGIN_REGISTRY.plugin_configs());
27
31
  self.plugin_records = Some(PLUGIN_REGISTRY.available_plugin_names_by_category());
28
32
  }
29
33
 
@@ -35,6 +39,14 @@ impl PluginStore {
35
39
  self.plugins.as_ref().unwrap()
36
40
  }
37
41
 
42
+ pub fn plugin_configs(&mut self) -> &Vec<Rc<PluginStaticConfig>> {
43
+ if self.plugins.is_none() {
44
+ self.init_lazy();
45
+ }
46
+
47
+ self.plugin_configs.as_ref().unwrap()
48
+ }
49
+
38
50
  pub fn plugin_records(&mut self) -> &HashMap<String, Vec<String>> {
39
51
  if self.plugins.is_none() {
40
52
  self.init_lazy();
@@ -10,7 +10,9 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- use crate::js::plugin::ViewConfigRequirements;
13
+ use std::rc::Rc;
14
+
15
+ use crate::config::PluginStaticConfig;
14
16
  use crate::renderer::limits::RenderLimits;
15
17
  use crate::utils::PtrEqRc;
16
18
 
@@ -23,12 +25,35 @@ pub struct RendererProps {
23
25
  /// Name of the currently active plugin (e.g. `"Datagrid"`).
24
26
  pub plugin_name: Option<String>,
25
27
 
26
- /// Column count / config requirements reported by the active plugin.
27
- pub requirements: ViewConfigRequirements,
28
+ /// Cached static config of the active plugin (column requirements,
29
+ /// rollup modes, render caps, etc.). Shared with the renderer's
30
+ /// internal `metadata` — `Rc::ptr_eq` works.
31
+ pub config: Rc<PluginStaticConfig>,
28
32
 
29
33
  /// Most recently emitted render limits, if any.
30
34
  pub render_limits: Option<RenderLimits>,
31
35
 
32
36
  /// Names of all registered plugins, in registration order.
33
37
  pub available_plugins: PtrEqRc<Vec<String>>,
38
+
39
+ /// `true` when the active plugin is anything other than the
40
+ /// `Datagrid`. Changes only when the active plugin swaps, so reading
41
+ /// from this prop avoids a per-render `Renderer::is_chart()` call.
42
+ pub is_chart: bool,
43
+
44
+ /// Snapshot of the active plugin's `plugin_config` bucket. Re-read
45
+ /// by `Renderer::to_props` on `plugin_config_changed` /
46
+ /// `plugin_changed` (the active bucket changes on plugin switch).
47
+ /// Consumed by `PluginTab` so the tab is a pure function of its
48
+ /// props — no direct `Renderer::get_plugin_config()` reads against
49
+ /// the interior-mutable handle, no manual PubSub subscription, no
50
+ /// race window between `plugins_idx` swap and the schema query.
51
+ pub plugin_config: PtrEqRc<serde_json::Map<String, serde_json::Value>>,
52
+ }
53
+
54
+ impl RendererProps {
55
+ /// Whether the active plugin opts into per-column style controls.
56
+ pub fn can_render_column_styles(&self) -> bool {
57
+ self.config.can_render_column_styles
58
+ }
34
59
  }
@@ -21,6 +21,7 @@ use wasm_bindgen::JsCast;
21
21
  use wasm_bindgen::prelude::*;
22
22
  use web_sys::*;
23
23
 
24
+ use crate::config::{ColumnSelectMode, PluginStaticConfig};
24
25
  use crate::js::plugin::*;
25
26
 
26
27
  thread_local! {
@@ -28,10 +29,8 @@ thread_local! {
28
29
  }
29
30
 
30
31
  pub struct PluginRecord {
31
- name: String,
32
- category: String,
33
32
  tag_name: String,
34
- priority: i32,
33
+ config: Rc<PluginStaticConfig>,
35
34
  }
36
35
 
37
36
  /// A global registry of all plugins that have been registered.
@@ -59,13 +58,27 @@ pub impl LocalKey<Rc<RefCell<Vec<PluginRecord>>>> {
59
58
  .unwrap()
60
59
  }
61
60
 
61
+ /// Returns the cached `PluginStaticConfig`s for every registered
62
+ /// plugin, in registration order. The renderer reads these at
63
+ /// activation time instead of calling back into JS for each field.
64
+ fn plugin_configs(&'static self) -> Vec<Rc<PluginStaticConfig>> {
65
+ register_default();
66
+ self.with(|plugins| {
67
+ plugins
68
+ .borrow()
69
+ .iter()
70
+ .map(|plugin| plugin.config.clone())
71
+ .collect()
72
+ })
73
+ }
74
+
62
75
  fn default_plugin_name(&'static self) -> String {
63
76
  register_default();
64
77
  self.with(|plugins| {
65
78
  plugins
66
79
  .borrow()
67
80
  .iter()
68
- .map(|plugin| plugin.name.to_owned())
81
+ .map(|plugin| plugin.config.name.clone())
69
82
  .next()
70
83
  .unwrap()
71
84
  })
@@ -77,9 +90,15 @@ pub impl LocalKey<Rc<RefCell<Vec<PluginRecord>>>> {
77
90
  plugins.borrow().iter().fold(
78
91
  HashMap::<String, Vec<String>>::default(),
79
92
  |mut acc, plugin| {
80
- acc.entry(plugin.category.to_owned())
93
+ let category = plugin
94
+ .config
95
+ .category
96
+ .clone()
97
+ .unwrap_or_else(|| "Custom".to_owned());
98
+
99
+ acc.entry(category)
81
100
  .or_default()
82
- .push(plugin.name.to_owned());
101
+ .push(plugin.config.name.clone());
83
102
  acc
84
103
  },
85
104
  )
@@ -94,13 +113,10 @@ pub impl LocalKey<Rc<RefCell<Vec<PluginRecord>>>> {
94
113
 
95
114
  self.with(|plugin| {
96
115
  let plugin_inst = create_plugin(tag_name);
116
+ let config = Rc::new(plugin_inst.read_static_config());
97
117
  let record = PluginRecord {
98
118
  tag_name: tag_name.to_owned(),
99
- name: plugin_inst.name(),
100
- category: plugin_inst
101
- .category()
102
- .unwrap_or_else(|| "Custom".to_owned()),
103
- priority: plugin_inst.priority().unwrap_or_default(),
119
+ config,
104
120
  };
105
121
 
106
122
  let mut plugins = plugin.borrow_mut();
@@ -111,7 +127,12 @@ pub impl LocalKey<Rc<RefCell<Vec<PluginRecord>>>> {
111
127
  }
112
128
 
113
129
  plugins.push(record);
114
- plugins.sort_by(|a, b| Ord::cmp(&b.priority, &a.priority));
130
+ plugins.sort_by(|a, b| {
131
+ Ord::cmp(
132
+ &b.config.priority.unwrap_or(0),
133
+ &a.config.priority.unwrap_or(0),
134
+ )
135
+ });
115
136
  });
116
137
  }
117
138
 
@@ -125,10 +146,14 @@ fn register_default() {
125
146
  PLUGIN_REGISTRY.with(|plugins| {
126
147
  if plugins.borrow().is_empty() {
127
148
  plugins.borrow_mut().push(PluginRecord {
128
- name: "Debug".to_owned(),
129
- category: "Custom".to_owned(),
130
149
  tag_name: "perspective-viewer-plugin".to_owned(),
131
- priority: -1,
150
+ config: Rc::new(PluginStaticConfig {
151
+ name: "Debug".to_owned(),
152
+ category: Some("Custom".to_owned()),
153
+ select_mode: ColumnSelectMode::Select,
154
+ priority: Some(-1),
155
+ ..PluginStaticConfig::default()
156
+ }),
132
157
  })
133
158
  }
134
159
  })