@opendata-ai/openchart-core 3.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -157,20 +157,82 @@ interface ColumnConfig {
157
157
  * These types define what a user (or Claude) writes to describe a visualization.
158
158
  * The engine validates, normalizes, and compiles specs into layout objects.
159
159
  *
160
- * Encoding vocabulary follows Vega-Lite conventions (field/type/aggregate)
160
+ * Encoding vocabulary follows Vega-Lite conventions (field/type/aggregate/mark)
161
161
  * with editorial extensions for chrome, annotations, responsive, and dark mode.
162
162
  */
163
163
 
164
- /** Supported chart types. Graph is separate since it uses nodes/edges, not data + encoding. */
165
- type ChartType = 'line' | 'area' | 'bar' | 'column' | 'pie' | 'donut' | 'dot' | 'scatter';
164
+ /**
165
+ * Supported mark types, following Vega-Lite conventions.
166
+ *
167
+ * Mapping from previous OpenChart chart types:
168
+ * - 'bar' covers both horizontal bars (old 'bar') and vertical columns (old 'column')
169
+ * - 'arc' covers both pie (old 'pie') and donut (old 'donut')
170
+ * - 'point' replaces old 'scatter'
171
+ * - 'circle' replaces old 'dot'
172
+ * - 'line' and 'area' unchanged
173
+ *
174
+ * New mark types not in previous OpenChart:
175
+ * - 'text': data-positioned text labels
176
+ * - 'rule': reference lines as data marks
177
+ * - 'tick': strip/rug plot marks
178
+ * - 'rect': heatmaps and 2D binned plots
179
+ */
180
+ type MarkType = 'bar' | 'line' | 'area' | 'point' | 'circle' | 'arc' | 'text' | 'rule' | 'tick' | 'rect';
181
+ /** @deprecated Use MarkType instead. Kept for internal migration references. */
182
+ type ChartType = MarkType;
183
+ /**
184
+ * Mark definition object with visual properties.
185
+ *
186
+ * When `mark` is a string, it's shorthand for `{ type: markString }`.
187
+ * When it's an object, it can include properties like interpolation,
188
+ * point markers, orientation, and more.
189
+ */
190
+ interface MarkDef {
191
+ /** The mark type. */
192
+ type: MarkType;
193
+ /**
194
+ * Show point markers on line/area marks.
195
+ * - true: filled circles at each data point
196
+ * - 'transparent': invisible hover targets (legacy behavior)
197
+ * - false: no point marks (default; uses voronoi overlay for tooltips)
198
+ */
199
+ point?: boolean | 'transparent';
200
+ /**
201
+ * Curve interpolation for line/area marks.
202
+ * Maps to d3-shape curve factories.
203
+ */
204
+ interpolate?: 'linear' | 'monotone' | 'step' | 'step-before' | 'step-after' | 'basis' | 'cardinal' | 'natural';
205
+ /** Explicit orientation override for bar marks. */
206
+ orient?: 'horizontal' | 'vertical';
207
+ /** Inner radius for arc marks. >0 produces a donut, 0 or omitted produces a pie. */
208
+ innerRadius?: number;
209
+ /** Outer radius for arc marks. */
210
+ outerRadius?: number;
211
+ /** Corner radius for rect/bar marks. */
212
+ cornerRadius?: number;
213
+ /** Whether the mark is filled (vs stroked only). */
214
+ filled?: boolean;
215
+ /** Default opacity (0-1). */
216
+ opacity?: number;
217
+ /** Default fill color. */
218
+ fill?: string;
219
+ /** Default stroke color. */
220
+ stroke?: string;
221
+ /** Default stroke width. */
222
+ strokeWidth?: number;
223
+ /** Tooltip behavior. null disables tooltips. */
224
+ tooltip?: boolean | null;
225
+ /** Clip marks to the chart area. */
226
+ clip?: boolean;
227
+ }
166
228
  /** Data field type, following Vega-Lite conventions. */
167
229
  type FieldType = 'quantitative' | 'temporal' | 'nominal' | 'ordinal';
168
230
  /** Aggregate function applied to a field before encoding. */
169
231
  type AggregateOp = 'count' | 'sum' | 'mean' | 'median' | 'min' | 'max';
170
232
  /** Axis configuration for an encoding channel. */
171
233
  interface AxisConfig {
172
- /** Axis label text. If omitted, the field name is used. */
173
- label?: string;
234
+ /** Axis title text. If omitted, the field name is used. */
235
+ title?: string;
174
236
  /** Number format string (d3-format). e.g. ",.0f" for comma-separated integers. */
175
237
  format?: string;
176
238
  /** Override tick count. Engine picks a sensible default if omitted. */
@@ -178,6 +240,28 @@ interface AxisConfig {
178
240
  /** Whether to show gridlines for this axis. */
179
241
  grid?: boolean;
180
242
  /** Rotation angle in degrees for tick labels. Common values: -45, -90, 90. */
243
+ labelAngle?: number;
244
+ /** Axis orientation override. */
245
+ orient?: 'top' | 'bottom' | 'left' | 'right';
246
+ /** Explicit tick values. */
247
+ values?: unknown[];
248
+ /** How to handle overlapping labels. */
249
+ labelOverlap?: boolean | 'parity' | 'greedy';
250
+ /** Whether to flush labels to the axis edges. */
251
+ labelFlush?: boolean;
252
+ /** Whether to show the axis domain line. */
253
+ domain?: boolean;
254
+ /** Whether to show tick marks. */
255
+ ticks?: boolean;
256
+ /** Axis position offset in pixels. */
257
+ offset?: number;
258
+ /** Padding between axis title and axis. */
259
+ titlePadding?: number;
260
+ /** Padding between tick labels and axis. */
261
+ labelPadding?: number;
262
+ /** @deprecated Use `title` instead. */
263
+ label?: string;
264
+ /** @deprecated Use `labelAngle` instead. */
181
265
  tickAngle?: number;
182
266
  }
183
267
  /** Scale configuration for an encoding channel. */
@@ -185,14 +269,34 @@ interface ScaleConfig {
185
269
  /** Explicit domain override. Auto-derived from data if omitted. */
186
270
  domain?: [number, number] | string[];
187
271
  /** Scale type override. Usually inferred from field type. */
188
- type?: 'linear' | 'log' | 'time' | 'band' | 'point' | 'ordinal';
272
+ type?: ScaleType;
189
273
  /** Whether to nice-ify the domain for clean tick values. Defaults to true. */
190
274
  nice?: boolean;
191
275
  /** Whether the domain should include zero. Defaults to true for quantitative. */
192
276
  zero?: boolean;
193
277
  /** When true and domain is set, filter out data rows with values outside the domain range. */
194
278
  clip?: boolean;
195
- }
279
+ /** Explicit range override. */
280
+ range?: unknown[];
281
+ /** Reverse the range direction. */
282
+ reverse?: boolean;
283
+ /** Clamp output to the range. */
284
+ clamp?: boolean;
285
+ /** Padding for band/point scales. */
286
+ padding?: number;
287
+ /** Inner padding for band scales. */
288
+ paddingInner?: number;
289
+ /** Outer padding for band scales. */
290
+ paddingOuter?: number;
291
+ /** Exponent for pow scales. */
292
+ exponent?: number;
293
+ /** Base for log scales (default 10). */
294
+ base?: number;
295
+ /** Constant for symlog scales. */
296
+ constant?: number;
297
+ }
298
+ /** Scale type, following Vega-Lite conventions. */
299
+ type ScaleType = 'linear' | 'log' | 'pow' | 'sqrt' | 'symlog' | 'time' | 'utc' | 'ordinal' | 'band' | 'point' | 'quantile' | 'quantize' | 'threshold';
196
300
  /**
197
301
  * A single encoding channel mapping a data field to a visual property.
198
302
  *
@@ -220,20 +324,44 @@ interface EncodingChannel {
220
324
  }
221
325
  /**
222
326
  * Encoding object mapping visual channels to data fields.
223
- * Which channels are required depends on the chart type.
224
- * See ChartEncodingRules in encoding.ts for per-type requirements.
327
+ * Which channels are required depends on the mark type.
328
+ * See MARK_ENCODING_RULES in encoding.ts for per-type requirements.
225
329
  */
226
330
  interface Encoding {
227
331
  /** Horizontal position channel. */
228
332
  x?: EncodingChannel;
229
333
  /** Vertical position channel. */
230
334
  y?: EncodingChannel;
231
- /** Color channel (series differentiation or heatmap). */
232
- color?: EncodingChannel;
233
- /** Size channel (bubble charts, dot plots). */
234
- size?: EncodingChannel;
335
+ /** Color channel (series differentiation or heatmap). Accepts conditional definitions. */
336
+ color?: EncodingChannel | ConditionalValueDef;
337
+ /** Size channel (bubble charts, dot plots). Accepts conditional definitions. */
338
+ size?: EncodingChannel | ConditionalValueDef;
235
339
  /** Detail channel (group without encoding to a visual property). */
236
340
  detail?: EncodingChannel;
341
+ /** Secondary x position (for ranges, error bars). */
342
+ x2?: EncodingChannel;
343
+ /** Secondary y position (for ranges, error bars). */
344
+ y2?: EncodingChannel;
345
+ /** Data-driven opacity (0-1). Accepts conditional definitions. */
346
+ opacity?: EncodingChannel | ConditionalValueDef;
347
+ /** Point shape encoding (circle, square, diamond, triangle-up, etc.). */
348
+ shape?: EncodingChannel;
349
+ /** Data-driven stroke dash patterns. */
350
+ strokeDash?: EncodingChannel;
351
+ /** Rotation angle encoding. */
352
+ angle?: EncodingChannel;
353
+ /** Text content for text marks. */
354
+ text?: EncodingChannel;
355
+ /** Tooltip field(s). Can be a single channel or array. */
356
+ tooltip?: EncodingChannel | EncodingChannel[];
357
+ /** Hyperlink encoding. */
358
+ href?: EncodingChannel;
359
+ /** Stacking/drawing order. */
360
+ order?: EncodingChannel;
361
+ /** Angular position for arc marks. */
362
+ theta?: EncodingChannel;
363
+ /** Radial position for arc marks. */
364
+ radius?: EncodingChannel;
237
365
  }
238
366
  /** Encoding channel for graph nodes and edges. Same structure as EncodingChannel. */
239
367
  interface GraphEncodingChannel {
@@ -522,15 +650,21 @@ interface ChartSpecOverride {
522
650
  /**
523
651
  * Chart specification: the primary input for standard chart types.
524
652
  *
525
- * Combines a chart type with data, encoding channels, editorial chrome,
526
- * annotations, and configuration. The engine validates, normalizes, and
527
- * compiles this into a ChartLayout.
653
+ * Uses the Vega-Lite `mark` property instead of `type` to specify
654
+ * the visualization mark. The mark can be a string shorthand or an
655
+ * object with additional properties (interpolation, point markers, etc.).
528
656
  */
529
657
  interface ChartSpec {
530
- /** The chart type to render. */
531
- type: ChartType;
658
+ /**
659
+ * The mark type to render.
660
+ * String shorthand: `mark: 'bar'`
661
+ * Object with properties: `mark: { type: 'line', interpolate: 'step' }`
662
+ */
663
+ mark: MarkType | MarkDef;
532
664
  /** Data array: each element is a row with field values. */
533
665
  data: DataRow[];
666
+ /** Data transforms applied in order before encoding (filter, bin, calculate, timeUnit). */
667
+ transform?: Transform[];
534
668
  /** Encoding mapping data fields to visual channels. */
535
669
  encoding: Encoding;
536
670
  /** Editorial chrome (title, subtitle, source, etc.). */
@@ -608,13 +742,6 @@ interface GraphEdge {
608
742
  /** Arbitrary data fields (weight, type, confidence, etc.). */
609
743
  [key: string]: unknown;
610
744
  }
611
- /**
612
- * Graph specification: input for network/relationship visualizations.
613
- *
614
- * Uses a nodes + edges data model instead of the flat data + encoding model
615
- * used by chart types. The graph type is defined here for forward compatibility
616
- * but rendering is deferred to a future phase.
617
- */
618
745
  /** Per-node visual overrides, keyed by node id. */
619
746
  interface NodeOverride {
620
747
  /** Override fill color. */
@@ -651,12 +778,64 @@ interface GraphSpec {
651
778
  darkMode?: DarkMode;
652
779
  }
653
780
  /**
654
- * Top-level visualization spec: discriminated union on the `type` field.
781
+ * Resolution strategy for shared resources across layers.
782
+ * 'shared' (default): union domains, single axis/legend.
783
+ * 'independent': each layer gets its own scale/axis/legend.
784
+ */
785
+ type ResolveMode = 'shared' | 'independent';
786
+ /**
787
+ * Per-channel resolution config. Controls whether scales, axes, and legends
788
+ * are shared or independent across layers.
789
+ */
790
+ interface ResolveConfig {
791
+ scale?: Partial<Record<'x' | 'y' | 'color' | 'size', ResolveMode>>;
792
+ axis?: Partial<Record<'x' | 'y', ResolveMode>>;
793
+ legend?: Partial<Record<'color' | 'size', ResolveMode>>;
794
+ }
795
+ /**
796
+ * Layer specification: composites multiple chart layers into a single view.
655
797
  *
656
- * This is the primary API contract. Users (and Claude) write VizSpec objects,
657
- * the engine validates and compiles them into layout objects for rendering.
798
+ * Each element in `layer` is either a ChartSpec or another LayerSpec (nested).
799
+ * Shared data, encoding, and transforms at the LayerSpec level are inherited
800
+ * by children that don't define their own.
658
801
  */
659
- type VizSpec = ChartSpec | TableSpec | GraphSpec;
802
+ interface LayerSpec {
803
+ /** Array of child layers (ChartSpec or nested LayerSpec). */
804
+ layer: (ChartSpec | LayerSpec)[];
805
+ /** Shared data inherited by children without their own data. */
806
+ data?: DataRow[];
807
+ /** Shared encoding inherited by children (overridden per-channel by child). */
808
+ encoding?: Encoding;
809
+ /** Shared transforms. Parent transforms run before child transforms. */
810
+ transform?: Transform[];
811
+ /** Editorial chrome (title, subtitle, source, etc.). */
812
+ chrome?: Chrome;
813
+ /** Annotations on the layered view. */
814
+ annotations?: Annotation[];
815
+ /** Label display configuration. */
816
+ labels?: LabelConfig;
817
+ /** Legend display configuration. */
818
+ legend?: LegendConfig;
819
+ /** Whether the chart adapts to container width. Defaults to true. */
820
+ responsive?: boolean;
821
+ /** Theme configuration overrides. */
822
+ theme?: ThemeConfig;
823
+ /** Dark mode behavior. Defaults to "off". */
824
+ darkMode?: DarkMode;
825
+ /** Resolution strategy for shared scales/axes/legends. */
826
+ resolve?: ResolveConfig;
827
+ /** Hidden series names. */
828
+ hiddenSeries?: string[];
829
+ }
830
+ /**
831
+ * Top-level visualization spec: union discriminated by structural shape.
832
+ *
833
+ * - ChartSpec: has `mark` field (no `type`, no `layer`)
834
+ * - LayerSpec: has `layer` field
835
+ * - TableSpec: has `type: 'table'`
836
+ * - GraphSpec: has `type: 'graph'`
837
+ */
838
+ type VizSpec = ChartSpec | LayerSpec | TableSpec | GraphSpec;
660
839
  /** Chart spec without runtime data, for persistence/storage. */
661
840
  type ChartSpecWithoutData = Omit<ChartSpec, 'data'>;
662
841
  /** Table spec without runtime data and columns, for persistence/storage. Columns can be auto-generated via dataTable(). */
@@ -665,25 +844,160 @@ type TableSpecWithoutData = Omit<TableSpec, 'data' | 'columns'>;
665
844
  type GraphSpecWithoutData = Omit<GraphSpec, 'nodes' | 'edges'>;
666
845
  /** Union of data-stripped spec types for persistence/storage. */
667
846
  type StoredVizSpec = ChartSpecWithoutData | TableSpecWithoutData | GraphSpecWithoutData;
668
- /** All valid chart type strings for runtime checking. */
847
+ /** Logical AND combinator for filter predicates. */
848
+ interface LogicalAnd<T> {
849
+ and: T[];
850
+ }
851
+ /** Logical OR combinator for filter predicates. */
852
+ interface LogicalOr<T> {
853
+ or: T[];
854
+ }
855
+ /** Logical NOT combinator for filter predicates. */
856
+ interface LogicalNot<T> {
857
+ not: T;
858
+ }
859
+ /** A predicate that tests a field value against a condition. */
860
+ interface FieldPredicate {
861
+ /** Data field to test. */
862
+ field: string;
863
+ /** Equals comparison. */
864
+ equal?: unknown;
865
+ /** Less than. */
866
+ lt?: number;
867
+ /** Less than or equal. */
868
+ lte?: number;
869
+ /** Greater than. */
870
+ gt?: number;
871
+ /** Greater than or equal. */
872
+ gte?: number;
873
+ /** Inclusive range [min, max]. */
874
+ range?: [number, number];
875
+ /** Value is one of these. */
876
+ oneOf?: unknown[];
877
+ /** Whether the value is valid (non-null, non-undefined, non-NaN). */
878
+ valid?: boolean;
879
+ }
880
+ /**
881
+ * A filter predicate: a field predicate or logical combination of predicates.
882
+ */
883
+ type FilterPredicate = FieldPredicate | LogicalAnd<FilterPredicate> | LogicalOr<FilterPredicate> | LogicalNot<FilterPredicate>;
884
+ /** Parameters for binning a field. */
885
+ interface BinParams {
886
+ /** Maximum number of bins. */
887
+ maxbins?: number;
888
+ /** Exact step size between bins. */
889
+ step?: number;
890
+ /** Whether to nice-ify bin boundaries. */
891
+ nice?: boolean;
892
+ /** Explicit extent [min, max] for binning. */
893
+ extent?: [number, number];
894
+ }
895
+ /** Expression for calculate transforms. */
896
+ interface CalculateExpression {
897
+ /** Arithmetic operation to apply. */
898
+ op: '+' | '-' | '*' | '/' | 'abs' | 'round' | 'floor' | 'ceil' | 'log' | 'sqrt';
899
+ /** Primary field to operate on. */
900
+ field: string;
901
+ /** Secondary field for binary operations (+, -, *, /). */
902
+ field2?: string;
903
+ /** Constant value for binary operations when field2 is not provided. */
904
+ value?: number;
905
+ }
906
+ /**
907
+ * Time unit granularity for temporal field transformations.
908
+ * Follows Vega-Lite conventions.
909
+ */
910
+ type TimeUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'dayofyear' | 'date' | 'hours' | 'minutes' | 'seconds' | 'milliseconds' | 'yearmonth' | 'yearmonthdate' | 'monthdate' | 'hoursminutes';
911
+ /** Filter transform: removes rows that don't match the predicate. */
912
+ interface FilterTransform {
913
+ filter: FilterPredicate;
914
+ }
915
+ /** Bin transform: adds binned field(s) to each row. */
916
+ interface BinTransform {
917
+ bin: true | BinParams;
918
+ field: string;
919
+ as: string | [string, string];
920
+ }
921
+ /** Calculate transform: adds a computed field to each row. */
922
+ interface CalculateTransform {
923
+ calculate: CalculateExpression;
924
+ as: string;
925
+ }
926
+ /** Time unit transform: extracts a time unit from a temporal field. */
927
+ interface TimeUnitTransform {
928
+ timeUnit: TimeUnit;
929
+ field: string;
930
+ as: string;
931
+ }
932
+ /** Discriminated union of all transform types. */
933
+ type Transform = FilterTransform | BinTransform | CalculateTransform | TimeUnitTransform;
934
+ /**
935
+ * A single condition with a test predicate and resulting value/field.
936
+ * When the test passes for a datum, the condition's value/field is used.
937
+ */
938
+ interface Condition {
939
+ /** Predicate to test against each datum. */
940
+ test: FilterPredicate;
941
+ /** Static value to use when the condition is true. */
942
+ value?: unknown;
943
+ /** Data field to use when the condition is true. */
944
+ field?: string;
945
+ /** Field type for the conditional field. */
946
+ type?: FieldType;
947
+ }
948
+ /**
949
+ * A conditional value definition for an encoding channel.
950
+ * Evaluates conditions in order, falling back to the default value.
951
+ */
952
+ interface ConditionalValueDef {
953
+ /** One or more conditions to evaluate. */
954
+ condition: Condition | Condition[];
955
+ /** Default value when no condition matches. */
956
+ value?: unknown;
957
+ }
958
+ /**
959
+ * Check if a channel definition is a regular EncodingChannel (has 'field' at top level).
960
+ * Use this to narrow `EncodingChannel | ConditionalValueDef` in encoding channels
961
+ * that support conditional encoding (color, size, opacity).
962
+ */
963
+ declare function isEncodingChannel(def: EncodingChannel | ConditionalValueDef | undefined): def is EncodingChannel;
964
+ /**
965
+ * Check if a channel definition is a ConditionalValueDef.
966
+ */
967
+ declare function isConditionalDef(def: EncodingChannel | ConditionalValueDef | undefined): def is ConditionalValueDef;
968
+ /** All valid mark type strings for runtime checking. */
969
+ declare const MARK_TYPES: ReadonlySet<string>;
970
+ /** @deprecated Use MARK_TYPES instead. */
669
971
  declare const CHART_TYPES: ReadonlySet<string>;
670
- /** Check if a spec is a ChartSpec (any standard chart type). */
671
- declare function isChartSpec(spec: VizSpec): spec is ChartSpec;
972
+ /**
973
+ * Extract the mark type string from a mark field (string or MarkDef).
974
+ */
975
+ declare function resolveMarkType(mark: MarkType | MarkDef): MarkType;
976
+ /**
977
+ * Extract the full MarkDef from a mark field, filling in defaults for string shorthand.
978
+ */
979
+ declare function resolveMarkDef(mark: MarkType | MarkDef): MarkDef;
980
+ /** Check if a spec is a ChartSpec (has `mark` field, not a layer/table/graph). */
981
+ declare function isChartSpec(spec: VizSpec | Record<string, unknown>): spec is ChartSpec;
982
+ /** Check if a spec is a LayerSpec (has `layer` array). */
983
+ declare function isLayerSpec(spec: VizSpec | Record<string, unknown>): spec is LayerSpec;
672
984
  /** Check if a spec is a TableSpec. */
673
- declare function isTableSpec(spec: VizSpec): spec is TableSpec;
985
+ declare function isTableSpec(spec: VizSpec | Record<string, unknown>): spec is TableSpec;
674
986
  /** Check if a spec is a GraphSpec. */
675
- declare function isGraphSpec(spec: VizSpec): spec is GraphSpec;
987
+ declare function isGraphSpec(spec: VizSpec | Record<string, unknown>): spec is GraphSpec;
676
988
  /** Check if an annotation is a TextAnnotation. */
677
989
  declare function isTextAnnotation(annotation: Annotation): annotation is TextAnnotation;
678
990
  /** Check if an annotation is a RangeAnnotation. */
679
991
  declare function isRangeAnnotation(annotation: Annotation): annotation is RangeAnnotation;
680
992
  /** Check if an annotation is a RefLineAnnotation. */
681
993
  declare function isRefLineAnnotation(annotation: Annotation): annotation is RefLineAnnotation;
994
+ /** Human-readable display names for mark types (used in alt text, error messages). */
995
+ declare const MARK_DISPLAY_NAMES: Record<MarkType, string>;
682
996
 
683
997
  /**
684
- * Per-chart-type encoding validation rules.
998
+ * Per-mark-type encoding validation rules.
685
999
  *
686
- * Defines which encoding channels are required vs optional for each chart type.
1000
+ * Defines which encoding channels are required vs optional for each mark type.
687
1001
  * The engine compiler uses these rules to validate specs at runtime (TypeScript
688
1002
  * catches compile-time errors; these catch runtime JSON from Claude or APIs).
689
1003
  */
@@ -699,25 +1013,41 @@ interface ChannelRule {
699
1013
  interface EncodingRule {
700
1014
  x: ChannelRule;
701
1015
  y: ChannelRule;
1016
+ x2?: ChannelRule;
1017
+ y2?: ChannelRule;
702
1018
  color: ChannelRule;
703
1019
  size: ChannelRule;
1020
+ shape?: ChannelRule;
1021
+ opacity?: ChannelRule;
1022
+ strokeDash?: ChannelRule;
1023
+ text?: ChannelRule;
1024
+ tooltip?: ChannelRule;
1025
+ href?: ChannelRule;
1026
+ order?: ChannelRule;
1027
+ theta?: ChannelRule;
1028
+ radius?: ChannelRule;
704
1029
  detail: ChannelRule;
705
1030
  }
706
1031
  /**
707
- * Encoding rules per chart type.
1032
+ * Encoding rules per mark type.
708
1033
  *
709
1034
  * Defines which channels are required and what field types they accept.
710
1035
  * The compiler uses this map to validate user specs at runtime.
711
1036
  *
712
1037
  * Key design decisions:
713
1038
  * - line/area: x is temporal/ordinal (the axis), y is quantitative (the value)
714
- * - bar: horizontal bars, so y is the category axis, x is the value
715
- * - column: vertical columns, so x is the category axis, y is the value
716
- * - pie/donut: no x axis; y is the value (quantitative), color is the category
717
- * - dot: y is the category, x is quantitative
718
- * - scatter: both axes are quantitative
719
- */
720
- declare const CHART_ENCODING_RULES: Record<ChartType, EncodingRule>;
1039
+ * - bar: covers both horizontal and vertical orientations, so both axes accept
1040
+ * all relevant types. The engine validates the combination later (one axis
1041
+ * must be quantitative).
1042
+ * - arc: no x axis; y is the value (quantitative), color is the category
1043
+ * - circle: y is the category, x is quantitative
1044
+ * - point: both axes are quantitative
1045
+ * - text/rule: fully optional positioning
1046
+ * - tick/rect: both axes required, any type
1047
+ */
1048
+ declare const MARK_ENCODING_RULES: Record<MarkType, EncodingRule>;
1049
+ /** @deprecated Use MARK_ENCODING_RULES instead. */
1050
+ declare const CHART_ENCODING_RULES: Record<MarkType, EncodingRule>;
721
1051
  /** Encoding rule for a single graph visual channel. */
722
1052
  interface GraphChannelRule {
723
1053
  /** Whether this channel is required. */
@@ -1070,6 +1400,22 @@ interface AxisLayout {
1070
1400
  start: Point;
1071
1401
  /** Axis line end position. */
1072
1402
  end: Point;
1403
+ /** Axis orientation (which side it appears on). */
1404
+ orient?: 'top' | 'bottom' | 'left' | 'right';
1405
+ /** Whether to show the axis domain line. Defaults to true. */
1406
+ domainLine?: boolean;
1407
+ /** Whether to show tick marks. Defaults to true. */
1408
+ tickMarks?: boolean;
1409
+ /** Axis position offset in pixels. */
1410
+ offset?: number;
1411
+ /** Padding between axis title and axis in pixels. */
1412
+ titlePadding?: number;
1413
+ /** Padding between tick labels and axis in pixels. */
1414
+ labelPadding?: number;
1415
+ /** How overlapping labels should be handled. */
1416
+ labelOverlap?: boolean | 'parity' | 'greedy';
1417
+ /** Whether to flush labels to the axis edges. */
1418
+ labelFlush?: boolean;
1073
1419
  }
1074
1420
  /** Accessibility attributes for a mark. */
1075
1421
  interface MarkAria {
@@ -1103,6 +1449,16 @@ interface LineMark {
1103
1449
  seriesKey?: string;
1104
1450
  /** Original data rows for this series. */
1105
1451
  data: Record<string, unknown>[];
1452
+ /**
1453
+ * Pixel-coordinate data points for spatial tooltip lookup (voronoi overlay).
1454
+ * Each entry pairs a pixel position with its original data row.
1455
+ */
1456
+ dataPoints?: Array<{
1457
+ x: number;
1458
+ y: number;
1459
+ datum: Record<string, unknown>;
1460
+ tooltip?: TooltipContent;
1461
+ }>;
1106
1462
  /** Resolved label after collision detection. */
1107
1463
  label?: ResolvedLabel;
1108
1464
  /** Accessibility attributes. */
@@ -1134,6 +1490,16 @@ interface AreaMark {
1134
1490
  seriesKey?: string;
1135
1491
  /** Original data rows. */
1136
1492
  data: Record<string, unknown>[];
1493
+ /**
1494
+ * Pixel-coordinate data points for spatial tooltip lookup (voronoi overlay).
1495
+ * Each entry pairs a pixel position with its original data row.
1496
+ */
1497
+ dataPoints?: Array<{
1498
+ x: number;
1499
+ y: number;
1500
+ datum: Record<string, unknown>;
1501
+ tooltip?: TooltipContent;
1502
+ }>;
1137
1503
  /** Accessibility attributes. */
1138
1504
  aria: MarkAria;
1139
1505
  }
@@ -1226,8 +1592,91 @@ interface PointMark {
1226
1592
  /** Accessibility attributes. */
1227
1593
  aria: MarkAria;
1228
1594
  }
1595
+ /**
1596
+ * Text mark: data-positioned text label.
1597
+ * Used by text charts for showing values directly at data coordinates.
1598
+ */
1599
+ interface TextMarkLayout {
1600
+ type: 'textMark';
1601
+ /** X position. */
1602
+ x: number;
1603
+ /** Y position. */
1604
+ y: number;
1605
+ /** Text content to display. */
1606
+ text: string;
1607
+ /** Fill color. */
1608
+ fill: string;
1609
+ /** Font size in pixels. */
1610
+ fontSize: number;
1611
+ /** Font weight. */
1612
+ fontWeight?: number;
1613
+ /** Font family override. */
1614
+ fontFamily?: string;
1615
+ /** Horizontal text alignment. */
1616
+ textAnchor: 'start' | 'middle' | 'end';
1617
+ /** Rotation angle in degrees. */
1618
+ angle?: number;
1619
+ /** Original data row. */
1620
+ data: Record<string, unknown>;
1621
+ /** Resolved label. */
1622
+ label?: ResolvedLabel;
1623
+ /** Accessibility attributes. */
1624
+ aria: MarkAria;
1625
+ }
1626
+ /**
1627
+ * Rule mark: a line segment between two points.
1628
+ * Used for reference lines rendered as data marks.
1629
+ */
1630
+ interface RuleMarkLayout {
1631
+ type: 'rule';
1632
+ /** Start x position. */
1633
+ x1: number;
1634
+ /** Start y position. */
1635
+ y1: number;
1636
+ /** End x position. */
1637
+ x2: number;
1638
+ /** End y position. */
1639
+ y2: number;
1640
+ /** Stroke color. */
1641
+ stroke: string;
1642
+ /** Stroke width in pixels. */
1643
+ strokeWidth: number;
1644
+ /** Stroke dash pattern (e.g. "4 2"). */
1645
+ strokeDasharray?: string;
1646
+ /** Opacity (0-1). */
1647
+ opacity?: number;
1648
+ /** Original data row. */
1649
+ data: Record<string, unknown>;
1650
+ /** Accessibility attributes. */
1651
+ aria: MarkAria;
1652
+ }
1653
+ /**
1654
+ * Tick mark: a short line segment at a data coordinate.
1655
+ * Used for strip plots and rug plots.
1656
+ */
1657
+ interface TickMarkLayout {
1658
+ type: 'tick';
1659
+ /** X position. */
1660
+ x: number;
1661
+ /** Y position. */
1662
+ y: number;
1663
+ /** Length of the tick mark in pixels. */
1664
+ length: number;
1665
+ /** Whether the tick is horizontal or vertical. */
1666
+ orient: 'horizontal' | 'vertical';
1667
+ /** Stroke color. */
1668
+ stroke: string;
1669
+ /** Stroke width in pixels. */
1670
+ strokeWidth: number;
1671
+ /** Opacity (0-1). */
1672
+ opacity?: number;
1673
+ /** Original data row. */
1674
+ data: Record<string, unknown>;
1675
+ /** Accessibility attributes. */
1676
+ aria: MarkAria;
1677
+ }
1229
1678
  /** Discriminated union of all mark types. */
1230
- type Mark = LineMark | AreaMark | RectMark | ArcMark | PointMark;
1679
+ type Mark = LineMark | AreaMark | RectMark | ArcMark | PointMark | TextMarkLayout | RuleMarkLayout | TickMarkLayout;
1231
1680
  /**
1232
1681
  * A resolved label: text with a computed position after collision detection.
1233
1682
  * The collision engine determines whether labels are visible or demoted to tooltip-only.
@@ -2152,4 +2601,4 @@ declare function scatterChart(data: DataRow[], x: FieldRef, y: FieldRef, options
2152
2601
  */
2153
2602
  declare function dataTable(data: DataRow[], options?: TableBuilderOptions): TableSpec;
2154
2603
 
2155
- export { type A11yMetadata, type AggregateOp, type Annotation, type AnnotationAnchor, type AnnotationOffset, type AnnotationPosition, type ArcMark, type AreaMark, type AxisConfig, type AxisLabelDensity, type AxisLayout, type AxisTick, BRAND_RESERVE_WIDTH, type BarColumnConfig, type BarTableCell, type Breakpoint, CATEGORICAL_PALETTE, CHART_ENCODING_RULES, CHART_TYPES, type CategoricalPalette, type CategoryColorsConfig, type CategoryTableCell, type CellStyle, type ChannelRule, type ChartBuilderOptions, type ChartEventHandlers, type ChartLayout, type ChartSpec, type ChartSpecOverride, type ChartSpecWithoutData, type ChartType, type Chrome, type ChromeDefaults, type ChromeKey, type ChromeMode, type ChromeText, type ChromeTextStyle, type ColorBlindnessType, type ColumnConfig, type CompileOptions, type CompileTableOptions, DEFAULT_THEME, DIVERGING_PALETTES, type DarkMode, type DataRow, type DateGranularity, type DivergingPalette, type ElementEdit, type Encoding, type EncodingChannel, type EncodingRule, type FieldRef, type FieldType, type FlagTableCell, GRAPH_ENCODING_RULES, type GraphChannelRule, type GraphEdge, type GraphEdgeLayout, type GraphEncoding, type GraphEncodingChannel, type GraphLayout, type GraphLayoutConfig, type GraphNode, type GraphNodeLayout, type GraphSpec, type GraphSpecWithoutData, type Gridline, type HeatmapColumnConfig, type HeatmapTableCell, type HeightClass, type ImageColumnConfig, type ImageTableCell, type LabelCandidate, type LabelConfig, type LabelDensity, type LabelMode, type LabelPriority, type LayoutStrategy, type LegendConfig, type LegendEntry, type LegendLayout, type LegendPosition, type LineMark, type Margins, type Mark, type MarkAria, type MarkEvent, type MeasureTextFn, type NodeOverride, type PaginationState, type Point, type PointMark, type RangeAnnotation, type Rect, type RectMark, type RefLineAnnotation, type ResolvedAnnotation, type ResolvedChrome, type ResolvedChromeElement, type ResolvedColumn, type ResolvedLabel, type ResolvedTheme, SEQUENTIAL_PALETTES, type ScaleConfig, type SequentialPalette, type SeriesStyle, type SortState, type SparklineColumnConfig, type SparklineData, type SparklineTableCell, type StoredVizSpec, type TableBuilderOptions, type TableCell, type TableCellBase, type TableLayout, type TableRow, type TableSpec, type TableSpecWithoutData, type TextAnnotation, type TextStyle, type TextTableCell, type Theme, type ThemeChromeDefaults, type ThemeColors, type ThemeConfig, type ThemeFontSizes, type ThemeFontWeights, type ThemeFonts, type ThemeSpacing, type TooltipContent, type TooltipField, type VizSpec, abbreviateNumber, adaptColorForDarkMode, adaptTheme, areaChart, barChart, buildD3Formatter, checkPaletteDistinguishability, columnChart, computeChrome, computeLabelBounds, contrastRatio, dataTable, detectCollision, donutChart, dotChart, estimateTextWidth, findAccessibleColor, formatDate, formatNumber, generateAltText, generateAriaLabels, generateDataTable, getBreakpoint, getHeightClass, getLayoutStrategy, inferFieldType, isChartSpec, isGraphSpec, isRangeAnnotation, isRefLineAnnotation, isTableSpec, isTextAnnotation, lineChart, meetsAA, pieChart, resolveCollisions, resolveTheme, scatterChart, simulateColorBlindness };
2604
+ export { type A11yMetadata, type AggregateOp, type Annotation, type AnnotationAnchor, type AnnotationOffset, type AnnotationPosition, type ArcMark, type AreaMark, type AxisConfig, type AxisLabelDensity, type AxisLayout, type AxisTick, BRAND_RESERVE_WIDTH, type BarColumnConfig, type BarTableCell, type BinParams, type BinTransform, type Breakpoint, CATEGORICAL_PALETTE, CHART_ENCODING_RULES, CHART_TYPES, type CalculateExpression, type CalculateTransform, type CategoricalPalette, type CategoryColorsConfig, type CategoryTableCell, type CellStyle, type ChannelRule, type ChartBuilderOptions, type ChartEventHandlers, type ChartLayout, type ChartSpec, type ChartSpecOverride, type ChartSpecWithoutData, type ChartType, type Chrome, type ChromeDefaults, type ChromeKey, type ChromeMode, type ChromeText, type ChromeTextStyle, type ColorBlindnessType, type ColumnConfig, type CompileOptions, type CompileTableOptions, type Condition, type ConditionalValueDef, DEFAULT_THEME, DIVERGING_PALETTES, type DarkMode, type DataRow, type DateGranularity, type DivergingPalette, type ElementEdit, type Encoding, type EncodingChannel, type EncodingRule, type FieldPredicate, type FieldRef, type FieldType, type FilterPredicate, type FilterTransform, type FlagTableCell, GRAPH_ENCODING_RULES, type GraphChannelRule, type GraphEdge, type GraphEdgeLayout, type GraphEncoding, type GraphEncodingChannel, type GraphLayout, type GraphLayoutConfig, type GraphNode, type GraphNodeLayout, type GraphSpec, type GraphSpecWithoutData, type Gridline, type HeatmapColumnConfig, type HeatmapTableCell, type HeightClass, type ImageColumnConfig, type ImageTableCell, type LabelCandidate, type LabelConfig, type LabelDensity, type LabelMode, type LabelPriority, type LayerSpec, type LayoutStrategy, type LegendConfig, type LegendEntry, type LegendLayout, type LegendPosition, type LineMark, type LogicalAnd, type LogicalNot, type LogicalOr, MARK_DISPLAY_NAMES, MARK_ENCODING_RULES, MARK_TYPES, type Margins, type Mark, type MarkAria, type MarkDef, type MarkEvent, type MarkType, type MeasureTextFn, type NodeOverride, type PaginationState, type Point, type PointMark, type RangeAnnotation, type Rect, type RectMark, type RefLineAnnotation, type ResolveConfig, type ResolveMode, type ResolvedAnnotation, type ResolvedChrome, type ResolvedChromeElement, type ResolvedColumn, type ResolvedLabel, type ResolvedTheme, type RuleMarkLayout, SEQUENTIAL_PALETTES, type ScaleConfig, type ScaleType, type SequentialPalette, type SeriesStyle, type SortState, type SparklineColumnConfig, type SparklineData, type SparklineTableCell, type StoredVizSpec, type TableBuilderOptions, type TableCell, type TableCellBase, type TableLayout, type TableRow, type TableSpec, type TableSpecWithoutData, type TextAnnotation, type TextMarkLayout, type TextStyle, type TextTableCell, type Theme, type ThemeChromeDefaults, type ThemeColors, type ThemeConfig, type ThemeFontSizes, type ThemeFontWeights, type ThemeFonts, type ThemeSpacing, type TickMarkLayout, type TimeUnit, type TimeUnitTransform, type TooltipContent, type TooltipField, type Transform, type VizSpec, abbreviateNumber, adaptColorForDarkMode, adaptTheme, areaChart, barChart, buildD3Formatter, checkPaletteDistinguishability, columnChart, computeChrome, computeLabelBounds, contrastRatio, dataTable, detectCollision, donutChart, dotChart, estimateTextWidth, findAccessibleColor, formatDate, formatNumber, generateAltText, generateAriaLabels, generateDataTable, getBreakpoint, getHeightClass, getLayoutStrategy, inferFieldType, isChartSpec, isConditionalDef, isEncodingChannel, isGraphSpec, isLayerSpec, isRangeAnnotation, isRefLineAnnotation, isTableSpec, isTextAnnotation, lineChart, meetsAA, pieChart, resolveCollisions, resolveMarkDef, resolveMarkType, resolveTheme, scatterChart, simulateColorBlindness };