@perspective-dev/viewer 5.4.0 → 5.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.
- package/dist/cdn/perspective-viewer.js +4 -4
- package/dist/cdn/perspective-viewer.js.map +2 -2
- package/dist/css/blueprint.css +1 -1
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/eggplant.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/ar.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/ledger.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/nord.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/css/velvet.css +1 -1
- package/dist/docs/perspective-docs.json +1 -1
- package/dist/esm/perspective-viewer.d.ts +2 -0
- package/dist/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +3 -3
- package/dist/esm/perspective-viewer.js +4 -4
- package/dist/esm/perspective-viewer.js.map +2 -2
- package/dist/esm/plugin.d.ts +9 -0
- package/dist/esm/ts-rs/AddPanelOptions.d.ts +9 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -1
- package/dist/esm/ts-rs/GetViewMode.d.ts +4 -0
- package/dist/esm/ts-rs/GetViewOptions.d.ts +8 -0
- package/dist/esm/ts-rs/RestoreOptions.d.ts +6 -0
- package/dist/esm/ts-rs/RestoreWorkspaceOptions.d.ts +9 -0
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +30 -22
- package/dist/wasm/perspective-viewer.d.ts +102 -47
- package/dist/wasm/perspective-viewer.js +233 -142
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +18 -18
- package/package.json +7 -7
- package/src/css/column-selector.css +11 -3
- package/src/css/column-style.css +162 -0
- package/src/css/config-selector.css +1 -1
- package/src/css/form/debug.css +9 -0
- package/src/css/status-bar.css +11 -0
- package/src/css/ui/containers/tabs.css +2 -1
- package/src/rust/agent/tools.rs +80 -7
- package/src/rust/components/column_selector/active_column.rs +9 -0
- package/src/rust/components/column_selector.rs +11 -0
- package/src/rust/components/column_settings_sidebar/style_tab/alignment_field.rs +90 -0
- package/src/rust/components/column_settings_sidebar/style_tab/font_field.rs +267 -0
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +68 -9
- package/src/rust/components/debug_panel.rs +107 -50
- package/src/rust/components/export_dropdown.rs +6 -0
- package/src/rust/components/main_panel/msg.rs +4 -0
- package/src/rust/components/main_panel.rs +14 -0
- package/src/rust/components/mod.rs +0 -1
- package/src/rust/components/plugin_tab.rs +57 -3
- package/src/rust/components/settings_panel.rs +6 -0
- package/src/rust/components/status_bar.rs +12 -3
- package/src/rust/components/status_indicator.rs +4 -0
- package/src/rust/components/viewer/filters.rs +2 -2
- package/src/rust/components/viewer/msg.rs +4 -0
- package/src/rust/components/viewer/panels.rs +6 -3
- package/src/rust/components/viewer/render.rs +1 -0
- package/src/rust/components/viewer/wiring.rs +14 -2
- package/src/rust/components/viewer.rs +2 -2
- package/src/rust/config/column_config_schema.rs +312 -8
- package/src/rust/config/datetime_column_style.rs +0 -11
- package/src/rust/config/export_method.rs +24 -0
- package/src/rust/config/mod.rs +0 -2
- package/src/rust/config/options.rs +50 -0
- package/src/rust/config/workspace_config.rs +69 -24
- package/src/rust/custom_elements/viewer.rs +214 -113
- package/src/rust/js/plugin.rs +3 -1
- package/src/rust/lib.rs +7 -3
- package/src/rust/queries/plugin_column_styles.rs +6 -5
- package/src/rust/renderer/plugin_config.rs +200 -41
- package/src/rust/renderer/plugin_store.rs +2 -1
- package/src/rust/renderer/props.rs +5 -0
- package/src/rust/renderer.rs +9 -0
- package/src/rust/session/metadata.rs +5 -10
- package/src/rust/session/props.rs +4 -0
- package/src/rust/session.rs +273 -195
- package/src/rust/tasks/copy_export.rs +67 -0
- package/src/rust/tasks/create_panel.rs +16 -13
- package/src/rust/tasks/pipeline.rs +26 -8
- package/src/rust/tasks/restore_panel.rs +129 -30
- package/src/rust/tasks/send_column_config.rs +3 -0
- package/src/rust/tasks/sync_update_panels.rs +148 -68
- package/src/rust/tasks/table_lifecycle.rs +7 -1
- package/src/rust/ui/containers/tab_list.rs +1 -1
- package/src/rust/ui/form/intl_label.rs +4 -23
- package/src/rust/ui/portal.rs +1 -0
- package/src/rust/utils/css_vars.rs +13 -0
- package/src/rust/{config/datetime_column_style/color_mode.rs → utils/in_flight.rs} +47 -35
- package/src/rust/utils/local_fonts.rs +395 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/pending_effects.rs +6 -30
- package/src/rust/workspace.rs +12 -0
- package/src/svg/status_pending.svg +3 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/intl/ar.css +20 -7
- package/src/themes/intl/de.css +20 -7
- package/src/themes/intl/es.css +20 -7
- package/src/themes/intl/fr.css +20 -7
- package/src/themes/intl/ja.css +20 -7
- package/src/themes/intl/pt.css +20 -7
- package/src/themes/intl/zh.css +20 -7
- package/src/themes/intl.css +20 -7
- package/src/themes/monokai.css +1 -1
- package/src/themes/vaporwave.css +1 -1
- package/src/ts/perspective-viewer.ts +2 -0
- package/src/ts/plugin.ts +9 -0
- package/src/ts/ts-rs/AddPanelOptions.ts +10 -0
- package/src/ts/ts-rs/ExportMethod.ts +1 -1
- package/src/ts/ts-rs/{DatetimeColorMode.ts → GetViewMode.ts} +4 -1
- package/src/ts/ts-rs/GetViewOptions.ts +7 -0
- package/src/ts/ts-rs/RestoreOptions.ts +7 -1
- package/src/ts/ts-rs/RestoreWorkspaceOptions.ts +10 -0
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +31 -20
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
- package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
- package/src/rust/components/string_column_style.rs +0 -120
- package/src/rust/config/string_column_style.rs +0 -135
- package/src/ts/ts-rs/FormatMode.ts +0 -3
- package/src/ts/ts-rs/StringColorMode.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline5.js +0 -0
|
@@ -74,6 +74,38 @@ pub enum ControlSpec {
|
|
|
74
74
|
variants: Vec<EnumVariant>,
|
|
75
75
|
default: String,
|
|
76
76
|
},
|
|
77
|
+
|
|
78
|
+
/// A CSS `font-family` picked from the generic keywords plus the families
|
|
79
|
+
/// the host can enumerate, with optional size, bold and italic inputs
|
|
80
|
+
/// each bound to its own key.
|
|
81
|
+
Font {
|
|
82
|
+
key: String,
|
|
83
|
+
default: String,
|
|
84
|
+
|
|
85
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
86
|
+
size: Option<FontSize>,
|
|
87
|
+
|
|
88
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
89
|
+
bold: Option<FontToggle>,
|
|
90
|
+
|
|
91
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
92
|
+
italic: Option<FontToggle>,
|
|
93
|
+
},
|
|
94
|
+
/// A 3×3 anchor picker whose value is one of the nine [`Alignment`]
|
|
95
|
+
/// tokens.
|
|
96
|
+
Alignment {
|
|
97
|
+
key: String,
|
|
98
|
+
|
|
99
|
+
/// The cell shown as the unmodified value and elided from serialized
|
|
100
|
+
/// configs, or `None` when an unset key stands for something no cell
|
|
101
|
+
/// can show.
|
|
102
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
103
|
+
default: Option<Alignment>,
|
|
104
|
+
|
|
105
|
+
/// Only the four corner cells are selectable.
|
|
106
|
+
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
|
107
|
+
corners: bool,
|
|
108
|
+
},
|
|
77
109
|
Bool {
|
|
78
110
|
key: String,
|
|
79
111
|
default: bool,
|
|
@@ -125,7 +157,6 @@ pub enum ControlSpec {
|
|
|
125
157
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
126
158
|
default: Option<DatetimeFormatType>,
|
|
127
159
|
},
|
|
128
|
-
StringFormat,
|
|
129
160
|
NumberSeriesStyle {
|
|
130
161
|
default: NumberSeriesStyleDefaultConfig,
|
|
131
162
|
},
|
|
@@ -147,6 +178,108 @@ pub enum ControlSpec {
|
|
|
147
178
|
},
|
|
148
179
|
}
|
|
149
180
|
|
|
181
|
+
/// One cell of a 3×3 anchor grid: a corner `top-left`/`top-right`/
|
|
182
|
+
/// `bottom-left`/`bottom-right`, an edge `top`/`left`/`right`/`bottom`, or
|
|
183
|
+
/// `center`.
|
|
184
|
+
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
|
185
|
+
#[serde(rename_all = "kebab-case")]
|
|
186
|
+
pub enum Alignment {
|
|
187
|
+
TopLeft,
|
|
188
|
+
Top,
|
|
189
|
+
TopRight,
|
|
190
|
+
Left,
|
|
191
|
+
Center,
|
|
192
|
+
Right,
|
|
193
|
+
BottomLeft,
|
|
194
|
+
Bottom,
|
|
195
|
+
BottomRight,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
impl Alignment {
|
|
199
|
+
/// Every cell in row-major order.
|
|
200
|
+
pub const ALL: [Alignment; 9] = [
|
|
201
|
+
Alignment::TopLeft,
|
|
202
|
+
Alignment::Top,
|
|
203
|
+
Alignment::TopRight,
|
|
204
|
+
Alignment::Left,
|
|
205
|
+
Alignment::Center,
|
|
206
|
+
Alignment::Right,
|
|
207
|
+
Alignment::BottomLeft,
|
|
208
|
+
Alignment::Bottom,
|
|
209
|
+
Alignment::BottomRight,
|
|
210
|
+
];
|
|
211
|
+
pub const CORNERS: [Alignment; 4] = [
|
|
212
|
+
Alignment::TopLeft,
|
|
213
|
+
Alignment::TopRight,
|
|
214
|
+
Alignment::BottomLeft,
|
|
215
|
+
Alignment::BottomRight,
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
pub fn is_corner(self) -> bool {
|
|
219
|
+
Self::CORNERS.contains(&self)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/// The serialized token.
|
|
223
|
+
pub fn as_str(self) -> &'static str {
|
|
224
|
+
match self {
|
|
225
|
+
Alignment::TopLeft => "top-left",
|
|
226
|
+
Alignment::Top => "top",
|
|
227
|
+
Alignment::TopRight => "top-right",
|
|
228
|
+
Alignment::Left => "left",
|
|
229
|
+
Alignment::Center => "center",
|
|
230
|
+
Alignment::Right => "right",
|
|
231
|
+
Alignment::BottomLeft => "bottom-left",
|
|
232
|
+
Alignment::Bottom => "bottom",
|
|
233
|
+
Alignment::BottomRight => "bottom-right",
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
pub fn parse(src: &str) -> Option<Self> {
|
|
238
|
+
Self::ALL.into_iter().find(|x| x.as_str() == src)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/// `Top Left`-style text for accessible names.
|
|
242
|
+
pub fn humanized(self) -> String {
|
|
243
|
+
self.as_str()
|
|
244
|
+
.split('-')
|
|
245
|
+
.map(|word| {
|
|
246
|
+
let mut chars = word.chars();
|
|
247
|
+
match chars.next() {
|
|
248
|
+
Some(first) => first.to_uppercase().chain(chars).collect::<String>(),
|
|
249
|
+
None => String::new(),
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
.collect::<Vec<_>>()
|
|
253
|
+
.join(" ")
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/// One boolean style toggle of a [`ControlSpec::Font`] control: the
|
|
258
|
+
/// config key it writes and the value that counts as "not set".
|
|
259
|
+
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
|
260
|
+
pub struct FontToggle {
|
|
261
|
+
pub key: String,
|
|
262
|
+
#[serde(default)]
|
|
263
|
+
pub default: bool,
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/// The size input of a [`ControlSpec::Font`] control: a number (CSS px)
|
|
267
|
+
/// under its own key, elided from serialized configs at `default`.
|
|
268
|
+
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
|
269
|
+
pub struct FontSize {
|
|
270
|
+
pub key: String,
|
|
271
|
+
pub default: f64,
|
|
272
|
+
|
|
273
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
274
|
+
pub min: Option<f64>,
|
|
275
|
+
|
|
276
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
277
|
+
pub max: Option<f64>,
|
|
278
|
+
|
|
279
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
280
|
+
pub step: Option<f64>,
|
|
281
|
+
}
|
|
282
|
+
|
|
150
283
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
|
151
284
|
pub struct EnumVariant {
|
|
152
285
|
pub value: String,
|
|
@@ -182,9 +315,7 @@ impl ColumnConfigSchema {
|
|
|
182
315
|
fn is_format(spec: &ControlSpec) -> bool {
|
|
183
316
|
matches!(
|
|
184
317
|
spec,
|
|
185
|
-
ControlSpec::NumberFormat { .. }
|
|
186
|
-
| ControlSpec::DatetimeFormat { .. }
|
|
187
|
-
| ControlSpec::StringFormat
|
|
318
|
+
ControlSpec::NumberFormat { .. } | ControlSpec::DatetimeFormat { .. }
|
|
188
319
|
)
|
|
189
320
|
}
|
|
190
321
|
|
|
@@ -230,6 +361,18 @@ impl ColumnConfigSchema {
|
|
|
230
361
|
canonicalize_specs(fields);
|
|
231
362
|
return !fields.is_empty();
|
|
232
363
|
},
|
|
364
|
+
ControlSpec::Alignment {
|
|
365
|
+
key,
|
|
366
|
+
default: Some(default),
|
|
367
|
+
corners: true,
|
|
368
|
+
} if !default.is_corner() => {
|
|
369
|
+
tracing::error!(
|
|
370
|
+
"Dropping `{key}` — default `{}` is not a corner",
|
|
371
|
+
default.as_str()
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
return false;
|
|
375
|
+
},
|
|
233
376
|
ControlSpec::Color { key, default } => (CssKind::Color, key, default),
|
|
234
377
|
ControlSpec::Palette { key, default, .. } => (CssKind::Palette, key, default),
|
|
235
378
|
ControlSpec::GradientStops { key, default, .. } => {
|
|
@@ -255,6 +398,16 @@ impl ColumnConfigSchema {
|
|
|
255
398
|
self
|
|
256
399
|
}
|
|
257
400
|
|
|
401
|
+
/// The variants of the [`ControlSpec::Enum`] owning `key`, if any.
|
|
402
|
+
pub fn enum_variants_of(&self, key: &str) -> Option<&[EnumVariant]> {
|
|
403
|
+
self.leaf_fields().into_iter().find_map(|spec| match spec {
|
|
404
|
+
ControlSpec::Enum {
|
|
405
|
+
key: k, variants, ..
|
|
406
|
+
} if k == key => Some(variants.as_slice()),
|
|
407
|
+
_ => None,
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
|
|
258
411
|
/// The CSS kind of the control owning `key`, if it is CSS-valued.
|
|
259
412
|
pub fn css_kind_of(&self, key: &str) -> Option<CssKind> {
|
|
260
413
|
self.leaf_fields().into_iter().find_map(|spec| match spec {
|
|
@@ -275,12 +428,27 @@ impl ControlSpec {
|
|
|
275
428
|
pub fn serialized_keys(&self) -> Vec<&str> {
|
|
276
429
|
match self {
|
|
277
430
|
ControlSpec::DatetimeFormat { .. } => vec!["date_format"],
|
|
278
|
-
ControlSpec::
|
|
431
|
+
ControlSpec::Font {
|
|
432
|
+
key,
|
|
433
|
+
size,
|
|
434
|
+
bold,
|
|
435
|
+
italic,
|
|
436
|
+
..
|
|
437
|
+
} => [
|
|
438
|
+
Some(key.as_str()),
|
|
439
|
+
size.as_ref().map(|s| s.key.as_str()),
|
|
440
|
+
bold.as_ref().map(|t| t.key.as_str()),
|
|
441
|
+
italic.as_ref().map(|t| t.key.as_str()),
|
|
442
|
+
]
|
|
443
|
+
.into_iter()
|
|
444
|
+
.flatten()
|
|
445
|
+
.collect(),
|
|
279
446
|
ControlSpec::NumberSeriesStyle { .. } => vec!["chart_type", "stack"],
|
|
280
447
|
ControlSpec::Symbols { .. } => vec!["symbols"],
|
|
281
448
|
ControlSpec::NumberFormat { .. } => vec!["number_format"],
|
|
282
449
|
ControlSpec::AggregateDepth => vec!["aggregate_depth"],
|
|
283
450
|
ControlSpec::Enum { key, .. }
|
|
451
|
+
| ControlSpec::Alignment { key, .. }
|
|
284
452
|
| ControlSpec::Bool { key, .. }
|
|
285
453
|
| ControlSpec::Number { key, .. }
|
|
286
454
|
| ControlSpec::String { key, .. }
|
|
@@ -396,13 +564,46 @@ mod tests {
|
|
|
396
564
|
assert_eq!(flat.css_kind_of("stack"), grouped.css_kind_of("stack"));
|
|
397
565
|
}
|
|
398
566
|
|
|
567
|
+
#[test]
|
|
568
|
+
fn enum_variants_see_through_groups() {
|
|
569
|
+
let mode = ControlSpec::Enum {
|
|
570
|
+
key: "fg_mode".to_owned(),
|
|
571
|
+
default: "color".to_owned(),
|
|
572
|
+
variants: vec![
|
|
573
|
+
EnumVariant {
|
|
574
|
+
value: "disabled".to_owned(),
|
|
575
|
+
label: None,
|
|
576
|
+
},
|
|
577
|
+
EnumVariant {
|
|
578
|
+
value: "color".to_owned(),
|
|
579
|
+
label: None,
|
|
580
|
+
},
|
|
581
|
+
],
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
let grouped = ColumnConfigSchema {
|
|
585
|
+
fields: vec![group("color", vec![mode, flag("flag")])],
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
let values: Vec<&str> = grouped
|
|
589
|
+
.enum_variants_of("fg_mode")
|
|
590
|
+
.unwrap()
|
|
591
|
+
.iter()
|
|
592
|
+
.map(|v| v.value.as_str())
|
|
593
|
+
.collect();
|
|
594
|
+
|
|
595
|
+
assert_eq!(values, vec!["disabled", "color"]);
|
|
596
|
+
assert!(grouped.enum_variants_of("flag").is_none());
|
|
597
|
+
assert!(grouped.enum_variants_of("missing").is_none());
|
|
598
|
+
}
|
|
599
|
+
|
|
399
600
|
#[test]
|
|
400
601
|
fn format_controls_group_and_merge() {
|
|
401
602
|
let schema = ColumnConfigSchema {
|
|
402
603
|
fields: vec![
|
|
403
604
|
ControlSpec::NumberFormat { default: None },
|
|
404
605
|
flag("flag"),
|
|
405
|
-
ControlSpec::
|
|
606
|
+
ControlSpec::DatetimeFormat { default: None },
|
|
406
607
|
],
|
|
407
608
|
}
|
|
408
609
|
.group_format_controls();
|
|
@@ -414,19 +615,45 @@ mod tests {
|
|
|
414
615
|
|
|
415
616
|
assert_eq!(key, "format");
|
|
416
617
|
assert!(matches!(fields[0], ControlSpec::NumberFormat { .. }));
|
|
417
|
-
assert!(matches!(fields[1], ControlSpec::
|
|
618
|
+
assert!(matches!(fields[1], ControlSpec::DatetimeFormat { .. }));
|
|
418
619
|
assert!(matches!(&schema.fields[1], ControlSpec::Bool { .. }));
|
|
419
620
|
|
|
420
621
|
assert_eq!(
|
|
421
622
|
schema.active_keys(),
|
|
422
623
|
HashSet::from([
|
|
423
624
|
"number_format".to_owned(),
|
|
424
|
-
"
|
|
625
|
+
"date_format".to_owned(),
|
|
425
626
|
"flag".to_owned()
|
|
426
627
|
])
|
|
427
628
|
);
|
|
428
629
|
}
|
|
429
630
|
|
|
631
|
+
#[test]
|
|
632
|
+
fn font_owns_its_size_and_toggle_keys() {
|
|
633
|
+
let spec = ControlSpec::Font {
|
|
634
|
+
key: "font_family".to_owned(),
|
|
635
|
+
default: "inherit".to_owned(),
|
|
636
|
+
size: Some(FontSize {
|
|
637
|
+
key: "font_size".to_owned(),
|
|
638
|
+
default: 12.0,
|
|
639
|
+
min: None,
|
|
640
|
+
max: None,
|
|
641
|
+
step: None,
|
|
642
|
+
}),
|
|
643
|
+
bold: Some(FontToggle {
|
|
644
|
+
key: "bold".to_owned(),
|
|
645
|
+
default: false,
|
|
646
|
+
}),
|
|
647
|
+
italic: None,
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
assert_eq!(spec.serialized_keys(), vec![
|
|
651
|
+
"font_family",
|
|
652
|
+
"font_size",
|
|
653
|
+
"bold"
|
|
654
|
+
]);
|
|
655
|
+
}
|
|
656
|
+
|
|
430
657
|
#[test]
|
|
431
658
|
fn format_grouping_recurses_but_never_double_wraps() {
|
|
432
659
|
let schema = ColumnConfigSchema {
|
|
@@ -536,6 +763,83 @@ mod tests {
|
|
|
536
763
|
);
|
|
537
764
|
}
|
|
538
765
|
|
|
766
|
+
#[test]
|
|
767
|
+
fn alignment_tokens_round_trip() {
|
|
768
|
+
for align in Alignment::ALL {
|
|
769
|
+
assert_eq!(Alignment::parse(align.as_str()), Some(align));
|
|
770
|
+
assert_eq!(serde_json::to_value(align).unwrap(), json!(align.as_str()));
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
for bad in ["middle", "left-top", "top-center", "middle-left", ""] {
|
|
774
|
+
assert_eq!(Alignment::parse(bad), None, "{bad}");
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
assert_eq!(Alignment::ALL.iter().filter(|x| x.is_corner()).count(), 4);
|
|
778
|
+
assert_eq!(Alignment::TopLeft.humanized(), "Top Left");
|
|
779
|
+
assert_eq!(Alignment::Center.humanized(), "Center");
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
#[test]
|
|
783
|
+
fn alignment_deserializes_with_optional_default_and_corners() {
|
|
784
|
+
let schema: ColumnConfigSchema = serde_json::from_value(json!({
|
|
785
|
+
"fields": [
|
|
786
|
+
{ "kind": "Alignment", "key": "align" },
|
|
787
|
+
{ "kind": "Alignment", "key": "legend_anchor", "default": "top-right", "corners": true }
|
|
788
|
+
]
|
|
789
|
+
}))
|
|
790
|
+
.unwrap();
|
|
791
|
+
|
|
792
|
+
assert!(matches!(&schema.fields[0], ControlSpec::Alignment {
|
|
793
|
+
default: None,
|
|
794
|
+
corners: false,
|
|
795
|
+
..
|
|
796
|
+
}));
|
|
797
|
+
assert!(matches!(&schema.fields[1], ControlSpec::Alignment {
|
|
798
|
+
default: Some(Alignment::TopRight),
|
|
799
|
+
corners: true,
|
|
800
|
+
..
|
|
801
|
+
}));
|
|
802
|
+
assert_eq!(
|
|
803
|
+
schema.active_keys(),
|
|
804
|
+
HashSet::from(["align".to_owned(), "legend_anchor".to_owned()])
|
|
805
|
+
);
|
|
806
|
+
assert!(
|
|
807
|
+
serde_json::from_value::<ColumnConfigSchema>(json!({
|
|
808
|
+
"fields": [{ "kind": "Alignment", "key": "x", "default": "middle" }]
|
|
809
|
+
}))
|
|
810
|
+
.is_err()
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
#[test]
|
|
815
|
+
fn canonicalize_defaults_drops_non_corner_default_of_corners_field() {
|
|
816
|
+
let schema = ColumnConfigSchema {
|
|
817
|
+
fields: vec![
|
|
818
|
+
ControlSpec::Alignment {
|
|
819
|
+
key: "bad".to_owned(),
|
|
820
|
+
default: Some(Alignment::Top),
|
|
821
|
+
corners: true,
|
|
822
|
+
},
|
|
823
|
+
ControlSpec::Alignment {
|
|
824
|
+
key: "ok".to_owned(),
|
|
825
|
+
default: Some(Alignment::Top),
|
|
826
|
+
corners: false,
|
|
827
|
+
},
|
|
828
|
+
ControlSpec::Alignment {
|
|
829
|
+
key: "unset".to_owned(),
|
|
830
|
+
default: None,
|
|
831
|
+
corners: true,
|
|
832
|
+
},
|
|
833
|
+
],
|
|
834
|
+
}
|
|
835
|
+
.canonicalize_defaults();
|
|
836
|
+
|
|
837
|
+
assert_eq!(
|
|
838
|
+
schema.active_keys(),
|
|
839
|
+
HashSet::from(["ok".to_owned(), "unset".to_owned()])
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
|
|
539
843
|
#[test]
|
|
540
844
|
fn canonicalize_defaults_recurses_and_drops_empty_groups() {
|
|
541
845
|
let schema = ColumnConfigSchema {
|
|
@@ -10,13 +10,11 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
mod color_mode;
|
|
14
13
|
mod custom;
|
|
15
14
|
mod custom_format;
|
|
16
15
|
mod simple;
|
|
17
16
|
mod simple_format;
|
|
18
17
|
|
|
19
|
-
pub use color_mode::*;
|
|
20
18
|
pub use custom::*;
|
|
21
19
|
pub use custom_format::*;
|
|
22
20
|
use serde::{Deserialize, Serialize};
|
|
@@ -65,13 +63,4 @@ pub struct DatetimeColumnStyleConfig {
|
|
|
65
63
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
66
64
|
#[ts(optional, as = "Option<_>")]
|
|
67
65
|
pub date_format: Option<DatetimeFormatType>,
|
|
68
|
-
|
|
69
|
-
#[serde(default)]
|
|
70
|
-
#[serde(skip_serializing_if = "DatetimeColorMode::is_none")]
|
|
71
|
-
pub datetime_color_mode: DatetimeColorMode,
|
|
72
|
-
|
|
73
|
-
#[serde(default)]
|
|
74
|
-
#[serde(skip_serializing_if = "Option::is_none")]
|
|
75
|
-
#[ts(skip)]
|
|
76
|
-
pub color: Option<String>,
|
|
77
66
|
}
|
|
@@ -69,6 +69,24 @@ pub enum ExportMethod {
|
|
|
69
69
|
#[serde(rename = "arrow-all")]
|
|
70
70
|
ArrowAll,
|
|
71
71
|
|
|
72
|
+
#[serde(rename = "arrow-lz4")]
|
|
73
|
+
ArrowLz4,
|
|
74
|
+
|
|
75
|
+
#[serde(rename = "arrow-lz4-selected")]
|
|
76
|
+
ArrowLz4Selected,
|
|
77
|
+
|
|
78
|
+
#[serde(rename = "arrow-lz4-all")]
|
|
79
|
+
ArrowLz4All,
|
|
80
|
+
|
|
81
|
+
#[serde(rename = "arrow-zstd")]
|
|
82
|
+
ArrowZstd,
|
|
83
|
+
|
|
84
|
+
#[serde(rename = "arrow-zstd-selected")]
|
|
85
|
+
ArrowZstdSelected,
|
|
86
|
+
|
|
87
|
+
#[serde(rename = "arrow-zstd-all")]
|
|
88
|
+
ArrowZstdAll,
|
|
89
|
+
|
|
72
90
|
#[serde(rename = "json-config")]
|
|
73
91
|
JsonConfig,
|
|
74
92
|
}
|
|
@@ -94,6 +112,12 @@ impl ExportMethod {
|
|
|
94
112
|
Self::CsvSelected => ".selected.csv",
|
|
95
113
|
Self::JsonSelected => ".selected.json",
|
|
96
114
|
Self::ArrowSelected => ".selected.arrow",
|
|
115
|
+
Self::ArrowLz4 => ".lz4.arrow",
|
|
116
|
+
Self::ArrowLz4Selected => ".selected.lz4.arrow",
|
|
117
|
+
Self::ArrowLz4All => ".all.lz4.arrow",
|
|
118
|
+
Self::ArrowZstd => ".zstd.arrow",
|
|
119
|
+
Self::ArrowZstdSelected => ".selected.zstd.arrow",
|
|
120
|
+
Self::ArrowZstdAll => ".all.zstd.arrow",
|
|
97
121
|
Self::Ndjson => ".ndjson",
|
|
98
122
|
Self::NdjsonAll => ".all.ndjson",
|
|
99
123
|
Self::NdjsonSelected => ".selected.ndjson",
|
package/src/rust/config/mod.rs
CHANGED
|
@@ -22,7 +22,6 @@ mod number_series_style;
|
|
|
22
22
|
mod number_string_format;
|
|
23
23
|
mod options;
|
|
24
24
|
mod plugin_static_config;
|
|
25
|
-
mod string_column_style;
|
|
26
25
|
pub mod view_config;
|
|
27
26
|
mod viewer_config;
|
|
28
27
|
mod workspace_config;
|
|
@@ -35,7 +34,6 @@ pub use number_series_style::*;
|
|
|
35
34
|
pub use number_string_format::*;
|
|
36
35
|
pub use options::*;
|
|
37
36
|
pub use plugin_static_config::*;
|
|
38
|
-
pub use string_column_style::*;
|
|
39
37
|
pub use view_config::*;
|
|
40
38
|
pub use viewer_config::*;
|
|
41
39
|
pub use workspace_config::*;
|
|
@@ -44,6 +44,28 @@ pub struct RestoreOptions {
|
|
|
44
44
|
/// known-good config to recover exactly.
|
|
45
45
|
#[ts(optional)]
|
|
46
46
|
pub suppress_errors: Option<bool>,
|
|
47
|
+
|
|
48
|
+
/// When `true`, a `table` no loaded client hosts yet leaves the panel
|
|
49
|
+
/// empty and pending until the table is created, instead of the default
|
|
50
|
+
/// error.
|
|
51
|
+
#[ts(optional)]
|
|
52
|
+
pub wait_for_table: Option<bool>,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// Options for the `restoreWorkspace()` method.
|
|
56
|
+
#[derive(Deserialize, Default, TS)]
|
|
57
|
+
pub struct RestoreWorkspaceOptions {
|
|
58
|
+
/// As `RestoreOptions::wait_for_table`, applied to every panel entry.
|
|
59
|
+
#[ts(optional)]
|
|
60
|
+
pub wait_for_table: Option<bool>,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Options for the `addPanel()` method.
|
|
64
|
+
#[derive(Deserialize, Default, TS)]
|
|
65
|
+
pub struct AddPanelOptions {
|
|
66
|
+
/// As `RestoreOptions::wait_for_table`.
|
|
67
|
+
#[ts(optional)]
|
|
68
|
+
pub wait_for_table: Option<bool>,
|
|
47
69
|
}
|
|
48
70
|
|
|
49
71
|
/// The `eject` argument: the loaded client to remove by name; the active
|
|
@@ -77,6 +99,34 @@ pub struct GetTableOptions {
|
|
|
77
99
|
pub panel: Option<String>,
|
|
78
100
|
}
|
|
79
101
|
|
|
102
|
+
/// How `getView` resolves the `View` it returns.
|
|
103
|
+
#[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq, TS)]
|
|
104
|
+
#[serde(rename_all = "lowercase")]
|
|
105
|
+
pub enum GetViewMode {
|
|
106
|
+
/// The panel's own bound `View`, which the viewer replaces on config
|
|
107
|
+
/// change and deletes on auto-pause or `delete()`; rejects when none is
|
|
108
|
+
/// bound.
|
|
109
|
+
#[default]
|
|
110
|
+
Live,
|
|
111
|
+
|
|
112
|
+
/// A caller-owned `View` built from the panel's effective config,
|
|
113
|
+
/// independent of the render lifecycle.
|
|
114
|
+
Clone,
|
|
115
|
+
|
|
116
|
+
/// `live` when the panel has a bound `View`, else `clone`.
|
|
117
|
+
Auto,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// The `getView` argument: the `mode` and the target panel.
|
|
121
|
+
#[derive(Deserialize, Default, TS)]
|
|
122
|
+
pub struct GetViewOptions {
|
|
123
|
+
#[ts(optional)]
|
|
124
|
+
pub mode: Option<GetViewMode>,
|
|
125
|
+
|
|
126
|
+
#[ts(optional)]
|
|
127
|
+
pub panel: Option<String>,
|
|
128
|
+
}
|
|
129
|
+
|
|
80
130
|
/// The `getClient` argument: whether to `wait` for a `Client`, and the target
|
|
81
131
|
/// panel.
|
|
82
132
|
#[derive(Deserialize, Default, TS)]
|