@zuilib/charts 0.3.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.
Files changed (41) hide show
  1. package/README.md +140 -0
  2. package/dist/authoring.d.ts +47 -0
  3. package/dist/authoring.js +11 -0
  4. package/dist/chart-defaults.d.ts +60 -0
  5. package/dist/chart-defaults.js +24 -0
  6. package/dist/chart-frame-B9fxUxGG.d.ts +90 -0
  7. package/dist/chart-frame.d.ts +4 -0
  8. package/dist/chart-frame.js +14 -0
  9. package/dist/chart-legend.d.ts +25 -0
  10. package/dist/chart-legend.js +13 -0
  11. package/dist/chart-spec-CH0tAkLG.d.ts +226 -0
  12. package/dist/chart-tooltip.d.ts +44 -0
  13. package/dist/chart-tooltip.js +11 -0
  14. package/dist/chart.d.ts +78 -0
  15. package/dist/chart.js +24 -0
  16. package/dist/chunk-3VGLTPGL.js +19 -0
  17. package/dist/chunk-6QTIAMA3.js +169 -0
  18. package/dist/chunk-7WABBHMT.js +88 -0
  19. package/dist/chunk-7WJ26NHR.js +48 -0
  20. package/dist/chunk-BFTWWI46.js +148 -0
  21. package/dist/chunk-D7K23UFP.js +43 -0
  22. package/dist/chunk-G4FXJJ66.js +169 -0
  23. package/dist/chunk-HNJKYOPE.js +45 -0
  24. package/dist/chunk-IPOBQIYU.js +13 -0
  25. package/dist/chunk-MJDIQVJX.js +148 -0
  26. package/dist/chunk-PV27RZSV.js +61 -0
  27. package/dist/chunk-SHQZRND7.js +83 -0
  28. package/dist/chunk-UN3XPBZ5.js +17 -0
  29. package/dist/chunk-WVWGHGZE.js +90 -0
  30. package/dist/chunk-YMPZODMC.js +1084 -0
  31. package/dist/cross-filter.d.ts +62 -0
  32. package/dist/cross-filter.js +13 -0
  33. package/dist/format.d.ts +17 -0
  34. package/dist/format.js +7 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.js +93 -0
  37. package/dist/interop.d.ts +46 -0
  38. package/dist/interop.js +12 -0
  39. package/dist/registry.d.ts +111 -0
  40. package/dist/registry.js +25 -0
  41. package/package.json +98 -0
@@ -0,0 +1,1084 @@
1
+ import {
2
+ activeCategoryValues,
3
+ categoryOf,
4
+ markDimOpacity,
5
+ reportMarkClick
6
+ } from "./chunk-HNJKYOPE.js";
7
+ import {
8
+ warnOnce
9
+ } from "./chunk-3VGLTPGL.js";
10
+ import {
11
+ ChartTooltipPanel
12
+ } from "./chunk-PV27RZSV.js";
13
+ import {
14
+ ChartLegendList
15
+ } from "./chunk-SHQZRND7.js";
16
+ import {
17
+ cartesianGridDefaults,
18
+ chartColorVar,
19
+ seriesColorVar,
20
+ tooltipCrosshairDefaults,
21
+ tooltipCursorDefaults,
22
+ xAxisDefaults,
23
+ yAxisDefaults
24
+ } from "./chunk-7WJ26NHR.js";
25
+
26
+ // src/charts/area.tsx
27
+ import { Area, AreaChart } from "recharts";
28
+
29
+ // src/charts/cartesian.tsx
30
+ import { Brush, CartesianGrid, Legend, ReferenceLine, Tooltip, XAxis, YAxis } from "recharts";
31
+ import { jsx } from "react/jsx-runtime";
32
+ function stackIdOf(series, stacked) {
33
+ return series.stackId ?? (stacked ? "stack" : void 0);
34
+ }
35
+ function valueFormatOf(spec, stacked) {
36
+ return stacked === "percent" ? "percent" : spec.yAxis?.format ?? "number";
37
+ }
38
+ function renderXAxis(xKey, spec, formats, options) {
39
+ const axis = spec.xAxis ?? {};
40
+ const numeric = options?.numeric || axis.scale !== void 0 && axis.scale !== "band";
41
+ return /* @__PURE__ */ jsx(
42
+ XAxis,
43
+ {
44
+ dataKey: xKey,
45
+ ...xAxisDefaults,
46
+ type: numeric ? "number" : "category",
47
+ ...axis.scale === "log" ? { scale: "log", domain: ["auto", "auto"] } : {},
48
+ ...axis.scale === "time" ? { domain: ["dataMin", "dataMax"] } : {},
49
+ hide: axis.hidden,
50
+ tickCount: axis.tickCount,
51
+ tickFormatter: formats.resolve(axis.format, "none"),
52
+ label: axis.label ? { value: axis.label, position: "insideBottom", offset: -4, fill: "var(--muted-foreground)" } : void 0
53
+ },
54
+ "x"
55
+ );
56
+ }
57
+ function renderYAxes(spec, formats, valueFormat, hasSecondary) {
58
+ const y = spec.yAxis ?? {};
59
+ const axes = [
60
+ /* @__PURE__ */ jsx(
61
+ YAxis,
62
+ {
63
+ yAxisId: "primary",
64
+ ...yAxisDefaults,
65
+ hide: y.hidden,
66
+ domain: y.domain,
67
+ tickCount: y.tickCount,
68
+ tickFormatter: formats.resolve(y.format, valueFormat),
69
+ label: y.label ? { value: y.label, angle: -90, position: "insideLeft", fill: "var(--muted-foreground)" } : void 0
70
+ },
71
+ "y"
72
+ )
73
+ ];
74
+ if (hasSecondary) {
75
+ const secondary = spec.secondaryAxis ?? {};
76
+ axes.push(
77
+ /* @__PURE__ */ jsx(
78
+ YAxis,
79
+ {
80
+ yAxisId: "secondary",
81
+ orientation: "right",
82
+ ...yAxisDefaults,
83
+ hide: secondary.hidden,
84
+ domain: secondary.domain,
85
+ tickCount: secondary.tickCount,
86
+ tickFormatter: formats.resolve(secondary.format, "number"),
87
+ label: secondary.label ? { value: secondary.label, angle: 90, position: "insideRight", fill: "var(--muted-foreground)" } : void 0
88
+ },
89
+ "y-secondary"
90
+ )
91
+ );
92
+ }
93
+ return axes;
94
+ }
95
+ function yAxisIdOf(series) {
96
+ return series.axis === "secondary" ? "secondary" : "primary";
97
+ }
98
+ function renderGrid(spec) {
99
+ if (spec.grid === false) return null;
100
+ const grid = typeof spec.grid === "object" ? spec.grid : {};
101
+ return /* @__PURE__ */ jsx(
102
+ CartesianGrid,
103
+ {
104
+ ...cartesianGridDefaults,
105
+ horizontal: grid.horizontal ?? true,
106
+ vertical: grid.vertical ?? false
107
+ },
108
+ "grid"
109
+ );
110
+ }
111
+ function renderReferenceLines(spec) {
112
+ return (spec.referenceLines ?? []).map((line, index) => /* @__PURE__ */ jsx(
113
+ ReferenceLine,
114
+ {
115
+ ...line.axis === "x" ? { x: line.value } : { y: line.value },
116
+ yAxisId: line.axis === "y2" ? "secondary" : "primary",
117
+ stroke: line.paletteSlot ? chartColorVar(line.paletteSlot) : "var(--muted-foreground)",
118
+ strokeDasharray: line.dashed === false ? void 0 : "4 4",
119
+ label: line.label ? { value: line.label, position: line.axis === "x" ? "top" : "insideTopRight", fill: "var(--muted-foreground)", fontSize: 12 } : void 0
120
+ },
121
+ `ref-${line.axis}-${String(line.value)}-${index}`
122
+ ));
123
+ }
124
+ function renderBrush(xKey, spec) {
125
+ if (!spec.brush) return null;
126
+ return /* @__PURE__ */ jsx(
127
+ Brush,
128
+ {
129
+ dataKey: xKey,
130
+ height: 24,
131
+ stroke: "var(--muted-foreground)",
132
+ fill: "var(--muted)",
133
+ travellerWidth: 8
134
+ },
135
+ "brush"
136
+ );
137
+ }
138
+ function legendEnabled(spec, entryCount) {
139
+ if (spec.legend === void 0) return entryCount >= 2;
140
+ return spec.legend !== false;
141
+ }
142
+ function renderLegend(spec, entryCount) {
143
+ if (!legendEnabled(spec, entryCount)) return null;
144
+ const placement = typeof spec.legend === "object" ? spec.legend.placement : "bottom";
145
+ return /* @__PURE__ */ jsx(Legend, { verticalAlign: placement, content: /* @__PURE__ */ jsx(ChartLegendList, {}) }, "legend");
146
+ }
147
+ function renderTooltip(spec, valueFormat, cursor) {
148
+ if (spec.tooltip === false) return null;
149
+ return /* @__PURE__ */ jsx(
150
+ Tooltip,
151
+ {
152
+ cursor,
153
+ content: /* @__PURE__ */ jsx(ChartTooltipPanel, { labelFormat: spec.xAxis?.format, valueFormat })
154
+ },
155
+ "tooltip"
156
+ );
157
+ }
158
+ function chartClickHandler(spec, rows, interaction) {
159
+ return (state, event) => {
160
+ const value = state?.activeLabel;
161
+ if (value === void 0 || value === null || value === "") return;
162
+ const row = rows.find((r) => r[spec.xKey] === value) ?? {};
163
+ const additive = Boolean(event?.shiftKey);
164
+ reportMarkClick(interaction, value, void 0, row, additive);
165
+ };
166
+ }
167
+ function warnOnSpecIssues(spec) {
168
+ const count = spec.series?.length ?? 0;
169
+ if (count > 8) {
170
+ warnOnce(
171
+ `series-${spec.type}-${count}`,
172
+ `@zuilib/charts: ${spec.type} spec declares ${count} series; the palette has 8 slots and never cycles \u2014 fold the rest into "Other" or use small multiples.`
173
+ );
174
+ }
175
+ }
176
+
177
+ // src/charts/area.tsx
178
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
179
+ function AreaChartRenderer({
180
+ spec,
181
+ rows,
182
+ formats,
183
+ hiddenSeries,
184
+ markInteraction,
185
+ width,
186
+ height,
187
+ animate
188
+ }) {
189
+ warnOnSpecIssues(spec);
190
+ const hasSecondary = spec.series.some((s) => s.axis === "secondary");
191
+ const valueFormat = valueFormatOf(spec, spec.stacked);
192
+ return /* @__PURE__ */ jsxs(
193
+ AreaChart,
194
+ {
195
+ data: rows,
196
+ width,
197
+ height,
198
+ onClick: chartClickHandler(spec, rows, markInteraction),
199
+ stackOffset: spec.stacked === "percent" ? "expand" : void 0,
200
+ margin: { top: 8, bottom: 4 },
201
+ children: [
202
+ renderGrid(spec),
203
+ renderXAxis(spec.xKey, spec, formats),
204
+ renderYAxes(spec, formats, valueFormat, hasSecondary),
205
+ renderTooltip(spec, valueFormat, tooltipCrosshairDefaults),
206
+ renderLegend(spec, spec.series.length),
207
+ renderReferenceLines(spec),
208
+ spec.series.map((series) => /* @__PURE__ */ jsx2(
209
+ Area,
210
+ {
211
+ yAxisId: yAxisIdOf(series),
212
+ dataKey: series.field,
213
+ name: series.label ?? series.field,
214
+ type: spec.curve ?? "monotone",
215
+ stackId: stackIdOf(series, spec.stacked),
216
+ stroke: seriesColorVar(series.field),
217
+ strokeWidth: 2,
218
+ fill: seriesColorVar(series.field),
219
+ fillOpacity: 0.2,
220
+ dot: false,
221
+ activeDot: { r: 4, strokeWidth: 2, stroke: "var(--background)" },
222
+ hide: hiddenSeries.includes(series.field),
223
+ isAnimationActive: animate
224
+ },
225
+ series.field
226
+ )),
227
+ renderBrush(spec.xKey, spec)
228
+ ]
229
+ }
230
+ );
231
+ }
232
+
233
+ // src/charts/bar.tsx
234
+ import { Bar, BarChart, Cell, XAxis as XAxis2, YAxis as YAxis2 } from "recharts";
235
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
236
+ function BarChartRenderer({
237
+ spec,
238
+ rows,
239
+ formats,
240
+ hiddenSeries,
241
+ markInteraction,
242
+ width,
243
+ height,
244
+ animate
245
+ }) {
246
+ warnOnSpecIssues(spec);
247
+ const horizontal = spec.orientation === "horizontal";
248
+ const hasSecondary = !horizontal && spec.series.some((s) => s.axis === "secondary");
249
+ const valueFormat = valueFormatOf(spec, spec.stacked);
250
+ const active = activeCategoryValues(markInteraction);
251
+ const radius = spec.stacked ? [0, 0, 0, 0] : horizontal ? [0, 4, 4, 0] : [4, 4, 0, 0];
252
+ const bars = spec.series.map((series) => /* @__PURE__ */ jsx3(
253
+ Bar,
254
+ {
255
+ yAxisId: horizontal ? void 0 : yAxisIdOf(series),
256
+ dataKey: series.field,
257
+ name: series.label ?? series.field,
258
+ stackId: stackIdOf(series, spec.stacked),
259
+ fill: seriesColorVar(series.field),
260
+ radius,
261
+ stroke: spec.stacked ? "var(--background)" : void 0,
262
+ strokeWidth: spec.stacked ? 2 : 0,
263
+ hide: hiddenSeries.includes(series.field),
264
+ isAnimationActive: animate,
265
+ children: rows.map((row, index) => /* @__PURE__ */ jsx3(Cell, { opacity: markDimOpacity(active, row[spec.xKey]) }, `${String(row[spec.xKey])}-${index}`))
266
+ },
267
+ series.field
268
+ ));
269
+ if (horizontal) {
270
+ return /* @__PURE__ */ jsxs2(
271
+ BarChart,
272
+ {
273
+ data: rows,
274
+ width,
275
+ height,
276
+ layout: "vertical",
277
+ onClick: chartClickHandler(spec, rows, markInteraction),
278
+ margin: { top: 8, bottom: 4 },
279
+ children: [
280
+ renderGrid(spec),
281
+ /* @__PURE__ */ jsx3(
282
+ XAxis2,
283
+ {
284
+ type: "number",
285
+ ...xAxisDefaults,
286
+ hide: spec.yAxis?.hidden,
287
+ domain: spec.yAxis?.domain,
288
+ tickFormatter: formats.resolve(spec.yAxis?.format, valueFormat)
289
+ },
290
+ "x"
291
+ ),
292
+ /* @__PURE__ */ jsx3(
293
+ YAxis2,
294
+ {
295
+ type: "category",
296
+ dataKey: spec.xKey,
297
+ ...yAxisDefaults,
298
+ hide: spec.xAxis?.hidden,
299
+ tickFormatter: formats.resolve(spec.xAxis?.format, "none")
300
+ },
301
+ "y"
302
+ ),
303
+ renderTooltip(spec, valueFormat, tooltipCursorDefaults),
304
+ renderLegend(spec, spec.series.length),
305
+ bars
306
+ ]
307
+ }
308
+ );
309
+ }
310
+ return /* @__PURE__ */ jsxs2(
311
+ BarChart,
312
+ {
313
+ data: rows,
314
+ width,
315
+ height,
316
+ onClick: chartClickHandler(spec, rows, markInteraction),
317
+ stackOffset: spec.stacked === "percent" ? "expand" : void 0,
318
+ margin: { top: 8, bottom: 4 },
319
+ children: [
320
+ renderGrid(spec),
321
+ renderXAxis(spec.xKey, spec, formats),
322
+ renderYAxes(spec, formats, valueFormat, hasSecondary),
323
+ renderTooltip(spec, valueFormat, tooltipCursorDefaults),
324
+ renderLegend(spec, spec.series.length),
325
+ renderReferenceLines(spec),
326
+ bars,
327
+ renderBrush(spec.xKey, spec)
328
+ ]
329
+ }
330
+ );
331
+ }
332
+
333
+ // src/charts/composed.tsx
334
+ import { Area as Area2, Bar as Bar2, ComposedChart, Line } from "recharts";
335
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
336
+ function renderSeries(series, spec, hidden, animate) {
337
+ const shared = {
338
+ key: series.field,
339
+ yAxisId: yAxisIdOf(series),
340
+ dataKey: series.field,
341
+ name: series.label ?? series.field,
342
+ hide: hidden,
343
+ isAnimationActive: animate
344
+ };
345
+ const color = seriesColorVar(series.field);
346
+ switch (series.mark ?? "bar") {
347
+ case "line":
348
+ return /* @__PURE__ */ jsx4(
349
+ Line,
350
+ {
351
+ ...shared,
352
+ type: "monotone",
353
+ stroke: color,
354
+ strokeWidth: 2,
355
+ dot: false,
356
+ activeDot: { r: 4, strokeWidth: 2, stroke: "var(--background)" }
357
+ }
358
+ );
359
+ case "area":
360
+ return /* @__PURE__ */ jsx4(Area2, { ...shared, type: "monotone", stroke: color, strokeWidth: 2, fill: color, fillOpacity: 0.2, dot: false });
361
+ default:
362
+ return /* @__PURE__ */ jsx4(
363
+ Bar2,
364
+ {
365
+ ...shared,
366
+ stackId: stackIdOf(series, spec.stacked),
367
+ fill: color,
368
+ radius: spec.stacked ? [0, 0, 0, 0] : [4, 4, 0, 0]
369
+ }
370
+ );
371
+ }
372
+ }
373
+ function ComposedChartRenderer({
374
+ spec,
375
+ rows,
376
+ formats,
377
+ hiddenSeries,
378
+ markInteraction,
379
+ width,
380
+ height,
381
+ animate
382
+ }) {
383
+ warnOnSpecIssues(spec);
384
+ const hasSecondary = spec.series.some((s) => s.axis === "secondary");
385
+ const valueFormat = valueFormatOf(spec);
386
+ return /* @__PURE__ */ jsxs3(
387
+ ComposedChart,
388
+ {
389
+ data: rows,
390
+ width,
391
+ height,
392
+ onClick: chartClickHandler(spec, rows, markInteraction),
393
+ margin: { top: 8, bottom: 4 },
394
+ children: [
395
+ renderGrid(spec),
396
+ renderXAxis(spec.xKey, spec, formats),
397
+ renderYAxes(spec, formats, valueFormat, hasSecondary),
398
+ renderTooltip(spec, valueFormat, tooltipCursorDefaults),
399
+ renderLegend(spec, spec.series.length),
400
+ renderReferenceLines(spec),
401
+ spec.series.map((series) => renderSeries(series, spec, hiddenSeries.includes(series.field), animate)),
402
+ renderBrush(spec.xKey, spec)
403
+ ]
404
+ }
405
+ );
406
+ }
407
+
408
+ // src/charts/funnel.tsx
409
+ import { Cell as Cell2, Funnel, FunnelChart, LabelList, Tooltip as Tooltip2 } from "recharts";
410
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
411
+ function FunnelChartRenderer({
412
+ spec,
413
+ rows,
414
+ markInteraction,
415
+ width,
416
+ height,
417
+ animate
418
+ }) {
419
+ const active = activeCategoryValues(markInteraction);
420
+ return /* @__PURE__ */ jsxs4(FunnelChart, { width, height, margin: { top: 8, bottom: 4 }, children: [
421
+ spec.tooltip !== false && /* @__PURE__ */ jsx5(Tooltip2, { content: /* @__PURE__ */ jsx5(ChartTooltipPanel, { showLabel: false, valueFormat: spec.format ?? "number" }) }),
422
+ renderLegend(spec, rows.length),
423
+ /* @__PURE__ */ jsxs4(
424
+ Funnel,
425
+ {
426
+ data: rows,
427
+ dataKey: spec.valueKey,
428
+ nameKey: spec.nameKey,
429
+ stroke: "var(--background)",
430
+ strokeWidth: 2,
431
+ isAnimationActive: animate,
432
+ onClick: (entry, index, event) => {
433
+ const row = entry?.payload ?? rows[index] ?? {};
434
+ const value = categoryOf(row, spec.nameKey);
435
+ if (value === null) return;
436
+ reportMarkClick(markInteraction, value, void 0, row, Boolean(event?.shiftKey));
437
+ },
438
+ children: [
439
+ /* @__PURE__ */ jsx5(LabelList, { dataKey: spec.nameKey, position: "right", fill: "var(--muted-foreground)", stroke: "none", fontSize: 12 }),
440
+ rows.map((row, index) => /* @__PURE__ */ jsx5(
441
+ Cell2,
442
+ {
443
+ fill: chartColorVar(index + 1),
444
+ opacity: markDimOpacity(active, row[spec.nameKey])
445
+ },
446
+ `${String(row[spec.nameKey])}-${index}`
447
+ ))
448
+ ]
449
+ }
450
+ )
451
+ ] });
452
+ }
453
+
454
+ // src/charts/line.tsx
455
+ import { Line as Line2, LineChart } from "recharts";
456
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
457
+ function LineChartRenderer({
458
+ spec,
459
+ rows,
460
+ formats,
461
+ hiddenSeries,
462
+ markInteraction,
463
+ width,
464
+ height,
465
+ animate
466
+ }) {
467
+ warnOnSpecIssues(spec);
468
+ const hasSecondary = spec.series.some((s) => s.axis === "secondary");
469
+ const valueFormat = valueFormatOf(spec);
470
+ return /* @__PURE__ */ jsxs5(
471
+ LineChart,
472
+ {
473
+ data: rows,
474
+ width,
475
+ height,
476
+ onClick: chartClickHandler(spec, rows, markInteraction),
477
+ margin: { top: 8, bottom: 4 },
478
+ children: [
479
+ renderGrid(spec),
480
+ renderXAxis(spec.xKey, spec, formats),
481
+ renderYAxes(spec, formats, valueFormat, hasSecondary),
482
+ renderTooltip(spec, valueFormat, tooltipCrosshairDefaults),
483
+ renderLegend(spec, spec.series.length),
484
+ renderReferenceLines(spec),
485
+ spec.series.map((series) => /* @__PURE__ */ jsx6(
486
+ Line2,
487
+ {
488
+ yAxisId: yAxisIdOf(series),
489
+ dataKey: series.field,
490
+ name: series.label ?? series.field,
491
+ type: spec.curve ?? "monotone",
492
+ stroke: seriesColorVar(series.field),
493
+ strokeWidth: 2,
494
+ dot: spec.dots ? { r: 3, fill: seriesColorVar(series.field), strokeWidth: 0 } : false,
495
+ activeDot: { r: 4, strokeWidth: 2, stroke: "var(--background)" },
496
+ hide: hiddenSeries.includes(series.field),
497
+ isAnimationActive: animate
498
+ },
499
+ series.field
500
+ )),
501
+ renderBrush(spec.xKey, spec)
502
+ ]
503
+ }
504
+ );
505
+ }
506
+
507
+ // src/charts/pie.tsx
508
+ import { Cell as Cell3, Pie, PieChart, Tooltip as Tooltip3 } from "recharts";
509
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
510
+ function PieChartRenderer({ spec, rows, markInteraction, width, height, animate }) {
511
+ const active = activeCategoryValues(markInteraction);
512
+ return /* @__PURE__ */ jsxs6(PieChart, { width, height, margin: { top: 8, bottom: 4 }, children: [
513
+ spec.tooltip !== false && /* @__PURE__ */ jsx7(Tooltip3, { content: /* @__PURE__ */ jsx7(ChartTooltipPanel, { showLabel: false, valueFormat: spec.format ?? "number" }) }),
514
+ renderLegend(spec, rows.length),
515
+ /* @__PURE__ */ jsx7(
516
+ Pie,
517
+ {
518
+ data: rows,
519
+ dataKey: spec.valueKey,
520
+ nameKey: spec.nameKey,
521
+ innerRadius: spec.type === "donut" ? "55%" : 0,
522
+ stroke: "var(--background)",
523
+ strokeWidth: 2,
524
+ paddingAngle: spec.type === "donut" ? 1 : 0,
525
+ isAnimationActive: animate,
526
+ label: spec.labels ? { fill: "var(--muted-foreground)", fontSize: 12 } : false,
527
+ labelLine: spec.labels ? { stroke: "var(--border)" } : false,
528
+ onClick: (entry, index, event) => {
529
+ const row = entry?.payload ?? rows[index] ?? {};
530
+ const value = categoryOf(row, spec.nameKey);
531
+ if (value === null) return;
532
+ reportMarkClick(markInteraction, value, void 0, row, Boolean(event?.shiftKey));
533
+ },
534
+ children: rows.map((row, index) => /* @__PURE__ */ jsx7(
535
+ Cell3,
536
+ {
537
+ fill: chartColorVar(index + 1),
538
+ opacity: markDimOpacity(active, row[spec.nameKey])
539
+ },
540
+ `${String(row[spec.nameKey])}-${index}`
541
+ ))
542
+ }
543
+ )
544
+ ] });
545
+ }
546
+
547
+ // src/charts/radar.tsx
548
+ import { PolarAngleAxis, PolarGrid, PolarRadiusAxis, Radar, RadarChart, Tooltip as Tooltip4 } from "recharts";
549
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
550
+ function RadarChartRenderer({
551
+ spec,
552
+ rows,
553
+ formats,
554
+ hiddenSeries,
555
+ width,
556
+ height,
557
+ animate
558
+ }) {
559
+ warnOnSpecIssues(spec);
560
+ return /* @__PURE__ */ jsxs7(RadarChart, { data: rows, width, height, margin: { top: 8, bottom: 4 }, children: [
561
+ /* @__PURE__ */ jsx8(PolarGrid, { stroke: "var(--border)" }),
562
+ /* @__PURE__ */ jsx8(
563
+ PolarAngleAxis,
564
+ {
565
+ dataKey: spec.xKey,
566
+ tick: { fill: "var(--muted-foreground)", fontSize: 12 },
567
+ tickFormatter: formats.resolve(void 0, "none")
568
+ }
569
+ ),
570
+ /* @__PURE__ */ jsx8(PolarRadiusAxis, { tick: false, axisLine: false }),
571
+ spec.tooltip !== false && /* @__PURE__ */ jsx8(Tooltip4, { content: /* @__PURE__ */ jsx8(ChartTooltipPanel, { valueFormat: "number" }) }),
572
+ renderLegend(spec, spec.series.length),
573
+ spec.series.map((series) => /* @__PURE__ */ jsx8(
574
+ Radar,
575
+ {
576
+ dataKey: series.field,
577
+ name: series.label ?? series.field,
578
+ stroke: seriesColorVar(series.field),
579
+ strokeWidth: 2,
580
+ fill: seriesColorVar(series.field),
581
+ fillOpacity: spec.filled === false ? 0 : 0.2,
582
+ hide: hiddenSeries.includes(series.field),
583
+ isAnimationActive: animate
584
+ },
585
+ series.field
586
+ ))
587
+ ] });
588
+ }
589
+
590
+ // src/charts/radial-bar.tsx
591
+ import { Cell as Cell4, PolarAngleAxis as PolarAngleAxis2, RadialBar, RadialBarChart, Tooltip as Tooltip5 } from "recharts";
592
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
593
+ function RadialBarChartRenderer({
594
+ spec,
595
+ rows,
596
+ markInteraction,
597
+ width,
598
+ height,
599
+ animate
600
+ }) {
601
+ const active = activeCategoryValues(markInteraction);
602
+ const max = spec.max ?? rows.reduce((top, row) => {
603
+ const value = row[spec.valueKey];
604
+ return typeof value === "number" && value > top ? value : top;
605
+ }, 0);
606
+ return /* @__PURE__ */ jsxs8(
607
+ RadialBarChart,
608
+ {
609
+ data: rows,
610
+ width,
611
+ height,
612
+ innerRadius: "25%",
613
+ outerRadius: "100%",
614
+ startAngle: 90,
615
+ endAngle: -270,
616
+ margin: { top: 8, bottom: 4 },
617
+ children: [
618
+ /* @__PURE__ */ jsx9(PolarAngleAxis2, { type: "number", domain: [spec.min ?? 0, max], tick: false }),
619
+ spec.tooltip !== false && /* @__PURE__ */ jsx9(Tooltip5, { content: /* @__PURE__ */ jsx9(ChartTooltipPanel, { showLabel: false, valueFormat: spec.format ?? "number" }) }),
620
+ renderLegend(spec, rows.length),
621
+ /* @__PURE__ */ jsx9(
622
+ RadialBar,
623
+ {
624
+ dataKey: spec.valueKey,
625
+ background: { fill: "var(--muted)" },
626
+ cornerRadius: 4,
627
+ isAnimationActive: animate,
628
+ onClick: (entry, index, event) => {
629
+ const row = entry?.payload ?? rows[index] ?? {};
630
+ const value = categoryOf(row, spec.nameKey);
631
+ if (value === null) return;
632
+ reportMarkClick(markInteraction, value, void 0, row, Boolean(event?.shiftKey));
633
+ },
634
+ children: rows.map((row, index) => /* @__PURE__ */ jsx9(
635
+ Cell4,
636
+ {
637
+ fill: chartColorVar(index + 1),
638
+ opacity: markDimOpacity(active, row[spec.nameKey])
639
+ },
640
+ `${String(row[spec.nameKey])}-${index}`
641
+ ))
642
+ }
643
+ )
644
+ ]
645
+ }
646
+ );
647
+ }
648
+
649
+ // src/charts/scatter.tsx
650
+ import { Scatter, ScatterChart, ZAxis } from "recharts";
651
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
652
+ var SCATTER_MAX_GROUPS = 3;
653
+ function ScatterChartRenderer({
654
+ spec,
655
+ rows,
656
+ formats,
657
+ markInteraction,
658
+ width,
659
+ height,
660
+ animate
661
+ }) {
662
+ const groups = spec.groupKey ? [...new Set(rows.map((row) => categoryOf(row, spec.groupKey)).filter((v) => v !== null))] : [null];
663
+ if (groups.length > SCATTER_MAX_GROUPS) {
664
+ warnOnce(
665
+ `scatter-${spec.groupKey}`,
666
+ `@zuilib/charts: scatter groups by "${spec.groupKey}" into ${groups.length} groups; only the first ${SCATTER_MAX_GROUPS} palette slots are validated for all-pairs discrimination \u2014 facet or filter instead.`
667
+ );
668
+ }
669
+ const active = activeCategoryValues(markInteraction);
670
+ const valueFormat = spec.yAxis?.format ?? "number";
671
+ return /* @__PURE__ */ jsxs9(ScatterChart, { width, height, margin: { top: 8, bottom: 4 }, children: [
672
+ renderGrid(spec),
673
+ renderXAxis(spec.xKey, spec, formats, { numeric: true }),
674
+ renderYAxes(spec, formats, valueFormat, false),
675
+ spec.sizeKey && /* @__PURE__ */ jsx10(ZAxis, { dataKey: spec.sizeKey, range: spec.sizeRange ?? [64, 400] }),
676
+ renderTooltip(spec, valueFormat, tooltipCrosshairDefaults),
677
+ spec.groupKey ? renderLegend(spec, groups.length) : null,
678
+ renderReferenceLines(spec),
679
+ groups.map((group, index) => {
680
+ const groupRows = group === null ? rows : rows.filter((row) => row[spec.groupKey] === group);
681
+ return /* @__PURE__ */ jsx10(
682
+ Scatter,
683
+ {
684
+ yAxisId: "primary",
685
+ name: group === null ? void 0 : String(group),
686
+ data: groupRows,
687
+ dataKey: spec.yKey,
688
+ fill: chartColorVar(index + 1),
689
+ stroke: "var(--background)",
690
+ strokeWidth: 2,
691
+ isAnimationActive: animate,
692
+ opacity: group === null ? void 0 : markDimOpacity(active, group),
693
+ onClick: (entry, _index, event) => {
694
+ const row = entry?.payload ?? {};
695
+ const value = group ?? categoryOf(row, spec.xKey);
696
+ if (value === null) return;
697
+ reportMarkClick(markInteraction, value, void 0, row, Boolean(event?.shiftKey));
698
+ }
699
+ },
700
+ group === null ? "all" : String(group)
701
+ );
702
+ })
703
+ ] });
704
+ }
705
+
706
+ // src/charts/treemap.tsx
707
+ import { Tooltip as Tooltip6, Treemap } from "recharts";
708
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
709
+ function TreemapNode({
710
+ x = 0,
711
+ y = 0,
712
+ width = 0,
713
+ height = 0,
714
+ depth = 0,
715
+ name,
716
+ root,
717
+ colorOf,
718
+ opacityOf,
719
+ onNodeClick
720
+ }) {
721
+ if (depth === 0) return null;
722
+ const groupName = depth === 1 ? name : root?.name;
723
+ const leaf = depth >= 1;
724
+ const showLabel = leaf && width > 48 && height > 24;
725
+ return /* @__PURE__ */ jsxs10("g", { onClick: (event) => onNodeClick(name, event), style: { cursor: "pointer" }, children: [
726
+ /* @__PURE__ */ jsx11(
727
+ "rect",
728
+ {
729
+ x,
730
+ y,
731
+ width,
732
+ height,
733
+ fill: colorOf(groupName),
734
+ opacity: opacityOf(name),
735
+ stroke: "var(--background)",
736
+ strokeWidth: 2
737
+ }
738
+ ),
739
+ showLabel && /* @__PURE__ */ jsx11("text", { x: x + 6, y: y + 16, fill: "var(--background)", fontSize: 12, pointerEvents: "none", children: name })
740
+ ] });
741
+ }
742
+ function TreemapChartRenderer({ spec, rows, markInteraction, width, height }) {
743
+ const active = activeCategoryValues(markInteraction);
744
+ const groups = [];
745
+ let treeRows = rows;
746
+ if (spec.groupKey) {
747
+ const byGroup = /* @__PURE__ */ new Map();
748
+ for (const row of rows) {
749
+ const group = String(row[spec.groupKey] ?? "");
750
+ if (!byGroup.has(group)) byGroup.set(group, []);
751
+ byGroup.get(group)?.push(row);
752
+ }
753
+ groups.push(...byGroup.keys());
754
+ treeRows = groups.map((group) => ({
755
+ [spec.nameKey]: group,
756
+ children: byGroup.get(group)
757
+ }));
758
+ } else {
759
+ groups.push(...rows.map((row) => String(row[spec.nameKey] ?? "")));
760
+ }
761
+ const colorOf = (name) => {
762
+ const index = groups.indexOf(name ?? "");
763
+ return chartColorVar((index === -1 ? 0 : index) + 1);
764
+ };
765
+ const opacityOf = (name) => name === void 0 ? void 0 : markDimOpacity(active, name);
766
+ const onNodeClick = (name, event) => {
767
+ if (name === void 0) return;
768
+ const row = rows.find((r) => categoryOf(r, spec.nameKey) === name) ?? { [spec.nameKey]: name };
769
+ reportMarkClick(markInteraction, name, void 0, row, event.shiftKey);
770
+ };
771
+ return /* @__PURE__ */ jsx11(
772
+ Treemap,
773
+ {
774
+ data: treeRows,
775
+ width,
776
+ height,
777
+ dataKey: spec.sizeKey,
778
+ nameKey: spec.nameKey,
779
+ isAnimationActive: false,
780
+ content: /* @__PURE__ */ jsx11(TreemapNode, { colorOf, opacityOf, onNodeClick }),
781
+ children: spec.tooltip !== false && /* @__PURE__ */ jsx11(Tooltip6, { content: /* @__PURE__ */ jsx11(ChartTooltipPanel, { showLabel: false, valueFormat: spec.format ?? "number" }) })
782
+ }
783
+ );
784
+ }
785
+
786
+ // src/registry.ts
787
+ function defineChartType(def) {
788
+ return def;
789
+ }
790
+ function createChartRegistry(...sources) {
791
+ const types = /* @__PURE__ */ new Map();
792
+ for (const source of sources) {
793
+ const defs = Array.isArray(source) ? source : source.types.values();
794
+ for (const def of defs) types.set(def.type, def);
795
+ }
796
+ return { types };
797
+ }
798
+ var FORMAT_TOKEN = {
799
+ type: "string",
800
+ description: 'Format token, e.g. "number", "compact", "percent", "currency:USD", "date:short".'
801
+ };
802
+ var PALETTE_SLOT = { type: "number", minimum: 1, maximum: 8, description: "Palette slot (--chart-N)." };
803
+ var COMMON_PROPERTIES = {
804
+ version: { const: 1, description: "Contract version of this spec." },
805
+ title: { type: "string", description: "Figure title, also the default accessible name." },
806
+ description: { type: "string", description: "Longer description for assistive tech." },
807
+ legend: {
808
+ anyOf: [
809
+ { type: "boolean" },
810
+ {
811
+ type: "object",
812
+ properties: { placement: { enum: ["top", "bottom"] } },
813
+ required: ["placement"],
814
+ additionalProperties: false
815
+ }
816
+ ],
817
+ description: "Legend visibility/placement. Defaults to true for two or more series."
818
+ },
819
+ tooltip: { type: "boolean" },
820
+ interaction: {
821
+ enum: ["filter", "highlight", "none"],
822
+ description: 'What a mark click does inside a CrossFilterProvider. Defaults to "filter".'
823
+ }
824
+ };
825
+ var AXIS_SCHEMA = {
826
+ type: "object",
827
+ properties: {
828
+ label: { type: "string", description: "Axis title." },
829
+ format: FORMAT_TOKEN,
830
+ domain: {
831
+ type: "array",
832
+ prefixItems: [
833
+ { anyOf: [{ type: "number" }, { enum: ["auto", "dataMin"] }] },
834
+ { anyOf: [{ type: "number" }, { enum: ["auto", "dataMax"] }] }
835
+ ],
836
+ items: false,
837
+ minItems: 2,
838
+ description: 'Value-axis domain. Defaults to ["auto", "auto"].'
839
+ },
840
+ tickCount: { type: "number", description: "Suggested tick count." },
841
+ hidden: { type: "boolean", description: "Hides the axis entirely." },
842
+ scale: { enum: ["band", "number", "time", "log"], description: 'X axis only. Defaults to "band".' }
843
+ },
844
+ additionalProperties: false
845
+ };
846
+ var SERIES_ITEM_SCHEMA = {
847
+ type: "object",
848
+ properties: {
849
+ field: { type: "string", description: "Row field holding this series' value." },
850
+ label: { type: "string", description: "Legend / tooltip name. Defaults to the field." },
851
+ paletteSlot: PALETTE_SLOT,
852
+ axis: { enum: ["primary", "secondary"], description: 'Value axis; "secondary" enables the secondary axis.' },
853
+ stackId: { type: "string", description: "Series sharing a stackId stack." },
854
+ mark: { enum: ["line", "area", "bar"], description: "Composed charts only: how this series is drawn." },
855
+ format: FORMAT_TOKEN
856
+ },
857
+ required: ["field"],
858
+ additionalProperties: false
859
+ };
860
+ var REFERENCE_LINE_SCHEMA = {
861
+ type: "object",
862
+ properties: {
863
+ axis: { enum: ["x", "y", "y2"], description: '"y"/"y2" draw horizontal lines ("y2" on the secondary axis), "x" vertical.' },
864
+ value: { anyOf: [{ type: "number" }, { type: "string" }], description: "Position on that axis." },
865
+ label: { type: "string", description: "Text beside the line." },
866
+ paletteSlot: PALETTE_SLOT,
867
+ dashed: { type: "boolean" }
868
+ },
869
+ required: ["axis", "value"],
870
+ additionalProperties: false
871
+ };
872
+ var FRAME_PROPERTIES = {
873
+ xAxis: AXIS_SCHEMA,
874
+ yAxis: AXIS_SCHEMA,
875
+ secondaryAxis: { ...AXIS_SCHEMA, description: 'Secondary value axis; used by series with axis: "secondary".' },
876
+ grid: {
877
+ anyOf: [
878
+ { type: "boolean" },
879
+ {
880
+ type: "object",
881
+ properties: { horizontal: { type: "boolean" }, vertical: { type: "boolean" } },
882
+ additionalProperties: false
883
+ }
884
+ ],
885
+ description: "Grid lines. Defaults to horizontal only."
886
+ },
887
+ referenceLines: { type: "array", items: REFERENCE_LINE_SCHEMA },
888
+ brush: { type: "boolean", description: "Renders a range brush under the plot." }
889
+ };
890
+ var CARTESIAN_PROPERTIES = {
891
+ ...FRAME_PROPERTIES,
892
+ xKey: { type: "string", description: "Category / x field. Also the cross-filter field." },
893
+ series: {
894
+ type: "array",
895
+ items: SERIES_ITEM_SCHEMA,
896
+ minItems: 1,
897
+ description: "The plotted series, in palette-slot order."
898
+ }
899
+ };
900
+ var STACKED_SCHEMA = {
901
+ anyOf: [{ type: "boolean" }, { const: "percent" }],
902
+ description: 'true stacks the series; "percent" normalizes each stack to 100%.'
903
+ };
904
+ function chartTypeSchema(type, properties, required) {
905
+ return {
906
+ type: "object",
907
+ properties: { ...COMMON_PROPERTIES, type: { const: type }, ...properties },
908
+ required: ["version", "type", ...required],
909
+ additionalProperties: false
910
+ };
911
+ }
912
+ function namedConfig(spec) {
913
+ return { [spec.valueKey]: { label: spec.title ?? spec.valueKey, format: spec.format } };
914
+ }
915
+ function pieDef(type) {
916
+ return defineChartType({
917
+ type,
918
+ family: "named",
919
+ render: PieChartRenderer,
920
+ crossFilterField: (spec) => spec.nameKey,
921
+ categoryField: (spec) => spec.nameKey,
922
+ configFrom: namedConfig,
923
+ schema: chartTypeSchema(type, {
924
+ nameKey: { type: "string", description: "Row field of the slice name; also the cross-filter field." },
925
+ valueKey: { type: "string", description: "Row field of the slice value." },
926
+ format: FORMAT_TOKEN,
927
+ labels: { type: "boolean", description: "Direct labels beside the slices." }
928
+ }, ["nameKey", "valueKey"])
929
+ });
930
+ }
931
+ var defaultChartTypes = [
932
+ defineChartType({
933
+ type: "line",
934
+ family: "cartesian",
935
+ render: LineChartRenderer,
936
+ crossFilterField: (spec) => spec.xKey,
937
+ schema: chartTypeSchema("line", {
938
+ ...CARTESIAN_PROPERTIES,
939
+ curve: { enum: ["linear", "monotone", "step"] },
940
+ dots: { type: "boolean", description: "Dots on every point (dots always show on hover)." }
941
+ }, ["xKey", "series"])
942
+ }),
943
+ defineChartType({
944
+ type: "area",
945
+ family: "cartesian",
946
+ render: AreaChartRenderer,
947
+ crossFilterField: (spec) => spec.xKey,
948
+ schema: chartTypeSchema("area", {
949
+ ...CARTESIAN_PROPERTIES,
950
+ curve: { enum: ["linear", "monotone", "step"] },
951
+ stacked: STACKED_SCHEMA
952
+ }, ["xKey", "series"])
953
+ }),
954
+ defineChartType({
955
+ type: "bar",
956
+ family: "cartesian",
957
+ render: BarChartRenderer,
958
+ crossFilterField: (spec) => spec.xKey,
959
+ schema: chartTypeSchema("bar", {
960
+ ...CARTESIAN_PROPERTIES,
961
+ orientation: { enum: ["vertical", "horizontal"], description: 'Bar direction: "horizontal" lays categories on the y axis.' },
962
+ stacked: STACKED_SCHEMA
963
+ }, ["xKey", "series"])
964
+ }),
965
+ defineChartType({
966
+ type: "composed",
967
+ family: "cartesian",
968
+ render: ComposedChartRenderer,
969
+ crossFilterField: (spec) => spec.xKey,
970
+ schema: chartTypeSchema("composed", {
971
+ ...CARTESIAN_PROPERTIES,
972
+ stacked: { type: "boolean", description: "Stacks the bar series." }
973
+ }, ["xKey", "series"])
974
+ }),
975
+ defineChartType({
976
+ type: "scatter",
977
+ family: "scatter",
978
+ render: ScatterChartRenderer,
979
+ crossFilterField: (spec) => spec.groupKey ?? spec.xKey,
980
+ categoryField: (spec) => spec.groupKey,
981
+ configFrom: (spec) => ({
982
+ [spec.yKey]: { label: spec.yAxis?.label ?? spec.yKey, format: spec.yAxis?.format }
983
+ }),
984
+ schema: chartTypeSchema("scatter", {
985
+ ...FRAME_PROPERTIES,
986
+ xKey: { type: "string", description: "Row field of the x value (numeric)." },
987
+ yKey: { type: "string", description: "Row field of the y value." },
988
+ groupKey: {
989
+ type: "string",
990
+ description: "Row field that splits points into colored groups (at most 3); also the cross-filter field."
991
+ },
992
+ sizeKey: { type: "string", description: "Row field sized into bubble area." },
993
+ sizeRange: {
994
+ type: "array",
995
+ prefixItems: [{ type: "number" }, { type: "number" }],
996
+ items: false,
997
+ minItems: 2,
998
+ description: "Bubble size range in px\xB2. Defaults to [64, 400]."
999
+ }
1000
+ }, ["xKey", "yKey"])
1001
+ }),
1002
+ pieDef("pie"),
1003
+ pieDef("donut"),
1004
+ defineChartType({
1005
+ type: "radar",
1006
+ family: "radar",
1007
+ render: RadarChartRenderer,
1008
+ crossFilterField: (spec) => spec.xKey,
1009
+ schema: chartTypeSchema("radar", {
1010
+ xKey: { type: "string", description: "Row field of the spoke name." },
1011
+ series: { type: "array", items: SERIES_ITEM_SCHEMA, minItems: 1 },
1012
+ filled: { type: "boolean", description: "Translucent fill under each outline." }
1013
+ }, ["xKey", "series"])
1014
+ }),
1015
+ defineChartType({
1016
+ type: "radial-bar",
1017
+ family: "named",
1018
+ render: RadialBarChartRenderer,
1019
+ crossFilterField: (spec) => spec.nameKey,
1020
+ categoryField: (spec) => spec.nameKey,
1021
+ configFrom: namedConfig,
1022
+ schema: chartTypeSchema("radial-bar", {
1023
+ nameKey: { type: "string", description: "Row field of the ring name; also the cross-filter field." },
1024
+ valueKey: { type: "string", description: "Row field of the ring value." },
1025
+ min: { type: "number", description: "Domain start. Defaults to 0." },
1026
+ max: { type: "number", description: "Domain end. Defaults to the data max." },
1027
+ format: FORMAT_TOKEN
1028
+ }, ["nameKey", "valueKey"])
1029
+ }),
1030
+ defineChartType({
1031
+ type: "funnel",
1032
+ family: "named",
1033
+ render: FunnelChartRenderer,
1034
+ crossFilterField: (spec) => spec.nameKey,
1035
+ categoryField: (spec) => spec.nameKey,
1036
+ configFrom: namedConfig,
1037
+ schema: chartTypeSchema("funnel", {
1038
+ nameKey: { type: "string", description: "Row field of the stage name; also the cross-filter field." },
1039
+ valueKey: { type: "string", description: "Row field of the stage value." },
1040
+ format: FORMAT_TOKEN
1041
+ }, ["nameKey", "valueKey"])
1042
+ }),
1043
+ defineChartType({
1044
+ type: "treemap",
1045
+ family: "treemap",
1046
+ render: TreemapChartRenderer,
1047
+ crossFilterField: (spec) => spec.nameKey,
1048
+ categoryField: (spec) => spec.nameKey,
1049
+ configFrom: (spec) => ({
1050
+ [spec.sizeKey]: { label: spec.title ?? spec.sizeKey, format: spec.format }
1051
+ }),
1052
+ schema: chartTypeSchema("treemap", {
1053
+ nameKey: { type: "string", description: "Row field of the tile name; also the cross-filter field." },
1054
+ sizeKey: { type: "string", description: "Row field sized into tile area." },
1055
+ groupKey: { type: "string", description: "Row field that groups tiles into colored clusters." },
1056
+ format: FORMAT_TOKEN
1057
+ }, ["nameKey", "sizeKey"])
1058
+ })
1059
+ ];
1060
+ var defaultChartRegistry = createChartRegistry(defaultChartTypes);
1061
+ function chartSpecJsonSchema(registry = defaultChartRegistry) {
1062
+ const defs = [...registry.types.values()];
1063
+ return {
1064
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1065
+ title: "ChartSpec",
1066
+ description: 'The serializable chart description <Chart> renders. Discriminated on "type".',
1067
+ type: "object",
1068
+ properties: { type: { enum: defs.map((def) => def.type) } },
1069
+ required: ["type"],
1070
+ allOf: defs.map((def) => ({
1071
+ if: { properties: { type: { const: def.type } }, required: ["type"] },
1072
+ then: def.schema
1073
+ }))
1074
+ };
1075
+ }
1076
+
1077
+ export {
1078
+ defineChartType,
1079
+ createChartRegistry,
1080
+ chartTypeSchema,
1081
+ defaultChartTypes,
1082
+ defaultChartRegistry,
1083
+ chartSpecJsonSchema
1084
+ };