@opendata-ai/openchart-engine 7.10.0 → 8.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/index.d.ts +142 -7
  2. package/dist/index.js +16182 -10032
  3. package/dist/index.js.map +1 -1
  4. package/package.json +11 -4
  5. package/src/__tests__/__snapshots__/compile-snapshot.test.ts.snap +170 -56
  6. package/src/__tests__/annotation-behavior.test.ts +721 -0
  7. package/src/__tests__/axes.test.ts +50 -3
  8. package/src/__tests__/compile-chart.test.ts +30 -0
  9. package/src/__tests__/compile-footnotes.test.ts +277 -0
  10. package/src/__tests__/compile-layer.test.ts +120 -1
  11. package/src/__tests__/dimensions.test.ts +49 -4
  12. package/src/__tests__/helpers/invariants.ts +54 -20
  13. package/src/__tests__/known-bugs.test.ts +455 -2
  14. package/src/__tests__/legend.test.ts +120 -4
  15. package/src/__tests__/ranking-recipes.test.ts +260 -0
  16. package/src/__tests__/scales.test.ts +9 -3
  17. package/src/__tests__/series-search.test.ts +92 -0
  18. package/src/__tests__/spec-sugar.test.ts +801 -0
  19. package/src/__tests__/you-draw-it.test.ts +160 -0
  20. package/src/annotations/__tests__/compute.test.ts +207 -92
  21. package/src/annotations/__tests__/geometry.test.ts +66 -0
  22. package/src/annotations/__tests__/resolve-text.test.ts +527 -27
  23. package/src/annotations/__tests__/rich-text.test.ts +91 -0
  24. package/src/annotations/__tests__/thinning.test.ts +148 -0
  25. package/src/annotations/collisions.ts +130 -84
  26. package/src/annotations/compute.ts +83 -85
  27. package/src/annotations/constants.ts +116 -6
  28. package/src/annotations/geometry.ts +222 -77
  29. package/src/annotations/move.ts +135 -0
  30. package/src/annotations/placement.ts +62 -14
  31. package/src/annotations/resolve-range.ts +2 -0
  32. package/src/annotations/resolve-refline.ts +2 -0
  33. package/src/annotations/resolve-text.ts +312 -111
  34. package/src/annotations/rich-text.ts +65 -0
  35. package/src/annotations/thinning.ts +84 -10
  36. package/src/barlist/compile-barlist.ts +16 -6
  37. package/src/charts/_shared/format-label-value.ts +9 -8
  38. package/src/charts/bar/__tests__/compute.test.ts +57 -10
  39. package/src/charts/bar/__tests__/labels.test.ts +5 -4
  40. package/src/charts/bar/compute.ts +2 -6
  41. package/src/charts/bar/index.ts +8 -1
  42. package/src/charts/bar/labels.ts +3 -3
  43. package/src/charts/beeswarm/__tests__/compute.test.ts +280 -0
  44. package/src/charts/beeswarm/__tests__/dodge.test.ts +148 -0
  45. package/src/charts/beeswarm/compute.ts +203 -0
  46. package/src/charts/beeswarm/dodge.ts +155 -0
  47. package/src/charts/beeswarm/index.ts +32 -0
  48. package/src/charts/builtin.ts +12 -1
  49. package/src/charts/calendar/__tests__/compute.test.ts +417 -0
  50. package/src/charts/calendar/compute.ts +319 -0
  51. package/src/charts/calendar/index.ts +32 -0
  52. package/src/charts/column/__tests__/compute.test.ts +21 -7
  53. package/src/charts/column/__tests__/labels.test.ts +76 -1
  54. package/src/charts/column/compute.ts +2 -6
  55. package/src/charts/column/index.ts +10 -2
  56. package/src/charts/column/labels.ts +95 -21
  57. package/src/charts/dot/index.ts +8 -1
  58. package/src/charts/dot/labels.ts +3 -3
  59. package/src/charts/line/__tests__/compute.test.ts +15 -19
  60. package/src/charts/line/area.ts +8 -23
  61. package/src/charts/line/compute.ts +32 -2
  62. package/src/charts/parliament/__tests__/compute.test.ts +411 -0
  63. package/src/charts/parliament/compute.ts +313 -0
  64. package/src/charts/parliament/index.ts +32 -0
  65. package/src/charts/pie/__tests__/compute.test.ts +103 -0
  66. package/src/charts/pie/compute.ts +63 -8
  67. package/src/charts/pie/labels.ts +1 -0
  68. package/src/charts/range/__tests__/compute.test.ts +486 -0
  69. package/src/charts/range/compute.ts +273 -0
  70. package/src/charts/range/index.ts +82 -0
  71. package/src/charts/range/labels.ts +169 -0
  72. package/src/charts/rect/__tests__/compute.test.ts +120 -0
  73. package/src/charts/rect/index.ts +127 -0
  74. package/src/charts/scatter/compute.ts +7 -21
  75. package/src/charts/text/__tests__/compute.test.ts +307 -0
  76. package/src/charts/text/index.ts +44 -7
  77. package/src/charts/tick/__tests__/compute.test.ts +75 -0
  78. package/src/charts/tick/index.ts +7 -4
  79. package/src/charts/utils.ts +5 -3
  80. package/src/charts/waffle/__tests__/compute.test.ts +305 -0
  81. package/src/charts/waffle/compute.ts +197 -0
  82. package/src/charts/waffle/index.ts +31 -0
  83. package/src/compile/__tests__/color-scale-reverse.test.ts +89 -0
  84. package/src/compile/__tests__/data-clip.test.ts +68 -0
  85. package/src/compile/__tests__/fill-patterns.test.ts +154 -0
  86. package/src/compile/__tests__/size-scale.test.ts +108 -0
  87. package/src/compile/color-scale-range.ts +54 -33
  88. package/src/compile/data-clip.ts +21 -6
  89. package/src/compile/fill-patterns.ts +74 -0
  90. package/src/compile/layer.ts +117 -21
  91. package/src/compile/size-scale.ts +139 -0
  92. package/src/compile/spec-sugar.ts +758 -0
  93. package/src/compile/you-draw-it.ts +123 -0
  94. package/src/compile.ts +315 -103
  95. package/src/compiler/__tests__/a11y-warnings.test.ts +148 -0
  96. package/src/compiler/__tests__/fixtures/vl-parity/axis-null.json +19 -0
  97. package/src/compiler/__tests__/fixtures/vl-parity/color-value.json +20 -0
  98. package/src/compiler/__tests__/fixtures/vl-parity/count-aggregate.json +22 -0
  99. package/src/compiler/__tests__/fixtures/vl-parity/data-values.json +19 -0
  100. package/src/compiler/__tests__/fixtures/vl-parity/layer-axis-null.json +14 -0
  101. package/src/compiler/__tests__/fixtures/vl-parity/layer-count.json +34 -0
  102. package/src/compiler/__tests__/fixtures/vl-parity/layer-data-values.json +22 -0
  103. package/src/compiler/__tests__/fixtures/vl-parity/layer-legend-null.json +41 -0
  104. package/src/compiler/__tests__/fixtures/vl-parity/layer-scheme.json +38 -0
  105. package/src/compiler/__tests__/fixtures/vl-parity/layer-sort.json +28 -0
  106. package/src/compiler/__tests__/fixtures/vl-parity/layer-theta.json +28 -0
  107. package/src/compiler/__tests__/fixtures/vl-parity/layer-title.json +30 -0
  108. package/src/compiler/__tests__/fixtures/vl-parity/layer-value-def.json +29 -0
  109. package/src/compiler/__tests__/fixtures/vl-parity/legend-null.json +32 -0
  110. package/src/compiler/__tests__/fixtures/vl-parity/scheme.json +25 -0
  111. package/src/compiler/__tests__/fixtures/vl-parity/sort-by-value.json +19 -0
  112. package/src/compiler/__tests__/fixtures/vl-parity/theta-arc.json +19 -0
  113. package/src/compiler/__tests__/fixtures/vl-parity/title-subtitle.json +21 -0
  114. package/src/compiler/__tests__/fixtures/vl-parity/width-height.json +23 -0
  115. package/src/compiler/__tests__/normalize.test.ts +65 -1
  116. package/src/compiler/__tests__/validate-did-you-mean.test.ts +86 -0
  117. package/src/compiler/__tests__/validate-near-miss.test.ts +89 -0
  118. package/src/compiler/__tests__/validate.test.ts +156 -0
  119. package/src/compiler/__tests__/vl-parity.test.ts +68 -0
  120. package/src/compiler/a11y-warnings.ts +110 -0
  121. package/src/compiler/normalize.ts +150 -7
  122. package/src/compiler/types.ts +11 -0
  123. package/src/compiler/validate.ts +664 -18
  124. package/src/endpoint-labels/__tests__/compute.test.ts +88 -0
  125. package/src/endpoint-labels/compute.ts +40 -12
  126. package/src/endpoint-labels/format.ts +45 -15
  127. package/src/endpoint-labels/predict.ts +50 -36
  128. package/src/format/__tests__/field-format.test.ts +164 -0
  129. package/src/format/field-format.ts +27 -0
  130. package/src/geo/__tests__/compile-map.test.ts +621 -0
  131. package/src/geo/compile-map.ts +856 -0
  132. package/src/geo/join.ts +115 -0
  133. package/src/geo/projections.ts +45 -0
  134. package/src/geo/types.ts +24 -0
  135. package/src/graphs/__tests__/compile-graph.test.ts +25 -0
  136. package/src/graphs/compile-graph.ts +27 -18
  137. package/src/index.ts +28 -2
  138. package/src/layout/axes/ticks.ts +59 -10
  139. package/src/layout/axes.ts +30 -2
  140. package/src/layout/dimensions.ts +178 -95
  141. package/src/layout/facet.ts +14 -3
  142. package/src/layout/plan.ts +86 -35
  143. package/src/layout/scales.ts +132 -15
  144. package/src/legend/__tests__/continuous.test.ts +318 -0
  145. package/src/legend/__tests__/size.test.ts +348 -0
  146. package/src/legend/__tests__/suppression.test.ts +17 -1
  147. package/src/legend/compute.ts +126 -14
  148. package/src/legend/continuous.ts +327 -0
  149. package/src/legend/size.ts +407 -0
  150. package/src/legend/suppression.ts +8 -7
  151. package/src/legend/wrap.ts +8 -0
  152. package/src/sankey/compile-sankey.ts +31 -19
  153. package/src/tables/format-cells.ts +16 -7
  154. package/src/tilemap/__tests__/compile-tilemap.test.ts +39 -0
  155. package/src/tilemap/compile-tilemap.ts +24 -7
  156. package/src/tooltips/__tests__/compute.test.ts +2 -2
  157. package/src/tooltips/compute.ts +422 -41
  158. package/src/transforms/__tests__/conditional.test.ts +18 -0
  159. package/src/transforms/aggregate.ts +2 -1
@@ -20,6 +20,8 @@ import type {
20
20
  GraphSpec,
21
21
  LabelSpec,
22
22
  LayerSpec,
23
+ MapSpec,
24
+ MarkDef,
23
25
  SankeySpec,
24
26
  TableSpec,
25
27
  TileMapSpec,
@@ -30,6 +32,7 @@ import {
30
32
  isChartSpec,
31
33
  isGraphSpec,
32
34
  isLayerSpec,
35
+ isMapSpec,
33
36
  isSankeySpec,
34
37
  isTableSpec,
35
38
  isTileMapSpec,
@@ -37,6 +40,7 @@ import {
37
40
  resolveMarkType,
38
41
  } from '@opendata-ai/openchart-core';
39
42
  import type { NormalizedBarListSpec } from '../barlist/types';
43
+ import type { NormalizedMapSpec } from '../geo/types';
40
44
  import type { NormalizedSankeySpec } from '../sankey/types';
41
45
  import { STATE_CODE_SET } from '../tilemap/layout';
42
46
  import type { NormalizedTileMapSpec } from '../tilemap/types';
@@ -138,6 +142,9 @@ function inferEncodingTypes(encoding: Encoding, data: DataRow[], warnings: strin
138
142
 
139
143
  // Skip conditional value definitions - they don't have field/type at the top level
140
144
  if ('condition' in spec) continue;
145
+ // Skip bare value defs (no field). The sugar expansion moves these to
146
+ // mark-level properties before normalize runs on the compile path.
147
+ if (!('field' in spec)) continue;
141
148
 
142
149
  if (!spec.type) {
143
150
  const inferred = inferFieldType(data, spec.field);
@@ -168,13 +175,20 @@ function inferEncodingTypes(encoding: Encoding, data: DataRow[], warnings: strin
168
175
  function normalizeAnnotations(annotations: Annotation[] | undefined): Annotation[] {
169
176
  if (!annotations || annotations.length === 0) return [];
170
177
 
178
+ // The spec-sugar pass rewrites the deprecated `type: 'rule'` annotation
179
+ // alias to `'refline'` (with a warning) before validation/normalization
180
+ // ever runs, so by this point every annotation is in canonical form.
171
181
  return annotations.map((ann) => {
172
182
  switch (ann.type) {
173
183
  case 'text':
184
+ // Deliberately does NOT default fontSize/fontWeight. The annotation
185
+ // layer owns those (DEFAULT_ANNOTATION_FONT_SIZE, and the lede rule
186
+ // that promotes a subtitle-bearing primary line to bold). Stamping
187
+ // them here makes `annotation.fontWeight` always defined, so
188
+ // `resolveLedeFontWeight` can never fire and the size default can
189
+ // never apply — both features become dead code.
174
190
  return {
175
191
  ...ann,
176
- fontSize: ann.fontSize ?? 12,
177
- fontWeight: ann.fontWeight ?? 400,
178
192
  opacity: ann.opacity ?? 1,
179
193
  };
180
194
  case 'range':
@@ -184,10 +198,8 @@ function normalizeAnnotations(annotations: Annotation[] | undefined): Annotation
184
198
  fill: ann.fill ?? '#000000',
185
199
  };
186
200
  case 'refline':
187
- case 'rule':
188
201
  return {
189
202
  ...ann,
190
- type: 'refline' as const,
191
203
  style: ann.style ?? 'dashed',
192
204
  strokeWidth: ann.strokeWidth ?? 1,
193
205
  stroke: ann.stroke ?? '#666666',
@@ -254,10 +266,104 @@ function normalizeHighlight(encoding: Encoding, data: DataRow[], warnings: strin
254
266
  return highlight;
255
267
  }
256
268
 
269
+ // ---------------------------------------------------------------------------
270
+ // Series search normalization
271
+ // ---------------------------------------------------------------------------
272
+
273
+ /**
274
+ * Normalize `seriesSearch` to a config object, or undefined when disabled.
275
+ * Search needs a categorical color encoding to enumerate series values;
276
+ * warns and disables when there isn't one.
277
+ */
278
+ function normalizeSeriesSearch(
279
+ spec: ChartSpec,
280
+ encoding: Encoding,
281
+ warnings: string[],
282
+ ): import('@opendata-ai/openchart-core').SeriesSearchConfig | undefined {
283
+ if (!spec.seriesSearch) return undefined;
284
+ const color = encoding.color;
285
+ const hasCategoricalColor =
286
+ !!color &&
287
+ !('condition' in color) &&
288
+ 'field' in color &&
289
+ !!color.field &&
290
+ color.type !== 'quantitative';
291
+ if (!hasCategoricalColor) {
292
+ warnings.push(
293
+ '[openchart] seriesSearch requires a categorical color encoding (encoding.color.field with a nominal/ordinal type); ignoring seriesSearch.',
294
+ );
295
+ return undefined;
296
+ }
297
+ return typeof spec.seriesSearch === 'object' ? { ...spec.seriesSearch } : {};
298
+ }
299
+
300
+ // ---------------------------------------------------------------------------
301
+ // You draw it normalization
302
+ // ---------------------------------------------------------------------------
303
+
304
+ /**
305
+ * Normalize `youDrawIt` to a config object with defaults filled in, or
306
+ * undefined when disabled. Mark type, single-series, and `from` presence are
307
+ * enforced by validateSpec before normalize runs; this only fills defaults.
308
+ */
309
+ function normalizeYouDrawIt(
310
+ spec: ChartSpec,
311
+ ): import('@opendata-ai/openchart-core').YouDrawItConfig | undefined {
312
+ if (!spec.youDrawIt) return undefined;
313
+ return {
314
+ prompt: 'Draw your guess',
315
+ revealLabel: 'Show me',
316
+ ...spec.youDrawIt,
317
+ };
318
+ }
319
+
257
320
  // ---------------------------------------------------------------------------
258
321
  // Spec-level normalization
259
322
  // ---------------------------------------------------------------------------
260
323
 
324
+ /**
325
+ * Beeswarm point budget. Past this count the dodge layout still resolves
326
+ * every collision, but the swarm piles into a solid band that reads no
327
+ * better than an overplotted strip, and layout cost keeps growing.
328
+ */
329
+ const BEESWARM_POINT_BUDGET = 2000;
330
+
331
+ /**
332
+ * Warn when a parliament `majorityLine.seats` override lands outside the chamber
333
+ * (below 1 or above the seat total). The mark falls back to a simple majority in
334
+ * that case, so this is a non-fatal warning routed through the shared warnings
335
+ * array (dedup + single emit boundary) rather than a raw console.warn in mark
336
+ * computation. Only the object form of majorityLine carries a seat count.
337
+ */
338
+ function warnParliamentMajorityRange(
339
+ markDef: MarkDef,
340
+ encoding: Encoding,
341
+ data: DataRow[],
342
+ warnings: string[],
343
+ ): void {
344
+ const majorityLine = markDef.majorityLine;
345
+ if (!majorityLine || typeof majorityLine !== 'object') return;
346
+ const requested = majorityLine.seats;
347
+ if (requested === undefined) return;
348
+
349
+ const valueField = encoding.theta?.field ?? encoding.y?.field;
350
+ if (!valueField) return;
351
+
352
+ let totalSeats = 0;
353
+ for (const row of data) {
354
+ const v = Number(row[valueField]);
355
+ if (Number.isFinite(v)) totalSeats += v;
356
+ }
357
+ if (totalSeats <= 0) return;
358
+
359
+ if (!Number.isFinite(requested) || requested < 1 || requested > totalSeats) {
360
+ const fallback = Math.floor(totalSeats / 2) + 1;
361
+ warnings.push(
362
+ `[openchart] parliament mark.majorityLine.seats (${requested}) is outside the valid range 1..${totalSeats}; using the default majority threshold of ${fallback}.`,
363
+ );
364
+ }
365
+ }
366
+
261
367
  function normalizeChartSpec(spec: ChartSpec, warnings: string[]): NormalizedChartSpec {
262
368
  const encoding = inferEncodingTypes(spec.encoding, spec.data, warnings);
263
369
  const markType = resolveMarkType(spec.mark);
@@ -276,6 +382,16 @@ function normalizeChartSpec(spec: ChartSpec, warnings: string[]): NormalizedChar
276
382
  );
277
383
  }
278
384
 
385
+ if (markType === 'beeswarm' && spec.data.length > BEESWARM_POINT_BUDGET) {
386
+ warnings.push(
387
+ `[openchart] beeswarm received ${spec.data.length} data points, past the ~${BEESWARM_POINT_BUDGET}-point budget where individual dots stop being readable and the swarm collapses into a solid band. Sample the data down, or summarize the distribution with mark: 'tick' (strip plot) or a binned histogram (bin transform + mark: 'bar').`,
388
+ );
389
+ }
390
+
391
+ if (markType === 'parliament') {
392
+ warnParliamentMajorityRange(markDef, encoding, spec.data, warnings);
393
+ }
394
+
279
395
  return {
280
396
  markType,
281
397
  markDef,
@@ -283,6 +399,8 @@ function normalizeChartSpec(spec: ChartSpec, warnings: string[]): NormalizedChar
283
399
  encoding,
284
400
  chrome: normalizeChrome(spec.chrome),
285
401
  metrics: spec.metrics,
402
+ seriesSearch: normalizeSeriesSearch(spec, encoding, warnings),
403
+ youDrawIt: normalizeYouDrawIt(spec),
286
404
  annotations: normalizeAnnotations(spec.annotations),
287
405
  labels: normalizeLabels(spec.labels),
288
406
  legend: spec.legend,
@@ -298,6 +416,7 @@ function normalizeChartSpec(spec: ChartSpec, warnings: string[]): NormalizedChar
298
416
  seriesStyles: spec.seriesStyles ?? {},
299
417
  watermark: spec.watermark ?? true,
300
418
  highlight: normalizeHighlight(encoding, spec.data, warnings),
419
+ a11y: spec.a11y,
301
420
  display,
302
421
  resolve: spec.resolve,
303
422
  // Default empty userExplicit; compileChart overwrites this with the real
@@ -358,7 +477,7 @@ function normalizeSankeySpec(spec: SankeySpec, _warnings: string[]): NormalizedS
358
477
  };
359
478
  }
360
479
 
361
- function normalizeGraphSpec(spec: GraphSpec, _warnings: string[]): NormalizedGraphSpec {
480
+ function normalizeGraphSpec(spec: GraphSpec): NormalizedGraphSpec {
362
481
  // Default layout with chargeStrength and linkDistance
363
482
  const defaultLayout = {
364
483
  type: 'force' as const,
@@ -458,6 +577,27 @@ function normalizeTileMapSpec(spec: TileMapSpec, warnings: string[]): Normalized
458
577
  };
459
578
  }
460
579
 
580
+ function normalizeMapSpec(spec: MapSpec, _warnings: string[]): NormalizedMapSpec {
581
+ return {
582
+ type: 'map',
583
+ geo: {
584
+ features: spec.geo.features,
585
+ idField: spec.geo.idField ?? 'id',
586
+ projection: spec.geo.projection ?? 'albersUsa',
587
+ focus: spec.geo.focus ?? null,
588
+ },
589
+ data: spec.data,
590
+ encoding: spec.encoding,
591
+ chrome: normalizeChrome(spec.chrome),
592
+ legend: spec.legend,
593
+ theme: spec.theme ?? {},
594
+ darkMode: spec.darkMode ?? 'off',
595
+ watermark: spec.watermark ?? true,
596
+ animation: spec.animation,
597
+ valueFormat: spec.valueFormat,
598
+ };
599
+ }
600
+
461
601
  function normalizeBarListSpec(spec: BarListSpec, _warnings: string[]): NormalizedBarListSpec {
462
602
  return {
463
603
  type: 'barlist',
@@ -504,7 +644,7 @@ export function normalizeSpec(spec: VizSpec, warnings: string[] = []): Normalize
504
644
  return normalizeTableSpec(spec, warnings);
505
645
  }
506
646
  if (isGraphSpec(spec)) {
507
- return normalizeGraphSpec(spec, warnings);
647
+ return normalizeGraphSpec(spec);
508
648
  }
509
649
  if (isSankeySpec(spec)) {
510
650
  return normalizeSankeySpec(spec, warnings);
@@ -512,12 +652,15 @@ export function normalizeSpec(spec: VizSpec, warnings: string[] = []): Normalize
512
652
  if (isTileMapSpec(spec)) {
513
653
  return normalizeTileMapSpec(spec, warnings);
514
654
  }
655
+ if (isMapSpec(spec)) {
656
+ return normalizeMapSpec(spec, warnings);
657
+ }
515
658
  if (isBarListSpec(spec)) {
516
659
  return normalizeBarListSpec(spec, warnings);
517
660
  }
518
661
  // Should never happen after validation
519
662
  throw new Error(
520
- `Unknown spec shape. Expected mark (chart), layer, type: 'table', type: 'graph', type: 'sankey', type: 'tilemap', or type: 'barlist'.`,
663
+ `Unknown spec shape. Expected mark (chart), layer, type: 'table', type: 'graph', type: 'sankey', type: 'tilemap', type: 'map', or type: 'barlist'.`,
521
664
  );
522
665
  }
523
666
 
@@ -30,6 +30,7 @@ import type {
30
30
  ThemeConfig,
31
31
  } from '@opendata-ai/openchart-core';
32
32
  import type { NormalizedBarListSpec } from '../barlist/types';
33
+ import type { NormalizedMapSpec } from '../geo/types';
33
34
  import type { NormalizedSankeySpec } from '../sankey/types';
34
35
  import type { NormalizedTileMapSpec } from '../tilemap/types';
35
36
 
@@ -107,6 +108,13 @@ export interface NormalizedChartSpec {
107
108
  chrome: NormalizedChrome;
108
109
  /** Optional KPI metric cells, passed through unchanged. */
109
110
  metrics?: import('@opendata-ai/openchart-core').Metric[];
111
+ /**
112
+ * Searchable series highlight config. Present only when `seriesSearch` is
113
+ * enabled AND the spec has a categorical color encoding to search over.
114
+ */
115
+ seriesSearch?: import('@opendata-ai/openchart-core').SeriesSearchConfig;
116
+ /** Resolved "you draw it" config with defaults filled in. Present only when `youDrawIt` is enabled. */
117
+ youDrawIt?: import('@opendata-ai/openchart-core').YouDrawItConfig;
110
118
  annotations: Annotation[];
111
119
  /** Normalized label configuration with defaults applied. density, format, and prefix are always set; offsets and color stay optional. */
112
120
  labels: Required<Pick<LabelConfig, 'density' | 'format' | 'prefix'>> &
@@ -126,6 +134,8 @@ export interface NormalizedChartSpec {
126
134
  hiddenSeries: string[];
127
135
  /** Per-series visual style overrides. */
128
136
  seriesStyles: Record<string, import('@opendata-ai/openchart-core').SeriesStyle>;
137
+ /** Author accessibility overrides (alt-text description, aria-hidden opt-out). */
138
+ a11y?: import('@opendata-ai/openchart-core').A11yConfig;
129
139
  /** Display mode controlling chrome/axes/legend stripping. Defaults to `'full'`. */
130
140
  display: Display;
131
141
  /** Resolve configuration for independent/shared scales in faceted charts. */
@@ -184,6 +194,7 @@ export type NormalizedSpec =
184
194
  | NormalizedGraphSpec
185
195
  | NormalizedSankeySpec
186
196
  | NormalizedTileMapSpec
197
+ | NormalizedMapSpec
187
198
  | NormalizedBarListSpec;
188
199
 
189
200
  // ---------------------------------------------------------------------------