@opendata-ai/openchart-core 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.
- package/dist/index.d.ts +1154 -119
- package/dist/index.js +530 -41
- 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 +8957 -0
- package/schema/table.schema.json +861 -0
- package/schema/vizspec.schema.json +17694 -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/index.ts +2 -0
- package/src/responsive/metrics.ts +74 -9
- 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 +197 -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 +115 -100
- 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 +12 -0
- package/src/types/index.ts +39 -3
- package/src/types/layout.ts +414 -8
- package/src/types/schema-roots.ts +32 -0
- package/src/types/spec.ts +643 -84
- package/src/types/table.ts +3 -2
package/src/types/layout.ts
CHANGED
|
@@ -127,6 +127,12 @@ export interface AxisTick {
|
|
|
127
127
|
position: number;
|
|
128
128
|
/** Formatted label string for display. */
|
|
129
129
|
label: string;
|
|
130
|
+
/**
|
|
131
|
+
* The untruncated label, set only when `label` was shortened with an ellipsis
|
|
132
|
+
* to fit the rotated-tick reservation. Renderers should surface this as the
|
|
133
|
+
* tick's accessible/tooltip text so the full category name is never lost.
|
|
134
|
+
*/
|
|
135
|
+
fullLabel?: string;
|
|
130
136
|
/** Secondary label text from axis.labelField. */
|
|
131
137
|
subtitle?: string;
|
|
132
138
|
}
|
|
@@ -190,6 +196,25 @@ export interface AxisLayout {
|
|
|
190
196
|
// Marks (data visual elements)
|
|
191
197
|
// ---------------------------------------------------------------------------
|
|
192
198
|
|
|
199
|
+
/** The four built-in fill pattern shapes for series reinforcement. */
|
|
200
|
+
export type FillPatternType = 'diagonal' | 'dot' | 'crosshatch' | 'vertical';
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* A resolved per-mark fill pattern (engine output for `mark.fillPattern: 'auto'`).
|
|
204
|
+
*
|
|
205
|
+
* The renderer builds one SVG `<pattern>` per unique (type, base, line)
|
|
206
|
+
* combination: a tile of `base` color overlaid with `line`-colored pattern
|
|
207
|
+
* geometry. Marks referencing the same resolved pattern share one def.
|
|
208
|
+
*/
|
|
209
|
+
export interface ResolvedFillPattern {
|
|
210
|
+
/** Pattern shape assigned to this mark's series. */
|
|
211
|
+
type: FillPatternType;
|
|
212
|
+
/** Base tile color: the series' solid color. */
|
|
213
|
+
base: string;
|
|
214
|
+
/** Pattern line/dot color, contrast-picked against `base`. */
|
|
215
|
+
line: string;
|
|
216
|
+
}
|
|
217
|
+
|
|
193
218
|
/** Accessibility attributes for a mark. */
|
|
194
219
|
export interface MarkAria {
|
|
195
220
|
/** ARIA label for the mark. Optional when `decorative: true` — decorative
|
|
@@ -277,6 +302,8 @@ export interface AreaMark {
|
|
|
277
302
|
interpolate?: string;
|
|
278
303
|
/** Fill color or gradient. */
|
|
279
304
|
fill: string | GradientDef;
|
|
305
|
+
/** Resolved fill pattern. Present only when `mark.fillPattern: 'auto'` assigned one. */
|
|
306
|
+
pattern?: ResolvedFillPattern;
|
|
280
307
|
/** Fill opacity. */
|
|
281
308
|
fillOpacity: number;
|
|
282
309
|
/** Optional stroke for the top boundary. */
|
|
@@ -323,6 +350,8 @@ export interface RectMark {
|
|
|
323
350
|
height: number;
|
|
324
351
|
/** Fill color or gradient. */
|
|
325
352
|
fill: string | GradientDef;
|
|
353
|
+
/** Resolved fill pattern. Present only when `mark.fillPattern: 'auto'` assigned one. */
|
|
354
|
+
pattern?: ResolvedFillPattern;
|
|
326
355
|
/** Stroke color. */
|
|
327
356
|
stroke?: string;
|
|
328
357
|
/** Stroke width. */
|
|
@@ -376,6 +405,8 @@ export interface ArcMark {
|
|
|
376
405
|
endAngle: number;
|
|
377
406
|
/** Fill color or gradient. */
|
|
378
407
|
fill: string | GradientDef;
|
|
408
|
+
/** Resolved fill pattern. Present only when `mark.fillPattern: 'auto'` assigned one. */
|
|
409
|
+
pattern?: ResolvedFillPattern;
|
|
379
410
|
/** Stroke color (usually white for slice separation). */
|
|
380
411
|
stroke: string;
|
|
381
412
|
/** Stroke width. */
|
|
@@ -434,10 +465,14 @@ export interface TextMarkLayout {
|
|
|
434
465
|
type: 'textMark';
|
|
435
466
|
/** Stable identity key for data-update transitions. */
|
|
436
467
|
key?: string;
|
|
437
|
-
/** X position. */
|
|
468
|
+
/** X position, including any `dx` offset. */
|
|
438
469
|
x: number;
|
|
439
|
-
/** Y position. */
|
|
470
|
+
/** Y position, including any `dy` offset. */
|
|
440
471
|
y: number;
|
|
472
|
+
/** Data-space anchor before `dx` was applied. Set only when the mark is offset. */
|
|
473
|
+
anchorX?: number;
|
|
474
|
+
/** Data-space anchor before `dy` was applied. Set only when the mark is offset. */
|
|
475
|
+
anchorY?: number;
|
|
441
476
|
/** Text content to display. */
|
|
442
477
|
text: string;
|
|
443
478
|
/** Fill color. */
|
|
@@ -450,6 +485,11 @@ export interface TextMarkLayout {
|
|
|
450
485
|
fontFamily?: string;
|
|
451
486
|
/** Horizontal text alignment. */
|
|
452
487
|
textAnchor: 'start' | 'middle' | 'end';
|
|
488
|
+
/**
|
|
489
|
+
* Vertical baseline. Omit for the SVG default (alphabetic), which the calendar
|
|
490
|
+
* and parliament marks rely on — they hand-compute baseline-relative offsets.
|
|
491
|
+
*/
|
|
492
|
+
dominantBaseline?: 'auto' | 'hanging' | 'central' | 'text-after-edge';
|
|
453
493
|
/** Rotation angle in degrees. */
|
|
454
494
|
angle?: number;
|
|
455
495
|
/** Original data row. */
|
|
@@ -574,6 +614,13 @@ export interface ResolvedLabel {
|
|
|
574
614
|
stroke: string;
|
|
575
615
|
/** Connector style: straight line, curved arrow, or vertical drop-line through the data point. */
|
|
576
616
|
style: 'straight' | 'curve' | 'drop-line';
|
|
617
|
+
/** Whether to draw an arrowhead at the data-point end. */
|
|
618
|
+
arrow: boolean;
|
|
619
|
+
/**
|
|
620
|
+
* Which edge of the label block the connector leaves from. Renderers use it
|
|
621
|
+
* to shape the curve's control point. Internal; not part of the spec.
|
|
622
|
+
*/
|
|
623
|
+
exit?: 'horizontal' | 'vertical';
|
|
577
624
|
};
|
|
578
625
|
/** Background color behind the label text. */
|
|
579
626
|
background?: string;
|
|
@@ -595,6 +642,16 @@ export interface ResolvedAnnotation {
|
|
|
595
642
|
type: 'text' | 'range' | 'refline';
|
|
596
643
|
/** Stable identifier from the spec annotation, for selection/edit callbacks. */
|
|
597
644
|
id?: string;
|
|
645
|
+
/**
|
|
646
|
+
* Index of the originating annotation in `spec.annotations`.
|
|
647
|
+
*
|
|
648
|
+
* The resolved array is a *filtered* view of the spec array -- an annotation
|
|
649
|
+
* whose position falls outside the scale domain resolves to nothing and is
|
|
650
|
+
* dropped -- so a resolved array index is NOT a spec index. Anything that has
|
|
651
|
+
* to reach back to the authored annotation (thinning's priority/responsive
|
|
652
|
+
* lookup, faceted footnote numbering) must key on this.
|
|
653
|
+
*/
|
|
654
|
+
specIndex?: number;
|
|
598
655
|
/** Label text (if any). */
|
|
599
656
|
label?: ResolvedLabel;
|
|
600
657
|
/** For range: the highlighted rectangle in pixel coordinates. */
|
|
@@ -614,8 +671,9 @@ export interface ResolvedAnnotation {
|
|
|
614
671
|
/** Z-index for render ordering. Higher values render on top. */
|
|
615
672
|
zIndex?: number;
|
|
616
673
|
/**
|
|
617
|
-
* For text annotations:
|
|
618
|
-
* data
|
|
674
|
+
* For text annotations: the endpoint marker drawn at the data point.
|
|
675
|
+
* Coordinates sit on the data point itself (plus any `connectorOffset.to`),
|
|
676
|
+
* not on the pulled-back `label.connector.to`.
|
|
619
677
|
*/
|
|
620
678
|
dot?: {
|
|
621
679
|
x: number;
|
|
@@ -671,8 +729,22 @@ export interface LegendEntry {
|
|
|
671
729
|
overflow?: boolean;
|
|
672
730
|
}
|
|
673
731
|
|
|
732
|
+
/** The encoding channel a legend keys. */
|
|
733
|
+
export type LegendChannel = 'color' | 'size';
|
|
734
|
+
|
|
674
735
|
/** Base legend layout fields shared by all legend types. */
|
|
675
736
|
export interface BaseLegendLayout {
|
|
737
|
+
/**
|
|
738
|
+
* Which encoding channel this legend keys. Omitted means `'color'` (every
|
|
739
|
+
* legend was a color legend before size legends existed).
|
|
740
|
+
*
|
|
741
|
+
* This is the identity that makes plural legends safe: click-to-toggle-series
|
|
742
|
+
* must fire for color entries and never for size circles, and selection/drag
|
|
743
|
+
* must be able to tell two legends apart. Without it, `.oc-legend` and
|
|
744
|
+
* `data-legend-index` are ambiguous across legends and the DOM queries that
|
|
745
|
+
* read them silently pick whichever comes first.
|
|
746
|
+
*/
|
|
747
|
+
channel?: LegendChannel;
|
|
676
748
|
/** Where the legend is positioned relative to the chart area. */
|
|
677
749
|
position: 'top' | 'right' | 'bottom' | 'bottom-right' | 'inline';
|
|
678
750
|
/** Bounding box for the legend (pixel coordinates). */
|
|
@@ -733,8 +805,103 @@ export interface GradientLegendLayout extends BaseLegendLayout {
|
|
|
733
805
|
maxLabel: string;
|
|
734
806
|
}
|
|
735
807
|
|
|
736
|
-
/**
|
|
737
|
-
export
|
|
808
|
+
/** A positioned value label on a continuous/binned color legend. */
|
|
809
|
+
export interface ContinuousLegendTick {
|
|
810
|
+
/** The data value this label marks. */
|
|
811
|
+
value: number;
|
|
812
|
+
/** Formatted label text (channel format applied). */
|
|
813
|
+
label: string;
|
|
814
|
+
/** Label x position (pixel coordinates). */
|
|
815
|
+
x: number;
|
|
816
|
+
/** Horizontal text anchor for the label. */
|
|
817
|
+
anchor: 'start' | 'middle' | 'end';
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/** A discrete class swatch in a binned continuous legend. */
|
|
821
|
+
export interface ContinuousLegendBin {
|
|
822
|
+
/** Swatch x position (pixel coordinates). */
|
|
823
|
+
x: number;
|
|
824
|
+
/** Swatch width in pixels. */
|
|
825
|
+
width: number;
|
|
826
|
+
/** Fill color. */
|
|
827
|
+
color: string;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Continuous color legend for quantitative color scales on charts.
|
|
832
|
+
*
|
|
833
|
+
* Two rendering modes, resolved from the color channel's scale type:
|
|
834
|
+
* - `gradient`: a single gradient-filled bar with min/max labels (plus a
|
|
835
|
+
* midpoint label at the neutral value for diverging ramps).
|
|
836
|
+
* - `binned`: a contiguous swatch row (quantile/quantize/threshold scales)
|
|
837
|
+
* with boundary value labels between swatches at the class breaks.
|
|
838
|
+
*/
|
|
839
|
+
export interface ContinuousLegendLayout extends BaseLegendLayout {
|
|
840
|
+
/** Discriminant for legend type. */
|
|
841
|
+
type: 'continuous';
|
|
842
|
+
/** Rendering mode: gradient bar or binned swatch row. */
|
|
843
|
+
mode: 'gradient' | 'binned';
|
|
844
|
+
/** The color bar rectangle (pixel coordinates). */
|
|
845
|
+
bar: Rect;
|
|
846
|
+
/** Gradient color stops (empty in binned mode). */
|
|
847
|
+
colorStops: GradientColorStop[];
|
|
848
|
+
/** Class swatches, left to right (empty in gradient mode). */
|
|
849
|
+
bins: ContinuousLegendBin[];
|
|
850
|
+
/** Value labels rendered below the bar. */
|
|
851
|
+
ticks: ContinuousLegendTick[];
|
|
852
|
+
/** Text baseline y for the value labels (pixel coordinates). */
|
|
853
|
+
labelY: number;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* One graduated circle in a size legend: a representative value from the size
|
|
858
|
+
* scale's domain, drawn at the radius that value actually resolves to.
|
|
859
|
+
*/
|
|
860
|
+
export interface SizeLegendCircle {
|
|
861
|
+
/** The data value this circle stands for. */
|
|
862
|
+
value: number;
|
|
863
|
+
/** Formatted label text. */
|
|
864
|
+
label: string;
|
|
865
|
+
/** Radius in pixels -- the *same* scale the marks use, never a re-derivation. */
|
|
866
|
+
radius: number;
|
|
867
|
+
/** Center x, relative to the legend bounds. */
|
|
868
|
+
cx: number;
|
|
869
|
+
/** Center y, relative to the legend bounds. Circles sit on a common baseline. */
|
|
870
|
+
cy: number;
|
|
871
|
+
/** Label baseline y, relative to the legend bounds. */
|
|
872
|
+
labelY: number;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Size legend: graduated circles keying a quantitative `size` encoding.
|
|
877
|
+
*
|
|
878
|
+
* The circles are drawn nested (concentric, sharing a bottom edge) rather than
|
|
879
|
+
* side by side -- the newsroom convention, and it makes the *ratio* between
|
|
880
|
+
* magnitudes legible instead of just their order.
|
|
881
|
+
*
|
|
882
|
+
* The keyed values come from the scale's DOMAIN, not the data extent. The size
|
|
883
|
+
* scale clamps, so with an explicit `scale.domain` every datum past `domain[1]`
|
|
884
|
+
* renders at max radius; keying the data extent would imply the biggest circle
|
|
885
|
+
* equals the biggest datum when it may not.
|
|
886
|
+
*/
|
|
887
|
+
export interface SizeLegendLayout extends BaseLegendLayout {
|
|
888
|
+
/** Discriminant for legend type. */
|
|
889
|
+
type: 'size';
|
|
890
|
+
/** Graduated circles, smallest first. */
|
|
891
|
+
circles: SizeLegendCircle[];
|
|
892
|
+
/** Stroke color for the circle outlines. */
|
|
893
|
+
stroke: string;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Resolved legend layout: categorical (swatches), gradient (tilemap bar),
|
|
898
|
+
* continuous (chart color bar), or size (graduated circles).
|
|
899
|
+
*/
|
|
900
|
+
export type LegendLayout =
|
|
901
|
+
| CategoricalLegendLayout
|
|
902
|
+
| GradientLegendLayout
|
|
903
|
+
| ContinuousLegendLayout
|
|
904
|
+
| SizeLegendLayout;
|
|
738
905
|
|
|
739
906
|
// ---------------------------------------------------------------------------
|
|
740
907
|
// Endpoint labels (right-side per-series column for line/area charts)
|
|
@@ -826,7 +993,7 @@ export interface TooltipContent {
|
|
|
826
993
|
|
|
827
994
|
/** Accessibility metadata for the entire visualization. */
|
|
828
995
|
export interface A11yMetadata {
|
|
829
|
-
/**
|
|
996
|
+
/** Alt text describing the visualization: the author's `a11y.description` / `description` when set, auto-generated otherwise. */
|
|
830
997
|
altText: string;
|
|
831
998
|
/** Tabular data fallback for screen readers. Each inner array is a row. */
|
|
832
999
|
dataTableFallback: unknown[][];
|
|
@@ -834,6 +1001,13 @@ export interface A11yMetadata {
|
|
|
834
1001
|
role: string;
|
|
835
1002
|
/** Whether the visualization is keyboard-navigable. */
|
|
836
1003
|
keyboardNavigable: boolean;
|
|
1004
|
+
/**
|
|
1005
|
+
* Hide the visualization from assistive technology (`aria-hidden="true"`,
|
|
1006
|
+
* no screen-reader table, no keyboard mark navigation). Optional because
|
|
1007
|
+
* only chart compilation sets it, and only on author opt-out via
|
|
1008
|
+
* `a11y.hidden`.
|
|
1009
|
+
*/
|
|
1010
|
+
hidden?: boolean;
|
|
837
1011
|
}
|
|
838
1012
|
|
|
839
1013
|
// ---------------------------------------------------------------------------
|
|
@@ -900,6 +1074,90 @@ export interface ResolvedMetricBar {
|
|
|
900
1074
|
cells: ResolvedMetricCell[];
|
|
901
1075
|
}
|
|
902
1076
|
|
|
1077
|
+
// ---------------------------------------------------------------------------
|
|
1078
|
+
// Series search (resolved)
|
|
1079
|
+
// ---------------------------------------------------------------------------
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Reserved band for the series search input (`seriesSearch`). The band is
|
|
1083
|
+
* empty SVG space between the chrome/metrics block and the top legend; the
|
|
1084
|
+
* vanilla adapter overlays an absolutely-positioned DOM combobox aligned to
|
|
1085
|
+
* this rect, so mounting it never changes the container's size.
|
|
1086
|
+
*/
|
|
1087
|
+
export interface ResolvedSeriesSearch {
|
|
1088
|
+
/** Band left x in layout coordinates. */
|
|
1089
|
+
x: number;
|
|
1090
|
+
/** Band top y in layout coordinates. */
|
|
1091
|
+
y: number;
|
|
1092
|
+
/** Band width. */
|
|
1093
|
+
width: number;
|
|
1094
|
+
/** Input row height (the reservation adds a gap below this). */
|
|
1095
|
+
height: number;
|
|
1096
|
+
/** Resolved input placeholder text. */
|
|
1097
|
+
placeholder: string;
|
|
1098
|
+
/** Distinct color-channel values available for search, in data order. */
|
|
1099
|
+
values: string[];
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// ---------------------------------------------------------------------------
|
|
1103
|
+
// You draw it (resolved)
|
|
1104
|
+
// ---------------------------------------------------------------------------
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* One x-sample the reader's drawing snaps to: a pixel x position paired with
|
|
1108
|
+
* its data-x value. `xValue` is the value reported by `onReveal`; it falls
|
|
1109
|
+
* back to the pixel x when the data value can't be recovered.
|
|
1110
|
+
*/
|
|
1111
|
+
export interface YouDrawItSample {
|
|
1112
|
+
/** Pixel x position within the chart area. */
|
|
1113
|
+
px: number;
|
|
1114
|
+
/** Data-coordinate x value at this sample (from the target line's data). */
|
|
1115
|
+
xValue: string | number;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Linear y pixel-to-data anchors, so the vanilla layer can map a drawn pixel
|
|
1120
|
+
* y back to a data value for `onReveal` without holding the scale object.
|
|
1121
|
+
* Present only when the y scale is invertible (continuous scales).
|
|
1122
|
+
*/
|
|
1123
|
+
export interface YouDrawItYInvert {
|
|
1124
|
+
/** Top pixel of the drawing area. */
|
|
1125
|
+
topPixel: number;
|
|
1126
|
+
/** Bottom pixel of the drawing area. */
|
|
1127
|
+
bottomPixel: number;
|
|
1128
|
+
/** Data value at the top pixel. */
|
|
1129
|
+
topData: number;
|
|
1130
|
+
/** Data value at the bottom pixel. */
|
|
1131
|
+
bottomData: number;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Resolved geometry and config for the "you draw it" interactive format
|
|
1136
|
+
* (`youDrawIt`). The vanilla adapter uses this to render the hatched drawing
|
|
1137
|
+
* region, capture pointer input, and mask/reveal the real line. Present only
|
|
1138
|
+
* when the spec enables `youDrawIt` on a valid single-series line chart.
|
|
1139
|
+
*/
|
|
1140
|
+
export interface ResolvedYouDrawIt {
|
|
1141
|
+
/** Pixel x position of `from` within the chart area (drawing starts here). */
|
|
1142
|
+
fromX: number;
|
|
1143
|
+
/** The chart drawing area, for clamping pointer input and sizing the hatch region. */
|
|
1144
|
+
area: Rect;
|
|
1145
|
+
/** X samples (pixel + data value) at or after `from`, ascending by pixel x. Drawing snaps to these. */
|
|
1146
|
+
samples: YouDrawItSample[];
|
|
1147
|
+
/** Resolved prompt text for the hatched region. */
|
|
1148
|
+
prompt: string;
|
|
1149
|
+
/** Resolved skip-to-reveal button label. */
|
|
1150
|
+
revealLabel: string;
|
|
1151
|
+
/** Stroke color of the target line (the reader's guess uses a distinct pen style, but shares the palette for continuity). */
|
|
1152
|
+
lineColor: string;
|
|
1153
|
+
/** seriesKey of the target line mark, so the vanilla layer can find its DOM element. Undefined for a single-series line with no color encoding. */
|
|
1154
|
+
targetSeriesKey?: string;
|
|
1155
|
+
/** Pixel-to-data y anchors for reporting the guess in data coordinates. Absent when the y scale isn't invertible. */
|
|
1156
|
+
yInvert?: YouDrawItYInvert;
|
|
1157
|
+
/** Optional comparison line, resolved to pixel points parallel to the target line's points. */
|
|
1158
|
+
comparisonPoints?: Point[];
|
|
1159
|
+
}
|
|
1160
|
+
|
|
903
1161
|
// ---------------------------------------------------------------------------
|
|
904
1162
|
// ChartLayout (the main engine output for charts)
|
|
905
1163
|
// ---------------------------------------------------------------------------
|
|
@@ -951,6 +1209,10 @@ export interface ChartLayout {
|
|
|
951
1209
|
chrome: ResolvedChrome;
|
|
952
1210
|
/** Resolved KPI metric bar. Present only when spec.metrics is supplied and fits. */
|
|
953
1211
|
metrics?: ResolvedMetricBar;
|
|
1212
|
+
/** Reserved series-search band. Present only when spec.seriesSearch is enabled. */
|
|
1213
|
+
seriesSearch?: ResolvedSeriesSearch;
|
|
1214
|
+
/** Resolved "you draw it" config. Present only when spec.youDrawIt is enabled and valid. */
|
|
1215
|
+
youDrawIt?: ResolvedYouDrawIt;
|
|
954
1216
|
/** Resolved axis layouts. */
|
|
955
1217
|
axes: {
|
|
956
1218
|
x?: AxisLayout;
|
|
@@ -962,8 +1224,22 @@ export interface ChartLayout {
|
|
|
962
1224
|
marks: Mark[];
|
|
963
1225
|
/** Resolved annotations with pixel positions. */
|
|
964
1226
|
annotations: ResolvedAnnotation[];
|
|
965
|
-
/**
|
|
1227
|
+
/**
|
|
1228
|
+
* Primary legend (the color legend). Kept as a singular slot: it is what every
|
|
1229
|
+
* existing consumer reads, and a chart's legend is a color legend unless it
|
|
1230
|
+
* says otherwise.
|
|
1231
|
+
*/
|
|
966
1232
|
legend: LegendLayout;
|
|
1233
|
+
/**
|
|
1234
|
+
* Every legend on the chart, in render order -- the color legend plus, when a
|
|
1235
|
+
* quantitative `size` channel is encoded, a size legend.
|
|
1236
|
+
*
|
|
1237
|
+
* `legend` is `legends[0]` when a color legend exists. Consumers that reserve
|
|
1238
|
+
* space or hit-test **must** iterate this array: a bubble chart keys both
|
|
1239
|
+
* continent (color) and population (size), and reserving margin for only the
|
|
1240
|
+
* first leaves the second drawing on top of the plot.
|
|
1241
|
+
*/
|
|
1242
|
+
legends: LegendLayout[];
|
|
967
1243
|
/**
|
|
968
1244
|
* Right-side endpoint labels column for multi-series line/area charts.
|
|
969
1245
|
* Empty `entries` means the column is suppressed (single-series, opt-out, or
|
|
@@ -1429,6 +1705,106 @@ export interface TileMapLayout {
|
|
|
1429
1705
|
measureText: MeasureTextFn;
|
|
1430
1706
|
}
|
|
1431
1707
|
|
|
1708
|
+
// ---------------------------------------------------------------------------
|
|
1709
|
+
// MapLayout (engine output for map visualizations)
|
|
1710
|
+
// ---------------------------------------------------------------------------
|
|
1711
|
+
|
|
1712
|
+
/** A structured compile warning with a code and context. */
|
|
1713
|
+
export interface CompileWarning {
|
|
1714
|
+
code: string;
|
|
1715
|
+
message: string;
|
|
1716
|
+
context?: Record<string, unknown>;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/** Resolved focus target for map camera framing. */
|
|
1720
|
+
export interface MapFocusLayout {
|
|
1721
|
+
target: { x: number; y: number; width: number; height: number; padding: number };
|
|
1722
|
+
ids: Array<string | number>;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
/** A resolved map feature mark with computed SVG path and fill. */
|
|
1726
|
+
export interface MapFeatureMark {
|
|
1727
|
+
type: 'map-feature';
|
|
1728
|
+
/** SVG path `d` attribute for this feature's shape. */
|
|
1729
|
+
path: string;
|
|
1730
|
+
/** CSS fill color. */
|
|
1731
|
+
fill: string;
|
|
1732
|
+
/** CSS stroke color (border). */
|
|
1733
|
+
stroke: string;
|
|
1734
|
+
/** Stroke width in px. */
|
|
1735
|
+
strokeWidth: number;
|
|
1736
|
+
/** Feature ID (from TopoJSON). */
|
|
1737
|
+
id: string | number;
|
|
1738
|
+
/** Feature name (from properties, if available). */
|
|
1739
|
+
name?: string;
|
|
1740
|
+
/** Original joined data row (null if no data matched this feature). */
|
|
1741
|
+
data: Record<string, unknown> | null;
|
|
1742
|
+
/** Accessibility attributes. */
|
|
1743
|
+
aria: MarkAria;
|
|
1744
|
+
/** Index for stagger animation ordering. */
|
|
1745
|
+
animationIndex: number;
|
|
1746
|
+
/** Bounding box in map-local coordinates. */
|
|
1747
|
+
bounds: { x: number; y: number; width: number; height: number };
|
|
1748
|
+
/** Centroid in map-local coordinates. */
|
|
1749
|
+
centroid: [number, number];
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
/** Border paths for the map (interior borders and coastline/outline). */
|
|
1753
|
+
export interface MapBorders {
|
|
1754
|
+
/** SVG path `d` for interior borders between features. */
|
|
1755
|
+
interiorPath: string;
|
|
1756
|
+
/** SVG path `d` for the outer boundary / coastline. */
|
|
1757
|
+
outlinePath: string;
|
|
1758
|
+
/** Stroke color for interior borders. */
|
|
1759
|
+
interiorStroke: string;
|
|
1760
|
+
/** Stroke color for outer boundary. */
|
|
1761
|
+
outlineStroke: string;
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
/**
|
|
1765
|
+
* MapLayout: the complete engine output for map visualizations.
|
|
1766
|
+
*
|
|
1767
|
+
* Contains everything an adapter needs to render the map: dimensions,
|
|
1768
|
+
* chrome, feature paths, borders, legend, tooltip descriptors, and
|
|
1769
|
+
* accessibility metadata.
|
|
1770
|
+
*/
|
|
1771
|
+
export interface MapLayout {
|
|
1772
|
+
/** The map drawing area (after chrome and legend are subtracted). */
|
|
1773
|
+
area: Rect;
|
|
1774
|
+
/** Resolved chrome text elements with positions and styles. */
|
|
1775
|
+
chrome: ResolvedChrome;
|
|
1776
|
+
/** Resolved feature marks with paths, fills, and joined data. */
|
|
1777
|
+
features: MapFeatureMark[];
|
|
1778
|
+
/** Border paths (interior mesh and outline). */
|
|
1779
|
+
borders: MapBorders;
|
|
1780
|
+
/** Continuous color legend for quantitative mode (null if hidden or categorical). */
|
|
1781
|
+
continuousLegend: ContinuousLegendLayout | null;
|
|
1782
|
+
/** Categorical swatch legend for nominal mode (null if hidden or quantitative). */
|
|
1783
|
+
categoricalLegend: CategoricalLegendLayout | null;
|
|
1784
|
+
/** Tooltip content descriptors keyed by feature ID. */
|
|
1785
|
+
tooltipDescriptors: Map<string, TooltipContent>;
|
|
1786
|
+
/** Accessibility metadata for the map. */
|
|
1787
|
+
a11y: A11yMetadata;
|
|
1788
|
+
/** Resolved theme. */
|
|
1789
|
+
theme: ResolvedTheme;
|
|
1790
|
+
/** Total SVG width in pixels. */
|
|
1791
|
+
width: number;
|
|
1792
|
+
/** Total SVG height in pixels. */
|
|
1793
|
+
height: number;
|
|
1794
|
+
/** Resolved animation config (undefined if animation is disabled). */
|
|
1795
|
+
animation: ResolvedAnimation | undefined;
|
|
1796
|
+
/** Whether to render the watermark. */
|
|
1797
|
+
watermark: boolean;
|
|
1798
|
+
/** Text measurement function for the rendering adapter. */
|
|
1799
|
+
measureText: MeasureTextFn;
|
|
1800
|
+
/** Structured compile warnings (unmatched keys, missing data, winding issues). */
|
|
1801
|
+
warnings: CompileWarning[];
|
|
1802
|
+
/** The (width, height) passed to the projection's fitSize -- camera fits against this, not the SVG viewBox. */
|
|
1803
|
+
mapSize: { width: number; height: number };
|
|
1804
|
+
/** Resolved focus target for camera framing (null if no focus). */
|
|
1805
|
+
focus: MapFocusLayout | null;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1432
1808
|
// ---------------------------------------------------------------------------
|
|
1433
1809
|
// BarListLayout (engine output for bar list visualizations)
|
|
1434
1810
|
// ---------------------------------------------------------------------------
|
|
@@ -1529,6 +1905,24 @@ export interface CompileOptions {
|
|
|
1529
1905
|
darkMode?: boolean;
|
|
1530
1906
|
/** Whether to show the tryOpenData.ai watermark. Defaults to true. */
|
|
1531
1907
|
watermark?: boolean;
|
|
1908
|
+
/**
|
|
1909
|
+
* Enable development-time diagnostics (WCAG contrast warnings via
|
|
1910
|
+
* `console.warn`). The engine is isomorphic, so it never sniffs
|
|
1911
|
+
* `process.env`; the host decides what "dev" means and passes this flag.
|
|
1912
|
+
* Warnings are advisory only and never throw. Defaults to false.
|
|
1913
|
+
*/
|
|
1914
|
+
dev?: boolean;
|
|
1915
|
+
/**
|
|
1916
|
+
* Sink for advisory spec warnings (deprecations, did-you-mean suggestions,
|
|
1917
|
+
* unknown scheme names, overplotting/beeswarm budget notes, etc.). The engine
|
|
1918
|
+
* is isomorphic and side-effect-free by default: rather than writing to the
|
|
1919
|
+
* global `console`, it routes every advisory warning through this callback so
|
|
1920
|
+
* a host can collect, reroute, or silence them (e.g. suppress under SSR, fail
|
|
1921
|
+
* a test on any warning, surface them in a dev overlay). When omitted, the
|
|
1922
|
+
* engine defaults to `console.warn`. Never called with fatal errors, which are
|
|
1923
|
+
* thrown instead.
|
|
1924
|
+
*/
|
|
1925
|
+
onWarn?: (message: string) => void;
|
|
1532
1926
|
/**
|
|
1533
1927
|
* Real text measurement function provided by the adapter.
|
|
1534
1928
|
* Uses a hidden canvas or DOM element for accurate text dimensions.
|
|
@@ -1537,6 +1931,18 @@ export interface CompileOptions {
|
|
|
1537
1931
|
measureText?: MeasureTextFn;
|
|
1538
1932
|
/** Extra pixels to reserve on the right margin for a secondary y-axis. Set by compileLayer when resolve.scale.y is 'independent'. */
|
|
1539
1933
|
rightAxisReserve?: number;
|
|
1934
|
+
/**
|
|
1935
|
+
* Extra pixels to reserve below the plot for the auto-thinning footnote list.
|
|
1936
|
+
* Chicken-and-egg: thinning needs the chart area to decide what to demote, but
|
|
1937
|
+
* the footnotes it produces need space carved out of that same area. compileChart
|
|
1938
|
+
* resolves it by compiling once to learn the footnote count, then recompiling with
|
|
1939
|
+
* this set. Callers should not set it; it is internal to that second pass.
|
|
1940
|
+
*/
|
|
1941
|
+
footnoteReserve?: number;
|
|
1942
|
+
/** Recursion depth of the footnote-reserve convergence pass. Internal to compileChart. */
|
|
1943
|
+
footnotePass?: number;
|
|
1944
|
+
/** Set after facet height growth to prevent unbounded recursion. Internal to compileFaceted. */
|
|
1945
|
+
facetHeightGrown?: boolean;
|
|
1540
1946
|
/**
|
|
1541
1947
|
* Use this chart drawing area instead of computing one from chrome, axes,
|
|
1542
1948
|
* and legend reservations. Set by compileLayer when compiling leaf layers so
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concrete (non-generic) type aliases used as JSON Schema generation roots.
|
|
3
|
+
*
|
|
4
|
+
* `ts-json-schema-generator` cannot instantiate generic type parameters, so the
|
|
5
|
+
* schema generator (`scripts/generate-schema.mjs`) points at these fixed
|
|
6
|
+
* aliases instead of the generic `ChartSpec<TData>` / `TableSpec` directly.
|
|
7
|
+
* They resolve every generic to its `DataRow` default, which is the shape an
|
|
8
|
+
* LLM actually emits (untyped rows).
|
|
9
|
+
*
|
|
10
|
+
* These aliases exist only to shape schema output. They are not re-exported
|
|
11
|
+
* from the package barrel and add no runtime surface.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { ChartSpec, TableSpec, VizSpec } from './spec';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Root for the full published schema (`vizspec.schema.json`). The complete
|
|
18
|
+
* discriminated union of every openchart spec kind.
|
|
19
|
+
*/
|
|
20
|
+
export type VizSpecSchema = VizSpec;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Root for the ChartSpec subset schema (`chart.schema.json`). Covers all 16
|
|
24
|
+
* mark types. This is the LLM chart workhorse and the primary tool-use surface.
|
|
25
|
+
*/
|
|
26
|
+
export type ChartSpecSchema = ChartSpec;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Root for the TableSpec subset schema (`table.schema.json`). The data-table
|
|
30
|
+
* visualization spec.
|
|
31
|
+
*/
|
|
32
|
+
export type TableSpecSchema = TableSpec;
|