@opendata-ai/openchart-core 7.11.0 → 8.0.0-rc.10
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/index.d.ts +1348 -132
- package/dist/index.js +556 -48
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -1
- package/dist/styles.css.map +1 -0
- package/package.json +9 -3
- package/schema/chart.schema.json +9086 -0
- package/schema/table.schema.json +861 -0
- package/schema/vizspec.schema.json +17922 -0
- package/src/accessibility/alt-text.ts +39 -1
- package/src/accessibility/aria.ts +4 -2
- package/src/colors/__tests__/colorblind.test.ts +12 -0
- package/src/colors/colorblind.ts +11 -2
- package/src/colors/contrast.ts +11 -0
- package/src/colors/index.ts +9 -1
- package/src/colors/palettes.ts +47 -0
- package/src/helpers/__tests__/deep-merge.test.ts +54 -0
- package/src/helpers/__tests__/spec-builders.test.ts +3 -3
- package/src/helpers/deep-merge.ts +29 -0
- package/src/helpers/spec-builders.ts +7 -7
- package/src/index.ts +29 -1
- package/src/labels/collision.ts +1 -0
- package/src/layout/chrome.ts +24 -0
- package/src/layout/index.ts +1 -1
- package/src/locale/__tests__/format.test.ts +347 -11
- package/src/locale/format.ts +243 -18
- package/src/locale/index.ts +10 -1
- package/src/responsive/breakpoints.ts +7 -2
- package/src/responsive/index.ts +2 -0
- package/src/responsive/metrics.ts +77 -10
- package/src/schema/__tests__/generated-artifacts.test.ts +42 -0
- package/src/schema/__tests__/schema.test.ts +179 -0
- package/src/styles/__tests__/reduced-motion-selectors.test.ts +28 -0
- package/src/styles/animation.css +211 -168
- package/src/styles/base.css +89 -62
- package/src/styles/chrome.css +173 -179
- package/src/styles/dark.css +38 -35
- package/src/styles/graph.css +116 -111
- package/src/styles/index.css +5 -0
- package/src/styles/keyframes.css +130 -99
- package/src/styles/legend.css +14 -12
- package/src/styles/reduced-motion.css +61 -40
- package/src/styles/series-search.css +153 -0
- package/src/styles/sparkline.css +14 -12
- package/src/styles/table-animation.css +82 -80
- package/src/styles/table.css +314 -302
- package/src/styles/token-definitions.ts +199 -0
- package/src/styles/tokens.css +132 -128
- package/src/styles/tooltip.css +109 -115
- package/src/styles/you-draw-it.css +126 -0
- package/src/types/__tests__/encoding.test.ts +86 -17
- package/src/types/__tests__/spec.test.ts +16 -12
- package/src/types/encoding.ts +69 -25
- package/src/types/events.ts +107 -13
- package/src/types/index.ts +42 -3
- package/src/types/layout.ts +484 -11
- package/src/types/schema-roots.ts +32 -0
- package/src/types/spec.ts +718 -87
- package/src/types/table.ts +3 -2
package/src/types/spec.ts
CHANGED
|
@@ -32,6 +32,10 @@ import type { SeriesStrategy, TokenValue } from './theme';
|
|
|
32
32
|
* - 'rule': reference lines as data marks
|
|
33
33
|
* - 'tick': strip/rug plot marks
|
|
34
34
|
* - 'rect': heatmaps and 2D binned plots
|
|
35
|
+
* - 'range': dumbbell / arrow / range-bar plots spanning two values per category
|
|
36
|
+
* - 'waffle': unit grids ("x of 100") for part-to-whole counts
|
|
37
|
+
* - 'calendar': GitHub-style calendar heatmap (weeks x weekdays, daily dates)
|
|
38
|
+
* - 'parliament': hemicycle seat-dot chart for election/legislature results
|
|
35
39
|
*/
|
|
36
40
|
export type MarkType =
|
|
37
41
|
| 'bar'
|
|
@@ -44,10 +48,12 @@ export type MarkType =
|
|
|
44
48
|
| 'rule'
|
|
45
49
|
| 'tick'
|
|
46
50
|
| 'rect'
|
|
47
|
-
| 'lollipop'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
| 'lollipop'
|
|
52
|
+
| 'beeswarm'
|
|
53
|
+
| 'range'
|
|
54
|
+
| 'waffle'
|
|
55
|
+
| 'calendar'
|
|
56
|
+
| 'parliament';
|
|
51
57
|
|
|
52
58
|
// ---------------------------------------------------------------------------
|
|
53
59
|
// Gradient definitions (Vega-aligned)
|
|
@@ -174,6 +180,19 @@ export interface MarkDef {
|
|
|
174
180
|
innerRadius?: number;
|
|
175
181
|
/** Outer radius for arc marks. */
|
|
176
182
|
outerRadius?: number;
|
|
183
|
+
/**
|
|
184
|
+
* Start angle in radians for arc marks. Defaults to 0 (full pie/donut).
|
|
185
|
+
* Combined with `endAngle`, restricts the pie/donut to a partial sweep,
|
|
186
|
+
* e.g. `startAngle: -Math.PI / 2, endAngle: Math.PI / 2` for a half-donut
|
|
187
|
+
* (election-style results donut). Angles follow d3's convention: 0 is
|
|
188
|
+
* straight up, increasing clockwise. Only meaningful when `type` is `'arc'`.
|
|
189
|
+
*/
|
|
190
|
+
startAngle?: number;
|
|
191
|
+
/**
|
|
192
|
+
* End angle in radians for arc marks. Defaults to 2*Math.PI (full pie/donut).
|
|
193
|
+
* See `startAngle`. Only meaningful when `type` is `'arc'`.
|
|
194
|
+
*/
|
|
195
|
+
endAngle?: number;
|
|
177
196
|
/** Corner radius for rect/bar marks. 'pill' sets rx to half the bar thickness. */
|
|
178
197
|
cornerRadius?: number | 'pill';
|
|
179
198
|
/** Fixed bar thickness in pixels for bar/column marks. When set, bars are this height (horizontal) or width (vertical), centered within the band. */
|
|
@@ -200,6 +219,99 @@ export interface MarkDef {
|
|
|
200
219
|
* two competing diagonals.
|
|
201
220
|
*/
|
|
202
221
|
trendline?: boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Horizontal pixel offset from the data anchor. Only meaningful when `type`
|
|
224
|
+
* is `'text'`. Use it to lift a label clear of the mark it annotates instead
|
|
225
|
+
* of shifting the underlying data value.
|
|
226
|
+
*/
|
|
227
|
+
dx?: number;
|
|
228
|
+
/**
|
|
229
|
+
* Vertical pixel offset from the data anchor (negative = up). Only meaningful
|
|
230
|
+
* when `type` is `'text'`. `{ type: 'text', dy: -10 }` floats each label ten
|
|
231
|
+
* pixels above its point.
|
|
232
|
+
*/
|
|
233
|
+
dy?: number;
|
|
234
|
+
/** Horizontal alignment of text marks relative to their anchor. Defaults to `'center'`. */
|
|
235
|
+
align?: 'left' | 'center' | 'right';
|
|
236
|
+
/** Vertical alignment of text marks relative to their anchor. Defaults to `'middle'`. */
|
|
237
|
+
baseline?: 'top' | 'middle' | 'bottom';
|
|
238
|
+
/**
|
|
239
|
+
* Font size in pixels for text marks. Ignored when the `size` encoding channel
|
|
240
|
+
* is present (which scales font size from a data field). `size` is already
|
|
241
|
+
* taken by bar thickness, hence the distinct name.
|
|
242
|
+
*/
|
|
243
|
+
fontSize?: number;
|
|
244
|
+
/**
|
|
245
|
+
* Pattern-fill reinforcement for filled marks (bar, area, arc).
|
|
246
|
+
*
|
|
247
|
+
* - `'auto'`: assign a per-series SVG pattern (diagonal hatch, dots,
|
|
248
|
+
* crosshatch, vertical lines) layered over each series color so series
|
|
249
|
+
* remain distinguishable without color vision. Marks too small to show
|
|
250
|
+
* a legible pattern keep their solid fill.
|
|
251
|
+
* - `'none'` (default): solid fills only.
|
|
252
|
+
*/
|
|
253
|
+
fillPattern?: 'auto' | 'none';
|
|
254
|
+
/**
|
|
255
|
+
* Visual style for range marks. Only meaningful when `type` is `'range'`.
|
|
256
|
+
* - 'dumbbell' (default): a dot at each end joined by a connector line.
|
|
257
|
+
* The start dot is muted, the end dot carries the accent color.
|
|
258
|
+
* - 'arrow': a line with an arrowhead at the x2/y2 end, the strongest
|
|
259
|
+
* "change between two points in time" form.
|
|
260
|
+
* - 'bar': a plain floating range bar spanning start to end.
|
|
261
|
+
*/
|
|
262
|
+
style?: 'dumbbell' | 'arrow' | 'bar';
|
|
263
|
+
/**
|
|
264
|
+
* Color range marks by direction of change. Only meaningful when `type` is
|
|
265
|
+
* `'range'`. When true, increases (x2 > x, or y2 > y) use the theme's
|
|
266
|
+
* `positive` semantic color and decreases use `negative`. A field-based
|
|
267
|
+
* `encoding.color` takes precedence over direction coloring.
|
|
268
|
+
*/
|
|
269
|
+
colorByDirection?: boolean;
|
|
270
|
+
/**
|
|
271
|
+
* Total number of cells in a waffle grid. Only meaningful when `type` is
|
|
272
|
+
* `'waffle'`. Category values normalize to this many cells via
|
|
273
|
+
* largest-remainder rounding so the grid always sums exactly. Default 100.
|
|
274
|
+
*/
|
|
275
|
+
units?: number;
|
|
276
|
+
/**
|
|
277
|
+
* Number of columns in a waffle grid. Only meaningful when `type` is
|
|
278
|
+
* `'waffle'`. Rows derive from `units / columns`. Default 10.
|
|
279
|
+
*/
|
|
280
|
+
columns?: number;
|
|
281
|
+
/**
|
|
282
|
+
* First day of the week for calendar marks. Only meaningful when `type` is
|
|
283
|
+
* `'calendar'`. Controls which weekday occupies the top row of each band.
|
|
284
|
+
* Defaults to 'monday' (ISO week convention).
|
|
285
|
+
*/
|
|
286
|
+
weekStart?: 'monday' | 'sunday';
|
|
287
|
+
/**
|
|
288
|
+
* Corner radius in pixels for calendar day cells. Only meaningful when
|
|
289
|
+
* `type` is `'calendar'`. Defaults to 1.
|
|
290
|
+
*/
|
|
291
|
+
cellRadius?: number;
|
|
292
|
+
/**
|
|
293
|
+
* Seat layout shape for parliament marks. Only meaningful when `type` is
|
|
294
|
+
* `'parliament'`. `'hemicycle'` (default, and currently the only shape)
|
|
295
|
+
* packs seats into concentric semicircular arcs, party-grouped left to
|
|
296
|
+
* right.
|
|
297
|
+
*/
|
|
298
|
+
shape?: 'hemicycle';
|
|
299
|
+
/**
|
|
300
|
+
* Seat dot radius in pixels for parliament marks. `'auto'` (default) sizes
|
|
301
|
+
* dots to fill the available hemicycle rings for the given seat count.
|
|
302
|
+
* Only meaningful when `type` is `'parliament'`.
|
|
303
|
+
*/
|
|
304
|
+
seatRadius?: number | 'auto';
|
|
305
|
+
/**
|
|
306
|
+
* The majority-threshold line and "N to win" label on parliament marks. Only
|
|
307
|
+
* meaningful when `type` is `'parliament'`. `true` (default) draws the line at
|
|
308
|
+
* a simple majority (half the seats plus one); `false` hides it. The object
|
|
309
|
+
* form overrides the threshold and label: `{ seats }` sets a custom seat count
|
|
310
|
+
* (e.g. a two-thirds supermajority) and `{ label }` overrides the default
|
|
311
|
+
* "N to win" text. A `seats` value outside `1..totalSeats` warns and falls
|
|
312
|
+
* back to the simple-majority default.
|
|
313
|
+
*/
|
|
314
|
+
majorityLine?: boolean | { seats?: number; label?: string };
|
|
203
315
|
}
|
|
204
316
|
|
|
205
317
|
// ---------------------------------------------------------------------------
|
|
@@ -227,7 +339,11 @@ export type AggregateOp =
|
|
|
227
339
|
export interface AxisConfig {
|
|
228
340
|
/** Axis title text. If omitted, the field name is used. */
|
|
229
341
|
title?: string;
|
|
230
|
-
/**
|
|
342
|
+
/**
|
|
343
|
+
* Number format: d3-format string (e.g. ",.0f"), or semantic keyword
|
|
344
|
+
* `'percent'` / `'currency'`. When omitted, compact notation (1k, 2.5M)
|
|
345
|
+
* is applied automatically.
|
|
346
|
+
*/
|
|
231
347
|
format?: string;
|
|
232
348
|
/** Override tick count. Engine picks a sensible default if omitted. */
|
|
233
349
|
tickCount?: number;
|
|
@@ -271,8 +387,12 @@ export interface AxisConfig {
|
|
|
271
387
|
|
|
272
388
|
/** Scale configuration for an encoding channel. */
|
|
273
389
|
export interface ScaleConfig {
|
|
274
|
-
/**
|
|
275
|
-
|
|
390
|
+
/**
|
|
391
|
+
* Explicit domain override. Auto-derived from data if omitted.
|
|
392
|
+
* Continuous scales take `[min, max]`; threshold scales take the full
|
|
393
|
+
* list of class break values; categorical scales take the value list.
|
|
394
|
+
*/
|
|
395
|
+
domain?: number[] | string[];
|
|
276
396
|
/** Scale type override. Usually inferred from field type. */
|
|
277
397
|
type?: ScaleType;
|
|
278
398
|
/** Whether to nice-ify the domain for clean tick values. Defaults to true. */
|
|
@@ -283,6 +403,15 @@ export interface ScaleConfig {
|
|
|
283
403
|
clip?: boolean;
|
|
284
404
|
/** Explicit range override. */
|
|
285
405
|
range?: unknown[];
|
|
406
|
+
/**
|
|
407
|
+
* Named color scheme (Vega-Lite aligned). Resolved against the core palette
|
|
408
|
+
* registry (sequential: blue, green, orange, purple, teal; diverging:
|
|
409
|
+
* redBlue, brownTeal; categorical) during the pre-validation sugar
|
|
410
|
+
* expansion; common VL names (blues, greens, category10, ...) are accepted
|
|
411
|
+
* as aliases. Unknown names fail validation with the supported list.
|
|
412
|
+
* An explicit `range` wins over `scheme`.
|
|
413
|
+
*/
|
|
414
|
+
scheme?: string;
|
|
286
415
|
/** Reverse the range direction. */
|
|
287
416
|
reverse?: boolean;
|
|
288
417
|
/** Clamp output to the range. */
|
|
@@ -317,6 +446,30 @@ export type ScaleType =
|
|
|
317
446
|
| 'quantize'
|
|
318
447
|
| 'threshold';
|
|
319
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Sort a categorical domain by the aggregated values of another field
|
|
451
|
+
* (Vega-Lite EncodingSortField).
|
|
452
|
+
*/
|
|
453
|
+
export interface SortByField {
|
|
454
|
+
/** Data field whose values determine the category order. */
|
|
455
|
+
field: string;
|
|
456
|
+
/** Aggregate applied per category before comparing. Defaults to 'sum'. */
|
|
457
|
+
op?: AggregateOp;
|
|
458
|
+
/** Sort direction. Defaults to 'ascending'. */
|
|
459
|
+
order?: 'ascending' | 'descending';
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* A constant value definition for an encoding channel (Vega-Lite aligned).
|
|
464
|
+
* The VL idiom for a fixed visual property, e.g. `color: { value: '#1b7fa3' }`.
|
|
465
|
+
* Expanded to the matching mark-level property (fill/stroke, size, opacity)
|
|
466
|
+
* during the pre-validation sugar expansion.
|
|
467
|
+
*/
|
|
468
|
+
export interface ValueDef {
|
|
469
|
+
/** The constant value: CSS color string, size number, opacity (0-1), or gradient. */
|
|
470
|
+
value: string | number | boolean | null | GradientDef;
|
|
471
|
+
}
|
|
472
|
+
|
|
320
473
|
/**
|
|
321
474
|
* A single encoding channel mapping a data field to a visual property.
|
|
322
475
|
*
|
|
@@ -348,8 +501,11 @@ export interface EncodingChannel<TData extends DataRow = DataRow> {
|
|
|
348
501
|
type: FieldType;
|
|
349
502
|
/** Optional aggregate to apply before encoding. */
|
|
350
503
|
aggregate?: AggregateOp;
|
|
351
|
-
/**
|
|
352
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Axis configuration. Set to `false` to suppress axis entirely (no space
|
|
506
|
+
* reserved). `null` is accepted as a VL-aligned alias for `false`.
|
|
507
|
+
*/
|
|
508
|
+
axis?: AxisConfig | false | null;
|
|
353
509
|
/** Scale configuration. */
|
|
354
510
|
scale?: ScaleConfig;
|
|
355
511
|
/**
|
|
@@ -361,26 +517,28 @@ export interface EncodingChannel<TData extends DataRow = DataRow> {
|
|
|
361
517
|
* The string forms are still the canonical input — the boolean shorthand is
|
|
362
518
|
* normalized to the matching string before reaching layout.
|
|
363
519
|
*
|
|
364
|
-
* - undefined: chart-type default (see below)
|
|
520
|
+
* - undefined: chart-type default (see below) -- stacked for bar/column/area
|
|
365
521
|
* - true | 'zero': stack from zero baseline
|
|
366
522
|
* - 'normalize': stack and normalize to fraction of total (0-1 per category)
|
|
367
523
|
* - 'center': center stacks around zero (streamgraph style)
|
|
368
|
-
* - null | false: no stacking -- renders
|
|
524
|
+
* - null | false: no stacking -- renders grouped/dodged (bar) or overlap (area)
|
|
369
525
|
*
|
|
370
526
|
* **Defaults differ by chart type:**
|
|
371
|
-
* - **Bar/Column**: defaults to
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
527
|
+
* - **Bar/Column**: defaults to stacked (`'zero'`), Vega-Lite aligned. Use
|
|
528
|
+
* `stack: null` (or `false`) for grouped/side-by-side bars.
|
|
529
|
+
* - **Area**: defaults to stacked (`'zero'`), Vega-Lite aligned. Use
|
|
530
|
+
* `stack: null` (or `false`) to opt into overlap rendering, where each
|
|
531
|
+
* series renders as a translucent gradient band anchored at the
|
|
532
|
+
* y-domain baseline.
|
|
375
533
|
* - **Line**: stacking is not applied (lines always overlap).
|
|
376
534
|
*
|
|
377
535
|
* @example
|
|
378
|
-
* //
|
|
379
|
-
* "x": { "field": "revenue", "type": "quantitative", "stack":
|
|
536
|
+
* // Grouped horizontal bars (opt-out; default is stacked):
|
|
537
|
+
* "x": { "field": "revenue", "type": "quantitative", "stack": null }
|
|
380
538
|
*
|
|
381
539
|
* @example
|
|
382
|
-
* //
|
|
383
|
-
* "y": { "field": "value", "type": "quantitative", "stack":
|
|
540
|
+
* // Overlap area (opt-out; default is stacked):
|
|
541
|
+
* "y": { "field": "value", "type": "quantitative", "stack": null }
|
|
384
542
|
*/
|
|
385
543
|
stack?: boolean | 'zero' | 'normalize' | 'center' | null;
|
|
386
544
|
/**
|
|
@@ -403,8 +561,22 @@ export interface EncodingChannel<TData extends DataRow = DataRow> {
|
|
|
403
561
|
* - 'descending': sort domain values descending
|
|
404
562
|
* - null: use data order (no sorting)
|
|
405
563
|
* - undefined: ascending (VL default)
|
|
564
|
+
* - 'x' | '-x' | 'y' | '-y': sort by another channel's values ('-' prefix
|
|
565
|
+
* for descending). The VL ranked-bar idiom: `sort: '-y'` orders categories
|
|
566
|
+
* by value, largest first. Resolved into an explicit domain during the
|
|
567
|
+
* pre-validation sugar expansion.
|
|
568
|
+
* - string[]: explicit value order. Listed values come first (in the given
|
|
569
|
+
* order); unlisted data values follow in data order.
|
|
570
|
+
* - SortByField: sort by the aggregated values of another field.
|
|
406
571
|
*/
|
|
407
|
-
sort?: 'ascending' | 'descending' | null;
|
|
572
|
+
sort?: 'ascending' | 'descending' | null | 'x' | '-x' | 'y' | '-y' | string[] | SortByField;
|
|
573
|
+
/**
|
|
574
|
+
* Legend configuration for this channel (Vega-Lite aligned).
|
|
575
|
+
* Only meaningful on the `color` channel. `null` hides the legend (the VL
|
|
576
|
+
* idiom for `legend.show = false`); a config object merges into the
|
|
577
|
+
* top-level `legend` (top-level keys win on conflict).
|
|
578
|
+
*/
|
|
579
|
+
legend?: LegendConfig | null;
|
|
408
580
|
/**
|
|
409
581
|
* Display title override (Vega-Lite aligned).
|
|
410
582
|
* Used as the label in tooltips instead of the raw field name.
|
|
@@ -413,7 +585,8 @@ export interface EncodingChannel<TData extends DataRow = DataRow> {
|
|
|
413
585
|
title?: string;
|
|
414
586
|
/**
|
|
415
587
|
* Format string for values (Vega-Lite aligned).
|
|
416
|
-
* For quantitative fields: d3-format string (e.g. ",.0f", "$,.2f")
|
|
588
|
+
* For quantitative fields: d3-format string (e.g. ",.0f", "$,.2f"),
|
|
589
|
+
* or semantic keyword `'percent'` / `'currency'`.
|
|
417
590
|
* For temporal fields: d3-time-format string (e.g. "%Y", "%b %d").
|
|
418
591
|
* Used in tooltips; `axis.format` takes precedence for axis tick labels.
|
|
419
592
|
*/
|
|
@@ -475,14 +648,16 @@ export interface Encoding<TData extends DataRow = DataRow> {
|
|
|
475
648
|
/**
|
|
476
649
|
* Color channel. Required for arc marks (determines pie/donut slice coloring).
|
|
477
650
|
* Optional for all other marks -- used for series differentiation on multi-series charts,
|
|
478
|
-
* or heatmap intensity. Accepts a conditional definition to apply colors based on data predicates
|
|
651
|
+
* or heatmap intensity. Accepts a conditional definition to apply colors based on data predicates,
|
|
652
|
+
* or a bare `{ value }` constant (VL aligned; expanded to the mark-level fill/stroke).
|
|
479
653
|
*/
|
|
480
|
-
color?: EncodingChannel<TData> | ConditionalValueDef<TData
|
|
654
|
+
color?: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef;
|
|
481
655
|
/**
|
|
482
656
|
* Size channel. Used by point/bubble charts to scale dot area by a quantitative field.
|
|
483
|
-
* Accepts a conditional definition to vary size based on data predicates
|
|
657
|
+
* Accepts a conditional definition to vary size based on data predicates,
|
|
658
|
+
* or a bare `{ value }` constant (VL aligned; expanded to `mark.size`).
|
|
484
659
|
*/
|
|
485
|
-
size?: EncodingChannel<TData> | ConditionalValueDef<TData
|
|
660
|
+
size?: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef;
|
|
486
661
|
/**
|
|
487
662
|
* Detail channel. Groups data into multiple series without mapping to a visual property.
|
|
488
663
|
* Useful when you want separate lines per category but don't need the color to differ.
|
|
@@ -506,17 +681,14 @@ export interface Encoding<TData extends DataRow = DataRow> {
|
|
|
506
681
|
y2?: EncodingChannel<TData>;
|
|
507
682
|
/**
|
|
508
683
|
* Data-driven opacity (0-1 range). Accepts a conditional definition to vary opacity
|
|
509
|
-
* based on data predicates (e.g., highlight selected points)
|
|
684
|
+
* based on data predicates (e.g., highlight selected points), or a bare `{ value }`
|
|
685
|
+
* constant (VL aligned; expanded to `mark.opacity`).
|
|
510
686
|
*/
|
|
511
|
-
opacity?: EncodingChannel<TData> | ConditionalValueDef<TData
|
|
687
|
+
opacity?: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef;
|
|
512
688
|
/**
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
|
|
516
|
-
shape?: EncodingChannel<TData>;
|
|
517
|
-
/**
|
|
518
|
-
* Stroke dash pattern encoding. Maps a nominal field to different dash patterns
|
|
519
|
-
* on line marks. Useful when color alone doesn't distinguish series well.
|
|
689
|
+
* Stroke dash pattern encoding. Maps a nominal/ordinal field to different
|
|
690
|
+
* dash patterns on line and rule marks. Useful when color alone doesn't
|
|
691
|
+
* distinguish series well.
|
|
520
692
|
*/
|
|
521
693
|
strokeDash?: EncodingChannel<TData>;
|
|
522
694
|
/** Rotation angle encoding for point marks. Maps a quantitative field to 0-360 degrees. */
|
|
@@ -531,25 +703,15 @@ export interface Encoding<TData extends DataRow = DataRow> {
|
|
|
531
703
|
* multi-field tooltips. Independent of the x/y/color encoding.
|
|
532
704
|
*/
|
|
533
705
|
tooltip?: EncodingChannel<TData> | EncodingChannel<TData>[];
|
|
534
|
-
/** Hyperlink encoding. Maps a field containing URLs to clickable marks. */
|
|
535
|
-
href?: EncodingChannel<TData>;
|
|
536
|
-
/**
|
|
537
|
-
* Drawing order. Controls z-order and stacking sort order for bar/area marks.
|
|
538
|
-
* Lower values are drawn first (behind higher values).
|
|
539
|
-
*/
|
|
540
|
-
order?: EncodingChannel<TData>;
|
|
541
706
|
/**
|
|
542
|
-
* Angular position for arc marks (pie/donut)
|
|
543
|
-
*
|
|
544
|
-
*
|
|
707
|
+
* Angular position (slice value) for arc marks (pie/donut), the canonical
|
|
708
|
+
* value channel in v8. Waffle and parliament marks accept it too (the same
|
|
709
|
+
* part-to-whole value channel). `y` is still accepted on these marks as a
|
|
710
|
+
* deprecated alias for backward compatibility (a compile warning is emitted
|
|
711
|
+
* and `y` is populated from `theta` internally). Not used by any other mark
|
|
712
|
+
* type.
|
|
545
713
|
*/
|
|
546
714
|
theta?: EncodingChannel<TData>;
|
|
547
|
-
/**
|
|
548
|
-
* Radial distance from center for arc marks.
|
|
549
|
-
* Optional -- only meaningful on donut charts (controls inner radius boundary).
|
|
550
|
-
* Not used by any other mark type.
|
|
551
|
-
*/
|
|
552
|
-
radius?: EncodingChannel<TData>;
|
|
553
715
|
/**
|
|
554
716
|
* Facet channel: partitions data into a grid of small-multiple panels.
|
|
555
717
|
* Each unique value of the facet field produces one panel. Panels share
|
|
@@ -557,6 +719,20 @@ export interface Encoding<TData extends DataRow = DataRow> {
|
|
|
557
719
|
* per-panel axes.
|
|
558
720
|
*/
|
|
559
721
|
facet?: FacetChannel<TData>;
|
|
722
|
+
/**
|
|
723
|
+
* Row facet channel: partitions data into vertically-stacked panels.
|
|
724
|
+
* Each unique value of the row field produces one panel, arranged in a
|
|
725
|
+
* single column. Shares the x-axis scale by default; y-axis is independent.
|
|
726
|
+
* Mutually exclusive with `facet` and `column`.
|
|
727
|
+
*/
|
|
728
|
+
row?: FacetChannel<TData>;
|
|
729
|
+
/**
|
|
730
|
+
* Column facet channel: partitions data into side-by-side panels.
|
|
731
|
+
* Each unique value of the column field produces one panel, arranged in a
|
|
732
|
+
* single row. Shares the y-axis scale by default; x-axis is independent.
|
|
733
|
+
* Mutually exclusive with `facet` and `row`.
|
|
734
|
+
*/
|
|
735
|
+
column?: FacetChannel<TData>;
|
|
560
736
|
}
|
|
561
737
|
|
|
562
738
|
// ---------------------------------------------------------------------------
|
|
@@ -682,15 +858,26 @@ export interface AnnotationOffset {
|
|
|
682
858
|
/** Anchor direction for annotation label placement relative to the data point. */
|
|
683
859
|
export type AnnotationAnchor = 'top' | 'bottom' | 'left' | 'right' | 'auto';
|
|
684
860
|
|
|
685
|
-
/**
|
|
861
|
+
/** Connector type for annotation labels. */
|
|
862
|
+
export type ConnectorType = 'straight' | 'curve' | 'drop-line';
|
|
863
|
+
|
|
864
|
+
/** Object form of the connector config, allowing arrow control. */
|
|
865
|
+
export interface ConnectorConfig {
|
|
866
|
+
/** Connector style. */
|
|
867
|
+
type: ConnectorType;
|
|
868
|
+
/** Whether to draw an arrowhead at the data-point end. Default: true for curve, false for straight. Drop-line never takes a head. */
|
|
869
|
+
arrow?: boolean;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/** Style overrides for the dot marker drawn at the data point. */
|
|
686
873
|
export interface AnnotationDot {
|
|
687
|
-
/** Circle radius in pixels. Default
|
|
874
|
+
/** Circle radius in pixels. Default 4. */
|
|
688
875
|
radius?: number;
|
|
689
876
|
/** Fill color. Defaults to theme background for an "open ring" look. */
|
|
690
877
|
fill?: string;
|
|
691
|
-
/** Stroke color. Defaults to
|
|
878
|
+
/** Stroke color. Defaults to the connector's resolved stroke, so marker and leader read as one system. */
|
|
692
879
|
stroke?: string;
|
|
693
|
-
/** Stroke width in pixels. Default
|
|
880
|
+
/** Stroke width in pixels. Default 1.5. */
|
|
694
881
|
strokeWidth?: number;
|
|
695
882
|
}
|
|
696
883
|
|
|
@@ -722,7 +909,13 @@ export interface TextAnnotation extends AnnotationBase {
|
|
|
722
909
|
x: string | number;
|
|
723
910
|
/** Y-axis data value or position. */
|
|
724
911
|
y: string | number;
|
|
725
|
-
/**
|
|
912
|
+
/**
|
|
913
|
+
* The annotation text. Required for text annotations.
|
|
914
|
+
*
|
|
915
|
+
* Supports inline `**bold**` spans, so emphasis lands on the key phrase rather
|
|
916
|
+
* than the whole block: `'Inflation peaked at **8.5%**'`. Unmatched `**` (and
|
|
917
|
+
* empty `****`) render literally. `\n` starts a new line.
|
|
918
|
+
*/
|
|
726
919
|
text: string;
|
|
727
920
|
/** Thinning priority (lower = kept longer at narrow widths). When omitted, spec order is used. */
|
|
728
921
|
priority?: number;
|
|
@@ -730,12 +923,23 @@ export interface TextAnnotation extends AnnotationBase {
|
|
|
730
923
|
* Optional muted second-tone text rendered below the primary `text`.
|
|
731
924
|
* Used for supporting context (e.g. methodology, source). Newlines in
|
|
732
925
|
* `text` still produce multi-line primary; subtitle is a separate block.
|
|
926
|
+
*
|
|
927
|
+
* Supports the same inline `**bold**` spans as `text`. When a subtitle is
|
|
928
|
+
* present and no `fontWeight` is set, the primary `text` resolves to weight
|
|
929
|
+
* 700 — the lede + context stack.
|
|
733
930
|
*/
|
|
734
931
|
subtitle?: string;
|
|
735
932
|
/**
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
*
|
|
933
|
+
* Open-ring marker drawn on the data point itself (not on the pulled-back
|
|
934
|
+
* connector tip).
|
|
935
|
+
*
|
|
936
|
+
* Left unset, a default marker appears whenever a connector is enabled and
|
|
937
|
+
* carries no arrowhead — the leader points, the ring lands. An arrowed
|
|
938
|
+
* connector gets no marker unless you ask for one: the head already marks the
|
|
939
|
+
* spot. `dot: false` is always bare; an explicit `dot` always wins.
|
|
940
|
+
*
|
|
941
|
+
* `true` uses the default style; pass an object to override radius, fill,
|
|
942
|
+
* stroke, or strokeWidth.
|
|
739
943
|
*/
|
|
740
944
|
dot?: boolean | AnnotationDot;
|
|
741
945
|
/** Font size override. */
|
|
@@ -748,13 +952,19 @@ export interface TextAnnotation extends AnnotationBase {
|
|
|
748
952
|
anchor?: AnnotationAnchor;
|
|
749
953
|
/**
|
|
750
954
|
* Connector from label to anchor point.
|
|
751
|
-
* - `true` (default): straight line
|
|
752
|
-
* - `'straight'`: straight line
|
|
955
|
+
* - `true` (default): straight line, no arrow
|
|
956
|
+
* - `'straight'`: straight line, no arrow
|
|
753
957
|
* - `'curve'`: curved arrow with arrowhead
|
|
754
|
-
* - `'drop-line'`: vertical line through the data point's x
|
|
958
|
+
* - `'drop-line'`: vertical line through the data point's x
|
|
959
|
+
* - `{ type, arrow? }`: object form for explicit arrow control
|
|
755
960
|
* - `false`: no connector
|
|
961
|
+
*
|
|
962
|
+
* The connector leaves the text block on the side facing the data point, with
|
|
963
|
+
* a small standoff gap. A leader shorter than 8px is dropped as noise (the
|
|
964
|
+
* marker alone reads better), as is a connector whose target sits inside the
|
|
965
|
+
* text block. Widen `offset` if you want the line back.
|
|
756
966
|
*/
|
|
757
|
-
connector?: boolean |
|
|
967
|
+
connector?: boolean | ConnectorType | ConnectorConfig;
|
|
758
968
|
/** Per-endpoint offsets for the connector line. Allows fine-tuning where the connector starts and ends. */
|
|
759
969
|
connectorOffset?: {
|
|
760
970
|
/** Offset for the label-end of the connector. */
|
|
@@ -762,8 +972,14 @@ export interface TextAnnotation extends AnnotationBase {
|
|
|
762
972
|
/** Offset for the data-point-end of the connector. */
|
|
763
973
|
to?: AnnotationOffset;
|
|
764
974
|
};
|
|
765
|
-
/**
|
|
766
|
-
|
|
975
|
+
/**
|
|
976
|
+
* Background plate behind the text, for readability over chart lines.
|
|
977
|
+
*
|
|
978
|
+
* `true` uses the theme surface, so the plate follows light/dark mode. A
|
|
979
|
+
* color string sets it explicitly. Prefer `true`: a hardcoded '#ffffff' stays
|
|
980
|
+
* white in dark mode and the text turns light-gray-on-white.
|
|
981
|
+
*/
|
|
982
|
+
background?: string | true;
|
|
767
983
|
/** Whether to show the paint-order stroke halo behind text. Default true. Set false for white text on colored backgrounds. */
|
|
768
984
|
halo?: boolean;
|
|
769
985
|
}
|
|
@@ -807,7 +1023,14 @@ export interface RangeAnnotation extends AnnotationBase {
|
|
|
807
1023
|
* Useful for baselines (zero), targets, or thresholds.
|
|
808
1024
|
*/
|
|
809
1025
|
export interface RefLineAnnotation extends AnnotationBase {
|
|
810
|
-
|
|
1026
|
+
/**
|
|
1027
|
+
* Discriminant. `'refline'` is canonical and the only value in the type.
|
|
1028
|
+
* `'rule'` (it collides with the `rule` mark type) is still accepted at
|
|
1029
|
+
* runtime for backward compatibility -- the spec-sugar pass rewrites it to
|
|
1030
|
+
* `'refline'` with a deprecation warning before validation -- but it is not
|
|
1031
|
+
* part of this type. Use `'refline'`.
|
|
1032
|
+
*/
|
|
1033
|
+
type: 'refline';
|
|
811
1034
|
/** X-axis value for a vertical reference line. */
|
|
812
1035
|
x?: string | number;
|
|
813
1036
|
/** Y-axis value for a horizontal reference line. */
|
|
@@ -1007,7 +1230,11 @@ export interface LabelConfig {
|
|
|
1007
1230
|
suffix?: string;
|
|
1008
1231
|
/** Fixed CSS color for all labels. Overrides the default fill-derived color. */
|
|
1009
1232
|
color?: string;
|
|
1010
|
-
/**
|
|
1233
|
+
/**
|
|
1234
|
+
* Per-series pixel offsets for fine-tuning label positions, keyed by series name.
|
|
1235
|
+
* @deprecated Per-series pixel offsets are a workaround for collision bugs
|
|
1236
|
+
* now fixed by the layout engine. Will be removed in a future version.
|
|
1237
|
+
*/
|
|
1011
1238
|
offsets?: Record<string, AnnotationOffset>;
|
|
1012
1239
|
/** Font size in pixels for bar/column value labels. */
|
|
1013
1240
|
fontSize?: number;
|
|
@@ -1038,6 +1265,46 @@ export interface LegendConfig {
|
|
|
1038
1265
|
exclude?: string[];
|
|
1039
1266
|
}
|
|
1040
1267
|
|
|
1268
|
+
/**
|
|
1269
|
+
* Configuration for the searchable series highlight input (`seriesSearch`).
|
|
1270
|
+
* The boolean form (`seriesSearch: true`) uses the defaults.
|
|
1271
|
+
*/
|
|
1272
|
+
export interface SeriesSearchConfig {
|
|
1273
|
+
/** Placeholder text for the search input. Defaults to "Find a series". */
|
|
1274
|
+
placeholder?: string;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
/**
|
|
1278
|
+
* Configuration for the "you draw it" interactive engagement format
|
|
1279
|
+
* (`youDrawIt`). The reader draws their guess of the trend from `from` to the
|
|
1280
|
+
* right edge before the real line reveals. Line marks only, single-series only.
|
|
1281
|
+
*/
|
|
1282
|
+
export interface YouDrawItConfig {
|
|
1283
|
+
/**
|
|
1284
|
+
* The x value (matching `encoding.x`'s domain) where drawing starts. Data
|
|
1285
|
+
* before this point renders normally; data at or after it is hidden behind
|
|
1286
|
+
* a hatched "draw here" region until reveal.
|
|
1287
|
+
*/
|
|
1288
|
+
from: string | number;
|
|
1289
|
+
/** Prompt text shown in the hatched drawing region. Defaults to "Draw your guess". */
|
|
1290
|
+
prompt?: string;
|
|
1291
|
+
/** Label for the skip-to-reveal button. Defaults to "Show me". */
|
|
1292
|
+
revealLabel?: string;
|
|
1293
|
+
/**
|
|
1294
|
+
* Optional extra comparison line (e.g. "what everyone else guessed"),
|
|
1295
|
+
* supplied by the host app. Rendered in a third, visually distinct style
|
|
1296
|
+
* alongside the reader's guess and the real line after reveal.
|
|
1297
|
+
*/
|
|
1298
|
+
comparisonLine?: Array<{ x: string | number; y: number }>;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/**
|
|
1302
|
+
* Content composition for an endpoint-label entry: the series name, the
|
|
1303
|
+
* formatted value, or both joined on one line. See
|
|
1304
|
+
* {@link EndpointLabelsConfig.content}.
|
|
1305
|
+
*/
|
|
1306
|
+
export type EndpointLabelContent = 'label' | 'value' | 'label value';
|
|
1307
|
+
|
|
1041
1308
|
/**
|
|
1042
1309
|
* Configuration for the endpoint labels column rendered at the chart's right edge
|
|
1043
1310
|
* for multi-series line/area charts. Each entry pairs the series name with its
|
|
@@ -1075,6 +1342,20 @@ export interface EndpointLabelsConfig {
|
|
|
1075
1342
|
* - `'both'`: labels on both left (leading) and right (trailing) edges.
|
|
1076
1343
|
*/
|
|
1077
1344
|
ends?: 'end' | 'both';
|
|
1345
|
+
/**
|
|
1346
|
+
* What each entry renders.
|
|
1347
|
+
* - `'label'`: series name only.
|
|
1348
|
+
* - `'value'`: formatted value only.
|
|
1349
|
+
* - `'label value'`: series name and value joined on one line.
|
|
1350
|
+
*
|
|
1351
|
+
* When omitted, entries render the series name with the formatted value on
|
|
1352
|
+
* a second line (the classic endpoint column). Pass an object to set the
|
|
1353
|
+
* leading and trailing columns independently, e.g. the classic slope-chart
|
|
1354
|
+
* look is `{ leading: 'label value', trailing: 'value' }`.
|
|
1355
|
+
*/
|
|
1356
|
+
content?:
|
|
1357
|
+
| EndpointLabelContent
|
|
1358
|
+
| { leading?: EndpointLabelContent; trailing?: EndpointLabelContent };
|
|
1078
1359
|
/** Field to read the displayed value from. Defaults to `encoding.y.field`. */
|
|
1079
1360
|
valueField?: string;
|
|
1080
1361
|
/** d3-format string for the value. Defaults to `encoding.y.axis.format`. */
|
|
@@ -1250,14 +1531,14 @@ export interface Metric {
|
|
|
1250
1531
|
|
|
1251
1532
|
/**
|
|
1252
1533
|
* Encoding for arc marks (pie/donut charts).
|
|
1253
|
-
* - `
|
|
1534
|
+
* - `theta`: required (quantitative — the canonical slice value channel)
|
|
1254
1535
|
* - `color`: required (nominal/ordinal — the category)
|
|
1255
|
-
* - `
|
|
1256
|
-
* - `radius`: optional (donut inner radius)
|
|
1536
|
+
* - `y`: deprecated alias for `theta`, accepted for backward compatibility
|
|
1257
1537
|
*/
|
|
1258
1538
|
export interface ArcEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1259
|
-
|
|
1260
|
-
|
|
1539
|
+
/** Canonical value channel for arc marks (quantitative — the slice value). */
|
|
1540
|
+
theta: EncodingChannel<TData>;
|
|
1541
|
+
color: EncodingChannel<TData> | ConditionalValueDef<TData>;
|
|
1261
1542
|
}
|
|
1262
1543
|
|
|
1263
1544
|
/**
|
|
@@ -1320,6 +1601,67 @@ export interface LollipopEncoding<TData extends DataRow = DataRow> extends Encod
|
|
|
1320
1601
|
y: EncodingChannel<TData>;
|
|
1321
1602
|
}
|
|
1322
1603
|
|
|
1604
|
+
/**
|
|
1605
|
+
* Encoding for beeswarm marks (dodged distribution dots).
|
|
1606
|
+
* - Exactly one positional channel is quantitative: the value axis
|
|
1607
|
+
* (x = horizontal swarm, y = vertical swarm).
|
|
1608
|
+
* - The other positional channel is optional (nominal/ordinal): grouped
|
|
1609
|
+
* swarms, one lane per category. The cross axis has no scale; the dodge
|
|
1610
|
+
* layout computes pixel offsets around each lane center.
|
|
1611
|
+
*/
|
|
1612
|
+
export interface BeeswarmEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1613
|
+
x?: EncodingChannel<TData>;
|
|
1614
|
+
y?: EncodingChannel<TData>;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
/**
|
|
1618
|
+
* Encoding for range marks (dumbbell / arrow / range-bar plots).
|
|
1619
|
+
* - Horizontal (the common editorial form): `y` nominal/ordinal category,
|
|
1620
|
+
* `x` quantitative start, `x2` quantitative end.
|
|
1621
|
+
* - Vertical: `x` nominal/ordinal category, `y` quantitative start,
|
|
1622
|
+
* `y2` quantitative end.
|
|
1623
|
+
*/
|
|
1624
|
+
export interface RangeEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1625
|
+
x: EncodingChannel<TData>;
|
|
1626
|
+
y: EncodingChannel<TData>;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* Encoding for waffle marks (unit grids for part-to-whole counts).
|
|
1631
|
+
* - `color`: required (nominal/ordinal, the category)
|
|
1632
|
+
* - `theta`: the canonical quantitative share, the same part-to-whole value
|
|
1633
|
+
* channel arc marks use. `y` is a deprecated alias, accepted for backward
|
|
1634
|
+
* compatibility.
|
|
1635
|
+
*/
|
|
1636
|
+
export interface WaffleEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1637
|
+
color: EncodingChannel<TData> | ConditionalValueDef<TData>;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
/**
|
|
1641
|
+
* Encoding for parliament marks (hemicycle seat-dot charts).
|
|
1642
|
+
* - `color`: required (nominal/ordinal, the party)
|
|
1643
|
+
* - `theta`: the canonical quantitative seat count, the same part-to-whole
|
|
1644
|
+
* value channel arc/waffle marks use. `y` is a deprecated alias, accepted
|
|
1645
|
+
* for backward compatibility.
|
|
1646
|
+
*/
|
|
1647
|
+
export interface ParliamentEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1648
|
+
color: EncodingChannel<TData> | ConditionalValueDef<TData>;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
/**
|
|
1652
|
+
* Encoding for calendar marks (GitHub-style calendar heatmaps).
|
|
1653
|
+
* - `x`: required (temporal, daily dates, one row per day)
|
|
1654
|
+
* - `color`: required (quantitative, the per-day value)
|
|
1655
|
+
*
|
|
1656
|
+
* The calendar computes its own weeks-x-weekdays geometry: no positional
|
|
1657
|
+
* scales or axes. Multi-year data partitions into one stacked band per year,
|
|
1658
|
+
* all bands sharing a single color scale and legend.
|
|
1659
|
+
*/
|
|
1660
|
+
export interface CalendarEncoding<TData extends DataRow = DataRow> extends Encoding<TData> {
|
|
1661
|
+
x: EncodingChannel<TData>;
|
|
1662
|
+
color: EncodingChannel<TData>;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1323
1665
|
/**
|
|
1324
1666
|
* Encoding for text marks (data-positioned labels).
|
|
1325
1667
|
* - `text`: required (the field to render as text)
|
|
@@ -1349,6 +1691,33 @@ export interface RectEncoding<TData extends DataRow = DataRow> extends Encoding<
|
|
|
1349
1691
|
y: EncodingChannel<TData>;
|
|
1350
1692
|
}
|
|
1351
1693
|
|
|
1694
|
+
// ---------------------------------------------------------------------------
|
|
1695
|
+
// Accessibility configuration
|
|
1696
|
+
// ---------------------------------------------------------------------------
|
|
1697
|
+
|
|
1698
|
+
/**
|
|
1699
|
+
* Author-facing accessibility overrides.
|
|
1700
|
+
*
|
|
1701
|
+
* Everything here is optional; when omitted, openchart auto-generates alt
|
|
1702
|
+
* text, ARIA labels, and a screen-reader data table from the spec and data.
|
|
1703
|
+
*/
|
|
1704
|
+
export interface A11yConfig {
|
|
1705
|
+
/**
|
|
1706
|
+
* Alt text announced by screen readers for the chart as a whole. Replaces
|
|
1707
|
+
* the auto-generated description. Also settable via the top-level
|
|
1708
|
+
* `description` field (Vega-Lite convention); this field wins when both
|
|
1709
|
+
* are present.
|
|
1710
|
+
*/
|
|
1711
|
+
description?: string;
|
|
1712
|
+
/**
|
|
1713
|
+
* Hide the chart from assistive technology entirely (`aria-hidden`).
|
|
1714
|
+
* Use only when the chart is decorative or the surrounding content
|
|
1715
|
+
* already conveys the same information. Also suppresses the hidden
|
|
1716
|
+
* screen-reader data table and keyboard mark navigation.
|
|
1717
|
+
*/
|
|
1718
|
+
hidden?: boolean;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1352
1721
|
// ---------------------------------------------------------------------------
|
|
1353
1722
|
// Shared (non-mark-specific) ChartSpec properties
|
|
1354
1723
|
// ---------------------------------------------------------------------------
|
|
@@ -1360,12 +1729,44 @@ export interface RectEncoding<TData extends DataRow = DataRow> extends Encoding<
|
|
|
1360
1729
|
* @internal
|
|
1361
1730
|
*/
|
|
1362
1731
|
interface BaseChartSpec<TData extends DataRow = DataRow> {
|
|
1363
|
-
/**
|
|
1732
|
+
/**
|
|
1733
|
+
* Data array: each element is a row with field values.
|
|
1734
|
+
* The Vega-Lite object form `{ values: [...] }` is also accepted at runtime
|
|
1735
|
+
* and unwrapped during the pre-validation sugar expansion. `{ url }` is not
|
|
1736
|
+
* supported (openchart does not fetch data).
|
|
1737
|
+
*/
|
|
1364
1738
|
data: TData[];
|
|
1365
1739
|
/** Data transforms applied in order before encoding (filter, bin, calculate, timeUnit). */
|
|
1366
1740
|
transform?: Transform[];
|
|
1367
1741
|
/** Editorial chrome (title, subtitle, source, etc.). */
|
|
1368
1742
|
chrome?: Chrome;
|
|
1743
|
+
/**
|
|
1744
|
+
* Top-level title sugar (Vega-Lite aligned). Expanded into `chrome.title`
|
|
1745
|
+
* (and `chrome.subtitle` for the object form). `chrome.title` wins when
|
|
1746
|
+
* both are set.
|
|
1747
|
+
*/
|
|
1748
|
+
title?: string | { text: string; subtitle?: string };
|
|
1749
|
+
/** Top-level subtitle sugar. Expanded into `chrome.subtitle`; `chrome.subtitle` wins. */
|
|
1750
|
+
subtitle?: string;
|
|
1751
|
+
/**
|
|
1752
|
+
* Alt text for the rendered chart (Vega-Lite aligned). Sugar for
|
|
1753
|
+
* `a11y.description`; `a11y.description` wins when both are set.
|
|
1754
|
+
* When absent, alt text is auto-generated from the spec and data.
|
|
1755
|
+
*/
|
|
1756
|
+
description?: string;
|
|
1757
|
+
/** Accessibility overrides. See {@link A11yConfig}. */
|
|
1758
|
+
a11y?: A11yConfig;
|
|
1759
|
+
/**
|
|
1760
|
+
* Fixed render width in pixels (Vega-Lite aligned). Overrides the
|
|
1761
|
+
* container-derived width. When both `width` and `height` are set,
|
|
1762
|
+
* `responsive: false` is implied unless `responsive` is set explicitly.
|
|
1763
|
+
* Omit for the default container-driven sizing.
|
|
1764
|
+
*/
|
|
1765
|
+
width?: number;
|
|
1766
|
+
/** Fixed render height in pixels (Vega-Lite aligned). See `width`. */
|
|
1767
|
+
height?: number;
|
|
1768
|
+
/** Accepted for Vega-Lite compatibility and ignored (with a compile warning). */
|
|
1769
|
+
$schema?: string;
|
|
1369
1770
|
/**
|
|
1370
1771
|
* KPI/metric cells rendered as a horizontal row between subtitle and chart
|
|
1371
1772
|
* area. Each cell shows a label/value pair with optional delta and secondary
|
|
@@ -1402,7 +1803,12 @@ interface BaseChartSpec<TData extends DataRow = DataRow> {
|
|
|
1402
1803
|
darkMode?: DarkMode;
|
|
1403
1804
|
/** Whether to show the tryOpenData.ai watermark. Defaults to true. */
|
|
1404
1805
|
watermark?: boolean;
|
|
1405
|
-
/**
|
|
1806
|
+
/**
|
|
1807
|
+
* Series names to hide from rendering by default. This is the authored
|
|
1808
|
+
* persistence target for legend visibility. Runtime legend toggles
|
|
1809
|
+
* (legend-toggle edit events) layer on top of this via ephemeral runtime
|
|
1810
|
+
* sets but never modify it.
|
|
1811
|
+
*/
|
|
1406
1812
|
hiddenSeries?: string[];
|
|
1407
1813
|
/** Per-series visual overrides, keyed by series name (the color field value). */
|
|
1408
1814
|
seriesStyles?: Record<string, SeriesStyle>;
|
|
@@ -1426,6 +1832,22 @@ interface BaseChartSpec<TData extends DataRow = DataRow> {
|
|
|
1426
1832
|
* explicitly set.
|
|
1427
1833
|
*/
|
|
1428
1834
|
crosshair?: boolean;
|
|
1835
|
+
/**
|
|
1836
|
+
* Searchable series highlight ("find your country"). Renders a compact
|
|
1837
|
+
* search input above the chart with typeahead over the color channel's
|
|
1838
|
+
* distinct values. Selecting a value adds it to the highlight set
|
|
1839
|
+
* (multi-select chips, removable); clearing restores the authored
|
|
1840
|
+
* `encoding.color.highlight` baseline. Requires a categorical color
|
|
1841
|
+
* encoding. Mutually exclusive with edit mode (search wins).
|
|
1842
|
+
*/
|
|
1843
|
+
seriesSearch?: boolean | SeriesSearchConfig;
|
|
1844
|
+
/**
|
|
1845
|
+
* "You draw it" interactive engagement format: the reader draws their
|
|
1846
|
+
* guess of the trend before the real line reveals. Line marks only,
|
|
1847
|
+
* single-series only. Mutually exclusive with edit mode (validation
|
|
1848
|
+
* warning if both are enabled; youDrawIt is disabled).
|
|
1849
|
+
*/
|
|
1850
|
+
youDrawIt?: YouDrawItConfig;
|
|
1429
1851
|
/**
|
|
1430
1852
|
* Display mode controlling how much chart chrome is rendered.
|
|
1431
1853
|
*
|
|
@@ -1521,6 +1943,18 @@ export type ChartSpec<TData extends DataRow = DataRow> =
|
|
|
1521
1943
|
mark: 'lollipop' | (MarkDef & { type: 'lollipop' });
|
|
1522
1944
|
encoding: LollipopEncoding<TData>;
|
|
1523
1945
|
})
|
|
1946
|
+
| (BaseChartSpec<TData> & {
|
|
1947
|
+
mark: 'beeswarm' | (MarkDef & { type: 'beeswarm' });
|
|
1948
|
+
encoding: BeeswarmEncoding<TData>;
|
|
1949
|
+
})
|
|
1950
|
+
| (BaseChartSpec<TData> & {
|
|
1951
|
+
mark: 'range' | (MarkDef & { type: 'range' });
|
|
1952
|
+
encoding: RangeEncoding<TData>;
|
|
1953
|
+
})
|
|
1954
|
+
| (BaseChartSpec<TData> & {
|
|
1955
|
+
mark: 'waffle' | (MarkDef & { type: 'waffle' });
|
|
1956
|
+
encoding: WaffleEncoding<TData>;
|
|
1957
|
+
})
|
|
1524
1958
|
| (BaseChartSpec<TData> & {
|
|
1525
1959
|
mark: 'text' | (MarkDef & { type: 'text' });
|
|
1526
1960
|
encoding: TextEncoding<TData>;
|
|
@@ -1536,6 +1970,14 @@ export type ChartSpec<TData extends DataRow = DataRow> =
|
|
|
1536
1970
|
| (BaseChartSpec<TData> & {
|
|
1537
1971
|
mark: 'rule' | (MarkDef & { type: 'rule' });
|
|
1538
1972
|
encoding: Encoding<TData>;
|
|
1973
|
+
})
|
|
1974
|
+
| (BaseChartSpec<TData> & {
|
|
1975
|
+
mark: 'calendar' | (MarkDef & { type: 'calendar' });
|
|
1976
|
+
encoding: CalendarEncoding<TData>;
|
|
1977
|
+
})
|
|
1978
|
+
| (BaseChartSpec<TData> & {
|
|
1979
|
+
mark: 'parliament' | (MarkDef & { type: 'parliament' });
|
|
1980
|
+
encoding: ParliamentEncoding<TData>;
|
|
1539
1981
|
});
|
|
1540
1982
|
|
|
1541
1983
|
/**
|
|
@@ -1676,7 +2118,26 @@ export interface LayerSpec<TData extends DataRow = DataRow> {
|
|
|
1676
2118
|
transform?: Transform[];
|
|
1677
2119
|
/** Editorial chrome (title, subtitle, source, etc.). */
|
|
1678
2120
|
chrome?: Chrome;
|
|
1679
|
-
/**
|
|
2121
|
+
/** Top-level title sugar (VL aligned). Expanded into `chrome.title`; `chrome.title` wins. */
|
|
2122
|
+
title?: string | { text: string; subtitle?: string };
|
|
2123
|
+
/** Top-level subtitle sugar. Expanded into `chrome.subtitle`; `chrome.subtitle` wins. */
|
|
2124
|
+
subtitle?: string;
|
|
2125
|
+
/** Fixed render width in pixels (VL aligned). Overrides the container-derived width. */
|
|
2126
|
+
width?: number;
|
|
2127
|
+
/** Fixed render height in pixels (VL aligned). Overrides the container-derived height. */
|
|
2128
|
+
height?: number;
|
|
2129
|
+
/** Accepted for Vega-Lite compatibility and ignored (with a compile warning). */
|
|
2130
|
+
$schema?: string;
|
|
2131
|
+
/**
|
|
2132
|
+
* Annotations for the layered chart. When present, these are the
|
|
2133
|
+
* annotations rendered and available for editing. When absent, falls back
|
|
2134
|
+
* to the first leaf layer's annotations. Annotations on second and later
|
|
2135
|
+
* leaf layers are not rendered.
|
|
2136
|
+
*
|
|
2137
|
+
* For edit persistence: the `data-annotation-index` stamped on each
|
|
2138
|
+
* rendered annotation maps to this array (or the first leaf's if this is
|
|
2139
|
+
* unset). Place annotations here for reliable index-based edit matching.
|
|
2140
|
+
*/
|
|
1680
2141
|
annotations?: Annotation[];
|
|
1681
2142
|
/** Label display configuration. `false` disables all labels, `true` uses defaults. */
|
|
1682
2143
|
labels?: LabelSpec;
|
|
@@ -1692,7 +2153,12 @@ export interface LayerSpec<TData extends DataRow = DataRow> {
|
|
|
1692
2153
|
watermark?: boolean;
|
|
1693
2154
|
/** Resolution strategy for shared scales/axes/legends. */
|
|
1694
2155
|
resolve?: ResolveConfig;
|
|
1695
|
-
/**
|
|
2156
|
+
/**
|
|
2157
|
+
* Series names to hide from rendering by default. This is the authored
|
|
2158
|
+
* persistence target for legend visibility. Runtime legend toggles
|
|
2159
|
+
* (legend-toggle edit events) layer on top of this via ephemeral runtime
|
|
2160
|
+
* sets but never modify it.
|
|
2161
|
+
*/
|
|
1696
2162
|
hiddenSeries?: string[];
|
|
1697
2163
|
/** Endpoint labels column, inherited by child layers that don't set their own. */
|
|
1698
2164
|
endpointLabels?: boolean | EndpointLabelsConfig;
|
|
@@ -1774,6 +2240,8 @@ export interface SankeySpec {
|
|
|
1774
2240
|
* number (data value 28 renders as "28%"). For currency: "$,.0f" or "$~s".
|
|
1775
2241
|
* For SI suffixes: "~s" (renders 1000 as "1k"). When not set, values use
|
|
1776
2242
|
* the default number formatter.
|
|
2243
|
+
* @deprecated Use the encoding channel's `format` field instead. This
|
|
2244
|
+
* property is expanded into the encoding during compilation.
|
|
1777
2245
|
*/
|
|
1778
2246
|
valueFormat?: string;
|
|
1779
2247
|
}
|
|
@@ -1840,6 +2308,109 @@ export interface TileMapSpec {
|
|
|
1840
2308
|
/**
|
|
1841
2309
|
* d3-format string applied to tile values, legend labels, and tooltips.
|
|
1842
2310
|
* Examples: ".1f" for one decimal, "$,.0f" for currency, "~s" for SI.
|
|
2311
|
+
* @deprecated Use the encoding channel's `format` field instead. This
|
|
2312
|
+
* property is expanded into the encoding during compilation.
|
|
2313
|
+
*/
|
|
2314
|
+
valueFormat?: string;
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
// ---------------------------------------------------------------------------
|
|
2318
|
+
// Map spec (choropleth / symbol maps)
|
|
2319
|
+
// ---------------------------------------------------------------------------
|
|
2320
|
+
|
|
2321
|
+
/** Supported map projections. */
|
|
2322
|
+
export type MapProjection = 'albersUsa' | 'mercator' | 'equalEarth' | 'identity';
|
|
2323
|
+
|
|
2324
|
+
/** Focus target for map camera: feature id(s) to zoom/pan to. */
|
|
2325
|
+
/**
|
|
2326
|
+
* Fit the point layer's cluster. `true` fits every point; `{ field, value }`
|
|
2327
|
+
* fits only the points whose data row has `row[field] === value` (e.g. only the
|
|
2328
|
+
* campuses rated "F"), which lets a story pan between sub-clusters.
|
|
2329
|
+
*/
|
|
2330
|
+
export type MapPointsFocus = true | { field: string; value: string | number };
|
|
2331
|
+
|
|
2332
|
+
export type MapFocus =
|
|
2333
|
+
| string
|
|
2334
|
+
| number
|
|
2335
|
+
| Array<string | number>
|
|
2336
|
+
| { features: string | number | Array<string | number>; padding?: number }
|
|
2337
|
+
| { points: MapPointsFocus; padding?: number };
|
|
2338
|
+
|
|
2339
|
+
/** Geo configuration for map specs. */
|
|
2340
|
+
export interface MapGeo {
|
|
2341
|
+
/** TopoJSON topology object. User imports this from us-atlas, world-atlas, or their own source. */
|
|
2342
|
+
features: unknown;
|
|
2343
|
+
/** Field in the TopoJSON feature properties to use as the join key. Defaults to 'id'. */
|
|
2344
|
+
idField?: string;
|
|
2345
|
+
/** Map projection. Defaults to 'albersUsa'. */
|
|
2346
|
+
projection?: MapProjection;
|
|
2347
|
+
/**
|
|
2348
|
+
* Focus the camera. A feature id (or array) fits those features; `{ features, padding }`
|
|
2349
|
+
* adds breathing room; `{ points: true, padding }` fits the points layer's cluster
|
|
2350
|
+
* instead of any feature (use when points occupy a small part of a large feature, so
|
|
2351
|
+
* fitting the feature would leave the cluster small and off-center);
|
|
2352
|
+
* `{ points: { field, value }, padding }` fits only the matching point subset, so a
|
|
2353
|
+
* story can pan between sub-clusters. null clears focus from a prior story step.
|
|
2354
|
+
*/
|
|
2355
|
+
focus?: MapFocus | null;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
/** Encoding channels specific to map visualizations. */
|
|
2359
|
+
export interface MapEncoding {
|
|
2360
|
+
/** Join key field in the data. Required for choropleth; optional in basemap-only mode (points layer with empty data). */
|
|
2361
|
+
key?: EncodingChannel;
|
|
2362
|
+
/** Color encoding (quantitative or nominal). Drives fill color of features. Optional when a points layer is present (basemap-only mode). */
|
|
2363
|
+
color?: EncodingChannel;
|
|
2364
|
+
/** Tooltip encoding (optional). */
|
|
2365
|
+
tooltip?: EncodingChannel | EncodingChannel[];
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
/** Point/symbol layer rendered above choropleth features. */
|
|
2369
|
+
export interface MapPointsLayer {
|
|
2370
|
+
/** Tabular data for the points. Independent of the choropleth data join. */
|
|
2371
|
+
data: DataRow[];
|
|
2372
|
+
/** Field holding longitude (x coordinate). */
|
|
2373
|
+
longitude: EncodingChannel;
|
|
2374
|
+
/** Field holding latitude (y coordinate). */
|
|
2375
|
+
latitude: EncodingChannel;
|
|
2376
|
+
/** Optional quantitative size encoding. Area-proportional: r proportional to sqrt(value). No size legend is rendered in v1; explain the scale in chrome.subtitle if needed. */
|
|
2377
|
+
size?: EncodingChannel;
|
|
2378
|
+
/** Optional color encoding (nominal or quantitative). Independent scale from choropleth. */
|
|
2379
|
+
color?: EncodingChannel;
|
|
2380
|
+
/** Tooltip channel(s), same shape as MapEncoding.tooltip. */
|
|
2381
|
+
tooltip?: EncodingChannel | EncodingChannel[];
|
|
2382
|
+
/** Stable id for event callbacks. Data-update transitions for points are not yet supported. */
|
|
2383
|
+
key?: EncodingChannel;
|
|
2384
|
+
/** Fill opacity for point circles. Default 0.65. Range 0-1. */
|
|
2385
|
+
opacity?: number;
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
export interface MapSpec {
|
|
2389
|
+
/** Discriminant: always "map". */
|
|
2390
|
+
type: 'map';
|
|
2391
|
+
/** Geo configuration: TopoJSON features, join key, and projection. */
|
|
2392
|
+
geo: MapGeo;
|
|
2393
|
+
/** Tabular data to join to geo features. */
|
|
2394
|
+
data: DataRow[];
|
|
2395
|
+
/** Encoding channels mapping data fields to visual properties. */
|
|
2396
|
+
encoding: MapEncoding;
|
|
2397
|
+
/** Editorial chrome (title, subtitle, source, byline, footer). */
|
|
2398
|
+
chrome?: Chrome;
|
|
2399
|
+
/** Legend display configuration. */
|
|
2400
|
+
legend?: LegendConfig;
|
|
2401
|
+
/** Theme configuration overrides. */
|
|
2402
|
+
theme?: ThemeConfig;
|
|
2403
|
+
/** Dark mode behavior. Defaults to "off". */
|
|
2404
|
+
darkMode?: DarkMode;
|
|
2405
|
+
/** Whether to show the tryOpenData.ai watermark. Defaults to true. */
|
|
2406
|
+
watermark?: boolean;
|
|
2407
|
+
/** Optional point/symbol layer rendered above choropleth features. */
|
|
2408
|
+
points?: MapPointsLayer;
|
|
2409
|
+
/** Animation configuration for entrance animations. */
|
|
2410
|
+
animation?: AnimationSpec;
|
|
2411
|
+
/**
|
|
2412
|
+
* d3-format string applied to color values in tooltips and legend.
|
|
2413
|
+
* @deprecated Use the encoding channel's `format` field instead.
|
|
1843
2414
|
*/
|
|
1844
2415
|
valueFormat?: string;
|
|
1845
2416
|
}
|
|
@@ -1877,6 +2448,8 @@ export interface BarListSpec {
|
|
|
1877
2448
|
/**
|
|
1878
2449
|
* d3-format string applied to bar values and tooltips.
|
|
1879
2450
|
* Examples: ".1f" for one decimal, "$,.0f" for currency, "~s" for SI.
|
|
2451
|
+
* @deprecated Use the encoding channel's `format` field instead. This
|
|
2452
|
+
* property is expanded into the encoding during compilation.
|
|
1880
2453
|
*/
|
|
1881
2454
|
valueFormat?: string;
|
|
1882
2455
|
}
|
|
@@ -1904,7 +2477,15 @@ export interface BarListEncoding {
|
|
|
1904
2477
|
* - GraphSpec: has `type: 'graph'`
|
|
1905
2478
|
* - SankeySpec: has `type: 'sankey'`
|
|
1906
2479
|
* - TileMapSpec: has `type: 'tilemap'`
|
|
2480
|
+
* - MapSpec: has `type: 'map'`
|
|
1907
2481
|
* - BarListSpec: has `type: 'barlist'`
|
|
2482
|
+
*
|
|
2483
|
+
* Election parliament (hemicycle) charts are `ChartSpec` with `mark:
|
|
2484
|
+
* 'parliament'`, not a separate top-level type: seat data (party + seats)
|
|
2485
|
+
* maps naturally onto encoding.color/y like arc and waffle, and riding the
|
|
2486
|
+
* existing chart pipeline gets scales, legend, tooltips, a11y, and dark mode
|
|
2487
|
+
* for free instead of a second bespoke compile path (see
|
|
2488
|
+
* `packages/engine/src/charts/parliament/`).
|
|
1908
2489
|
*/
|
|
1909
2490
|
export type VizSpec =
|
|
1910
2491
|
| ChartSpec
|
|
@@ -1913,6 +2494,7 @@ export type VizSpec =
|
|
|
1913
2494
|
| GraphSpec
|
|
1914
2495
|
| SankeySpec
|
|
1915
2496
|
| TileMapSpec
|
|
2497
|
+
| MapSpec
|
|
1916
2498
|
| BarListSpec;
|
|
1917
2499
|
|
|
1918
2500
|
/**
|
|
@@ -1928,6 +2510,10 @@ export type GraphSpecWithoutData = Omit<GraphSpec, 'nodes' | 'edges'>;
|
|
|
1928
2510
|
export type SankeySpecWithoutData = Omit<SankeySpec, 'data'>;
|
|
1929
2511
|
/** TileMap spec without runtime data, for persistence/storage. */
|
|
1930
2512
|
export type TileMapSpecWithoutData = Omit<TileMapSpec, 'data'>;
|
|
2513
|
+
/** Map spec without runtime data, for persistence/storage. */
|
|
2514
|
+
export type MapSpecWithoutData = Omit<MapSpec, 'data' | 'points'> & {
|
|
2515
|
+
points?: Omit<MapPointsLayer, 'data'>;
|
|
2516
|
+
};
|
|
1931
2517
|
/** BarList spec without runtime data, for persistence/storage. */
|
|
1932
2518
|
export type BarListSpecWithoutData = Omit<BarListSpec, 'data'>;
|
|
1933
2519
|
/** Union of data-stripped spec types for persistence/storage. */
|
|
@@ -1937,6 +2523,7 @@ export type StoredVizSpec =
|
|
|
1937
2523
|
| GraphSpecWithoutData
|
|
1938
2524
|
| SankeySpecWithoutData
|
|
1939
2525
|
| TileMapSpecWithoutData
|
|
2526
|
+
| MapSpecWithoutData
|
|
1940
2527
|
| BarListSpecWithoutData;
|
|
1941
2528
|
|
|
1942
2529
|
// ---------------------------------------------------------------------------
|
|
@@ -2144,9 +2731,10 @@ export interface Condition<TData extends DataRow = DataRow> {
|
|
|
2144
2731
|
test: FilterPredicate;
|
|
2145
2732
|
/**
|
|
2146
2733
|
* Static value to use when the condition is true.
|
|
2147
|
-
* Accepted values: CSS color string, opacity (0-1), size number,
|
|
2734
|
+
* Accepted values: CSS color string, opacity (0-1), size number, boolean flag,
|
|
2735
|
+
* or a gradient definition for color channels.
|
|
2148
2736
|
*/
|
|
2149
|
-
value?: string | number | boolean | null;
|
|
2737
|
+
value?: string | number | boolean | null | GradientDef;
|
|
2150
2738
|
/**
|
|
2151
2739
|
* Data field to use when the condition is true.
|
|
2152
2740
|
* Constrained to column names of `TData` when using `ChartSpec<TData>`.
|
|
@@ -2167,18 +2755,19 @@ export interface ConditionalValueDef<TData extends DataRow = DataRow> {
|
|
|
2167
2755
|
condition: Condition<TData> | Condition<TData>[];
|
|
2168
2756
|
/**
|
|
2169
2757
|
* Default value when no condition matches.
|
|
2170
|
-
* Accepted values: CSS color string, opacity (0-1), size number,
|
|
2758
|
+
* Accepted values: CSS color string, opacity (0-1), size number, boolean flag,
|
|
2759
|
+
* or a gradient definition for color channels.
|
|
2171
2760
|
*/
|
|
2172
|
-
value?: string | number | boolean | null;
|
|
2761
|
+
value?: string | number | boolean | null | GradientDef;
|
|
2173
2762
|
}
|
|
2174
2763
|
|
|
2175
2764
|
/**
|
|
2176
2765
|
* Check if a channel definition is a regular EncodingChannel (has 'field' at top level).
|
|
2177
|
-
* Use this to narrow `EncodingChannel | ConditionalValueDef` in encoding
|
|
2178
|
-
* that support conditional encoding (color, size, opacity).
|
|
2766
|
+
* Use this to narrow `EncodingChannel | ConditionalValueDef | ValueDef` in encoding
|
|
2767
|
+
* channels that support conditional encoding (color, size, opacity).
|
|
2179
2768
|
*/
|
|
2180
2769
|
export function isEncodingChannel<TData extends DataRow = DataRow>(
|
|
2181
|
-
def: EncodingChannel<TData> | ConditionalValueDef<TData> | undefined,
|
|
2770
|
+
def: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef | undefined,
|
|
2182
2771
|
): def is EncodingChannel<TData> {
|
|
2183
2772
|
if (!def) return false;
|
|
2184
2773
|
return 'field' in def && !('condition' in def);
|
|
@@ -2188,12 +2777,24 @@ export function isEncodingChannel<TData extends DataRow = DataRow>(
|
|
|
2188
2777
|
* Check if a channel definition is a ConditionalValueDef.
|
|
2189
2778
|
*/
|
|
2190
2779
|
export function isConditionalDef<TData extends DataRow = DataRow>(
|
|
2191
|
-
def: EncodingChannel<TData> | ConditionalValueDef<TData> | undefined,
|
|
2780
|
+
def: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef | undefined,
|
|
2192
2781
|
): def is ConditionalValueDef<TData> {
|
|
2193
2782
|
if (!def) return false;
|
|
2194
2783
|
return 'condition' in def;
|
|
2195
2784
|
}
|
|
2196
2785
|
|
|
2786
|
+
/**
|
|
2787
|
+
* Check if a channel definition is a bare ValueDef (constant value, no field
|
|
2788
|
+
* or condition). These are expanded to mark-level properties during the
|
|
2789
|
+
* pre-validation sugar expansion.
|
|
2790
|
+
*/
|
|
2791
|
+
export function isValueDef<TData extends DataRow = DataRow>(
|
|
2792
|
+
def: EncodingChannel<TData> | ConditionalValueDef<TData> | ValueDef | undefined,
|
|
2793
|
+
): def is ValueDef {
|
|
2794
|
+
if (!def) return false;
|
|
2795
|
+
return 'value' in def && !('condition' in def) && !('field' in def);
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2197
2798
|
// ---------------------------------------------------------------------------
|
|
2198
2799
|
// Mark type helpers
|
|
2199
2800
|
// ---------------------------------------------------------------------------
|
|
@@ -2211,10 +2812,25 @@ export const MARK_TYPES: ReadonlySet<string> = new Set<MarkType>([
|
|
|
2211
2812
|
'tick',
|
|
2212
2813
|
'rect',
|
|
2213
2814
|
'lollipop',
|
|
2815
|
+
'beeswarm',
|
|
2816
|
+
'range',
|
|
2817
|
+
'waffle',
|
|
2818
|
+
'calendar',
|
|
2819
|
+
'parliament',
|
|
2214
2820
|
]);
|
|
2215
2821
|
|
|
2216
|
-
/**
|
|
2217
|
-
|
|
2822
|
+
/**
|
|
2823
|
+
* Mark types that lay out inside the chart area without positional axes
|
|
2824
|
+
* (no axis or gridline computation; margins shrink to padding).
|
|
2825
|
+
*/
|
|
2826
|
+
export function isAxislessMark(markType: MarkType): boolean {
|
|
2827
|
+
return (
|
|
2828
|
+
markType === 'arc' ||
|
|
2829
|
+
markType === 'waffle' ||
|
|
2830
|
+
markType === 'calendar' ||
|
|
2831
|
+
markType === 'parliament'
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2218
2834
|
|
|
2219
2835
|
/**
|
|
2220
2836
|
* Extract the mark type string from a mark field (string or MarkDef).
|
|
@@ -2269,6 +2885,11 @@ export function isBarListSpec(spec: VizSpec | Record<string, unknown>): spec is
|
|
|
2269
2885
|
return 'type' in spec && (spec as Record<string, unknown>).type === 'barlist';
|
|
2270
2886
|
}
|
|
2271
2887
|
|
|
2888
|
+
/** Check if a spec is a MapSpec. */
|
|
2889
|
+
export function isMapSpec(spec: VizSpec | Record<string, unknown>): spec is MapSpec {
|
|
2890
|
+
return 'type' in spec && (spec as Record<string, unknown>).type === 'map';
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2272
2893
|
// ---------------------------------------------------------------------------
|
|
2273
2894
|
// Annotation type guards
|
|
2274
2895
|
// ---------------------------------------------------------------------------
|
|
@@ -2283,9 +2904,14 @@ export function isRangeAnnotation(annotation: Annotation): annotation is RangeAn
|
|
|
2283
2904
|
return annotation.type === 'range';
|
|
2284
2905
|
}
|
|
2285
2906
|
|
|
2286
|
-
/**
|
|
2907
|
+
/**
|
|
2908
|
+
* Check if an annotation is a RefLineAnnotation. Also accepts the deprecated
|
|
2909
|
+
* `'rule'` type at runtime (pre-sugar-expansion input), since `annotation.type`
|
|
2910
|
+
* may not yet be narrowed to the canonical `'refline'` form.
|
|
2911
|
+
*/
|
|
2287
2912
|
export function isRefLineAnnotation(annotation: Annotation): annotation is RefLineAnnotation {
|
|
2288
|
-
|
|
2913
|
+
const type: string = annotation.type;
|
|
2914
|
+
return type === 'refline' || type === 'rule';
|
|
2289
2915
|
}
|
|
2290
2916
|
|
|
2291
2917
|
// ---------------------------------------------------------------------------
|
|
@@ -2305,4 +2931,9 @@ export const MARK_DISPLAY_NAMES: Record<MarkType, string> = {
|
|
|
2305
2931
|
tick: 'Tick plot',
|
|
2306
2932
|
rect: 'Heatmap',
|
|
2307
2933
|
lollipop: 'Lollipop chart',
|
|
2934
|
+
beeswarm: 'Beeswarm chart',
|
|
2935
|
+
range: 'Range plot',
|
|
2936
|
+
waffle: 'Waffle chart',
|
|
2937
|
+
calendar: 'Calendar heatmap',
|
|
2938
|
+
parliament: 'Parliament chart',
|
|
2308
2939
|
};
|