@perspective-dev/viewer 5.1.0 → 5.3.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 +9 -9
- 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/docs/perspective-docs.json +1 -0
- package/dist/esm/column-format.d.ts +19 -28
- package/dist/esm/perspective-viewer.d.ts +3 -0
- package/dist/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +9 -9
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +10 -0
- package/dist/esm/providers.d.ts +79 -0
- package/dist/esm/ts-rs/CompactDisplay.d.ts +5 -0
- package/dist/esm/ts-rs/CurrencyCode.d.ts +1 -0
- package/dist/esm/ts-rs/CurrencyDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/CurrencyNumberFormatStyle.d.ts +8 -0
- package/dist/esm/ts-rs/CurrencySign.d.ts +1 -0
- package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +1 -0
- package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +54 -0
- package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +34 -0
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +1 -0
- package/dist/esm/ts-rs/DatetimeFormatType.d.ts +6 -0
- package/dist/esm/ts-rs/FormatMode.d.ts +1 -0
- package/dist/esm/ts-rs/FormatUnit.d.ts +1 -0
- package/dist/esm/ts-rs/Notation.d.ts +17 -0
- package/dist/esm/ts-rs/NumberFormatStyle.d.ts +18 -0
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +42 -2
- package/dist/esm/ts-rs/PluginStaticConfig.d.ts +35 -0
- package/dist/esm/ts-rs/RestoreOptions.d.ts +19 -0
- package/dist/esm/ts-rs/RoundingMode.d.ts +1 -0
- package/dist/esm/ts-rs/RoundingPriority.d.ts +1 -0
- package/dist/esm/ts-rs/SaveWorkspaceOptions.d.ts +10 -0
- package/dist/esm/ts-rs/SignDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +1 -0
- package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +24 -0
- package/dist/esm/ts-rs/SplitRollupMode.d.ts +9 -0
- package/dist/esm/ts-rs/StringColorMode.d.ts +1 -0
- package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/Unit.d.ts +1 -0
- package/dist/esm/ts-rs/UnitDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/UnitNumberFormatStyle.d.ts +6 -0
- package/dist/esm/ts-rs/UseGrouping.d.ts +1 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +42 -2
- package/dist/esm/ts-rs/ViewerConfigInitial.d.ts +175 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +63 -0
- package/dist/esm/ts-rs/WindowSpec.d.ts +3 -2
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +20 -9
- package/dist/wasm/perspective-viewer.d.ts +157 -41
- package/dist/wasm/perspective-viewer.js +452 -151
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +22 -17
- package/package.json +2 -1
- package/src/css/_viewer_bundle.css +1 -0
- package/src/css/column-selector.css +8 -0
- package/src/css/column-settings-panel.css +9 -5
- package/src/css/column-style.css +209 -31
- package/src/css/config-selector.css +38 -3
- package/src/css/dom/select.css +2 -1
- package/src/css/form/code-editor.css +6 -7
- package/src/css/form/mirrored-textarea.css +81 -0
- package/src/css/viewer.css +328 -0
- package/src/rust/agent/client/mod.rs +19 -0
- package/src/rust/agent/client/protocol.rs +320 -0
- package/src/rust/agent/client/transport.rs +287 -0
- package/src/rust/agent/client/turn.rs +174 -0
- package/src/rust/agent/config.rs +159 -0
- package/src/rust/agent/docs.rs +293 -0
- package/src/rust/agent/markdown/block.rs +509 -0
- package/src/rust/agent/markdown/entity.rs +52 -0
- package/src/rust/agent/markdown/events.rs +71 -0
- package/src/rust/agent/markdown/inline.rs +497 -0
- package/src/rust/agent/markdown/mod.rs +466 -0
- package/src/rust/agent/mod.rs +23 -0
- package/src/rust/agent/preamble.md +16 -0
- package/src/rust/agent/runtime.rs +201 -0
- package/src/rust/agent/slot.rs +236 -0
- package/src/rust/agent/tools.rs +1141 -0
- package/src/rust/components/chat_panel.rs +289 -0
- package/src/rust/components/column_selector/active_column.rs +2 -2
- package/src/rust/components/column_selector/add_expression_button.rs +3 -3
- package/src/rust/components/column_selector/aggregate_selector.rs +2 -3
- package/src/rust/components/column_selector/config_selector.rs +84 -7
- package/src/rust/components/column_selector/expr_edit_button.rs +4 -10
- package/src/rust/components/column_selector/inactive_column.rs +2 -2
- package/src/rust/components/column_selector.rs +55 -4
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +293 -126
- package/src/rust/components/column_settings_sidebar/style_tab.rs +262 -225
- package/src/rust/components/column_settings_sidebar.rs +88 -69
- package/src/rust/components/containers/dragdrop_list.rs +37 -0
- package/src/rust/components/editable_header.rs +85 -144
- package/src/rust/components/expression_editor.rs +9 -16
- package/src/rust/components/form/code_editor.rs +29 -28
- package/src/rust/components/form/debug.rs +9 -5
- package/src/rust/components/form/mirrored_textarea.rs +165 -0
- package/src/rust/components/form/mod.rs +4 -1
- package/src/rust/components/form/multi_stop_gradient_selector.rs +476 -0
- package/src/rust/components/form/named_value_picker.rs +86 -0
- package/src/rust/components/form/palette_selector.rs +440 -0
- package/src/rust/components/main_panel/msg.rs +2 -2
- package/src/rust/components/main_panel/reconcile.rs +4 -4
- package/src/rust/components/mod.rs +2 -0
- package/src/rust/components/plugin_tab.rs +4 -28
- package/src/rust/components/settings_panel.rs +105 -22
- package/src/rust/components/viewer/msg.rs +46 -7
- package/src/rust/components/viewer/panels.rs +17 -20
- package/src/rust/components/viewer/render.rs +10 -3
- package/src/rust/components/viewer/settings.rs +163 -23
- package/src/rust/components/viewer/snapshots.rs +46 -21
- package/src/rust/components/viewer/wiring.rs +14 -25
- package/src/rust/components/viewer.rs +12 -8
- package/src/rust/components/window_editor.rs +75 -103
- package/src/rust/config/column_config_schema.rs +100 -41
- package/src/rust/config/css_scale.rs +882 -0
- package/src/rust/config/datetime_column_style/custom.rs +17 -0
- package/src/rust/config/datetime_column_style/simple.rs +10 -0
- package/src/rust/config/mod.rs +2 -0
- package/src/rust/config/number_string_format.rs +33 -0
- package/src/rust/config/options.rs +28 -0
- package/src/rust/config/plugin_static_config.rs +120 -5
- package/src/rust/config/viewer_config.rs +216 -3
- package/src/rust/config/workspace_config.rs +138 -10
- package/src/rust/custom_elements/viewer.rs +369 -119
- package/src/rust/custom_events.rs +43 -1
- package/src/rust/js/regular_layout.rs +3 -3
- package/src/rust/lib.rs +15 -0
- package/src/rust/presentation/column_locator.rs +19 -5
- package/src/rust/presentation.rs +200 -36
- package/src/rust/queries/column_locator.rs +74 -44
- package/src/rust/queries/get_viewer_config.rs +2 -1
- package/src/rust/queries/mod.rs +2 -0
- package/src/rust/queries/palette_set.rs +82 -0
- package/src/rust/queries/plugin_column_styles.rs +6 -2
- package/src/rust/renderer/dispatch.rs +16 -4
- package/src/rust/renderer/plugin_config.rs +309 -47
- package/src/rust/renderer.rs +15 -42
- package/src/rust/session/column_defaults_update.rs +32 -7
- package/src/rust/session/metadata.rs +23 -21
- package/src/rust/session/props.rs +1 -0
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session.rs +9 -6
- package/src/rust/tasks/create_panel.rs +46 -49
- package/src/rust/tasks/edit_expression.rs +19 -23
- package/src/rust/tasks/edit_window.rs +9 -11
- package/src/rust/tasks/eject.rs +4 -1
- package/src/rust/tasks/pipeline.rs +2 -2
- package/src/rust/tasks/presize_panels.rs +44 -5
- package/src/rust/tasks/reset_all.rs +4 -4
- package/src/rust/tasks/restore_and_render.rs +17 -44
- package/src/rust/tasks/restore_panel.rs +37 -22
- package/src/rust/tasks/set_edit_mode.rs +3 -1
- package/src/rust/tasks/sync_update_panels.rs +18 -24
- package/src/rust/tasks/update_theme.rs +23 -18
- package/src/rust/utils/css_vars.rs +26 -0
- package/src/rust/utils/mod.rs +2 -0
- package/src/rust/utils/spawn.rs +1 -1
- package/src/rust/workspace.rs +454 -199
- package/src/svg/lock.svg +7 -0
- package/src/themes/botanical.css +10 -0
- package/src/themes/defaults.css +12 -0
- package/src/themes/dracula.css +17 -0
- package/src/themes/gruvbox-dark.css +20 -0
- package/src/themes/gruvbox.css +10 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/intl/de.css +16 -0
- package/src/themes/intl/es.css +16 -0
- package/src/themes/intl/fr.css +16 -0
- package/src/themes/intl/ja.css +16 -0
- package/src/themes/intl/pt.css +16 -0
- package/src/themes/intl/zh.css +16 -0
- package/src/themes/intl.css +16 -0
- package/src/themes/monokai.css +22 -0
- package/src/themes/phosphor.css +5 -0
- package/src/themes/pro-dark.css +10 -0
- package/src/themes/solarized-dark.css +7 -0
- package/src/themes/solarized.css +7 -0
- package/src/themes/vaporwave.css +20 -0
- package/src/ts/column-format.ts +67 -46
- package/src/ts/perspective-viewer.ts +3 -0
- package/src/ts/plugin.ts +14 -0
- package/src/ts/providers.ts +96 -0
- package/src/ts/ts-rs/CompactDisplay.ts +3 -0
- package/src/ts/ts-rs/CurrencyCode.ts +3 -0
- package/src/ts/ts-rs/CurrencyDisplay.ts +3 -0
- package/src/ts/ts-rs/CurrencyNumberFormatStyle.ts +6 -0
- package/src/ts/ts-rs/CurrencySign.ts +3 -0
- package/src/ts/ts-rs/CustomDatetimeFormat.ts +3 -0
- package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +54 -0
- package/src/ts/ts-rs/CustomNumberFormatConfig.ts +25 -0
- package/src/ts/ts-rs/DatetimeColorMode.ts +3 -0
- package/src/ts/ts-rs/DatetimeFormatType.ts +8 -0
- package/src/ts/ts-rs/FormatMode.ts +3 -0
- package/src/ts/ts-rs/FormatUnit.ts +3 -0
- package/src/ts/ts-rs/Notation.ts +11 -0
- package/src/ts/ts-rs/NumberFormatStyle.ts +12 -0
- package/src/ts/ts-rs/PanelViewerConfig.ts +48 -2
- package/src/ts/ts-rs/PluginStaticConfig.ts +36 -1
- package/src/ts/ts-rs/RestoreOptions.ts +20 -0
- package/src/ts/ts-rs/RoundingMode.ts +3 -0
- package/src/ts/ts-rs/RoundingPriority.ts +3 -0
- package/src/ts/ts-rs/SaveWorkspaceOptions.ts +11 -0
- package/src/ts/ts-rs/SignDisplay.ts +3 -0
- package/src/ts/ts-rs/SimpleDatetimeFormat.ts +3 -0
- package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +25 -0
- package/src/ts/ts-rs/SplitRollupMode.ts +11 -0
- package/src/ts/ts-rs/StringColorMode.ts +3 -0
- package/src/ts/ts-rs/TrailingZeroDisplay.ts +3 -0
- package/src/ts/ts-rs/Unit.ts +3 -0
- package/src/ts/ts-rs/UnitDisplay.ts +3 -0
- package/src/ts/ts-rs/UnitNumberFormatStyle.ts +5 -0
- package/src/ts/ts-rs/UseGrouping.ts +3 -0
- package/src/ts/ts-rs/ViewerConfig.ts +48 -2
- package/src/ts/ts-rs/ViewerConfigInitial.ts +164 -0
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +72 -2
- package/src/ts/ts-rs/WindowSpec.ts +3 -2
- package/src/ts/ts-rs/WorkspaceConfig.ts +8 -2
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +18 -9
- package/dist/esm/ts-rs/WindowAggregate.d.ts +0 -1
- package/src/rust/components/form/color_range_selector.rs +0 -137
- package/src/ts/ts-rs/WindowAggregate.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-39c3c3b28e3cbd48}/inline5.js +0 -0
|
@@ -62,14 +62,22 @@ const fn numeric_default() -> u32 {
|
|
|
62
62
|
0
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/// A datetime column's `date_format` in its `Custom` form: per-part
|
|
66
|
+
/// `Intl.DateTimeFormatOptions` overrides, discriminated from the `Simple`
|
|
67
|
+
/// preset form by the required `format: "custom"` key. Each part is a
|
|
68
|
+
/// [`CustomDatetimeFormat`] variant valid for that `Intl` option;
|
|
69
|
+
/// `"disabled"` omits the part from the formatted output entirely.
|
|
65
70
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TS)]
|
|
66
71
|
pub struct CustomDatetimeStyleConfig {
|
|
67
72
|
format: FormatUnit,
|
|
68
73
|
|
|
74
|
+
/// An IANA time zone name (e.g. `"America/New_York"`); defaults to the
|
|
75
|
+
/// browser's local time zone.
|
|
69
76
|
#[serde(default)]
|
|
70
77
|
#[serde(rename = "timeZone", skip_serializing_if = "Option::is_none")]
|
|
71
78
|
pub time_zone: Option<String>,
|
|
72
79
|
|
|
80
|
+
/// Sub-second digits to display, 0-3 (0 = none).
|
|
73
81
|
#[serde(
|
|
74
82
|
skip_serializing_if = "is_zero",
|
|
75
83
|
rename = "fractionalSecondDigits",
|
|
@@ -77,27 +85,36 @@ pub struct CustomDatetimeStyleConfig {
|
|
|
77
85
|
)]
|
|
78
86
|
pub fractional_seconds: u32,
|
|
79
87
|
|
|
88
|
+
/// Defaults to `"numeric"`.
|
|
80
89
|
#[serde(skip_serializing_if = "is_numeric", default = "second_default")]
|
|
81
90
|
pub second: CustomDatetimeFormat,
|
|
82
91
|
|
|
92
|
+
/// Defaults to `"numeric"`.
|
|
83
93
|
#[serde(skip_serializing_if = "is_numeric", default = "second_default")]
|
|
84
94
|
pub minute: CustomDatetimeFormat,
|
|
85
95
|
|
|
96
|
+
/// Defaults to `"numeric"`.
|
|
86
97
|
#[serde(skip_serializing_if = "is_numeric", default = "second_default")]
|
|
87
98
|
pub hour: CustomDatetimeFormat,
|
|
88
99
|
|
|
100
|
+
/// Defaults to `"numeric"`.
|
|
89
101
|
#[serde(skip_serializing_if = "is_numeric", default = "second_default")]
|
|
90
102
|
pub day: CustomDatetimeFormat,
|
|
91
103
|
|
|
104
|
+
/// A name form (`"long"`/`"short"`/`"narrow"`); defaults to
|
|
105
|
+
/// `"disabled"` (weekday not shown).
|
|
92
106
|
#[serde(skip_serializing_if = "is_disabled", default = "weekday_default")]
|
|
93
107
|
pub weekday: CustomDatetimeFormat,
|
|
94
108
|
|
|
109
|
+
/// Numeric or name form; defaults to `"numeric"`.
|
|
95
110
|
#[serde(skip_serializing_if = "is_numeric", default = "second_default")]
|
|
96
111
|
pub month: CustomDatetimeFormat,
|
|
97
112
|
|
|
113
|
+
/// Defaults to `"2-digit"`.
|
|
98
114
|
#[serde(skip_serializing_if = "is_two_digit", default = "year_default")]
|
|
99
115
|
pub year: CustomDatetimeFormat,
|
|
100
116
|
|
|
117
|
+
/// 12-hour clock; defaults to `true`.
|
|
101
118
|
#[serde(skip_serializing_if = "is_true", default = "hour12_default")]
|
|
102
119
|
pub hour12: bool,
|
|
103
120
|
}
|
|
@@ -23,12 +23,20 @@ const fn time_style_default() -> SimpleDatetimeFormat {
|
|
|
23
23
|
SimpleDatetimeFormat::Medium
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/// A datetime column's `date_format` in its `Simple` preset form:
|
|
27
|
+
/// `Intl.DateTimeFormatOptions`' `dateStyle`/`timeStyle` presets. This is
|
|
28
|
+
/// the default form (no `format` key); setting `format: "custom"` selects
|
|
29
|
+
/// the per-part `CustomDatetimeStyleConfig` instead.
|
|
26
30
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TS)]
|
|
27
31
|
pub struct SimpleDatetimeStyleConfig {
|
|
32
|
+
/// An IANA time zone name (e.g. `"America/New_York"`); defaults to the
|
|
33
|
+
/// browser's local time zone.
|
|
28
34
|
#[serde(default)]
|
|
29
35
|
#[serde(rename = "timeZone", skip_serializing_if = "Option::is_none")]
|
|
30
36
|
pub time_zone: Option<String>,
|
|
31
37
|
|
|
38
|
+
/// Date preset breadth, or `"disabled"` to omit the date entirely;
|
|
39
|
+
/// defaults to `"short"`.
|
|
32
40
|
#[serde(
|
|
33
41
|
default = "date_style_default",
|
|
34
42
|
rename = "dateStyle",
|
|
@@ -36,6 +44,8 @@ pub struct SimpleDatetimeStyleConfig {
|
|
|
36
44
|
)]
|
|
37
45
|
pub date_style: SimpleDatetimeFormat,
|
|
38
46
|
|
|
47
|
+
/// Time preset breadth, or `"disabled"` to omit the time entirely;
|
|
48
|
+
/// defaults to `"medium"`.
|
|
39
49
|
#[serde(
|
|
40
50
|
default = "time_style_default",
|
|
41
51
|
rename = "timeStyle",
|
package/src/rust/config/mod.rs
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
mod column_config_schema;
|
|
17
17
|
mod columns_config;
|
|
18
|
+
mod css_scale;
|
|
18
19
|
mod datetime_column_style;
|
|
19
20
|
mod export_method;
|
|
20
21
|
mod kvpair;
|
|
@@ -29,6 +30,7 @@ mod workspace_config;
|
|
|
29
30
|
|
|
30
31
|
pub use column_config_schema::*;
|
|
31
32
|
pub use columns_config::*;
|
|
33
|
+
pub use css_scale::*;
|
|
32
34
|
pub use datetime_column_style::*;
|
|
33
35
|
pub use export_method::*;
|
|
34
36
|
pub use number_series_style::*;
|
|
@@ -16,6 +16,11 @@ use serde::{Deserialize, Serialize};
|
|
|
16
16
|
use strum::{Display, EnumIter};
|
|
17
17
|
use ts_rs::TS;
|
|
18
18
|
|
|
19
|
+
/// The `style` family of a numeric column's `number_format` — serialized
|
|
20
|
+
/// FLATTENED into [`CustomNumberFormatConfig`]'s object, discriminated by
|
|
21
|
+
/// the `style` key (`"decimal"` default, `"currency"` + `currency`/
|
|
22
|
+
/// `currencyDisplay`/`currencySign`, `"percent"`, `"unit"` + `unit`/
|
|
23
|
+
/// `unitDisplay`), mirroring `Intl.NumberFormat` options.
|
|
19
24
|
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, TS)]
|
|
20
25
|
#[serde(rename_all = "camelCase", tag = "style")]
|
|
21
26
|
pub enum NumberFormatStyle {
|
|
@@ -127,6 +132,11 @@ pub enum TrailingZeroDisplay {
|
|
|
127
132
|
StripIfInteger,
|
|
128
133
|
}
|
|
129
134
|
|
|
135
|
+
/// The `notation` family of a numeric column's `number_format` —
|
|
136
|
+
/// serialized FLATTENED into [`CustomNumberFormatConfig`]'s object,
|
|
137
|
+
/// discriminated by the `notation` key (`"standard"` default,
|
|
138
|
+
/// `"scientific"`, `"engineering"`, `"compact"` + `compactDisplay`),
|
|
139
|
+
/// mirroring `Intl.NumberFormat` options.
|
|
130
140
|
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, TS)]
|
|
131
141
|
#[serde(rename_all = "camelCase", tag = "notation")]
|
|
132
142
|
pub enum Notation {
|
|
@@ -169,6 +179,14 @@ pub enum SignDisplay {
|
|
|
169
179
|
Never,
|
|
170
180
|
}
|
|
171
181
|
|
|
182
|
+
/// A numeric column's `number_format` (`columns_config` value) —
|
|
183
|
+
/// `Intl.NumberFormat`-shaped options, written by the Style tab's number
|
|
184
|
+
/// format editor and read by `createNumberFormatter`. The `style` and
|
|
185
|
+
/// `notation` families ([`NumberFormatStyle`] / [`Notation`]) are serde-
|
|
186
|
+
/// FLATTENED into this object but `#[ts(skip)]`'d (ts-rs cannot flatten
|
|
187
|
+
/// `Option<enum>`) — the package's `NumberFormatConfig` re-composes the
|
|
188
|
+
/// full wire type as `CustomNumberFormatConfig & Partial<NumberFormatStyle>
|
|
189
|
+
/// & Partial<Notation>` (see `column-format.ts`).
|
|
172
190
|
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Clone, TS)]
|
|
173
191
|
#[serde(rename_all = "camelCase")]
|
|
174
192
|
pub struct CustomNumberFormatConfig {
|
|
@@ -181,33 +199,42 @@ pub struct CustomNumberFormatConfig {
|
|
|
181
199
|
// these min/max props can all be specified but it results in possible conflicts
|
|
182
200
|
// may consider making them distinct options
|
|
183
201
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
202
|
+
#[ts(optional, as = "Option<_>")]
|
|
184
203
|
pub minimum_integer_digits: Option<f64>,
|
|
185
204
|
|
|
186
205
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
206
|
+
#[ts(optional, as = "Option<_>")]
|
|
187
207
|
pub minimum_fraction_digits: Option<f64>,
|
|
188
208
|
|
|
189
209
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
210
|
+
#[ts(optional, as = "Option<_>")]
|
|
190
211
|
pub maximum_fraction_digits: Option<f64>,
|
|
191
212
|
|
|
192
213
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
214
|
+
#[ts(optional, as = "Option<_>")]
|
|
193
215
|
pub minimum_significant_digits: Option<f64>,
|
|
194
216
|
|
|
195
217
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
218
|
+
#[ts(optional, as = "Option<_>")]
|
|
196
219
|
pub maximum_significant_digits: Option<f64>,
|
|
197
220
|
|
|
198
221
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
222
|
+
#[ts(optional, as = "Option<_>")]
|
|
199
223
|
pub rounding_priority: Option<RoundingPriority>,
|
|
200
224
|
|
|
201
225
|
// specific values https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#roundingincrement
|
|
202
226
|
// Only available with automatic rounding priority
|
|
203
227
|
// Cannot be mixed with sigfig rounding. (Does this mean max/min sigfig must be unset?)
|
|
204
228
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
229
|
+
#[ts(optional, as = "Option<_>")]
|
|
205
230
|
pub rounding_increment: Option<f64>,
|
|
206
231
|
|
|
207
232
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
233
|
+
#[ts(optional, as = "Option<_>")]
|
|
208
234
|
pub rounding_mode: Option<RoundingMode>,
|
|
209
235
|
|
|
210
236
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
237
|
+
#[ts(optional, as = "Option<_>")]
|
|
211
238
|
pub trailing_zero_display: Option<TrailingZeroDisplay>,
|
|
212
239
|
|
|
213
240
|
#[serde(flatten)]
|
|
@@ -215,10 +242,16 @@ pub struct CustomNumberFormatConfig {
|
|
|
215
242
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
216
243
|
pub _notation: Option<Notation>,
|
|
217
244
|
|
|
245
|
+
/// NOTE (audit 2026-08-05): serialized values are the STRINGS
|
|
246
|
+
/// `"always"`/`"auto"`/`"min2"` or the untagged BOOLEAN `false` —
|
|
247
|
+
/// the former hand-written TS `useGrouping?: boolean` was wrong for
|
|
248
|
+
/// the string cases.
|
|
218
249
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
250
|
+
#[ts(optional, as = "Option<_>")]
|
|
219
251
|
pub use_grouping: Option<UseGrouping>,
|
|
220
252
|
|
|
221
253
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
254
|
+
#[ts(optional, as = "Option<_>")]
|
|
222
255
|
pub sign_display: Option<SignDisplay>,
|
|
223
256
|
}
|
|
224
257
|
|
|
@@ -28,6 +28,24 @@ pub struct PanelOptions {
|
|
|
28
28
|
pub panel: Option<String>,
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/// Options for the `restore()` method.
|
|
32
|
+
#[derive(Deserialize, Default, TS)]
|
|
33
|
+
pub struct RestoreOptions {
|
|
34
|
+
/// The target panel; the active panel when omitted.
|
|
35
|
+
#[ts(optional)]
|
|
36
|
+
pub panel: Option<String>,
|
|
37
|
+
|
|
38
|
+
/// When `true`, a failed restore only REJECTS the returned `Promise` —
|
|
39
|
+
/// the error is not committed to the viewer's visible error state, and
|
|
40
|
+
/// the session remains usable for subsequent calls. For programmatic
|
|
41
|
+
/// callers (e.g. the LLM agent's `set_view_config` tool) for whom a
|
|
42
|
+
/// failed config patch is feedback rather than a user-facing fault.
|
|
43
|
+
/// The config may be partially applied on failure; restore a
|
|
44
|
+
/// known-good config to recover exactly.
|
|
45
|
+
#[ts(optional)]
|
|
46
|
+
pub suppress_errors: Option<bool>,
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
/// The `eject` argument: the loaded client to remove by name; the active
|
|
32
50
|
/// panel's client when omitted.
|
|
33
51
|
#[derive(Deserialize, Default, TS)]
|
|
@@ -69,3 +87,13 @@ pub struct GetClientOptions {
|
|
|
69
87
|
#[ts(optional)]
|
|
70
88
|
pub panel: Option<String>,
|
|
71
89
|
}
|
|
90
|
+
|
|
91
|
+
/// Options for the `saveWorkspace()` method.
|
|
92
|
+
#[derive(Deserialize, Default, TS)]
|
|
93
|
+
pub struct SaveWorkspaceOptions {
|
|
94
|
+
/// When `true`, the emitted `palette` is the full set the element
|
|
95
|
+
/// holds rather than only the values the panels reference.
|
|
96
|
+
#[serde(default)]
|
|
97
|
+
#[ts(optional)]
|
|
98
|
+
pub full_palette: Option<bool>,
|
|
99
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use perspective_client::config::GroupRollupMode;
|
|
13
|
+
use perspective_client::config::{GroupRollupMode, SplitRollupMode};
|
|
14
14
|
use serde::Deserialize;
|
|
15
15
|
use ts_rs::TS;
|
|
16
16
|
|
|
@@ -103,6 +103,13 @@ pub struct PluginStaticConfig {
|
|
|
103
103
|
#[ts(optional)]
|
|
104
104
|
pub group_rollup_modes: Option<Vec<GroupRollupMode>>,
|
|
105
105
|
|
|
106
|
+
/// Split-rollup modes the plugin accepts, in preference order.
|
|
107
|
+
/// The first entry that matches a feature flag becomes the default.
|
|
108
|
+
#[serde(default)]
|
|
109
|
+
#[ts(as = "Option<_>")]
|
|
110
|
+
#[ts(optional)]
|
|
111
|
+
pub split_rollup_modes: Option<Vec<SplitRollupMode>>,
|
|
112
|
+
|
|
106
113
|
/// Plugin load priority. Higher numbers win; ties resolve in
|
|
107
114
|
/// registration order. The highest-priority plugin is loaded by
|
|
108
115
|
/// default unless `restore({ plugin })` overrides it.
|
|
@@ -120,15 +127,70 @@ pub struct PluginStaticConfig {
|
|
|
120
127
|
#[ts(as = "Option<_>")]
|
|
121
128
|
#[ts(optional)]
|
|
122
129
|
pub can_render_column_styles: bool,
|
|
130
|
+
|
|
131
|
+
/// What `group_by` MEANS visually for this plugin, e.g. `"X Axis"`
|
|
132
|
+
/// for the Y-series charts or `"Hierarchy"` for treemap/sunburst.
|
|
133
|
+
/// `None` where the field has no visual role of its own and is a
|
|
134
|
+
/// plain aggregation key (the X/Y charts, whose axes both come from
|
|
135
|
+
/// `columns`).
|
|
136
|
+
///
|
|
137
|
+
/// This is the `group_by` counterpart of [`Self::config_column_names`]:
|
|
138
|
+
/// the same declaration that names the positional `columns` slots
|
|
139
|
+
/// should say what the other view fields draw, so that consumers —
|
|
140
|
+
/// the settings UI's field labels, and the agent's `list_plugins`
|
|
141
|
+
/// contract — read one source instead of restating the mapping.
|
|
142
|
+
#[serde(default)]
|
|
143
|
+
#[ts(as = "Option<_>")]
|
|
144
|
+
#[ts(optional)]
|
|
145
|
+
pub group_by_role: Option<String>,
|
|
146
|
+
|
|
147
|
+
/// What `split_by` MEANS visually for this plugin, e.g. `"Series"`.
|
|
148
|
+
/// See [`Self::group_by_role`].
|
|
149
|
+
#[serde(default)]
|
|
150
|
+
#[ts(as = "Option<_>")]
|
|
151
|
+
#[ts(optional)]
|
|
152
|
+
pub split_by_role: Option<String>,
|
|
153
|
+
|
|
154
|
+
/// `true` when this plugin CONNECTS its points in row order, so the
|
|
155
|
+
/// `View`'s row order is visible in the drawing: an unsorted config
|
|
156
|
+
/// renders the table's natural order, which reads as a tangle unless
|
|
157
|
+
/// the rows already arrive ordered along the axis. Declared rather
|
|
158
|
+
/// than inferred, because "unsorted" is not itself a mistake — a
|
|
159
|
+
/// pre-ordered table needs no `sort`, and the point plugins
|
|
160
|
+
/// (scatter, density) do not care at all.
|
|
161
|
+
#[serde(default)]
|
|
162
|
+
#[ts(as = "Option<_>")]
|
|
163
|
+
#[ts(optional)]
|
|
164
|
+
pub connects_row_order: bool,
|
|
123
165
|
}
|
|
124
166
|
|
|
125
167
|
impl PluginStaticConfig {
|
|
168
|
+
/// The number of leading `columns` slots that are POSITIONAL: a drop
|
|
169
|
+
/// there swaps with the column already present, and the slot's
|
|
170
|
+
/// meaning is fixed by [`Self::config_column_names`]. Everything from
|
|
171
|
+
/// this index on is the insert TAIL, which repeats the last named
|
|
172
|
+
/// role — which is why a `Y Line` (named slots: `["Y Axis"]`) takes
|
|
173
|
+
/// any number of columns as additional Y series, while an
|
|
174
|
+
/// `X/Y Line` (`["X Axis", "Y Axis", "Tooltip"]`) pins its two axes
|
|
175
|
+
/// and treats the rest as further tooltips.
|
|
176
|
+
///
|
|
177
|
+
/// The single definition of that rule: [`Self::is_swap`] and the
|
|
178
|
+
/// agent's `list_plugins` contract both derive from it, so the
|
|
179
|
+
/// convention cannot be read two different ways.
|
|
180
|
+
pub fn positional_columns(&self) -> usize {
|
|
181
|
+
self.config_column_names.len().saturating_sub(1)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// The role that `columns` past the positional slots repeat, i.e.
|
|
185
|
+
/// the last named slot. `None` when the plugin names no slots.
|
|
186
|
+
pub fn tail_column_role(&self) -> Option<&str> {
|
|
187
|
+
self.config_column_names.last().map(|x| x.as_str())
|
|
188
|
+
}
|
|
189
|
+
|
|
126
190
|
/// `true` if dropping a column at `index` should swap with the
|
|
127
|
-
/// column already there rather than insert.
|
|
128
|
-
/// (`config_column_names[..len()-1]`) participate in swap behaviour;
|
|
129
|
-
/// the trailing unnamed tail inserts.
|
|
191
|
+
/// column already there rather than insert.
|
|
130
192
|
pub fn is_swap(&self, index: usize) -> bool {
|
|
131
|
-
!self.config_column_names.is_empty() && index < self.
|
|
193
|
+
!self.config_column_names.is_empty() && index < self.positional_columns()
|
|
132
194
|
}
|
|
133
195
|
|
|
134
196
|
pub fn get_group_rollups(&self, rollup_features: &[GroupRollupMode]) -> Vec<GroupRollupMode> {
|
|
@@ -141,4 +203,57 @@ impl PluginStaticConfig {
|
|
|
141
203
|
})
|
|
142
204
|
.unwrap_or_default()
|
|
143
205
|
}
|
|
206
|
+
|
|
207
|
+
pub fn get_split_rollups(&self, rollup_features: &[SplitRollupMode]) -> Vec<SplitRollupMode> {
|
|
208
|
+
self.split_rollup_modes
|
|
209
|
+
.clone()
|
|
210
|
+
.map(|x| {
|
|
211
|
+
x.into_iter()
|
|
212
|
+
.filter(|y| rollup_features.is_empty() || rollup_features.contains(y))
|
|
213
|
+
.collect()
|
|
214
|
+
})
|
|
215
|
+
.unwrap_or_default()
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#[cfg(test)]
|
|
220
|
+
mod tests {
|
|
221
|
+
use super::*;
|
|
222
|
+
|
|
223
|
+
fn plugin(names: &[&str]) -> PluginStaticConfig {
|
|
224
|
+
PluginStaticConfig {
|
|
225
|
+
config_column_names: names.iter().map(|x| (*x).to_owned()).collect(),
|
|
226
|
+
..Default::default()
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/// The tail rule has ONE definition: `is_swap` and the role a
|
|
231
|
+
/// trailing column repeats must never disagree about where the
|
|
232
|
+
/// positional slots end.
|
|
233
|
+
#[test]
|
|
234
|
+
fn positional_slots_and_tail_agree() {
|
|
235
|
+
// `Y Line` — the only named slot IS the tail, so every column
|
|
236
|
+
// is another Y series and none of them swap.
|
|
237
|
+
let y_line = plugin(&["Y Axis"]);
|
|
238
|
+
assert_eq!(y_line.positional_columns(), 0);
|
|
239
|
+
assert_eq!(y_line.tail_column_role(), Some("Y Axis"));
|
|
240
|
+
assert!(!y_line.is_swap(0));
|
|
241
|
+
|
|
242
|
+
// `X/Y Line` — two pinned axes, then tooltips.
|
|
243
|
+
let xy_line = plugin(&["X Axis", "Y Axis", "Tooltip"]);
|
|
244
|
+
assert_eq!(xy_line.positional_columns(), 2);
|
|
245
|
+
assert_eq!(xy_line.tail_column_role(), Some("Tooltip"));
|
|
246
|
+
assert!(xy_line.is_swap(0));
|
|
247
|
+
assert!(xy_line.is_swap(1));
|
|
248
|
+
assert!(!xy_line.is_swap(2));
|
|
249
|
+
|
|
250
|
+
for index in 0..4 {
|
|
251
|
+
assert_eq!(xy_line.is_swap(index), index < xy_line.positional_columns());
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let unnamed = plugin(&[]);
|
|
255
|
+
assert_eq!(unnamed.positional_columns(), 0);
|
|
256
|
+
assert_eq!(unnamed.tail_column_role(), None);
|
|
257
|
+
assert!(!unnamed.is_swap(0));
|
|
258
|
+
}
|
|
144
259
|
}
|