@gridui/chart 0.0.0-stage → 0.0.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 (40) hide show
  1. package/README.md +65 -2
  2. package/dist/bar-chart/bar-chart.d.ts +12 -0
  3. package/dist/bar-series/bar-series.d.ts +17 -0
  4. package/dist/chart-cursor/chart-cursor.d.ts +13 -0
  5. package/dist/chart-grid/chart-grid.d.ts +18 -0
  6. package/dist/chart-plot/chart-plot.d.ts +13 -0
  7. package/dist/chart-tooltip/chart-tooltip.d.ts +14 -0
  8. package/dist/chart-tooltip/layout.d.ts +31 -0
  9. package/dist/chart-value-labels/chart-value-labels.d.ts +17 -0
  10. package/dist/chart-value-labels/layout.d.ts +28 -0
  11. package/dist/chart-x-axis/chart-x-axis.d.ts +12 -0
  12. package/dist/chart-y-axis/chart-y-axis.d.ts +12 -0
  13. package/dist/index.d.ts +29 -0
  14. package/dist/index.js +1276 -0
  15. package/dist/index.js.map +7 -0
  16. package/dist/line-chart/line-chart.d.ts +12 -0
  17. package/dist/line-series/line-series.d.ts +16 -0
  18. package/dist/shared/axis.d.ts +13 -0
  19. package/dist/shared/chart-root.d.ts +14 -0
  20. package/dist/shared/context.d.ts +38 -0
  21. package/dist/shared/datum-mark.d.ts +13 -0
  22. package/dist/shared/model.d.ts +13 -0
  23. package/dist/shared/ticks.d.ts +14 -0
  24. package/dist/shared/types.d.ts +46 -0
  25. package/dist/shared/use-measured-layout.d.ts +12 -0
  26. package/dist/styles.css +37 -0
  27. package/docs/catalog.json +168 -0
  28. package/docs/reference/README.md +14 -0
  29. package/docs/reference/bar-chart.md +97 -0
  30. package/docs/reference/bar-series.md +61 -0
  31. package/docs/reference/chart-cursor.md +39 -0
  32. package/docs/reference/chart-grid.md +61 -0
  33. package/docs/reference/chart-plot.md +37 -0
  34. package/docs/reference/chart-tooltip.md +37 -0
  35. package/docs/reference/chart-value-labels.md +57 -0
  36. package/docs/reference/chart-xaxis.md +71 -0
  37. package/docs/reference/chart-yaxis.md +71 -0
  38. package/docs/reference/line-chart.md +97 -0
  39. package/docs/reference/line-series.md +47 -0
  40. package/package.json +50 -3
package/dist/index.js ADDED
@@ -0,0 +1,1276 @@
1
+ // src/shared/context.ts
2
+ import { createContext, useContext } from "react";
3
+ var ChartContext = createContext(null);
4
+ var useChart = () => {
5
+ const state = useContext(ChartContext);
6
+ if (!state) {
7
+ throw new Error("Chart parts require a LineChart or BarChart.");
8
+ }
9
+ return state;
10
+ };
11
+ var PlotContext = createContext(null);
12
+ var usePlot = () => {
13
+ const state = useContext(PlotContext);
14
+ if (!state) {
15
+ throw new Error("Chart drawing parts require a ChartPlot.");
16
+ }
17
+ return state;
18
+ };
19
+
20
+ // src/shared/model.ts
21
+ var numericX = (value, scale) => {
22
+ const parsed = scale === "time" && typeof value === "string" ? Date.parse(value) : value;
23
+ const number = value instanceof Date ? value.getTime() : parsed;
24
+ if (typeof number !== "number" || !Number.isFinite(number)) {
25
+ throw new RangeError("Continuous chart coordinates must be finite numbers or valid dates.");
26
+ }
27
+ return number;
28
+ };
29
+ var prepareData = (data, scale) => {
30
+ const ids = /* @__PURE__ */ new Set();
31
+ for (const datum of data) {
32
+ if (!datum.id || ids.has(datum.id)) {
33
+ throw new Error("Chart datum IDs must be nonempty and unique.");
34
+ }
35
+ ids.add(datum.id);
36
+ if (datum.y !== null && !Number.isFinite(datum.y)) {
37
+ throw new RangeError("Chart values must be finite numbers or null.");
38
+ }
39
+ if (scale !== "category") {
40
+ numericX(datum.x, scale);
41
+ }
42
+ }
43
+ return scale === "category" ? data : [...data].sort((a, b) => {
44
+ return numericX(a.x, scale) - numericX(b.x, scale);
45
+ });
46
+ };
47
+ var valueDomain = (data, explicit) => {
48
+ let min = 0;
49
+ let max = 0;
50
+ for (const datum of data) {
51
+ if (datum.y !== null) {
52
+ min = Math.min(min, datum.y);
53
+ max = Math.max(max, datum.y);
54
+ }
55
+ }
56
+ if (explicit) {
57
+ if (!explicit.every(Number.isFinite) || explicit[0] >= explicit[1] || explicit[0] > min || explicit[1] < max) {
58
+ throw new RangeError("Chart domains must be increasing, finite, and include zero and all values.");
59
+ }
60
+ return explicit;
61
+ }
62
+ return min === max ? [
63
+ 0,
64
+ 1
65
+ ] : [
66
+ min,
67
+ max
68
+ ];
69
+ };
70
+ var valueTicks = (domain) => {
71
+ return [
72
+ .../* @__PURE__ */ new Set([
73
+ 0,
74
+ ...Array.from({ length: 5 }, (_, index) => {
75
+ return domain[0] + (domain[1] - domain[0]) * index / 4;
76
+ })
77
+ ])
78
+ ].sort((a, b) => {
79
+ return a - b;
80
+ });
81
+ };
82
+ var linePath = (data, x, y) => {
83
+ let connected = false;
84
+ return data.map((datum) => {
85
+ if (datum.y === null) {
86
+ connected = false;
87
+ return "";
88
+ }
89
+ const command = connected ? "L" : "M";
90
+ connected = true;
91
+ return `${command}${x(datum)},${y(datum.y)}`;
92
+ }).join(" ");
93
+ };
94
+ var datumLabel = (datum) => {
95
+ const x = datum.x instanceof Date ? datum.x.toISOString() : String(datum.x);
96
+ return `${x}: ${datum.y === null ? "\u2014" : String(datum.y)}`;
97
+ };
98
+
99
+ // src/shared/chart-root.tsx
100
+ import { cn } from "@gridui/style-utils";
101
+ import { useEffect, useMemo, useState } from "react";
102
+ import { jsx } from "react/jsx-runtime";
103
+ var ChartRoot = (props) => {
104
+ const {
105
+ label,
106
+ data,
107
+ children,
108
+ height = 300,
109
+ yDomain,
110
+ selectedId,
111
+ defaultSelectedId,
112
+ onSelectionChange,
113
+ formatDatum = datumLabel,
114
+ kind,
115
+ horizontal,
116
+ scale,
117
+ className,
118
+ ...rest
119
+ } = props;
120
+ const [
121
+ localSelection,
122
+ setLocalSelection
123
+ ] = useState(defaultSelectedId ?? null);
124
+ const [
125
+ hoveredId,
126
+ setHoveredId
127
+ ] = useState(null);
128
+ const [
129
+ focusedId,
130
+ setFocusedId
131
+ ] = useState(null);
132
+ const { ordered, domain, availableIds } = useMemo(() => {
133
+ const prepared = prepareData(data, scale);
134
+ return {
135
+ ordered: prepared,
136
+ domain: valueDomain(prepared, yDomain),
137
+ availableIds: new Set(prepared.filter((datum) => {
138
+ return datum.y !== null;
139
+ }).map((datum) => {
140
+ return datum.id;
141
+ }))
142
+ };
143
+ }, [
144
+ data,
145
+ scale,
146
+ yDomain
147
+ ]);
148
+ useEffect(() => {
149
+ setHoveredId((current) => {
150
+ return current !== null && availableIds.has(current) ? current : null;
151
+ });
152
+ setFocusedId((current) => {
153
+ return current !== null && availableIds.has(current) ? current : null;
154
+ });
155
+ }, [availableIds]);
156
+ const activeId = [
157
+ hoveredId,
158
+ focusedId
159
+ ].find((id) => {
160
+ return id !== null && availableIds.has(id);
161
+ }) ?? null;
162
+ const activate = (id, source) => {
163
+ if (source === "pointer") {
164
+ setHoveredId(id);
165
+ } else {
166
+ setFocusedId(id);
167
+ }
168
+ };
169
+ const dismiss = () => {
170
+ setHoveredId(null);
171
+ setFocusedId(null);
172
+ };
173
+ if (!Number.isFinite(height) || height < 160) {
174
+ throw new RangeError("Chart height must be finite and at least 160 pixels.");
175
+ }
176
+ const candidate = selectedId === void 0 ? localSelection : selectedId;
177
+ const selection = candidate !== null && availableIds.has(candidate) ? candidate : null;
178
+ const select = (id) => {
179
+ if (selectedId === void 0) {
180
+ setLocalSelection(id);
181
+ }
182
+ onSelectionChange?.(id);
183
+ };
184
+ return /* @__PURE__ */ jsx(
185
+ "div",
186
+ {
187
+ ...rest,
188
+ role: "group",
189
+ "aria-label": label,
190
+ className: cn("gridui-chart", className),
191
+ children: /* @__PURE__ */ jsx(
192
+ ChartContext,
193
+ {
194
+ value: {
195
+ data: ordered,
196
+ kind,
197
+ horizontal,
198
+ scale,
199
+ domain,
200
+ label,
201
+ height,
202
+ selectedId: selection,
203
+ activeId,
204
+ interactive: onSelectionChange !== void 0 || defaultSelectedId !== void 0,
205
+ select,
206
+ activate,
207
+ dismiss,
208
+ formatDatum
209
+ },
210
+ children
211
+ }
212
+ )
213
+ }
214
+ );
215
+ };
216
+
217
+ // src/bar-chart/bar-chart.tsx
218
+ import { jsx as jsx2 } from "react/jsx-runtime";
219
+ var BarChart = (props) => {
220
+ const { orientation = "vertical", ...restProps } = props;
221
+ return /* @__PURE__ */ jsx2(
222
+ ChartRoot,
223
+ {
224
+ ...restProps,
225
+ kind: "bar",
226
+ horizontal: orientation === "horizontal",
227
+ scale: "category"
228
+ }
229
+ );
230
+ };
231
+
232
+ // src/shared/datum-mark.tsx
233
+ import { isComposingKeyEvent } from "@gridui/interaction";
234
+ import { jsx as jsx3 } from "react/jsx-runtime";
235
+ var DatumMark = (props) => {
236
+ const { datum, children } = props;
237
+ const chart = useChart();
238
+ const selected = chart.selectedId === datum.id;
239
+ return /* @__PURE__ */ jsx3(
240
+ "g",
241
+ {
242
+ className: "gridui-chart-mark",
243
+ "data-selected": selected || void 0,
244
+ role: chart.interactive ? "button" : void 0,
245
+ tabIndex: chart.interactive ? 0 : void 0,
246
+ "aria-label": chart.formatDatum(datum),
247
+ "aria-pressed": chart.interactive ? selected : void 0,
248
+ onPointerEnter: () => {
249
+ return void chart.activate(datum.id, "pointer");
250
+ },
251
+ onPointerLeave: () => {
252
+ return void chart.activate(null, "pointer");
253
+ },
254
+ onFocus: () => {
255
+ return void chart.activate(datum.id, "focus");
256
+ },
257
+ onBlur: () => {
258
+ return void chart.activate(null, "focus");
259
+ },
260
+ onClick: chart.interactive ? () => {
261
+ return void chart.select(selected ? null : datum.id);
262
+ } : void 0,
263
+ onKeyDown: chart.interactive ? (event) => {
264
+ if (isComposingKeyEvent(event.nativeEvent)) {
265
+ return;
266
+ }
267
+ if (event.key === "Enter" || event.key === " ") {
268
+ event.preventDefault();
269
+ if (!event.repeat) {
270
+ chart.select(selected ? null : datum.id);
271
+ }
272
+ } else if (event.key === "Escape") {
273
+ chart.dismiss();
274
+ chart.select(null);
275
+ }
276
+ } : void 0,
277
+ children
278
+ }
279
+ );
280
+ };
281
+
282
+ // src/bar-series/bar-series.tsx
283
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
284
+ var BarSeries = (props) => {
285
+ const { color = "var(--gridui-chart-series)", selectedColor = "var(--gridui-chart-selected)", width, widthRatio = 0.7, gap = 4, opacity = 1, inactiveOpacity = 0.45 } = props;
286
+ const chart = useChart();
287
+ const plot = usePlot();
288
+ if (chart.kind !== "bar") {
289
+ throw new Error("BarSeries requires BarChart.");
290
+ }
291
+ const invalidWidth = width !== void 0 && (!Number.isFinite(width) || width <= 0);
292
+ if (!Number.isFinite(widthRatio) || widthRatio <= 0 || widthRatio > 1 || !Number.isFinite(gap) || gap < 0 || invalidWidth) {
293
+ throw new RangeError("Bar width must be positive, its ratio at most one, and gap nonnegative.");
294
+ }
295
+ const thickness = Math.min(width ?? plot.band * widthRatio, Math.max(Math.min(1, plot.band), plot.band - gap));
296
+ const baseline = plot.value(0);
297
+ return /* @__PURE__ */ jsx4("g", { children: chart.data.map((datum) => {
298
+ if (datum.y === null) {
299
+ return null;
300
+ }
301
+ const at = plot.category(datum);
302
+ const end = plot.value(datum.y);
303
+ const selected = chart.selectedId === datum.id;
304
+ return /* @__PURE__ */ jsxs(
305
+ DatumMark,
306
+ {
307
+ datum,
308
+ children: [
309
+ /* @__PURE__ */ jsx4(
310
+ "rect",
311
+ {
312
+ className: "gridui-chart-hit",
313
+ x: chart.horizontal ? plot.left : at - plot.band / 2,
314
+ y: chart.horizontal ? at - plot.band / 2 : plot.top,
315
+ width: chart.horizontal ? plot.right - plot.left : plot.band,
316
+ height: chart.horizontal ? plot.band : plot.bottom - plot.top,
317
+ fill: "transparent"
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsx4(
321
+ "rect",
322
+ {
323
+ x: chart.horizontal ? Math.min(end, baseline) : at - thickness / 2,
324
+ y: chart.horizontal ? at - thickness / 2 : Math.min(end, baseline),
325
+ width: chart.horizontal ? Math.abs(end - baseline) : thickness,
326
+ height: chart.horizontal ? thickness : Math.abs(end - baseline),
327
+ fill: selected ? selectedColor : color,
328
+ opacity: chart.selectedId && !selected ? inactiveOpacity : opacity,
329
+ pointerEvents: "none"
330
+ }
331
+ )
332
+ ]
333
+ },
334
+ datum.id
335
+ );
336
+ }) });
337
+ };
338
+
339
+ // src/chart-cursor/chart-cursor.tsx
340
+ import { jsx as jsx5 } from "react/jsx-runtime";
341
+ var ChartCursor = (props) => {
342
+ const { color = "var(--gridui-chart-axis)", strokeWidth = 1, dashArray = "3 3" } = props;
343
+ const chart = useChart();
344
+ const plot = usePlot();
345
+ const datum = chart.data.find((item) => {
346
+ return item.id === (chart.activeId ?? chart.selectedId);
347
+ });
348
+ if (!datum || datum.y === null) {
349
+ return null;
350
+ }
351
+ const at = plot.category(datum);
352
+ return /* @__PURE__ */ jsx5(
353
+ "line",
354
+ {
355
+ "aria-hidden": "true",
356
+ pointerEvents: "none",
357
+ x1: chart.horizontal ? plot.left : at,
358
+ x2: chart.horizontal ? plot.right : at,
359
+ y1: chart.horizontal ? at : plot.top,
360
+ y2: chart.horizontal ? at : plot.bottom,
361
+ stroke: color,
362
+ strokeWidth,
363
+ strokeDasharray: dashArray
364
+ }
365
+ );
366
+ };
367
+
368
+ // src/shared/ticks.ts
369
+ var axisTicks = (chart, plot, axis, options) => {
370
+ const { tickCount, tickValues } = options;
371
+ if (tickCount !== void 0 && (!Number.isSafeInteger(tickCount) || tickCount < 2)) {
372
+ throw new RangeError("Chart tickCount must be an integer of at least two.");
373
+ }
374
+ const dataAxis = axis === "x" !== chart.horizontal;
375
+ const first = chart.data[0];
376
+ const last = chart.data.at(-1);
377
+ if (dataAxis && (!first || !last)) {
378
+ return [];
379
+ }
380
+ if (dataAxis && chart.scale === "category") {
381
+ const requested = tickValues && new Set(tickValues.map((value) => {
382
+ return value instanceof Date ? value.getTime() : value;
383
+ }));
384
+ const candidates = chart.data.filter((datum) => {
385
+ return !requested || requested.has(datum.x instanceof Date ? datum.x.getTime() : datum.x);
386
+ });
387
+ const indices = tickCount !== void 0 && !requested && candidates.length > tickCount ? new Set(Array.from({ length: tickCount }, (_, index) => {
388
+ return Math.round(index * (candidates.length - 1) / (tickCount - 1));
389
+ })) : null;
390
+ return candidates.flatMap((datum, index) => {
391
+ return indices && !indices.has(index) ? [] : [
392
+ {
393
+ key: datum.id,
394
+ value: datum.x,
395
+ at: plot.category(datum)
396
+ }
397
+ ];
398
+ });
399
+ }
400
+ const low = dataAxis && first ? numericX(first.x, chart.scale) : chart.domain[0];
401
+ const high = dataAxis && last ? numericX(last.x, chart.scale) : chart.domain[1];
402
+ const count = tickCount ?? 5;
403
+ const generated = low === high ? [low] : Array.from({ length: count }, (_, index) => {
404
+ return low + (high - low) * index / (count - 1);
405
+ });
406
+ const defaults = dataAxis ? chart.data.map((datum) => {
407
+ return datum.x;
408
+ }) : valueTicks(chart.domain);
409
+ const values = tickValues ?? (tickCount !== void 0 ? generated : defaults);
410
+ const seen = /* @__PURE__ */ new Set();
411
+ return values.flatMap((value) => {
412
+ const number = numericX(value, dataAxis ? chart.scale : "linear");
413
+ if (number < low || number > high || seen.has(number)) {
414
+ return [];
415
+ }
416
+ seen.add(number);
417
+ const formattedValue = dataAxis && chart.scale === "time" ? new Date(number) : number;
418
+ return [
419
+ {
420
+ key: String(number),
421
+ value: formattedValue,
422
+ at: dataAxis ? plot.category({
423
+ id: "",
424
+ x: formattedValue,
425
+ y: null
426
+ }) : plot.value(number)
427
+ }
428
+ ];
429
+ }).sort((a, b) => {
430
+ return a.at - b.at;
431
+ });
432
+ };
433
+
434
+ // src/chart-grid/chart-grid.tsx
435
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
436
+ var ChartGrid = (props) => {
437
+ const { xTicks = {}, yTicks = {}, horizontal = true, vertical = false, color = "var(--gridui-chart-grid)", strokeWidth = 1, dashArray } = props;
438
+ const chart = useChart();
439
+ const plot = usePlot();
440
+ const x = axisTicks(chart, plot, "x", xTicks);
441
+ const y = axisTicks(chart, plot, "y", yTicks);
442
+ return /* @__PURE__ */ jsxs2(
443
+ "g",
444
+ {
445
+ className: "gridui-chart-grid",
446
+ "aria-hidden": "true",
447
+ pointerEvents: "none",
448
+ stroke: color,
449
+ strokeWidth,
450
+ strokeDasharray: dashArray,
451
+ children: [
452
+ horizontal && y.map(({ at }, index) => {
453
+ return /* @__PURE__ */ jsx6(
454
+ "line",
455
+ {
456
+ x1: plot.left,
457
+ x2: plot.right,
458
+ y1: at,
459
+ y2: at
460
+ },
461
+ `h-${index}`
462
+ );
463
+ }),
464
+ vertical && x.map(({ at }, index) => {
465
+ return /* @__PURE__ */ jsx6(
466
+ "line",
467
+ {
468
+ x1: at,
469
+ x2: at,
470
+ y1: plot.top,
471
+ y2: plot.bottom
472
+ },
473
+ `v-${index}`
474
+ );
475
+ })
476
+ ]
477
+ }
478
+ );
479
+ };
480
+
481
+ // src/chart-plot/chart-plot.tsx
482
+ import { useEffect as useEffect2, useId, useMemo as useMemo2, useRef, useState as useState2 } from "react";
483
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
484
+ var ChartPlot = (props) => {
485
+ const { children, background = "var(--gridui-chart-background)", padding } = props;
486
+ const chart = useChart();
487
+ const ref = useRef(null);
488
+ const [
489
+ width,
490
+ setWidth
491
+ ] = useState2(640);
492
+ const descriptionId = useId();
493
+ useEffect2(() => {
494
+ const element = ref.current;
495
+ if (!element) {
496
+ return;
497
+ }
498
+ const observer = new ResizeObserver((entries) => {
499
+ const measured = entries[0]?.contentRect.width;
500
+ if (measured && measured > 0) {
501
+ setWidth(measured);
502
+ }
503
+ });
504
+ observer.observe(element);
505
+ return () => {
506
+ return void observer.disconnect();
507
+ };
508
+ }, []);
509
+ const inset = {
510
+ left: padding?.left ?? (chart.horizontal ? 88 : 56),
511
+ right: padding?.right ?? 24,
512
+ top: padding?.top ?? 28,
513
+ bottom: padding?.bottom ?? 48
514
+ };
515
+ if (Object.values(inset).some((value) => {
516
+ return !Number.isFinite(value) || value < 0;
517
+ })) {
518
+ throw new RangeError("Chart padding must be finite and nonnegative.");
519
+ }
520
+ const left = Math.min(width, inset.left);
521
+ const right = Math.max(left, width - inset.right);
522
+ const top = Math.min(chart.height, inset.top);
523
+ const bottom = Math.max(top, chart.height - inset.bottom);
524
+ const drawable = right > left && bottom > top;
525
+ const plot = useMemo2(() => {
526
+ const extent = Math.max(1, chart.horizontal ? bottom - top : right - left);
527
+ const start = chart.horizontal ? top : left;
528
+ const count = chart.data.length;
529
+ const band = extent / Math.max(1, count);
530
+ const first = chart.data[0];
531
+ const last = chart.data[count - 1];
532
+ const low = first && chart.scale !== "category" ? numericX(first.x, chart.scale) : 0;
533
+ const high = last && chart.scale !== "category" ? numericX(last.x, chart.scale) : 0;
534
+ const indices = new Map(chart.data.map((datum, index) => {
535
+ return [
536
+ datum.id,
537
+ index
538
+ ];
539
+ }));
540
+ const category = (datum) => {
541
+ const index = indices.get(datum.id) ?? 0;
542
+ if (chart.scale !== "category") {
543
+ return start + (high === low ? extent / 2 : (numericX(datum.x, chart.scale) - low) / (high - low) * extent);
544
+ }
545
+ const linePosition = count < 2 ? extent / 2 : index * extent / (count - 1);
546
+ return start + (chart.kind === "bar" ? (index + 0.5) * band : linePosition);
547
+ };
548
+ const value = (number) => {
549
+ const ratio = (number - chart.domain[0]) / (chart.domain[1] - chart.domain[0]);
550
+ return chart.horizontal ? left + ratio * Math.max(1, right - left) : bottom - ratio * Math.max(1, bottom - top);
551
+ };
552
+ return {
553
+ width,
554
+ height: chart.height,
555
+ left,
556
+ right,
557
+ top,
558
+ bottom,
559
+ band,
560
+ category,
561
+ value
562
+ };
563
+ }, [
564
+ chart.data,
565
+ chart.domain,
566
+ chart.height,
567
+ chart.horizontal,
568
+ chart.kind,
569
+ chart.scale,
570
+ bottom,
571
+ left,
572
+ right,
573
+ top,
574
+ width
575
+ ]);
576
+ return /* @__PURE__ */ jsx7(
577
+ "div",
578
+ {
579
+ ref,
580
+ className: "gridui-chart-plot",
581
+ children: /* @__PURE__ */ jsxs3(
582
+ "svg",
583
+ {
584
+ width: "100%",
585
+ height: chart.height,
586
+ viewBox: `0 0 ${width} ${chart.height}`,
587
+ role: chart.interactive ? "group" : "img",
588
+ "aria-label": chart.label,
589
+ "aria-describedby": descriptionId,
590
+ children: [
591
+ /* @__PURE__ */ jsx7(
592
+ "desc",
593
+ {
594
+ id: descriptionId,
595
+ children: chart.data.map(chart.formatDatum).join("; ")
596
+ }
597
+ ),
598
+ /* @__PURE__ */ jsx7(
599
+ "rect",
600
+ {
601
+ x: left,
602
+ y: top,
603
+ width: Math.max(0, right - left),
604
+ height: Math.max(0, bottom - top),
605
+ fill: background,
606
+ pointerEvents: "none"
607
+ }
608
+ ),
609
+ /* @__PURE__ */ jsx7(
610
+ PlotContext,
611
+ {
612
+ value: plot,
613
+ children: drawable ? children : null
614
+ }
615
+ )
616
+ ]
617
+ }
618
+ )
619
+ }
620
+ );
621
+ };
622
+
623
+ // src/shared/use-measured-layout.ts
624
+ import { useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
625
+ var useMeasuredLayout = (calculate) => {
626
+ const ref = useRef2(null);
627
+ const [
628
+ result,
629
+ setResult
630
+ ] = useState3(null);
631
+ useLayoutEffect(() => {
632
+ const node = ref.current;
633
+ if (!node) {
634
+ return;
635
+ }
636
+ let disposed = false;
637
+ const update = () => {
638
+ if (disposed) {
639
+ return;
640
+ }
641
+ const cache = /* @__PURE__ */ new Map();
642
+ const value = calculate((text) => {
643
+ const cached = cache.get(text);
644
+ if (cached) {
645
+ return cached;
646
+ }
647
+ node.textContent = text;
648
+ const box = node.getBBox();
649
+ const bounds = {
650
+ x: box.x,
651
+ y: box.y,
652
+ width: box.width,
653
+ height: box.height
654
+ };
655
+ cache.set(text, bounds);
656
+ return bounds;
657
+ });
658
+ node.textContent = "M";
659
+ setResult({
660
+ calculate,
661
+ value
662
+ });
663
+ };
664
+ update();
665
+ const observer = new ResizeObserver(update);
666
+ observer.observe(node);
667
+ const fonts = node.ownerDocument.fonts;
668
+ void fonts.ready.then(update);
669
+ fonts.addEventListener("loadingdone", update);
670
+ return () => {
671
+ disposed = true;
672
+ observer.disconnect();
673
+ fonts.removeEventListener("loadingdone", update);
674
+ };
675
+ }, [calculate]);
676
+ return {
677
+ ref,
678
+ layout: result?.calculate === calculate ? result.value : void 0
679
+ };
680
+ };
681
+
682
+ // src/chart-tooltip/layout.ts
683
+ var PLOT_INSET = 4;
684
+ var POINT_GAP = 12;
685
+ var PADDING_INLINE = 10;
686
+ var PADDING_TOP = 8;
687
+ var PADDING_BOTTOM = 4;
688
+ var LINE_GAP = 4;
689
+ var MIN_LINE_HEIGHT = 18;
690
+ var fittingGraphemeCount = (segments, start, availableWidth, measure) => {
691
+ let low = 1;
692
+ let high = segments.length - start;
693
+ while (low < high) {
694
+ const count = Math.ceil((low + high) / 2);
695
+ if (measure(segments.slice(start, start + count).join("")).width <= availableWidth) {
696
+ low = count;
697
+ } else {
698
+ high = count - 1;
699
+ }
700
+ }
701
+ return low;
702
+ };
703
+ var wrapTooltipText = (text, availableWidth, measure) => {
704
+ const lines = [];
705
+ const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
706
+ for (const paragraph of text.split("\n")) {
707
+ const segments = Array.from(segmenter.segment(paragraph), (part) => {
708
+ return part.segment;
709
+ });
710
+ if (!segments.length) {
711
+ lines.push("");
712
+ }
713
+ let start = 0;
714
+ while (start < segments.length) {
715
+ let count = fittingGraphemeCount(segments, start, availableWidth, measure);
716
+ if (start + count < segments.length) {
717
+ const wordBreak = segments.slice(start, start + count).reduce((last, segment, index) => {
718
+ return /\s/u.test(segment) ? index : last;
719
+ }, -1);
720
+ if (wordBreak > 0) {
721
+ count = wordBreak + 1;
722
+ }
723
+ }
724
+ lines.push(segments.slice(start, start + count).join(""));
725
+ start += count;
726
+ }
727
+ }
728
+ return lines;
729
+ };
730
+ var calculateTooltipLayout = (text, plotWidth, measure) => {
731
+ if (text === null) {
732
+ return null;
733
+ }
734
+ const availableWidth = Math.max(1, plotWidth - 2 * (PLOT_INSET + PADDING_INLINE));
735
+ const lines = wrapTooltipText(text, availableWidth, measure);
736
+ const bounds = lines.map(measure);
737
+ const lineHeight = Math.max(MIN_LINE_HEIGHT, ...bounds.map((box) => {
738
+ return box.height + LINE_GAP;
739
+ }));
740
+ return {
741
+ lines: lines.map((line, index) => {
742
+ const box = bounds[index];
743
+ return {
744
+ text: line,
745
+ x: PADDING_INLINE - (box?.x ?? 0),
746
+ y: PADDING_TOP + index * lineHeight - (box?.y ?? 0)
747
+ };
748
+ }),
749
+ width: Math.max(PADDING_INLINE * 2, ...bounds.map((box) => {
750
+ return box.width + PADDING_INLINE * 2;
751
+ })),
752
+ height: lines.length * lineHeight + PADDING_TOP + PADDING_BOTTOM
753
+ };
754
+ };
755
+ var calculateTooltipPosition = (options) => {
756
+ const { datum, horizontal, plot, width, height } = options;
757
+ let pointX = 0;
758
+ let pointY = 0;
759
+ if (datum && datum.y !== null) {
760
+ if (horizontal) {
761
+ pointX = plot.value(datum.y);
762
+ pointY = plot.category(datum);
763
+ } else {
764
+ pointX = plot.category(datum);
765
+ pointY = plot.value(datum.y);
766
+ }
767
+ }
768
+ return {
769
+ x: Math.max(PLOT_INSET, Math.min(plot.width - width - PLOT_INSET, pointX - width / 2)),
770
+ y: Math.max(PLOT_INSET, Math.min(plot.height - height - PLOT_INSET, pointY - height - POINT_GAP))
771
+ };
772
+ };
773
+
774
+ // src/chart-tooltip/chart-tooltip.tsx
775
+ import { useCallback } from "react";
776
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
777
+ var ChartTooltip = (props) => {
778
+ const { format, background = "var(--gridui-background)", color = "var(--gridui-foreground)" } = props;
779
+ const chart = useChart();
780
+ const plot = usePlot();
781
+ const datum = chart.data.find((item) => {
782
+ return item.id === chart.activeId;
783
+ });
784
+ const text = datum && datum.y !== null ? (format ?? chart.formatDatum)(datum) : null;
785
+ const calculate = useCallback((measure) => {
786
+ return calculateTooltipLayout(text, plot.width, measure);
787
+ }, [
788
+ text,
789
+ plot.width
790
+ ]);
791
+ const { ref, layout } = useMeasuredLayout(calculate);
792
+ const { x, y } = calculateTooltipPosition({
793
+ datum,
794
+ horizontal: chart.horizontal,
795
+ plot,
796
+ width: layout?.width ?? 0,
797
+ height: layout?.height ?? 0
798
+ });
799
+ return /* @__PURE__ */ jsxs4(
800
+ "g",
801
+ {
802
+ className: text === null ? void 0 : "gridui-chart-tooltip",
803
+ "aria-hidden": "true",
804
+ pointerEvents: "none",
805
+ fontSize: 12,
806
+ children: [
807
+ /* @__PURE__ */ jsx8(
808
+ "text",
809
+ {
810
+ ref,
811
+ visibility: "hidden"
812
+ }
813
+ ),
814
+ layout && /* @__PURE__ */ jsxs4(
815
+ "g",
816
+ {
817
+ transform: `translate(${x} ${y})`,
818
+ children: [
819
+ /* @__PURE__ */ jsx8(
820
+ "rect",
821
+ {
822
+ width: layout.width,
823
+ height: layout.height,
824
+ fill: background,
825
+ stroke: "var(--gridui-border)"
826
+ }
827
+ ),
828
+ /* @__PURE__ */ jsx8(
829
+ "text",
830
+ {
831
+ fill: color,
832
+ children: layout.lines.map((line, index) => {
833
+ return /* @__PURE__ */ jsx8(
834
+ "tspan",
835
+ {
836
+ x: line.x,
837
+ y: line.y,
838
+ children: line.text
839
+ },
840
+ index
841
+ );
842
+ })
843
+ }
844
+ )
845
+ ]
846
+ }
847
+ )
848
+ ]
849
+ }
850
+ );
851
+ };
852
+
853
+ // src/chart-value-labels/layout.ts
854
+ var PLOT_INSET2 = 2;
855
+ var LABEL_GAP = 4;
856
+ var labelsOverlap = (left, right) => {
857
+ return left.x < right.x + right.width + LABEL_GAP && left.x + left.width + LABEL_GAP > right.x && left.y < right.y + right.height + LABEL_GAP && left.y + left.height + LABEL_GAP > right.y;
858
+ };
859
+ var calculateValueLabelLayout = (options) => {
860
+ const { data, selectedId, horizontal, plot, visibility, position, format, offset, measure } = options;
861
+ const occupied = [];
862
+ const labels = [];
863
+ for (const datum of data) {
864
+ if (visibility === "none" || datum.y === null || visibility === "selected" && datum.id !== selectedId) {
865
+ continue;
866
+ }
867
+ const text = format(datum.y, datum);
868
+ const box = measure(text);
869
+ if (box.width > plot.width - PLOT_INSET2 * 2 || box.height > plot.height - PLOT_INSET2 * 2) {
870
+ continue;
871
+ }
872
+ const categoryPosition = plot.category(datum);
873
+ let valuePosition = plot.value(datum.y);
874
+ if (position === "center") {
875
+ valuePosition = (valuePosition + plot.value(0)) / 2;
876
+ }
877
+ let centerX = categoryPosition;
878
+ let centerY = valuePosition;
879
+ if (horizontal) {
880
+ centerX = valuePosition;
881
+ centerY = categoryPosition;
882
+ }
883
+ if (position === "end") {
884
+ if (horizontal) {
885
+ const direction = datum.y < 0 ? -1 : 1;
886
+ centerX += direction * (offset + box.width / 2);
887
+ } else {
888
+ centerY -= Math.sign(datum.y || 1) * offset;
889
+ }
890
+ }
891
+ const bounds = {
892
+ x: Math.max(PLOT_INSET2, Math.min(plot.width - box.width - PLOT_INSET2, centerX - box.width / 2)),
893
+ y: Math.max(PLOT_INSET2, Math.min(plot.height - box.height - PLOT_INSET2, centerY - box.height / 2)),
894
+ width: box.width,
895
+ height: box.height
896
+ };
897
+ if (occupied.some((other) => {
898
+ return labelsOverlap(bounds, other);
899
+ })) {
900
+ continue;
901
+ }
902
+ occupied.push(bounds);
903
+ labels.push({
904
+ id: datum.id,
905
+ text,
906
+ x: bounds.x - box.x,
907
+ y: bounds.y - box.y
908
+ });
909
+ }
910
+ return labels;
911
+ };
912
+
913
+ // src/chart-value-labels/chart-value-labels.tsx
914
+ import { useCallback as useCallback2 } from "react";
915
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
916
+ var ChartValueLabels = (props) => {
917
+ const { visibility = "selected", position = "end", format = String, color = "var(--gridui-chart-value)", fontSize = 12, offset = 12 } = props;
918
+ const chart = useChart();
919
+ const plot = usePlot();
920
+ const calculate = useCallback2((measure) => {
921
+ return calculateValueLabelLayout({
922
+ data: chart.data,
923
+ selectedId: chart.selectedId,
924
+ horizontal: chart.horizontal,
925
+ plot,
926
+ visibility,
927
+ position,
928
+ format,
929
+ offset,
930
+ measure
931
+ });
932
+ }, [
933
+ chart,
934
+ plot,
935
+ visibility,
936
+ position,
937
+ format,
938
+ offset
939
+ ]);
940
+ const { ref, layout } = useMeasuredLayout(calculate);
941
+ return /* @__PURE__ */ jsxs5(
942
+ "g",
943
+ {
944
+ className: "gridui-chart-values",
945
+ "aria-hidden": "true",
946
+ pointerEvents: "none",
947
+ fill: color,
948
+ fontSize,
949
+ children: [
950
+ /* @__PURE__ */ jsx9(
951
+ "text",
952
+ {
953
+ ref,
954
+ visibility: "hidden"
955
+ }
956
+ ),
957
+ layout?.map((label) => {
958
+ return /* @__PURE__ */ jsx9(
959
+ "text",
960
+ {
961
+ x: label.x,
962
+ y: label.y,
963
+ children: label.text
964
+ },
965
+ label.id
966
+ );
967
+ })
968
+ ]
969
+ }
970
+ );
971
+ };
972
+
973
+ // src/shared/axis.tsx
974
+ import { useCallback as useCallback3, useMemo as useMemo3 } from "react";
975
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
976
+ var Axis = (props) => {
977
+ const { axis, position, line = true, ticks = true, labels = true, title, tickFormat, tickCount, tickValues, color = "var(--gridui-chart-axis)", strokeWidth = 1, labelColor = "var(--gridui-chart-label)", fontSize = 12 } = props;
978
+ const chart = useChart();
979
+ const plot = usePlot();
980
+ const { data, horizontal, scale, domain } = chart;
981
+ const isX = axis === "x";
982
+ const xEdge = position === "start" ? plot.top : plot.bottom;
983
+ const yEdge = position === "start" ? plot.left : plot.right;
984
+ const edge = isX ? xEdge : yEdge;
985
+ const titleX = position === "start" ? 12 : plot.width - 12;
986
+ const titleY = position === "start" ? 12 : plot.height - 2;
987
+ const sign = position === "start" ? -1 : 1;
988
+ const all = useMemo3(() => {
989
+ return axisTicks({
990
+ data,
991
+ horizontal,
992
+ scale,
993
+ domain
994
+ }, plot, axis, {
995
+ ...tickCount === void 0 ? {} : { tickCount },
996
+ ...tickValues === void 0 ? {} : { tickValues }
997
+ });
998
+ }, [
999
+ data,
1000
+ horizontal,
1001
+ scale,
1002
+ domain,
1003
+ plot,
1004
+ axis,
1005
+ tickCount,
1006
+ tickValues
1007
+ ]);
1008
+ const calculate = useCallback3((measure) => {
1009
+ const occupied = [];
1010
+ const shown = /* @__PURE__ */ new Map();
1011
+ const ordered = all.length > 1 ? [
1012
+ all[0],
1013
+ all.at(-1),
1014
+ ...all.slice(1, -1)
1015
+ ] : all;
1016
+ for (const tick of ordered) {
1017
+ const defaultText = tick.value instanceof Date ? tick.value.toISOString().slice(0, 10) : String(tick.value);
1018
+ const text = tickFormat ? tickFormat(tick.value) : defaultText;
1019
+ const box = measure(text);
1020
+ if (box.width > plot.width - 4 || box.height > plot.height - 4) {
1021
+ continue;
1022
+ }
1023
+ const outsideX = position === "start" ? edge - 9 - box.width : edge + 9;
1024
+ const outsideY = position === "start" ? edge - 9 - box.height : edge + 9;
1025
+ const originX = isX ? tick.at - box.width / 2 : outsideX;
1026
+ const originY = isX ? outsideY : tick.at - box.height / 2;
1027
+ const x = Math.max(2, Math.min(plot.width - box.width - 2, originX));
1028
+ const y = Math.max(2, Math.min(plot.height - box.height - 2, originY));
1029
+ if (occupied.some((other) => {
1030
+ return x < other.x + other.width + 4 && x + box.width + 4 > other.x && y < other.y + other.height + 4 && y + box.height + 4 > other.y;
1031
+ })) {
1032
+ continue;
1033
+ }
1034
+ occupied.push({
1035
+ x,
1036
+ y,
1037
+ width: box.width,
1038
+ height: box.height
1039
+ });
1040
+ shown.set(tick.key, {
1041
+ text,
1042
+ x: x - box.x,
1043
+ y: y - box.y
1044
+ });
1045
+ }
1046
+ return shown;
1047
+ }, [
1048
+ all,
1049
+ tickFormat,
1050
+ plot.width,
1051
+ plot.height,
1052
+ isX,
1053
+ position,
1054
+ edge
1055
+ ]);
1056
+ const { ref, layout } = useMeasuredLayout(calculate);
1057
+ return /* @__PURE__ */ jsxs6(
1058
+ "g",
1059
+ {
1060
+ "aria-hidden": "true",
1061
+ className: "gridui-chart-axis",
1062
+ "data-axis": axis,
1063
+ children: [
1064
+ line && /* @__PURE__ */ jsx10(
1065
+ "line",
1066
+ {
1067
+ x1: isX ? plot.left : edge,
1068
+ y1: isX ? edge : plot.top,
1069
+ x2: isX ? plot.right : edge,
1070
+ y2: isX ? edge : plot.bottom,
1071
+ stroke: color,
1072
+ strokeWidth
1073
+ }
1074
+ ),
1075
+ /* @__PURE__ */ jsx10(
1076
+ "text",
1077
+ {
1078
+ ref,
1079
+ visibility: "hidden",
1080
+ pointerEvents: "none",
1081
+ fontSize
1082
+ }
1083
+ ),
1084
+ all.map((tick) => {
1085
+ const label = layout?.get(tick.key);
1086
+ return /* @__PURE__ */ jsxs6(
1087
+ "g",
1088
+ {
1089
+ children: [
1090
+ ticks && /* @__PURE__ */ jsx10(
1091
+ "line",
1092
+ {
1093
+ x1: isX ? tick.at : edge,
1094
+ y1: isX ? edge : tick.at,
1095
+ x2: isX ? tick.at : edge + sign * 4,
1096
+ y2: isX ? edge + sign * 4 : tick.at,
1097
+ stroke: color,
1098
+ strokeWidth
1099
+ }
1100
+ ),
1101
+ labels && label && /* @__PURE__ */ jsx10(
1102
+ "text",
1103
+ {
1104
+ x: label.x,
1105
+ y: label.y,
1106
+ fill: labelColor,
1107
+ fontSize,
1108
+ children: label.text
1109
+ }
1110
+ )
1111
+ ]
1112
+ },
1113
+ tick.key
1114
+ );
1115
+ }),
1116
+ title && /* @__PURE__ */ jsx10(
1117
+ "text",
1118
+ {
1119
+ x: isX ? (plot.left + plot.right) / 2 : titleX,
1120
+ y: isX ? titleY : (plot.top + plot.bottom) / 2,
1121
+ transform: isX ? void 0 : `rotate(-90 ${position === "start" ? 12 : plot.width - 12} ${(plot.top + plot.bottom) / 2})`,
1122
+ textAnchor: "middle",
1123
+ fill: labelColor,
1124
+ fontSize,
1125
+ children: title
1126
+ }
1127
+ )
1128
+ ]
1129
+ }
1130
+ );
1131
+ };
1132
+
1133
+ // src/chart-x-axis/chart-x-axis.tsx
1134
+ import { jsx as jsx11 } from "react/jsx-runtime";
1135
+ var ChartXAxis = (props) => {
1136
+ const { position = "bottom", ...restProps } = props;
1137
+ return /* @__PURE__ */ jsx11(
1138
+ Axis,
1139
+ {
1140
+ ...restProps,
1141
+ axis: "x",
1142
+ position: position === "top" ? "start" : "end"
1143
+ }
1144
+ );
1145
+ };
1146
+
1147
+ // src/chart-y-axis/chart-y-axis.tsx
1148
+ import { jsx as jsx12 } from "react/jsx-runtime";
1149
+ var ChartYAxis = (props) => {
1150
+ const { position = "left", ...restProps } = props;
1151
+ return /* @__PURE__ */ jsx12(
1152
+ Axis,
1153
+ {
1154
+ ...restProps,
1155
+ axis: "y",
1156
+ position: position === "left" ? "start" : "end"
1157
+ }
1158
+ );
1159
+ };
1160
+
1161
+ // src/line-chart/line-chart.tsx
1162
+ import { jsx as jsx13 } from "react/jsx-runtime";
1163
+ var LineChart = (props) => {
1164
+ const { xScale = "category", ...restProps } = props;
1165
+ return /* @__PURE__ */ jsx13(
1166
+ ChartRoot,
1167
+ {
1168
+ ...restProps,
1169
+ kind: "line",
1170
+ horizontal: false,
1171
+ scale: xScale
1172
+ }
1173
+ );
1174
+ };
1175
+
1176
+ // src/line-series/line-series.tsx
1177
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1178
+ var LineSeries = (props) => {
1179
+ const { color = "var(--gridui-chart-series)", strokeWidth = 2, dashArray, points, selectedColor = "var(--gridui-chart-selected)" } = props;
1180
+ const chart = useChart();
1181
+ const plot = usePlot();
1182
+ if (chart.kind !== "line") {
1183
+ throw new Error("LineSeries requires LineChart.");
1184
+ }
1185
+ const size = points?.size ?? 5;
1186
+ const shape = points?.shape ?? "none";
1187
+ return /* @__PURE__ */ jsxs7("g", { children: [
1188
+ /* @__PURE__ */ jsx14(
1189
+ "path",
1190
+ {
1191
+ d: linePath(chart.data, plot.category, plot.value),
1192
+ fill: "none",
1193
+ stroke: color,
1194
+ strokeWidth,
1195
+ strokeDasharray: dashArray,
1196
+ strokeLinejoin: "miter",
1197
+ pointerEvents: "none"
1198
+ }
1199
+ ),
1200
+ chart.data.map((datum, index) => {
1201
+ if (datum.y === null) {
1202
+ return null;
1203
+ }
1204
+ const selected = chart.selectedId === datum.id;
1205
+ const isolated = (chart.data[index - 1]?.y ?? null) === null && (chart.data[index + 1]?.y ?? null) === null;
1206
+ const visible = shape !== "none" || selected || isolated;
1207
+ const markSize = selected ? Math.max(8, size) : size;
1208
+ const pointColor = selected ? selectedColor : points?.color ?? color;
1209
+ const fill = points?.fill === "hollow" && !selected ? "var(--gridui-chart-point-background)" : pointColor;
1210
+ const x = plot.category(datum);
1211
+ const y = plot.value(datum.y);
1212
+ const previous = chart.data[index - 1];
1213
+ const next = chart.data[index + 1];
1214
+ const start = previous ? (plot.category(previous) + x) / 2 : plot.left;
1215
+ const end = next ? (plot.category(next) + x) / 2 : plot.right;
1216
+ return /* @__PURE__ */ jsxs7(
1217
+ DatumMark,
1218
+ {
1219
+ datum,
1220
+ children: [
1221
+ /* @__PURE__ */ jsx14(
1222
+ "rect",
1223
+ {
1224
+ className: "gridui-chart-hit",
1225
+ x: start,
1226
+ y: plot.top,
1227
+ width: Math.max(1, end - start),
1228
+ height: plot.bottom - plot.top,
1229
+ fill: "transparent"
1230
+ }
1231
+ ),
1232
+ visible && (shape === "square" ? /* @__PURE__ */ jsx14(
1233
+ "rect",
1234
+ {
1235
+ x: x - markSize / 2,
1236
+ y: y - markSize / 2,
1237
+ width: markSize,
1238
+ height: markSize,
1239
+ fill,
1240
+ stroke: selected ? selectedColor : points?.color ?? color,
1241
+ strokeWidth: points?.strokeWidth ?? 1.5,
1242
+ pointerEvents: "none"
1243
+ }
1244
+ ) : /* @__PURE__ */ jsx14(
1245
+ "circle",
1246
+ {
1247
+ cx: x,
1248
+ cy: y,
1249
+ r: markSize / 2,
1250
+ fill,
1251
+ stroke: selected ? selectedColor : points?.color ?? color,
1252
+ strokeWidth: points?.strokeWidth ?? 1.5,
1253
+ pointerEvents: "none"
1254
+ }
1255
+ ))
1256
+ ]
1257
+ },
1258
+ datum.id
1259
+ );
1260
+ })
1261
+ ] });
1262
+ };
1263
+ export {
1264
+ BarChart,
1265
+ BarSeries,
1266
+ ChartCursor,
1267
+ ChartGrid,
1268
+ ChartPlot,
1269
+ ChartTooltip,
1270
+ ChartValueLabels,
1271
+ ChartXAxis,
1272
+ ChartYAxis,
1273
+ LineChart,
1274
+ LineSeries
1275
+ };
1276
+ //# sourceMappingURL=index.js.map