@opendata-ai/openchart-core 6.2.1 → 6.4.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 CHANGED
@@ -177,7 +177,7 @@ interface ColumnConfig {
177
177
  * - 'tick': strip/rug plot marks
178
178
  * - 'rect': heatmaps and 2D binned plots
179
179
  */
180
- type MarkType = 'bar' | 'line' | 'area' | 'point' | 'circle' | 'arc' | 'text' | 'rule' | 'tick' | 'rect';
180
+ type MarkType = 'bar' | 'line' | 'area' | 'point' | 'circle' | 'arc' | 'text' | 'rule' | 'tick' | 'rect' | 'lollipop';
181
181
  /** @deprecated Use MarkType instead. Kept for internal migration references. */
182
182
  type ChartType = MarkType;
183
183
  /**
@@ -455,6 +455,8 @@ interface AnnotationOffset {
455
455
  type AnnotationAnchor = 'top' | 'bottom' | 'left' | 'right' | 'auto';
456
456
  /** Base properties shared by all annotation types. */
457
457
  interface AnnotationBase {
458
+ /** Stable identifier for selection and edit callbacks. When provided, edit events include this ID for reliable element matching. */
459
+ id?: string;
458
460
  /** Human-readable label for the annotation. */
459
461
  label?: string;
460
462
  /** Fill color for the annotation element. */
@@ -618,6 +620,10 @@ interface LegendConfig {
618
620
  offset?: AnnotationOffset;
619
621
  /** Whether to show the legend. Defaults to true. Set to false to hide. */
620
622
  show?: boolean;
623
+ /** Number of columns for horizontal legend layout. Overrides the default row limit. */
624
+ columns?: number;
625
+ /** Max number of legend entries before truncation. Remaining entries show as "+N more". */
626
+ symbolLimit?: number;
621
627
  }
622
628
  /** Data row: a plain object with string keys. */
623
629
  type DataRow = Record<string, unknown>;
@@ -1079,9 +1085,42 @@ declare const GRAPH_ENCODING_RULES: Record<string, GraphChannelRule>;
1079
1085
 
1080
1086
  /** Identifies a specific chrome text element (title, subtitle, source, byline, footer). */
1081
1087
  type ChromeKey = 'title' | 'subtitle' | 'source' | 'byline' | 'footer';
1088
+ /**
1089
+ * Reference to an editable chart element.
1090
+ * Carries enough info to find the element in both the spec and the DOM.
1091
+ * The `annotation` variant uses two-tier identity: `id` (when the consumer provides one)
1092
+ * and `index` (always available, position in the spec's annotations array).
1093
+ */
1094
+ type ElementRef = {
1095
+ type: 'annotation';
1096
+ index: number;
1097
+ id?: string;
1098
+ } | {
1099
+ type: 'chrome';
1100
+ key: ChromeKey;
1101
+ } | {
1102
+ type: 'series-label';
1103
+ series: string;
1104
+ } | {
1105
+ type: 'legend';
1106
+ } | {
1107
+ type: 'legend-entry';
1108
+ series: string;
1109
+ index: number;
1110
+ };
1111
+ /** Helper constructors for ergonomic ElementRef creation. */
1112
+ declare const elementRef: {
1113
+ readonly annotation: (index: number, id?: string) => ElementRef;
1114
+ readonly chrome: (key: ChromeKey) => ElementRef;
1115
+ readonly seriesLabel: (series: string) => ElementRef;
1116
+ readonly legend: () => ElementRef;
1117
+ readonly legendEntry: (series: string, index: number) => ElementRef;
1118
+ };
1082
1119
  /**
1083
1120
  * Discriminated union of all element edit events.
1084
- * Fired by the `onEdit` callback when any editable chart element is repositioned.
1121
+ * Fired by the `onEdit` callback when any editable chart element is modified.
1122
+ * Covers repositioning (drag), deletion (Delete key), and text editing (double-click).
1123
+ * Selection events (onSelect/onDeselect) are separate callbacks, not part of this union.
1085
1124
  */
1086
1125
  type ElementEdit = {
1087
1126
  type: 'annotation';
@@ -1116,6 +1155,14 @@ type ElementEdit = {
1116
1155
  type: 'legend-toggle';
1117
1156
  series: string;
1118
1157
  hidden: boolean;
1158
+ } | {
1159
+ type: 'delete';
1160
+ element: ElementRef;
1161
+ } | {
1162
+ type: 'text-edit';
1163
+ element: ElementRef;
1164
+ oldText: string;
1165
+ newText: string;
1119
1166
  };
1120
1167
  /**
1121
1168
  * Event fired when a user interacts with a data mark (bar, point, line segment, etc.).
@@ -1155,8 +1202,14 @@ interface ChartEventHandlers {
1155
1202
  onAnnotationClick?: (annotation: Annotation, event: MouseEvent) => void;
1156
1203
  /** Called when a text annotation label is dragged to a new position. */
1157
1204
  onAnnotationEdit?: (annotation: TextAnnotation, updatedOffset: AnnotationOffset) => void;
1158
- /** Unified edit callback. Fires for any editable chart element (annotations, chrome, legend, series labels). */
1205
+ /** Unified edit callback. Fires for any spec-modifying edit (repositioning, deletion, text editing). */
1159
1206
  onEdit?: (edit: ElementEdit) => void;
1207
+ /** Fired when an element is selected via click or programmatic select(). */
1208
+ onSelect?: (element: ElementRef) => void;
1209
+ /** Fired when the current element is deselected (click empty, Escape, or new selection replaces old). */
1210
+ onDeselect?: (element: ElementRef) => void;
1211
+ /** Fired when inline text editing commits. Also flows through onEdit as a 'text-edit' event. */
1212
+ onTextEdit?: (element: ElementRef, oldText: string, newText: string) => void;
1160
1213
  }
1161
1214
 
1162
1215
  /**
@@ -1712,6 +1765,8 @@ interface ResolvedLabel {
1712
1765
  interface ResolvedAnnotation {
1713
1766
  /** Original annotation type. */
1714
1767
  type: 'text' | 'range' | 'refline';
1768
+ /** Stable identifier from the spec annotation, for selection/edit callbacks. */
1769
+ id?: string;
1715
1770
  /** Label text (if any). */
1716
1771
  label?: ResolvedLabel;
1717
1772
  /** For range: the highlighted rectangle in pixel coordinates. */
@@ -2342,6 +2397,18 @@ interface LabelCandidate {
2342
2397
  * Detect AABB (axis-aligned bounding box) overlap between two rectangles.
2343
2398
  */
2344
2399
  declare function detectCollision(a: Rect, b: Rect): boolean;
2400
+ /** An offset position to try when resolving a label collision. */
2401
+ interface OffsetStrategy {
2402
+ dx: number;
2403
+ dy: number;
2404
+ }
2405
+ /** Offsets to try when a label collides with an existing placement. */
2406
+ declare const OFFSET_STRATEGIES: readonly OffsetStrategy[];
2407
+ /**
2408
+ * Extended offset strategies with additional vertical spread for dense
2409
+ * multi-series endpoints (e.g. 5+ line series converging at similar y-values).
2410
+ */
2411
+ declare const EXTENDED_OFFSET_STRATEGIES: readonly OffsetStrategy[];
2345
2412
  /**
2346
2413
  * Resolve label collisions using a greedy placement algorithm.
2347
2414
  *
@@ -2351,9 +2418,10 @@ declare function detectCollision(a: Rect, b: Rect): boolean;
2351
2418
  * demoted to tooltip-only (visible: false).
2352
2419
  *
2353
2420
  * @param labels - Array of label candidates to position.
2421
+ * @param strategies - Optional offset strategies to use (defaults to OFFSET_STRATEGIES).
2354
2422
  * @returns Array of resolved labels with computed positions and visibility.
2355
2423
  */
2356
- declare function resolveCollisions(labels: LabelCandidate[]): ResolvedLabel[];
2424
+ declare function resolveCollisions(labels: LabelCandidate[], strategies?: readonly OffsetStrategy[]): ResolvedLabel[];
2357
2425
  /**
2358
2426
  * Compute the bounding rect of a resolved label from its position and text.
2359
2427
  * Uses heuristic text measurement so it works without DOM access.
@@ -2617,4 +2685,4 @@ declare function scatterChart(data: DataRow[], x: FieldRef, y: FieldRef, options
2617
2685
  */
2618
2686
  declare function dataTable(data: DataRow[], options?: TableBuilderOptions): TableSpec;
2619
2687
 
2620
- 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_FONT_SIZE, BRAND_MIN_WIDTH, 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, buildTemporalFormatter, 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 };
2688
+ 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_FONT_SIZE, BRAND_MIN_WIDTH, 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, EXTENDED_OFFSET_STRATEGIES, type ElementEdit, type ElementRef, 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, OFFSET_STRATEGIES, type OffsetStrategy, 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, buildTemporalFormatter, checkPaletteDistinguishability, columnChart, computeChrome, computeLabelBounds, contrastRatio, dataTable, detectCollision, donutChart, dotChart, elementRef, 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 };
package/dist/index.js CHANGED
@@ -44,8 +44,8 @@ var MARK_ENCODING_RULES = {
44
44
  detail: optional("nominal")
45
45
  },
46
46
  point: {
47
- x: required("quantitative"),
48
- y: required("quantitative"),
47
+ x: required("quantitative", "temporal", "nominal", "ordinal"),
48
+ y: required("quantitative", "temporal", "nominal", "ordinal"),
49
49
  color: optional("nominal", "ordinal", "quantitative"),
50
50
  size: optional("quantitative"),
51
51
  shape: optional("nominal", "ordinal"),
@@ -66,6 +66,17 @@ var MARK_ENCODING_RULES = {
66
66
  order: optional("quantitative", "ordinal"),
67
67
  detail: optional("nominal")
68
68
  },
69
+ lollipop: {
70
+ x: required("quantitative"),
71
+ y: required("nominal", "ordinal"),
72
+ color: optional("nominal", "ordinal", "quantitative"),
73
+ size: optional("quantitative"),
74
+ opacity: optional("quantitative"),
75
+ tooltip: optional(),
76
+ href: optional(),
77
+ order: optional("quantitative", "ordinal"),
78
+ detail: optional("nominal")
79
+ },
69
80
  arc: {
70
81
  x: optional(),
71
82
  y: required("quantitative"),
@@ -136,6 +147,19 @@ var GRAPH_ENCODING_RULES = {
136
147
  nodeLabel: { required: false, allowedTypes: [] }
137
148
  };
138
149
 
150
+ // src/types/events.ts
151
+ var elementRef = {
152
+ annotation: (index, id) => ({ type: "annotation", index, id }),
153
+ chrome: (key) => ({ type: "chrome", key }),
154
+ seriesLabel: (series) => ({ type: "series-label", series }),
155
+ legend: () => ({ type: "legend" }),
156
+ legendEntry: (series, index) => ({
157
+ type: "legend-entry",
158
+ series,
159
+ index
160
+ })
161
+ };
162
+
139
163
  // src/types/spec.ts
140
164
  function isEncodingChannel(def) {
141
165
  if (!def) return false;
@@ -155,7 +179,8 @@ var MARK_TYPES = /* @__PURE__ */ new Set([
155
179
  "text",
156
180
  "rule",
157
181
  "tick",
158
- "rect"
182
+ "rect",
183
+ "lollipop"
159
184
  ]);
160
185
  var CHART_TYPES = MARK_TYPES;
161
186
  function resolveMarkType(mark) {
@@ -196,7 +221,8 @@ var MARK_DISPLAY_NAMES = {
196
221
  text: "Text chart",
197
222
  rule: "Rule chart",
198
223
  tick: "Tick plot",
199
- rect: "Heatmap"
224
+ rect: "Heatmap",
225
+ lollipop: "Lollipop chart"
200
226
  };
201
227
 
202
228
  // ../../node_modules/.bun/d3-color@3.1.0/node_modules/d3-color/src/define.js
@@ -1293,7 +1319,22 @@ var OFFSET_STRATEGIES = [
1293
1319
  { dx: -1.1, dy: -1.2 }
1294
1320
  // upper-left
1295
1321
  ];
1296
- function resolveCollisions(labels) {
1322
+ var EXTENDED_OFFSET_STRATEGIES = [
1323
+ ...OFFSET_STRATEGIES,
1324
+ { dx: 0, dy: -2.4 },
1325
+ // further above
1326
+ { dx: 0, dy: 2.4 },
1327
+ // further below
1328
+ { dx: 0, dy: -3.6 },
1329
+ // even further above
1330
+ { dx: 0, dy: 3.6 },
1331
+ // even further below
1332
+ { dx: 1.1, dy: -2.4 },
1333
+ // upper-right far
1334
+ { dx: 1.1, dy: 2.4 }
1335
+ // lower-right far
1336
+ ];
1337
+ function resolveCollisions(labels, strategies = OFFSET_STRATEGIES) {
1297
1338
  const sorted = [...labels].sort(
1298
1339
  (a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]
1299
1340
  );
@@ -1303,7 +1344,7 @@ function resolveCollisions(labels) {
1303
1344
  let bestRect = null;
1304
1345
  let bestX = label.anchorX;
1305
1346
  let bestY = label.anchorY;
1306
- for (const offset of OFFSET_STRATEGIES) {
1347
+ for (const offset of strategies) {
1307
1348
  const candidateX = label.anchorX + offset.dx * label.width;
1308
1349
  const candidateY = label.anchorY + offset.dy * label.height;
1309
1350
  const candidateRect = {
@@ -2698,10 +2739,12 @@ export {
2698
2739
  CHART_TYPES,
2699
2740
  DEFAULT_THEME,
2700
2741
  DIVERGING_PALETTES,
2742
+ EXTENDED_OFFSET_STRATEGIES,
2701
2743
  GRAPH_ENCODING_RULES,
2702
2744
  MARK_DISPLAY_NAMES,
2703
2745
  MARK_ENCODING_RULES,
2704
2746
  MARK_TYPES,
2747
+ OFFSET_STRATEGIES,
2705
2748
  SEQUENTIAL_PALETTES,
2706
2749
  abbreviateNumber,
2707
2750
  adaptColorForDarkMode,
@@ -2719,6 +2762,7 @@ export {
2719
2762
  detectCollision,
2720
2763
  donutChart,
2721
2764
  dotChart,
2765
+ elementRef,
2722
2766
  estimateTextWidth,
2723
2767
  findAccessibleColor,
2724
2768
  formatDate,