@classic-homes/charts-react 0.1.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.js ADDED
@@ -0,0 +1,2167 @@
1
+ // src/components/base/ChartContainer.tsx
2
+ import * as React4 from "react";
3
+
4
+ // src/lib/utils.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ // src/components/base/ChartSkeleton.tsx
12
+ import * as React from "react";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ var ChartSkeleton = React.forwardRef(
15
+ ({ height = 400, className }, ref) => {
16
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
17
+ return /* @__PURE__ */ jsx(
18
+ "div",
19
+ {
20
+ ref,
21
+ "data-testid": "chart-skeleton",
22
+ className: cn("animate-pulse rounded-lg border border-border bg-muted", className),
23
+ style: { height: heightStyle },
24
+ children: /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col p-4", children: [
25
+ /* @__PURE__ */ jsx("div", { className: "mb-4 h-5 w-1/3 rounded bg-muted-foreground/20" }),
26
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-end gap-2 px-4 pb-8", children: [40, 65, 45, 80, 55, 70, 50].map((height2, i) => /* @__PURE__ */ jsx(
27
+ "div",
28
+ {
29
+ className: "flex-1 rounded-t bg-muted-foreground/20",
30
+ style: { height: `${height2}%` }
31
+ },
32
+ i
33
+ )) }),
34
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between px-4", children: [1, 2, 3, 4, 5, 6, 7].map((i) => /* @__PURE__ */ jsx("div", { className: "h-3 w-8 rounded bg-muted-foreground/20" }, i)) })
35
+ ] })
36
+ }
37
+ );
38
+ }
39
+ );
40
+ ChartSkeleton.displayName = "ChartSkeleton";
41
+
42
+ // src/components/base/ChartError.tsx
43
+ import * as React2 from "react";
44
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
45
+ var ChartError = React2.forwardRef(
46
+ ({ message, height = 400, onRetry, className }, ref) => {
47
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
48
+ return /* @__PURE__ */ jsxs2(
49
+ "div",
50
+ {
51
+ ref,
52
+ "data-testid": "chart-error",
53
+ role: "alert",
54
+ className: cn(
55
+ "flex flex-col items-center justify-center rounded-lg border border-destructive/50 bg-destructive/10",
56
+ className
57
+ ),
58
+ style: { height: heightStyle },
59
+ children: [
60
+ /* @__PURE__ */ jsx2(
61
+ "svg",
62
+ {
63
+ className: "mb-3 h-10 w-10 text-destructive",
64
+ xmlns: "http://www.w3.org/2000/svg",
65
+ fill: "none",
66
+ viewBox: "0 0 24 24",
67
+ stroke: "currentColor",
68
+ "aria-hidden": "true",
69
+ children: /* @__PURE__ */ jsx2(
70
+ "path",
71
+ {
72
+ strokeLinecap: "round",
73
+ strokeLinejoin: "round",
74
+ strokeWidth: 2,
75
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
76
+ }
77
+ )
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsx2("p", { className: "mb-2 text-sm font-medium text-destructive", children: message }),
81
+ onRetry && /* @__PURE__ */ jsx2(
82
+ "button",
83
+ {
84
+ onClick: onRetry,
85
+ className: "rounded-md bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground transition-colors hover:bg-destructive/90",
86
+ children: "Retry"
87
+ }
88
+ )
89
+ ]
90
+ }
91
+ );
92
+ }
93
+ );
94
+ ChartError.displayName = "ChartError";
95
+
96
+ // src/components/base/ChartEmpty.tsx
97
+ import * as React3 from "react";
98
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
99
+ var ChartEmpty = React3.forwardRef(
100
+ ({ message = "No data available", height = 400, className }, ref) => {
101
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
102
+ return /* @__PURE__ */ jsxs3(
103
+ "div",
104
+ {
105
+ ref,
106
+ "data-testid": "chart-empty",
107
+ className: cn(
108
+ "flex flex-col items-center justify-center rounded-lg border border-border bg-muted/50",
109
+ className
110
+ ),
111
+ style: { height: heightStyle },
112
+ children: [
113
+ /* @__PURE__ */ jsx3(
114
+ "svg",
115
+ {
116
+ className: "mb-3 h-10 w-10 text-muted-foreground",
117
+ xmlns: "http://www.w3.org/2000/svg",
118
+ fill: "none",
119
+ viewBox: "0 0 24 24",
120
+ stroke: "currentColor",
121
+ "aria-hidden": "true",
122
+ children: /* @__PURE__ */ jsx3(
123
+ "path",
124
+ {
125
+ strokeLinecap: "round",
126
+ strokeLinejoin: "round",
127
+ strokeWidth: 1.5,
128
+ d: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
129
+ }
130
+ )
131
+ }
132
+ ),
133
+ /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: message })
134
+ ]
135
+ }
136
+ );
137
+ }
138
+ );
139
+ ChartEmpty.displayName = "ChartEmpty";
140
+
141
+ // src/components/base/ChartContainer.tsx
142
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
143
+ var ChartContainer = React4.forwardRef(
144
+ ({
145
+ title,
146
+ description,
147
+ height = 400,
148
+ loading,
149
+ error,
150
+ empty,
151
+ emptyMessage,
152
+ onRetry,
153
+ className,
154
+ wrapperClassName,
155
+ children,
156
+ ...props
157
+ }, ref) => {
158
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
159
+ if (loading) {
160
+ return /* @__PURE__ */ jsx4(ChartSkeleton, { height, className: wrapperClassName });
161
+ }
162
+ if (error) {
163
+ return /* @__PURE__ */ jsx4(
164
+ ChartError,
165
+ {
166
+ message: error,
167
+ height,
168
+ onRetry,
169
+ className: wrapperClassName
170
+ }
171
+ );
172
+ }
173
+ if (empty) {
174
+ return /* @__PURE__ */ jsx4(ChartEmpty, { message: emptyMessage, height, className: wrapperClassName });
175
+ }
176
+ return /* @__PURE__ */ jsxs4(
177
+ "div",
178
+ {
179
+ ref,
180
+ role: "img",
181
+ "aria-label": title,
182
+ "aria-describedby": description ? `${title}-desc` : void 0,
183
+ "data-testid": "chart-container",
184
+ className: cn("rounded-lg border border-border bg-card", wrapperClassName),
185
+ ...props,
186
+ children: [
187
+ description && /* @__PURE__ */ jsx4("span", { id: `${title}-desc`, className: "sr-only", children: description }),
188
+ /* @__PURE__ */ jsx4("div", { className: cn("h-full w-full", className), style: { height: heightStyle }, children })
189
+ ]
190
+ }
191
+ );
192
+ }
193
+ );
194
+ ChartContainer.displayName = "ChartContainer";
195
+
196
+ // src/components/core/LineChart.tsx
197
+ import * as React5 from "react";
198
+ import * as echarts3 from "echarts/core";
199
+ import { LineChart as EChartsLineChart } from "echarts/charts";
200
+ import {
201
+ GridComponent,
202
+ TooltipComponent,
203
+ LegendComponent,
204
+ TitleComponent
205
+ } from "echarts/components";
206
+ import { CanvasRenderer } from "echarts/renderers";
207
+ import { generateLineChartDescription } from "@classic-homes/charts-core";
208
+
209
+ // src/hooks/useChart.ts
210
+ import { useEffect as useEffect4, useRef as useRef2 } from "react";
211
+ import * as echarts2 from "echarts/core";
212
+
213
+ // src/hooks/useChartTheme.ts
214
+ import { useEffect, useState, useCallback } from "react";
215
+ import * as echarts from "echarts/core";
216
+ import { lightTheme, darkTheme, THEME_LIGHT, THEME_DARK } from "@classic-homes/charts-core";
217
+ var themesRegistered = false;
218
+ function registerClassicThemes() {
219
+ if (themesRegistered) return;
220
+ echarts.registerTheme(THEME_LIGHT, lightTheme);
221
+ echarts.registerTheme(THEME_DARK, darkTheme);
222
+ themesRegistered = true;
223
+ }
224
+ function useChartTheme(preference = "auto") {
225
+ const [currentTheme, setCurrentTheme] = useState(THEME_LIGHT);
226
+ const updateTheme = useCallback(() => {
227
+ if (preference !== "auto") {
228
+ setCurrentTheme(preference === "dark" ? THEME_DARK : THEME_LIGHT);
229
+ return;
230
+ }
231
+ const isDark = document.documentElement.classList.contains("dark");
232
+ setCurrentTheme(isDark ? THEME_DARK : THEME_LIGHT);
233
+ }, [preference]);
234
+ useEffect(() => {
235
+ registerClassicThemes();
236
+ updateTheme();
237
+ if (preference !== "auto") return;
238
+ const observer = new MutationObserver((mutations) => {
239
+ mutations.forEach((mutation) => {
240
+ if (mutation.type === "attributes" && mutation.attributeName === "class") {
241
+ updateTheme();
242
+ }
243
+ });
244
+ });
245
+ observer.observe(document.documentElement, {
246
+ attributes: true,
247
+ attributeFilter: ["class"]
248
+ });
249
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
250
+ const handleMediaChange = () => updateTheme();
251
+ mediaQuery.addEventListener("change", handleMediaChange);
252
+ return () => {
253
+ observer.disconnect();
254
+ mediaQuery.removeEventListener("change", handleMediaChange);
255
+ };
256
+ }, [preference, updateTheme]);
257
+ return currentTheme;
258
+ }
259
+
260
+ // src/hooks/useChartResize.ts
261
+ import { useEffect as useEffect2, useRef } from "react";
262
+ function useChartResize(chartRef, containerRef) {
263
+ const resizeObserverRef = useRef(null);
264
+ useEffect2(() => {
265
+ const container = containerRef.current;
266
+ const chart = chartRef.current;
267
+ if (!container || !chart) return;
268
+ let resizeTimeout;
269
+ resizeObserverRef.current = new ResizeObserver(() => {
270
+ clearTimeout(resizeTimeout);
271
+ resizeTimeout = setTimeout(() => {
272
+ chart.resize();
273
+ }, 100);
274
+ });
275
+ resizeObserverRef.current.observe(container);
276
+ return () => {
277
+ clearTimeout(resizeTimeout);
278
+ resizeObserverRef.current?.disconnect();
279
+ };
280
+ }, [chartRef, containerRef]);
281
+ }
282
+
283
+ // src/hooks/useReducedMotion.ts
284
+ import { useState as useState2, useEffect as useEffect3 } from "react";
285
+ function useReducedMotion() {
286
+ const [reducedMotion, setReducedMotion] = useState2(false);
287
+ useEffect3(() => {
288
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
289
+ setReducedMotion(mediaQuery.matches);
290
+ const handleChange = (event) => {
291
+ setReducedMotion(event.matches);
292
+ };
293
+ mediaQuery.addEventListener("change", handleChange);
294
+ return () => {
295
+ mediaQuery.removeEventListener("change", handleChange);
296
+ };
297
+ }, []);
298
+ return reducedMotion;
299
+ }
300
+
301
+ // src/hooks/useChart.ts
302
+ function useChart({
303
+ option,
304
+ theme = "auto",
305
+ animation,
306
+ onReady
307
+ }) {
308
+ const containerRef = useRef2(null);
309
+ const chartRef = useRef2(null);
310
+ const currentTheme = useChartTheme(theme);
311
+ const reducedMotion = useReducedMotion();
312
+ useEffect4(() => {
313
+ if (!containerRef.current) return;
314
+ if (chartRef.current) {
315
+ chartRef.current.dispose();
316
+ }
317
+ chartRef.current = echarts2.init(containerRef.current, currentTheme);
318
+ if (onReady && chartRef.current) {
319
+ onReady(chartRef.current);
320
+ }
321
+ return () => {
322
+ chartRef.current?.dispose();
323
+ chartRef.current = null;
324
+ };
325
+ }, [currentTheme, onReady]);
326
+ useEffect4(() => {
327
+ if (!chartRef.current) return;
328
+ const shouldAnimate = animation ?? !reducedMotion;
329
+ const optionWithAnimation = {
330
+ ...option,
331
+ animation: shouldAnimate
332
+ };
333
+ chartRef.current.setOption(optionWithAnimation, {
334
+ notMerge: false,
335
+ lazyUpdate: true
336
+ });
337
+ }, [option, animation, reducedMotion]);
338
+ useEffect4(() => {
339
+ if (!chartRef.current || !containerRef.current) return;
340
+ const currentOption = chartRef.current.getOption();
341
+ chartRef.current.dispose();
342
+ chartRef.current = echarts2.init(containerRef.current, currentTheme);
343
+ chartRef.current.setOption(currentOption);
344
+ }, [currentTheme]);
345
+ useChartResize(chartRef, containerRef);
346
+ return {
347
+ chartRef,
348
+ containerRef,
349
+ currentTheme
350
+ };
351
+ }
352
+
353
+ // src/components/core/LineChart.tsx
354
+ import { jsx as jsx5 } from "react/jsx-runtime";
355
+ echarts3.use([
356
+ EChartsLineChart,
357
+ GridComponent,
358
+ TooltipComponent,
359
+ LegendComponent,
360
+ TitleComponent,
361
+ CanvasRenderer
362
+ ]);
363
+ var LineChart = React5.forwardRef(
364
+ ({
365
+ title,
366
+ description,
367
+ data,
368
+ height = 400,
369
+ loading,
370
+ error,
371
+ emptyMessage,
372
+ theme = "auto",
373
+ animation = true,
374
+ showLegend = true,
375
+ showTooltip = true,
376
+ showGrid = true,
377
+ smooth = false,
378
+ areaFilled = false,
379
+ showDataPoints = false,
380
+ stacked = false,
381
+ onClick,
382
+ onHover,
383
+ class: className,
384
+ ...props
385
+ }, ref) => {
386
+ const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
387
+ const option = React5.useMemo(() => {
388
+ if (isEmpty) return {};
389
+ return {
390
+ grid: {
391
+ left: "3%",
392
+ right: "4%",
393
+ bottom: "3%",
394
+ containLabel: true
395
+ },
396
+ tooltip: showTooltip ? {
397
+ trigger: "axis",
398
+ axisPointer: {
399
+ type: "cross",
400
+ label: {
401
+ backgroundColor: "#6a7985"
402
+ }
403
+ }
404
+ } : void 0,
405
+ legend: showLegend ? {
406
+ data: data.series.map((s) => s.name),
407
+ bottom: 0
408
+ } : void 0,
409
+ xAxis: {
410
+ type: "category",
411
+ boundaryGap: false,
412
+ data: data.categories,
413
+ splitLine: {
414
+ show: showGrid
415
+ }
416
+ },
417
+ yAxis: {
418
+ type: "value",
419
+ splitLine: {
420
+ show: showGrid
421
+ }
422
+ },
423
+ series: data.series.map((series) => ({
424
+ name: series.name,
425
+ type: "line",
426
+ data: series.data,
427
+ smooth,
428
+ showSymbol: showDataPoints,
429
+ symbolSize: showDataPoints ? 6 : 0,
430
+ stack: stacked ? "Total" : void 0,
431
+ areaStyle: areaFilled ? { opacity: 0.3 } : void 0,
432
+ itemStyle: series.color ? { color: series.color } : void 0,
433
+ emphasis: {
434
+ focus: "series"
435
+ }
436
+ }))
437
+ };
438
+ }, [
439
+ data,
440
+ isEmpty,
441
+ showTooltip,
442
+ showLegend,
443
+ showGrid,
444
+ smooth,
445
+ areaFilled,
446
+ showDataPoints,
447
+ stacked
448
+ ]);
449
+ const { containerRef } = useChart({
450
+ option,
451
+ theme,
452
+ animation,
453
+ onReady: (chart) => {
454
+ if (onClick) {
455
+ chart.on("click", (params) => {
456
+ onClick({
457
+ type: params.type || "click",
458
+ componentType: params.componentType || "series",
459
+ seriesIndex: params.seriesIndex,
460
+ seriesName: params.seriesName || "",
461
+ dataIndex: params.dataIndex || 0,
462
+ name: params.name || "",
463
+ value: params.value,
464
+ color: params.color
465
+ });
466
+ });
467
+ }
468
+ if (onHover) {
469
+ chart.on("mouseover", (params) => {
470
+ onHover({
471
+ type: params.type || "mouseover",
472
+ componentType: params.componentType || "series",
473
+ seriesIndex: params.seriesIndex,
474
+ seriesName: params.seriesName || "",
475
+ dataIndex: params.dataIndex || 0,
476
+ name: params.name || "",
477
+ value: params.value,
478
+ color: params.color
479
+ });
480
+ });
481
+ }
482
+ }
483
+ });
484
+ const accessibilityDescription = description || (!isEmpty ? generateLineChartDescription(title, data) : void 0);
485
+ return /* @__PURE__ */ jsx5(
486
+ ChartContainer,
487
+ {
488
+ ref,
489
+ title,
490
+ description: accessibilityDescription,
491
+ height,
492
+ loading,
493
+ error,
494
+ empty: isEmpty,
495
+ emptyMessage,
496
+ className: cn(className),
497
+ ...props,
498
+ children: /* @__PURE__ */ jsx5("div", { ref: containerRef, className: "h-full w-full" })
499
+ }
500
+ );
501
+ }
502
+ );
503
+ LineChart.displayName = "LineChart";
504
+
505
+ // src/components/core/BarChart.tsx
506
+ import * as React6 from "react";
507
+ import * as echarts4 from "echarts/core";
508
+ import { BarChart as EChartsBarChart } from "echarts/charts";
509
+ import {
510
+ GridComponent as GridComponent2,
511
+ TooltipComponent as TooltipComponent2,
512
+ LegendComponent as LegendComponent2,
513
+ TitleComponent as TitleComponent2
514
+ } from "echarts/components";
515
+ import { CanvasRenderer as CanvasRenderer2 } from "echarts/renderers";
516
+ import { generateBarChartDescription } from "@classic-homes/charts-core";
517
+ import { jsx as jsx6 } from "react/jsx-runtime";
518
+ echarts4.use([
519
+ EChartsBarChart,
520
+ GridComponent2,
521
+ TooltipComponent2,
522
+ LegendComponent2,
523
+ TitleComponent2,
524
+ CanvasRenderer2
525
+ ]);
526
+ var BarChart = React6.forwardRef(
527
+ ({
528
+ title,
529
+ description,
530
+ data,
531
+ height = 400,
532
+ loading,
533
+ error,
534
+ emptyMessage,
535
+ theme = "auto",
536
+ animation = true,
537
+ showLegend = true,
538
+ showTooltip = true,
539
+ showGrid = true,
540
+ orientation = "vertical",
541
+ stacked = false,
542
+ showValues = false,
543
+ onClick,
544
+ class: className,
545
+ ...props
546
+ }, ref) => {
547
+ const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
548
+ const isHorizontal = orientation === "horizontal";
549
+ const option = React6.useMemo(() => {
550
+ if (isEmpty) return {};
551
+ const categoryAxis = {
552
+ type: "category",
553
+ data: data.categories,
554
+ axisTick: {
555
+ alignWithLabel: true
556
+ }
557
+ };
558
+ const valueAxis = {
559
+ type: "value",
560
+ splitLine: {
561
+ show: showGrid
562
+ }
563
+ };
564
+ return {
565
+ grid: {
566
+ left: "3%",
567
+ right: "4%",
568
+ bottom: "3%",
569
+ containLabel: true
570
+ },
571
+ tooltip: showTooltip ? {
572
+ trigger: "axis",
573
+ axisPointer: {
574
+ type: "shadow"
575
+ }
576
+ } : void 0,
577
+ legend: showLegend ? {
578
+ data: data.series.map((s) => s.name),
579
+ bottom: 0
580
+ } : void 0,
581
+ xAxis: isHorizontal ? valueAxis : categoryAxis,
582
+ yAxis: isHorizontal ? categoryAxis : valueAxis,
583
+ series: data.series.map((series) => ({
584
+ name: series.name,
585
+ type: "bar",
586
+ data: series.data,
587
+ stack: stacked ? "Total" : void 0,
588
+ itemStyle: series.color ? { color: series.color } : void 0,
589
+ label: showValues ? {
590
+ show: true,
591
+ position: isHorizontal ? "right" : "top"
592
+ } : void 0,
593
+ emphasis: {
594
+ focus: "series"
595
+ }
596
+ }))
597
+ };
598
+ }, [data, isEmpty, showTooltip, showLegend, showGrid, isHorizontal, stacked, showValues]);
599
+ const { containerRef } = useChart({
600
+ option,
601
+ theme,
602
+ animation,
603
+ onReady: (chart) => {
604
+ if (onClick) {
605
+ chart.on("click", (params) => {
606
+ onClick({
607
+ type: params.type || "click",
608
+ componentType: params.componentType || "series",
609
+ seriesIndex: params.seriesIndex,
610
+ seriesName: params.seriesName || "",
611
+ dataIndex: params.dataIndex || 0,
612
+ name: params.name || "",
613
+ value: params.value,
614
+ color: params.color
615
+ });
616
+ });
617
+ }
618
+ }
619
+ });
620
+ const accessibilityDescription = description || (!isEmpty ? generateBarChartDescription(title, data) : void 0);
621
+ return /* @__PURE__ */ jsx6(
622
+ ChartContainer,
623
+ {
624
+ ref,
625
+ title,
626
+ description: accessibilityDescription,
627
+ height,
628
+ loading,
629
+ error,
630
+ empty: isEmpty,
631
+ emptyMessage,
632
+ className: cn(className),
633
+ ...props,
634
+ children: /* @__PURE__ */ jsx6("div", { ref: containerRef, className: "h-full w-full" })
635
+ }
636
+ );
637
+ }
638
+ );
639
+ BarChart.displayName = "BarChart";
640
+
641
+ // src/components/core/PieChart.tsx
642
+ import * as React7 from "react";
643
+ import * as echarts5 from "echarts/core";
644
+ import { PieChart as EChartsPieChart } from "echarts/charts";
645
+ import { TooltipComponent as TooltipComponent3, LegendComponent as LegendComponent3, TitleComponent as TitleComponent3 } from "echarts/components";
646
+ import { CanvasRenderer as CanvasRenderer3 } from "echarts/renderers";
647
+ import { generatePieChartDescription } from "@classic-homes/charts-core";
648
+ import { jsx as jsx7 } from "react/jsx-runtime";
649
+ echarts5.use([EChartsPieChart, TooltipComponent3, LegendComponent3, TitleComponent3, CanvasRenderer3]);
650
+ var PieChart = React7.forwardRef(
651
+ ({
652
+ title,
653
+ description,
654
+ data,
655
+ height = 400,
656
+ loading,
657
+ error,
658
+ emptyMessage,
659
+ theme = "auto",
660
+ animation = true,
661
+ showLegend = true,
662
+ showTooltip = true,
663
+ showLabels = true,
664
+ labelPosition = "outside",
665
+ innerRadius = 0,
666
+ onClick,
667
+ class: className,
668
+ ...props
669
+ }, ref) => {
670
+ const isEmpty = !data?.length;
671
+ const option = React7.useMemo(() => {
672
+ if (isEmpty) return {};
673
+ return {
674
+ tooltip: showTooltip ? {
675
+ trigger: "item",
676
+ formatter: "{a} <br/>{b}: {c} ({d}%)"
677
+ } : void 0,
678
+ legend: showLegend ? {
679
+ orient: "horizontal",
680
+ bottom: 0,
681
+ data: data.map((d) => d.name)
682
+ } : void 0,
683
+ series: [
684
+ {
685
+ name: title,
686
+ type: "pie",
687
+ radius: innerRadius === 0 ? "70%" : ["50%", "70%"],
688
+ center: ["50%", "45%"],
689
+ data: data.map((item) => ({
690
+ name: item.name,
691
+ value: item.value,
692
+ itemStyle: item.color ? { color: item.color } : void 0
693
+ })),
694
+ label: showLabels ? {
695
+ show: true,
696
+ position: labelPosition,
697
+ formatter: labelPosition === "inside" ? "{d}%" : "{b}: {d}%"
698
+ } : {
699
+ show: false
700
+ },
701
+ emphasis: {
702
+ itemStyle: {
703
+ shadowBlur: 10,
704
+ shadowOffsetX: 0,
705
+ shadowColor: "rgba(0, 0, 0, 0.5)"
706
+ }
707
+ }
708
+ }
709
+ ]
710
+ };
711
+ }, [data, isEmpty, showTooltip, showLegend, showLabels, labelPosition, innerRadius, title]);
712
+ const { containerRef } = useChart({
713
+ option,
714
+ theme,
715
+ animation,
716
+ onReady: (chart) => {
717
+ if (onClick) {
718
+ chart.on("click", (params) => {
719
+ onClick({
720
+ type: params.type || "click",
721
+ componentType: params.componentType || "series",
722
+ name: params.name || "",
723
+ value: params.value,
724
+ percent: params.percent,
725
+ color: params.color
726
+ });
727
+ });
728
+ }
729
+ }
730
+ });
731
+ const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription(title, data, false) : void 0);
732
+ return /* @__PURE__ */ jsx7(
733
+ ChartContainer,
734
+ {
735
+ ref,
736
+ title,
737
+ description: accessibilityDescription,
738
+ height,
739
+ loading,
740
+ error,
741
+ empty: isEmpty,
742
+ emptyMessage,
743
+ className: cn(className),
744
+ ...props,
745
+ children: /* @__PURE__ */ jsx7("div", { ref: containerRef, className: "h-full w-full" })
746
+ }
747
+ );
748
+ }
749
+ );
750
+ PieChart.displayName = "PieChart";
751
+
752
+ // src/components/core/AreaChart.tsx
753
+ import * as React8 from "react";
754
+ import * as echarts6 from "echarts/core";
755
+ import { LineChart as EChartsLineChart2 } from "echarts/charts";
756
+ import {
757
+ GridComponent as GridComponent3,
758
+ TooltipComponent as TooltipComponent4,
759
+ LegendComponent as LegendComponent4,
760
+ TitleComponent as TitleComponent4
761
+ } from "echarts/components";
762
+ import { CanvasRenderer as CanvasRenderer4 } from "echarts/renderers";
763
+ import { jsx as jsx8 } from "react/jsx-runtime";
764
+ echarts6.use([
765
+ EChartsLineChart2,
766
+ GridComponent3,
767
+ TooltipComponent4,
768
+ LegendComponent4,
769
+ TitleComponent4,
770
+ CanvasRenderer4
771
+ ]);
772
+ var AreaChart = React8.forwardRef(
773
+ ({
774
+ title,
775
+ description,
776
+ data,
777
+ height = 400,
778
+ loading,
779
+ error,
780
+ emptyMessage,
781
+ theme = "auto",
782
+ animation = true,
783
+ showLegend = true,
784
+ showTooltip = true,
785
+ showGrid = true,
786
+ smooth = false,
787
+ stacked = false,
788
+ gradient = true,
789
+ onClick,
790
+ class: className,
791
+ ...props
792
+ }, ref) => {
793
+ const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
794
+ const option = React8.useMemo(() => {
795
+ if (isEmpty) return {};
796
+ return {
797
+ grid: {
798
+ left: "3%",
799
+ right: "4%",
800
+ bottom: "3%",
801
+ containLabel: true
802
+ },
803
+ tooltip: showTooltip ? {
804
+ trigger: "axis",
805
+ axisPointer: {
806
+ type: "cross",
807
+ label: {
808
+ backgroundColor: "#6a7985"
809
+ }
810
+ }
811
+ } : void 0,
812
+ legend: showLegend ? {
813
+ data: data.series.map((s) => s.name),
814
+ bottom: 0
815
+ } : void 0,
816
+ xAxis: {
817
+ type: "category",
818
+ boundaryGap: false,
819
+ data: data.categories
820
+ },
821
+ yAxis: {
822
+ type: "value",
823
+ splitLine: {
824
+ show: showGrid
825
+ }
826
+ },
827
+ series: data.series.map((series, index) => ({
828
+ name: series.name,
829
+ type: "line",
830
+ data: series.data,
831
+ smooth,
832
+ stack: stacked ? "Total" : void 0,
833
+ areaStyle: gradient ? {
834
+ opacity: 0.8,
835
+ color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
836
+ {
837
+ offset: 0,
838
+ color: series.color || `rgba(${60 + index * 40}, ${160 - index * 20}, ${180 - index * 30}, 0.8)`
839
+ },
840
+ {
841
+ offset: 1,
842
+ color: series.color || `rgba(${60 + index * 40}, ${160 - index * 20}, ${180 - index * 30}, 0.1)`
843
+ }
844
+ ])
845
+ } : { opacity: 0.5 },
846
+ itemStyle: series.color ? { color: series.color } : void 0,
847
+ emphasis: {
848
+ focus: "series"
849
+ },
850
+ showSymbol: false
851
+ }))
852
+ };
853
+ }, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient]);
854
+ const { containerRef } = useChart({
855
+ option,
856
+ theme,
857
+ animation,
858
+ onReady: (chart) => {
859
+ if (onClick) {
860
+ chart.on("click", (params) => {
861
+ onClick({
862
+ type: params.type || "click",
863
+ componentType: params.componentType || "series",
864
+ seriesIndex: params.seriesIndex,
865
+ seriesName: params.seriesName || "",
866
+ dataIndex: params.dataIndex || 0,
867
+ name: params.name || "",
868
+ value: params.value,
869
+ color: params.color
870
+ });
871
+ });
872
+ }
873
+ }
874
+ });
875
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Area chart with ${data.categories.length} data points across ${data.series.length} series.` : void 0);
876
+ return /* @__PURE__ */ jsx8(
877
+ ChartContainer,
878
+ {
879
+ ref,
880
+ title,
881
+ description: accessibilityDescription,
882
+ height,
883
+ loading,
884
+ error,
885
+ empty: isEmpty,
886
+ emptyMessage,
887
+ className: cn(className),
888
+ ...props,
889
+ children: /* @__PURE__ */ jsx8("div", { ref: containerRef, className: "h-full w-full" })
890
+ }
891
+ );
892
+ }
893
+ );
894
+ AreaChart.displayName = "AreaChart";
895
+
896
+ // src/components/core/ScatterChart.tsx
897
+ import * as React9 from "react";
898
+ import * as echarts7 from "echarts/core";
899
+ import { ScatterChart as EChartsScatterChart } from "echarts/charts";
900
+ import {
901
+ GridComponent as GridComponent4,
902
+ TooltipComponent as TooltipComponent5,
903
+ LegendComponent as LegendComponent5,
904
+ TitleComponent as TitleComponent5
905
+ } from "echarts/components";
906
+ import { CanvasRenderer as CanvasRenderer5 } from "echarts/renderers";
907
+ import { generateScatterChartDescription } from "@classic-homes/charts-core";
908
+ import { jsx as jsx9 } from "react/jsx-runtime";
909
+ echarts7.use([
910
+ EChartsScatterChart,
911
+ GridComponent4,
912
+ TooltipComponent5,
913
+ LegendComponent5,
914
+ TitleComponent5,
915
+ CanvasRenderer5
916
+ ]);
917
+ var ScatterChart = React9.forwardRef(
918
+ ({
919
+ title,
920
+ description,
921
+ data,
922
+ height = 400,
923
+ loading,
924
+ error,
925
+ emptyMessage,
926
+ theme = "auto",
927
+ animation = true,
928
+ showLegend = true,
929
+ showTooltip = true,
930
+ showGrid = true,
931
+ showTrendLine = false,
932
+ symbolSize = 10,
933
+ onClick,
934
+ class: className,
935
+ ...props
936
+ }, ref) => {
937
+ const isEmpty = !data?.series?.length || data.series.every((s) => !s.data?.length);
938
+ const option = React9.useMemo(() => {
939
+ if (isEmpty) return {};
940
+ const series = data.series.map((s) => ({
941
+ name: s.name,
942
+ type: "scatter",
943
+ data: s.data,
944
+ symbolSize: typeof symbolSize === "function" ? symbolSize : symbolSize,
945
+ itemStyle: s.color ? { color: s.color } : void 0,
946
+ emphasis: {
947
+ focus: "series",
948
+ itemStyle: {
949
+ shadowBlur: 10,
950
+ shadowColor: "rgba(0, 0, 0, 0.5)"
951
+ }
952
+ }
953
+ }));
954
+ if (showTrendLine) {
955
+ data.series.forEach((s, index) => {
956
+ if (s.data.length < 2) return;
957
+ const n = s.data.length;
958
+ let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
959
+ s.data.forEach(([x, y]) => {
960
+ sumX += x;
961
+ sumY += y;
962
+ sumXY += x * y;
963
+ sumX2 += x * x;
964
+ });
965
+ const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
966
+ const intercept = (sumY - slope * sumX) / n;
967
+ const xValues = s.data.map(([x]) => x);
968
+ const minX = Math.min(...xValues);
969
+ const maxX = Math.max(...xValues);
970
+ series.push({
971
+ name: `${s.name} Trend`,
972
+ type: "line",
973
+ data: [
974
+ [minX, slope * minX + intercept],
975
+ [maxX, slope * maxX + intercept]
976
+ ],
977
+ smooth: false,
978
+ showSymbol: false,
979
+ lineStyle: {
980
+ type: "dashed",
981
+ opacity: 0.7
982
+ },
983
+ emphasis: {
984
+ disabled: true
985
+ },
986
+ z: index
987
+ });
988
+ });
989
+ }
990
+ return {
991
+ grid: {
992
+ left: "3%",
993
+ right: "4%",
994
+ bottom: "3%",
995
+ containLabel: true
996
+ },
997
+ tooltip: showTooltip ? {
998
+ trigger: "item",
999
+ formatter: (params) => {
1000
+ const p = params;
1001
+ if (!p.value) return "";
1002
+ return `${p.seriesName}<br/>X: ${p.value[0]}<br/>Y: ${p.value[1]}`;
1003
+ }
1004
+ } : void 0,
1005
+ legend: showLegend ? {
1006
+ data: data.series.map((s) => s.name),
1007
+ bottom: 0
1008
+ } : void 0,
1009
+ xAxis: {
1010
+ type: "value",
1011
+ splitLine: {
1012
+ show: showGrid
1013
+ }
1014
+ },
1015
+ yAxis: {
1016
+ type: "value",
1017
+ splitLine: {
1018
+ show: showGrid
1019
+ }
1020
+ },
1021
+ series
1022
+ };
1023
+ }, [data, isEmpty, showTooltip, showLegend, showGrid, showTrendLine, symbolSize]);
1024
+ const { containerRef } = useChart({
1025
+ option,
1026
+ theme,
1027
+ animation,
1028
+ onReady: (chart) => {
1029
+ if (onClick) {
1030
+ chart.on("click", (params) => {
1031
+ onClick({
1032
+ type: params.type || "click",
1033
+ componentType: params.componentType || "series",
1034
+ seriesIndex: params.seriesIndex,
1035
+ seriesName: params.seriesName || "",
1036
+ dataIndex: params.dataIndex || 0,
1037
+ name: params.name || "",
1038
+ value: params.value,
1039
+ color: params.color
1040
+ });
1041
+ });
1042
+ }
1043
+ }
1044
+ });
1045
+ const accessibilityDescription = description || (!isEmpty ? generateScatterChartDescription(title, data) : void 0);
1046
+ return /* @__PURE__ */ jsx9(
1047
+ ChartContainer,
1048
+ {
1049
+ ref,
1050
+ title,
1051
+ description: accessibilityDescription,
1052
+ height,
1053
+ loading,
1054
+ error,
1055
+ empty: isEmpty,
1056
+ emptyMessage,
1057
+ className: cn(className),
1058
+ ...props,
1059
+ children: /* @__PURE__ */ jsx9("div", { ref: containerRef, className: "h-full w-full" })
1060
+ }
1061
+ );
1062
+ }
1063
+ );
1064
+ ScatterChart.displayName = "ScatterChart";
1065
+
1066
+ // src/components/core/DonutChart.tsx
1067
+ import * as React10 from "react";
1068
+ import * as echarts8 from "echarts/core";
1069
+ import { PieChart as EChartsPieChart2 } from "echarts/charts";
1070
+ import { TooltipComponent as TooltipComponent6, LegendComponent as LegendComponent6, TitleComponent as TitleComponent6 } from "echarts/components";
1071
+ import { CanvasRenderer as CanvasRenderer6 } from "echarts/renderers";
1072
+ import { generatePieChartDescription as generatePieChartDescription2 } from "@classic-homes/charts-core";
1073
+ import { jsx as jsx10 } from "react/jsx-runtime";
1074
+ echarts8.use([EChartsPieChart2, TooltipComponent6, LegendComponent6, TitleComponent6, CanvasRenderer6]);
1075
+ var DonutChart = React10.forwardRef(
1076
+ ({
1077
+ title,
1078
+ description,
1079
+ data,
1080
+ height = 400,
1081
+ loading,
1082
+ error,
1083
+ emptyMessage,
1084
+ theme = "auto",
1085
+ animation = true,
1086
+ showLegend = true,
1087
+ showTooltip = true,
1088
+ showLabels = true,
1089
+ labelPosition = "outside",
1090
+ innerRadius = "50%",
1091
+ centerLabel,
1092
+ centerValue,
1093
+ onClick,
1094
+ class: className,
1095
+ ...props
1096
+ }, ref) => {
1097
+ const isEmpty = !data?.length;
1098
+ const option = React10.useMemo(() => {
1099
+ if (isEmpty) return {};
1100
+ const graphicElements = [];
1101
+ if (centerLabel || centerValue) {
1102
+ graphicElements.push({
1103
+ type: "group",
1104
+ left: "center",
1105
+ top: "40%",
1106
+ children: [
1107
+ ...centerValue !== void 0 ? [
1108
+ {
1109
+ type: "text",
1110
+ style: {
1111
+ text: String(centerValue),
1112
+ fontSize: 28,
1113
+ fontWeight: "bold",
1114
+ fill: "currentColor",
1115
+ textAlign: "center"
1116
+ },
1117
+ top: 0,
1118
+ left: "center"
1119
+ }
1120
+ ] : [],
1121
+ ...centerLabel ? [
1122
+ {
1123
+ type: "text",
1124
+ style: {
1125
+ text: centerLabel,
1126
+ fontSize: 14,
1127
+ fill: "#888",
1128
+ textAlign: "center"
1129
+ },
1130
+ top: centerValue !== void 0 ? 35 : 0,
1131
+ left: "center"
1132
+ }
1133
+ ] : []
1134
+ ]
1135
+ });
1136
+ }
1137
+ return {
1138
+ tooltip: showTooltip ? {
1139
+ trigger: "item",
1140
+ formatter: "{a} <br/>{b}: {c} ({d}%)"
1141
+ } : void 0,
1142
+ legend: showLegend ? {
1143
+ orient: "horizontal",
1144
+ bottom: 0,
1145
+ data: data.map((d) => d.name)
1146
+ } : void 0,
1147
+ graphic: graphicElements.length > 0 ? graphicElements : void 0,
1148
+ series: [
1149
+ {
1150
+ name: title,
1151
+ type: "pie",
1152
+ radius: [innerRadius, "70%"],
1153
+ center: ["50%", "45%"],
1154
+ avoidLabelOverlap: true,
1155
+ data: data.map((item) => ({
1156
+ name: item.name,
1157
+ value: item.value,
1158
+ itemStyle: item.color ? { color: item.color } : void 0
1159
+ })),
1160
+ label: showLabels ? {
1161
+ show: true,
1162
+ position: labelPosition,
1163
+ formatter: labelPosition === "inside" ? "{d}%" : "{b}: {d}%"
1164
+ } : {
1165
+ show: false
1166
+ },
1167
+ labelLine: {
1168
+ show: showLabels && labelPosition === "outside"
1169
+ },
1170
+ emphasis: {
1171
+ itemStyle: {
1172
+ shadowBlur: 10,
1173
+ shadowOffsetX: 0,
1174
+ shadowColor: "rgba(0, 0, 0, 0.5)"
1175
+ }
1176
+ }
1177
+ }
1178
+ ]
1179
+ };
1180
+ }, [
1181
+ data,
1182
+ isEmpty,
1183
+ showTooltip,
1184
+ showLegend,
1185
+ showLabels,
1186
+ labelPosition,
1187
+ innerRadius,
1188
+ centerLabel,
1189
+ centerValue,
1190
+ title
1191
+ ]);
1192
+ const { containerRef } = useChart({
1193
+ option,
1194
+ theme,
1195
+ animation,
1196
+ onReady: (chart) => {
1197
+ if (onClick) {
1198
+ chart.on("click", (params) => {
1199
+ onClick({
1200
+ type: params.type || "click",
1201
+ componentType: params.componentType || "series",
1202
+ name: params.name || "",
1203
+ value: params.value,
1204
+ percent: params.percent,
1205
+ color: params.color
1206
+ });
1207
+ });
1208
+ }
1209
+ }
1210
+ });
1211
+ const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription2(title, data, true) : void 0);
1212
+ return /* @__PURE__ */ jsx10(
1213
+ ChartContainer,
1214
+ {
1215
+ ref,
1216
+ title,
1217
+ description: accessibilityDescription,
1218
+ height,
1219
+ loading,
1220
+ error,
1221
+ empty: isEmpty,
1222
+ emptyMessage,
1223
+ className: cn(className),
1224
+ ...props,
1225
+ children: /* @__PURE__ */ jsx10("div", { ref: containerRef, className: "h-full w-full" })
1226
+ }
1227
+ );
1228
+ }
1229
+ );
1230
+ DonutChart.displayName = "DonutChart";
1231
+
1232
+ // src/components/extended/RadarChart.tsx
1233
+ import * as React11 from "react";
1234
+ import * as echarts9 from "echarts/core";
1235
+ import { RadarChart as EChartsRadarChart } from "echarts/charts";
1236
+ import {
1237
+ TooltipComponent as TooltipComponent7,
1238
+ LegendComponent as LegendComponent7,
1239
+ TitleComponent as TitleComponent7,
1240
+ RadarComponent
1241
+ } from "echarts/components";
1242
+ import { CanvasRenderer as CanvasRenderer7 } from "echarts/renderers";
1243
+ import { jsx as jsx11 } from "react/jsx-runtime";
1244
+ echarts9.use([
1245
+ EChartsRadarChart,
1246
+ TooltipComponent7,
1247
+ LegendComponent7,
1248
+ TitleComponent7,
1249
+ RadarComponent,
1250
+ CanvasRenderer7
1251
+ ]);
1252
+ var RadarChart = React11.forwardRef(
1253
+ ({
1254
+ title,
1255
+ description,
1256
+ data,
1257
+ indicators,
1258
+ height = 400,
1259
+ loading,
1260
+ error,
1261
+ emptyMessage,
1262
+ theme = "auto",
1263
+ animation = true,
1264
+ showLegend = true,
1265
+ showTooltip = true,
1266
+ shape = "polygon",
1267
+ class: className,
1268
+ ...props
1269
+ }, ref) => {
1270
+ const isEmpty = !data?.series?.length || !indicators?.length || data.series.every((s) => !s.data?.length);
1271
+ const option = React11.useMemo(() => {
1272
+ if (isEmpty) return {};
1273
+ return {
1274
+ tooltip: showTooltip ? {
1275
+ trigger: "item"
1276
+ } : void 0,
1277
+ legend: showLegend ? {
1278
+ data: data.series.map((s) => s.name),
1279
+ bottom: 0
1280
+ } : void 0,
1281
+ radar: {
1282
+ indicator: indicators.map((ind) => ({
1283
+ name: ind.name,
1284
+ max: ind.max,
1285
+ min: ind.min
1286
+ })),
1287
+ shape
1288
+ },
1289
+ series: [
1290
+ {
1291
+ type: "radar",
1292
+ data: data.series.map((series) => ({
1293
+ name: series.name,
1294
+ value: series.data,
1295
+ itemStyle: series.color ? { color: series.color } : void 0,
1296
+ areaStyle: {
1297
+ opacity: 0.2
1298
+ }
1299
+ }))
1300
+ }
1301
+ ]
1302
+ };
1303
+ }, [data, indicators, isEmpty, showTooltip, showLegend, shape]);
1304
+ const { containerRef } = useChart({
1305
+ option,
1306
+ theme,
1307
+ animation
1308
+ });
1309
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Radar chart with ${indicators.length} dimensions comparing ${data.series.length} series.` : void 0);
1310
+ return /* @__PURE__ */ jsx11(
1311
+ ChartContainer,
1312
+ {
1313
+ ref,
1314
+ title,
1315
+ description: accessibilityDescription,
1316
+ height,
1317
+ loading,
1318
+ error,
1319
+ empty: isEmpty,
1320
+ emptyMessage,
1321
+ className: cn(className),
1322
+ ...props,
1323
+ children: /* @__PURE__ */ jsx11("div", { ref: containerRef, className: "h-full w-full" })
1324
+ }
1325
+ );
1326
+ }
1327
+ );
1328
+ RadarChart.displayName = "RadarChart";
1329
+
1330
+ // src/components/extended/FunnelChart.tsx
1331
+ import * as React12 from "react";
1332
+ import * as echarts10 from "echarts/core";
1333
+ import { FunnelChart as EChartsFunnelChart } from "echarts/charts";
1334
+ import { TooltipComponent as TooltipComponent8, LegendComponent as LegendComponent8, TitleComponent as TitleComponent8 } from "echarts/components";
1335
+ import { CanvasRenderer as CanvasRenderer8 } from "echarts/renderers";
1336
+ import { jsx as jsx12 } from "react/jsx-runtime";
1337
+ echarts10.use([
1338
+ EChartsFunnelChart,
1339
+ TooltipComponent8,
1340
+ LegendComponent8,
1341
+ TitleComponent8,
1342
+ CanvasRenderer8
1343
+ ]);
1344
+ var FunnelChart = React12.forwardRef(
1345
+ ({
1346
+ title,
1347
+ description,
1348
+ data,
1349
+ height = 400,
1350
+ loading,
1351
+ error,
1352
+ emptyMessage,
1353
+ theme = "auto",
1354
+ animation = true,
1355
+ showLegend = true,
1356
+ showTooltip = true,
1357
+ sort = "descending",
1358
+ orientation = "vertical",
1359
+ showLabels = true,
1360
+ onClick,
1361
+ class: className,
1362
+ ...props
1363
+ }, ref) => {
1364
+ const isEmpty = !data?.length;
1365
+ const option = React12.useMemo(() => {
1366
+ if (isEmpty) return {};
1367
+ return {
1368
+ tooltip: showTooltip ? {
1369
+ trigger: "item",
1370
+ formatter: "{a} <br/>{b}: {c}"
1371
+ } : void 0,
1372
+ legend: showLegend ? {
1373
+ data: data.map((d) => d.name),
1374
+ bottom: 0
1375
+ } : void 0,
1376
+ series: [
1377
+ {
1378
+ name: title,
1379
+ type: "funnel",
1380
+ left: "10%",
1381
+ top: 60,
1382
+ bottom: 60,
1383
+ width: "80%",
1384
+ min: 0,
1385
+ max: Math.max(...data.map((d) => d.value)),
1386
+ minSize: "0%",
1387
+ maxSize: "100%",
1388
+ sort,
1389
+ orient: orientation,
1390
+ gap: 2,
1391
+ label: showLabels ? {
1392
+ show: true,
1393
+ position: "inside",
1394
+ formatter: "{b}: {c}"
1395
+ } : {
1396
+ show: false
1397
+ },
1398
+ labelLine: {
1399
+ show: false
1400
+ },
1401
+ emphasis: {
1402
+ label: {
1403
+ fontSize: 16
1404
+ }
1405
+ },
1406
+ data: data.map((item) => ({
1407
+ name: item.name,
1408
+ value: item.value,
1409
+ itemStyle: item.color ? { color: item.color } : void 0
1410
+ }))
1411
+ }
1412
+ ]
1413
+ };
1414
+ }, [data, isEmpty, showTooltip, showLegend, sort, orientation, showLabels, title]);
1415
+ const { containerRef } = useChart({
1416
+ option,
1417
+ theme,
1418
+ animation,
1419
+ onReady: (chart) => {
1420
+ if (onClick) {
1421
+ chart.on("click", (params) => {
1422
+ onClick({
1423
+ type: params.type || "click",
1424
+ componentType: params.componentType || "series",
1425
+ name: params.name || "",
1426
+ value: params.value,
1427
+ color: params.color
1428
+ });
1429
+ });
1430
+ }
1431
+ }
1432
+ });
1433
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Funnel chart with ${data.length} stages.` : void 0);
1434
+ return /* @__PURE__ */ jsx12(
1435
+ ChartContainer,
1436
+ {
1437
+ ref,
1438
+ title,
1439
+ description: accessibilityDescription,
1440
+ height,
1441
+ loading,
1442
+ error,
1443
+ empty: isEmpty,
1444
+ emptyMessage,
1445
+ className: cn(className),
1446
+ ...props,
1447
+ children: /* @__PURE__ */ jsx12("div", { ref: containerRef, className: "h-full w-full" })
1448
+ }
1449
+ );
1450
+ }
1451
+ );
1452
+ FunnelChart.displayName = "FunnelChart";
1453
+
1454
+ // src/components/extended/GaugeChart.tsx
1455
+ import * as React13 from "react";
1456
+ import * as echarts11 from "echarts/core";
1457
+ import { GaugeChart as EChartsGaugeChart } from "echarts/charts";
1458
+ import { TitleComponent as TitleComponent9 } from "echarts/components";
1459
+ import { CanvasRenderer as CanvasRenderer9 } from "echarts/renderers";
1460
+ import { jsx as jsx13 } from "react/jsx-runtime";
1461
+ echarts11.use([EChartsGaugeChart, TitleComponent9, CanvasRenderer9]);
1462
+ var GaugeChart = React13.forwardRef(
1463
+ ({
1464
+ title,
1465
+ description,
1466
+ value,
1467
+ min = 0,
1468
+ max = 100,
1469
+ height = 400,
1470
+ loading,
1471
+ error,
1472
+ emptyMessage,
1473
+ theme = "auto",
1474
+ animation = true,
1475
+ splitNumber = 10,
1476
+ showProgress = true,
1477
+ formatValue,
1478
+ class: className,
1479
+ ...props
1480
+ }, ref) => {
1481
+ const option = React13.useMemo(() => {
1482
+ return {
1483
+ series: [
1484
+ {
1485
+ type: "gauge",
1486
+ center: ["50%", "60%"],
1487
+ radius: "80%",
1488
+ min,
1489
+ max,
1490
+ splitNumber,
1491
+ progress: showProgress ? {
1492
+ show: true,
1493
+ width: 18
1494
+ } : void 0,
1495
+ axisLine: {
1496
+ lineStyle: {
1497
+ width: 18
1498
+ }
1499
+ },
1500
+ axisTick: {
1501
+ distance: -30,
1502
+ splitNumber: 5,
1503
+ lineStyle: {
1504
+ width: 2,
1505
+ color: "#999"
1506
+ }
1507
+ },
1508
+ splitLine: {
1509
+ distance: -32,
1510
+ length: 10,
1511
+ lineStyle: {
1512
+ width: 3,
1513
+ color: "#999"
1514
+ }
1515
+ },
1516
+ axisLabel: {
1517
+ distance: -20,
1518
+ color: "#999",
1519
+ fontSize: 12
1520
+ },
1521
+ anchor: {
1522
+ show: true,
1523
+ size: 20,
1524
+ itemStyle: {
1525
+ borderWidth: 2
1526
+ }
1527
+ },
1528
+ pointer: {
1529
+ width: 6,
1530
+ length: "60%"
1531
+ },
1532
+ title: {
1533
+ show: true,
1534
+ offsetCenter: [0, "70%"],
1535
+ fontSize: 14
1536
+ },
1537
+ detail: {
1538
+ valueAnimation: animation,
1539
+ fontSize: 28,
1540
+ fontWeight: "bold",
1541
+ offsetCenter: [0, "40%"],
1542
+ formatter: formatValue || "{value}"
1543
+ },
1544
+ data: [
1545
+ {
1546
+ value,
1547
+ name: title
1548
+ }
1549
+ ]
1550
+ }
1551
+ ]
1552
+ };
1553
+ }, [value, min, max, splitNumber, showProgress, formatValue, title, animation]);
1554
+ const { containerRef } = useChart({
1555
+ option,
1556
+ theme,
1557
+ animation
1558
+ });
1559
+ const accessibilityDescription = description || `${title}. Gauge showing value ${value} on scale from ${min} to ${max}.`;
1560
+ return /* @__PURE__ */ jsx13(
1561
+ ChartContainer,
1562
+ {
1563
+ ref,
1564
+ title,
1565
+ description: accessibilityDescription,
1566
+ height,
1567
+ loading,
1568
+ error,
1569
+ emptyMessage,
1570
+ className: cn(className),
1571
+ ...props,
1572
+ children: /* @__PURE__ */ jsx13("div", { ref: containerRef, className: "h-full w-full" })
1573
+ }
1574
+ );
1575
+ }
1576
+ );
1577
+ GaugeChart.displayName = "GaugeChart";
1578
+
1579
+ // src/components/extended/HeatmapChart.tsx
1580
+ import * as React14 from "react";
1581
+ import * as echarts12 from "echarts/core";
1582
+ import { HeatmapChart as EChartsHeatmapChart } from "echarts/charts";
1583
+ import {
1584
+ GridComponent as GridComponent5,
1585
+ TooltipComponent as TooltipComponent9,
1586
+ TitleComponent as TitleComponent10,
1587
+ VisualMapComponent
1588
+ } from "echarts/components";
1589
+ import { CanvasRenderer as CanvasRenderer10 } from "echarts/renderers";
1590
+ import { jsx as jsx14 } from "react/jsx-runtime";
1591
+ echarts12.use([
1592
+ EChartsHeatmapChart,
1593
+ GridComponent5,
1594
+ TooltipComponent9,
1595
+ TitleComponent10,
1596
+ VisualMapComponent,
1597
+ CanvasRenderer10
1598
+ ]);
1599
+ var HeatmapChart = React14.forwardRef(
1600
+ ({
1601
+ title,
1602
+ description,
1603
+ data,
1604
+ xAxis,
1605
+ yAxis,
1606
+ height = 400,
1607
+ loading,
1608
+ error,
1609
+ emptyMessage,
1610
+ theme = "auto",
1611
+ animation = true,
1612
+ showTooltip = true,
1613
+ showValues = false,
1614
+ onClick,
1615
+ class: className,
1616
+ ...props
1617
+ }, ref) => {
1618
+ const isEmpty = !data?.data?.length || !xAxis?.length || !yAxis?.length;
1619
+ const values = data?.data?.map(([, , value]) => value) || [];
1620
+ const minValue = data?.min ?? Math.min(...values);
1621
+ const maxValue = data?.max ?? Math.max(...values);
1622
+ const option = React14.useMemo(() => {
1623
+ if (isEmpty) return {};
1624
+ return {
1625
+ tooltip: showTooltip ? {
1626
+ position: "top",
1627
+ formatter: (params) => {
1628
+ const p = params;
1629
+ if (!p.value) return "";
1630
+ const [xIdx, yIdx, value] = p.value;
1631
+ return `${xAxis[xIdx]} / ${yAxis[yIdx]}: ${value}`;
1632
+ }
1633
+ } : void 0,
1634
+ grid: {
1635
+ left: "3%",
1636
+ right: "10%",
1637
+ bottom: "3%",
1638
+ containLabel: true
1639
+ },
1640
+ xAxis: {
1641
+ type: "category",
1642
+ data: xAxis,
1643
+ splitArea: {
1644
+ show: true
1645
+ }
1646
+ },
1647
+ yAxis: {
1648
+ type: "category",
1649
+ data: yAxis,
1650
+ splitArea: {
1651
+ show: true
1652
+ }
1653
+ },
1654
+ visualMap: {
1655
+ min: minValue,
1656
+ max: maxValue,
1657
+ calculable: true,
1658
+ orient: "vertical",
1659
+ right: "0%",
1660
+ top: "center"
1661
+ },
1662
+ series: [
1663
+ {
1664
+ name: title,
1665
+ type: "heatmap",
1666
+ data: data.data,
1667
+ label: showValues ? {
1668
+ show: true
1669
+ } : void 0,
1670
+ emphasis: {
1671
+ itemStyle: {
1672
+ shadowBlur: 10,
1673
+ shadowColor: "rgba(0, 0, 0, 0.5)"
1674
+ }
1675
+ }
1676
+ }
1677
+ ]
1678
+ };
1679
+ }, [data, xAxis, yAxis, isEmpty, showTooltip, showValues, minValue, maxValue, title]);
1680
+ const { containerRef } = useChart({
1681
+ option,
1682
+ theme,
1683
+ animation,
1684
+ onReady: (chart) => {
1685
+ if (onClick) {
1686
+ chart.on("click", (params) => {
1687
+ const [xIdx, yIdx, value] = params.value || [0, 0, 0];
1688
+ onClick({
1689
+ type: params.type || "click",
1690
+ componentType: params.componentType || "series",
1691
+ xIndex: xIdx,
1692
+ yIndex: yIdx,
1693
+ xLabel: xAxis[xIdx],
1694
+ yLabel: yAxis[yIdx],
1695
+ value
1696
+ });
1697
+ });
1698
+ }
1699
+ }
1700
+ });
1701
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Heatmap with ${xAxis.length} columns and ${yAxis.length} rows.` : void 0);
1702
+ return /* @__PURE__ */ jsx14(
1703
+ ChartContainer,
1704
+ {
1705
+ ref,
1706
+ title,
1707
+ description: accessibilityDescription,
1708
+ height,
1709
+ loading,
1710
+ error,
1711
+ empty: isEmpty,
1712
+ emptyMessage,
1713
+ className: cn(className),
1714
+ ...props,
1715
+ children: /* @__PURE__ */ jsx14("div", { ref: containerRef, className: "h-full w-full" })
1716
+ }
1717
+ );
1718
+ }
1719
+ );
1720
+ HeatmapChart.displayName = "HeatmapChart";
1721
+
1722
+ // src/components/extended/TreemapChart.tsx
1723
+ import * as React15 from "react";
1724
+ import * as echarts13 from "echarts/core";
1725
+ import { TreemapChart as EChartsTreemapChart } from "echarts/charts";
1726
+ import { TooltipComponent as TooltipComponent10, TitleComponent as TitleComponent11 } from "echarts/components";
1727
+ import { CanvasRenderer as CanvasRenderer11 } from "echarts/renderers";
1728
+ import { jsx as jsx15 } from "react/jsx-runtime";
1729
+ echarts13.use([EChartsTreemapChart, TooltipComponent10, TitleComponent11, CanvasRenderer11]);
1730
+ var TreemapChart = React15.forwardRef(
1731
+ ({
1732
+ title,
1733
+ description,
1734
+ data,
1735
+ levels,
1736
+ height = 400,
1737
+ loading,
1738
+ error,
1739
+ emptyMessage,
1740
+ theme = "auto",
1741
+ animation = true,
1742
+ showTooltip = true,
1743
+ onClick,
1744
+ class: className,
1745
+ ...props
1746
+ }, ref) => {
1747
+ const isEmpty = !data?.length;
1748
+ const option = React15.useMemo(() => {
1749
+ if (isEmpty) return {};
1750
+ return {
1751
+ tooltip: showTooltip ? {
1752
+ formatter: (params) => {
1753
+ const p = params;
1754
+ return `${p.name}: ${p.value}`;
1755
+ }
1756
+ } : void 0,
1757
+ series: [
1758
+ {
1759
+ type: "treemap",
1760
+ data,
1761
+ roam: false,
1762
+ levels: levels || [
1763
+ {
1764
+ itemStyle: {
1765
+ borderColor: "#555",
1766
+ borderWidth: 4,
1767
+ gapWidth: 4
1768
+ }
1769
+ },
1770
+ {
1771
+ colorSaturation: [0.3, 0.6],
1772
+ itemStyle: {
1773
+ borderColorSaturation: 0.7,
1774
+ gapWidth: 2,
1775
+ borderWidth: 2
1776
+ }
1777
+ },
1778
+ {
1779
+ colorSaturation: [0.3, 0.5],
1780
+ itemStyle: {
1781
+ borderColorSaturation: 0.6,
1782
+ gapWidth: 1
1783
+ }
1784
+ },
1785
+ {
1786
+ colorSaturation: [0.3, 0.5]
1787
+ }
1788
+ ],
1789
+ label: {
1790
+ show: true,
1791
+ formatter: "{b}"
1792
+ },
1793
+ upperLabel: {
1794
+ show: true,
1795
+ height: 30
1796
+ },
1797
+ breadcrumb: {
1798
+ show: true
1799
+ }
1800
+ }
1801
+ ]
1802
+ };
1803
+ }, [data, levels, isEmpty, showTooltip]);
1804
+ const { containerRef } = useChart({
1805
+ option,
1806
+ theme,
1807
+ animation,
1808
+ onReady: (chart) => {
1809
+ if (onClick) {
1810
+ chart.on("click", (params) => {
1811
+ const treePathInfo = params.treePathInfo || [];
1812
+ onClick({
1813
+ type: params.type || "click",
1814
+ componentType: params.componentType || "series",
1815
+ name: params.name || "",
1816
+ value: params.value,
1817
+ path: treePathInfo.map((item) => item.name || ""),
1818
+ depth: treePathInfo.length - 1
1819
+ });
1820
+ });
1821
+ }
1822
+ }
1823
+ });
1824
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Treemap chart showing hierarchical data.` : void 0);
1825
+ return /* @__PURE__ */ jsx15(
1826
+ ChartContainer,
1827
+ {
1828
+ ref,
1829
+ title,
1830
+ description: accessibilityDescription,
1831
+ height,
1832
+ loading,
1833
+ error,
1834
+ empty: isEmpty,
1835
+ emptyMessage,
1836
+ className: cn(className),
1837
+ ...props,
1838
+ children: /* @__PURE__ */ jsx15("div", { ref: containerRef, className: "h-full w-full" })
1839
+ }
1840
+ );
1841
+ }
1842
+ );
1843
+ TreemapChart.displayName = "TreemapChart";
1844
+
1845
+ // src/components/extended/CandlestickChart.tsx
1846
+ import * as React16 from "react";
1847
+ import * as echarts14 from "echarts/core";
1848
+ import {
1849
+ CandlestickChart as EChartsCandlestickChart,
1850
+ BarChart as EChartsBarChart2
1851
+ } from "echarts/charts";
1852
+ import {
1853
+ GridComponent as GridComponent6,
1854
+ TooltipComponent as TooltipComponent11,
1855
+ TitleComponent as TitleComponent12,
1856
+ DataZoomComponent
1857
+ } from "echarts/components";
1858
+ import { CanvasRenderer as CanvasRenderer12 } from "echarts/renderers";
1859
+ import { jsx as jsx16 } from "react/jsx-runtime";
1860
+ echarts14.use([
1861
+ EChartsCandlestickChart,
1862
+ EChartsBarChart2,
1863
+ GridComponent6,
1864
+ TooltipComponent11,
1865
+ TitleComponent12,
1866
+ DataZoomComponent,
1867
+ CanvasRenderer12
1868
+ ]);
1869
+ var CandlestickChart = React16.forwardRef(
1870
+ ({
1871
+ title,
1872
+ description,
1873
+ data,
1874
+ height = 400,
1875
+ loading,
1876
+ error,
1877
+ emptyMessage,
1878
+ theme = "auto",
1879
+ animation = true,
1880
+ showTooltip = true,
1881
+ showVolume = false,
1882
+ onClick,
1883
+ class: className,
1884
+ ...props
1885
+ }, ref) => {
1886
+ const isEmpty = !data?.dates?.length || !data?.data?.length;
1887
+ const option = React16.useMemo(() => {
1888
+ if (isEmpty) return {};
1889
+ const candlestickData = data.data.map((item) => [item.open, item.close, item.low, item.high]);
1890
+ const seriesArr = [
1891
+ {
1892
+ name: title,
1893
+ type: "candlestick",
1894
+ data: candlestickData,
1895
+ itemStyle: {
1896
+ color: "#ef4444",
1897
+ // Up color (red for bearish in some markets)
1898
+ color0: "#22c55e",
1899
+ // Down color (green for bullish)
1900
+ borderColor: "#ef4444",
1901
+ borderColor0: "#22c55e"
1902
+ }
1903
+ }
1904
+ ];
1905
+ const gridArr = [
1906
+ {
1907
+ left: "10%",
1908
+ right: "10%",
1909
+ top: 60,
1910
+ height: showVolume ? "50%" : "70%"
1911
+ }
1912
+ ];
1913
+ const xAxisArr = [
1914
+ {
1915
+ type: "category",
1916
+ data: data.dates,
1917
+ boundaryGap: false,
1918
+ axisLine: { onZero: false },
1919
+ splitLine: { show: false },
1920
+ min: "dataMin",
1921
+ max: "dataMax"
1922
+ }
1923
+ ];
1924
+ const yAxisArr = [
1925
+ {
1926
+ scale: true,
1927
+ splitArea: {
1928
+ show: true
1929
+ }
1930
+ }
1931
+ ];
1932
+ if (showVolume && data.volume) {
1933
+ gridArr.push({
1934
+ left: "10%",
1935
+ right: "10%",
1936
+ top: "73%",
1937
+ height: "12%"
1938
+ });
1939
+ xAxisArr.push({
1940
+ type: "category",
1941
+ gridIndex: 1,
1942
+ data: data.dates,
1943
+ boundaryGap: false,
1944
+ axisLine: { onZero: false },
1945
+ axisTick: { show: false },
1946
+ splitLine: { show: false },
1947
+ axisLabel: { show: false },
1948
+ min: "dataMin",
1949
+ max: "dataMax"
1950
+ });
1951
+ yAxisArr.push({
1952
+ scale: true,
1953
+ gridIndex: 1,
1954
+ splitNumber: 2,
1955
+ axisLabel: { show: false },
1956
+ axisLine: { show: false },
1957
+ axisTick: { show: false },
1958
+ splitLine: { show: false }
1959
+ });
1960
+ seriesArr.push({
1961
+ name: "Volume",
1962
+ type: "bar",
1963
+ xAxisIndex: 1,
1964
+ yAxisIndex: 1,
1965
+ data: data.volume,
1966
+ itemStyle: {
1967
+ color: "#6b7280"
1968
+ }
1969
+ });
1970
+ }
1971
+ return {
1972
+ tooltip: showTooltip ? {
1973
+ trigger: "axis",
1974
+ axisPointer: {
1975
+ type: "cross"
1976
+ }
1977
+ } : void 0,
1978
+ grid: gridArr,
1979
+ xAxis: xAxisArr,
1980
+ yAxis: yAxisArr,
1981
+ dataZoom: [
1982
+ {
1983
+ type: "inside",
1984
+ start: 80,
1985
+ end: 100
1986
+ },
1987
+ {
1988
+ show: true,
1989
+ type: "slider",
1990
+ top: "90%",
1991
+ start: 80,
1992
+ end: 100
1993
+ }
1994
+ ],
1995
+ series: seriesArr
1996
+ };
1997
+ }, [data, isEmpty, showTooltip, showVolume, title]);
1998
+ const { containerRef } = useChart({
1999
+ option,
2000
+ theme,
2001
+ animation,
2002
+ onReady: (chart) => {
2003
+ if (onClick) {
2004
+ chart.on("click", (params) => {
2005
+ const dataIndex = params.dataIndex || 0;
2006
+ const item = data.data[dataIndex];
2007
+ onClick({
2008
+ type: params.type || "click",
2009
+ componentType: params.componentType || "series",
2010
+ date: data.dates[dataIndex],
2011
+ open: item.open,
2012
+ close: item.close,
2013
+ high: item.high,
2014
+ low: item.low,
2015
+ volume: data.volume?.[dataIndex]
2016
+ });
2017
+ });
2018
+ }
2019
+ }
2020
+ });
2021
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Candlestick chart with ${data.dates.length} data points.` : void 0);
2022
+ return /* @__PURE__ */ jsx16(
2023
+ ChartContainer,
2024
+ {
2025
+ ref,
2026
+ title,
2027
+ description: accessibilityDescription,
2028
+ height,
2029
+ loading,
2030
+ error,
2031
+ empty: isEmpty,
2032
+ emptyMessage,
2033
+ className: cn(className),
2034
+ ...props,
2035
+ children: /* @__PURE__ */ jsx16("div", { ref: containerRef, className: "h-full w-full" })
2036
+ }
2037
+ );
2038
+ }
2039
+ );
2040
+ CandlestickChart.displayName = "CandlestickChart";
2041
+
2042
+ // src/components/extended/SankeyChart.tsx
2043
+ import * as React17 from "react";
2044
+ import * as echarts15 from "echarts/core";
2045
+ import { SankeyChart as EChartsSankeyChart } from "echarts/charts";
2046
+ import { TooltipComponent as TooltipComponent12, TitleComponent as TitleComponent13 } from "echarts/components";
2047
+ import { CanvasRenderer as CanvasRenderer13 } from "echarts/renderers";
2048
+ import { jsx as jsx17 } from "react/jsx-runtime";
2049
+ echarts15.use([EChartsSankeyChart, TooltipComponent12, TitleComponent13, CanvasRenderer13]);
2050
+ var SankeyChart = React17.forwardRef(
2051
+ ({
2052
+ title,
2053
+ description,
2054
+ data,
2055
+ height = 400,
2056
+ loading,
2057
+ error,
2058
+ emptyMessage,
2059
+ theme = "auto",
2060
+ animation = true,
2061
+ showTooltip = true,
2062
+ orient = "horizontal",
2063
+ onClick,
2064
+ class: className,
2065
+ ...props
2066
+ }, ref) => {
2067
+ const isEmpty = !data?.nodes?.length || !data?.links?.length;
2068
+ const option = React17.useMemo(() => {
2069
+ if (isEmpty) return {};
2070
+ return {
2071
+ tooltip: showTooltip ? {
2072
+ trigger: "item",
2073
+ triggerOn: "mousemove"
2074
+ } : void 0,
2075
+ series: [
2076
+ {
2077
+ type: "sankey",
2078
+ orient,
2079
+ emphasis: {
2080
+ focus: "adjacency"
2081
+ },
2082
+ data: data.nodes.map((node) => ({
2083
+ name: node.name,
2084
+ itemStyle: node.color ? { color: node.color } : void 0
2085
+ })),
2086
+ links: data.links.map((link) => ({
2087
+ source: link.source,
2088
+ target: link.target,
2089
+ value: link.value
2090
+ })),
2091
+ lineStyle: {
2092
+ color: "gradient",
2093
+ curveness: 0.5
2094
+ },
2095
+ label: {
2096
+ position: orient === "horizontal" ? "right" : "bottom"
2097
+ }
2098
+ }
2099
+ ]
2100
+ };
2101
+ }, [data, isEmpty, showTooltip, orient]);
2102
+ const { containerRef } = useChart({
2103
+ option,
2104
+ theme,
2105
+ animation,
2106
+ onReady: (chart) => {
2107
+ if (onClick) {
2108
+ chart.on("click", (params) => {
2109
+ const isEdge = params.dataType === "edge";
2110
+ onClick({
2111
+ type: params.type || "click",
2112
+ componentType: params.componentType || "series",
2113
+ dataType: isEdge ? "edge" : "node",
2114
+ name: params.name || "",
2115
+ value: isEdge ? params.value : void 0,
2116
+ source: isEdge ? params.data?.source : void 0,
2117
+ target: isEdge ? params.data?.target : void 0
2118
+ });
2119
+ });
2120
+ }
2121
+ }
2122
+ });
2123
+ const accessibilityDescription = description || (!isEmpty ? `${title}. Sankey diagram with ${data.nodes.length} nodes and ${data.links.length} links.` : void 0);
2124
+ return /* @__PURE__ */ jsx17(
2125
+ ChartContainer,
2126
+ {
2127
+ ref,
2128
+ title,
2129
+ description: accessibilityDescription,
2130
+ height,
2131
+ loading,
2132
+ error,
2133
+ empty: isEmpty,
2134
+ emptyMessage,
2135
+ className: cn(className),
2136
+ ...props,
2137
+ children: /* @__PURE__ */ jsx17("div", { ref: containerRef, className: "h-full w-full" })
2138
+ }
2139
+ );
2140
+ }
2141
+ );
2142
+ SankeyChart.displayName = "SankeyChart";
2143
+ export {
2144
+ AreaChart,
2145
+ BarChart,
2146
+ CandlestickChart,
2147
+ ChartContainer,
2148
+ ChartEmpty,
2149
+ ChartError,
2150
+ ChartSkeleton,
2151
+ DonutChart,
2152
+ FunnelChart,
2153
+ GaugeChart,
2154
+ HeatmapChart,
2155
+ LineChart,
2156
+ PieChart,
2157
+ RadarChart,
2158
+ SankeyChart,
2159
+ ScatterChart,
2160
+ TreemapChart,
2161
+ cn,
2162
+ registerClassicThemes,
2163
+ useChart,
2164
+ useChartResize,
2165
+ useChartTheme,
2166
+ useReducedMotion
2167
+ };