@classic-homes/charts-react 0.1.36 → 0.1.38

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.cjs CHANGED
@@ -135,10 +135,11 @@ var ChartError = React2.forwardRef(
135
135
  )
136
136
  }
137
137
  ),
138
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mb-2 text-sm font-medium text-destructive", children: message }),
138
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mb-2 text-sm font-medium text-foreground", children: message }),
139
139
  onRetry && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
140
140
  "button",
141
141
  {
142
+ type: "button",
142
143
  onClick: onRetry,
143
144
  className: "rounded-md bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground transition-colors hover:bg-destructive/90",
144
145
  children: "Retry"
@@ -214,6 +215,7 @@ var ChartContainer = React4.forwardRef(
214
215
  ...props
215
216
  }, ref) => {
216
217
  const heightStyle = typeof height === "number" ? `${height}px` : height;
218
+ const descriptionId = `${React4.useId()}-desc`;
217
219
  if (loading) {
218
220
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChartSkeleton, { height, className: wrapperClassName });
219
221
  }
@@ -237,12 +239,12 @@ var ChartContainer = React4.forwardRef(
237
239
  ref,
238
240
  role: "img",
239
241
  "aria-label": title,
240
- "aria-describedby": description ? `${title}-desc` : void 0,
242
+ "aria-describedby": description ? descriptionId : void 0,
241
243
  "data-testid": "chart-container",
242
244
  className: cn("rounded-lg border border-border bg-card", wrapperClassName),
243
245
  ...props,
244
246
  children: [
245
- description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { id: `${title}-desc`, className: "sr-only", children: description }),
247
+ description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { id: descriptionId, className: "sr-only", children: description }),
246
248
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: cn("h-full w-full", className), style: { height: heightStyle }, children })
247
249
  ]
248
250
  }
@@ -257,11 +259,12 @@ var echarts3 = __toESM(require("echarts/core"), 1);
257
259
  var import_charts = require("echarts/charts");
258
260
  var import_components = require("echarts/components");
259
261
  var import_renderers = require("echarts/renderers");
260
- var import_charts_core2 = require("@classic-homes/charts-core");
262
+ var import_charts_core3 = require("@classic-homes/charts-core");
261
263
 
262
264
  // src/hooks/useChart.ts
263
265
  var import_react4 = require("react");
264
266
  var echarts2 = __toESM(require("echarts/core"), 1);
267
+ var import_charts_core2 = require("@classic-homes/charts-core");
265
268
 
266
269
  // src/hooks/useChartTheme.ts
267
270
  var import_react = require("react");
@@ -274,18 +277,18 @@ function registerClassicThemes() {
274
277
  echarts.registerTheme(import_charts_core.THEME_DARK, import_charts_core.darkTheme);
275
278
  themesRegistered = true;
276
279
  }
280
+ function resolveTheme(preference) {
281
+ if (preference !== "auto") {
282
+ return preference === "dark" ? import_charts_core.THEME_DARK : import_charts_core.THEME_LIGHT;
283
+ }
284
+ if (typeof document === "undefined") return import_charts_core.THEME_LIGHT;
285
+ return document.documentElement.classList.contains("dark") ? import_charts_core.THEME_DARK : import_charts_core.THEME_LIGHT;
286
+ }
277
287
  function useChartTheme(preference = "auto") {
278
- const [currentTheme, setCurrentTheme] = (0, import_react.useState)(import_charts_core.THEME_LIGHT);
279
- const updateTheme = (0, import_react.useCallback)(() => {
280
- if (preference !== "auto") {
281
- setCurrentTheme(preference === "dark" ? import_charts_core.THEME_DARK : import_charts_core.THEME_LIGHT);
282
- return;
283
- }
284
- const isDark = document.documentElement.classList.contains("dark");
285
- setCurrentTheme(isDark ? import_charts_core.THEME_DARK : import_charts_core.THEME_LIGHT);
286
- }, [preference]);
288
+ const [currentTheme, setCurrentTheme] = (0, import_react.useState)(() => resolveTheme(preference));
287
289
  (0, import_react.useEffect)(() => {
288
290
  registerClassicThemes();
291
+ const updateTheme = () => setCurrentTheme(resolveTheme(preference));
289
292
  updateTheme();
290
293
  if (preference !== "auto") return;
291
294
  const observer = new MutationObserver((mutations) => {
@@ -299,38 +302,43 @@ function useChartTheme(preference = "auto") {
299
302
  attributes: true,
300
303
  attributeFilter: ["class"]
301
304
  });
302
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
303
- const handleMediaChange = () => updateTheme();
304
- mediaQuery.addEventListener("change", handleMediaChange);
305
305
  return () => {
306
306
  observer.disconnect();
307
- mediaQuery.removeEventListener("change", handleMediaChange);
308
307
  };
309
- }, [preference, updateTheme]);
308
+ }, [preference]);
310
309
  return currentTheme;
311
310
  }
312
311
 
313
312
  // src/hooks/useChartResize.ts
314
313
  var import_react2 = require("react");
314
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? import_react2.useEffect : import_react2.useLayoutEffect;
315
+ function useRefElement(ref) {
316
+ const [element, setElement] = (0, import_react2.useState)(null);
317
+ useIsomorphicLayoutEffect(() => {
318
+ setElement(ref.current);
319
+ });
320
+ return element;
321
+ }
315
322
  function useChartResize(chartRef, containerRef) {
316
- const resizeObserverRef = (0, import_react2.useRef)(null);
323
+ const container = useRefElement(containerRef);
317
324
  (0, import_react2.useEffect)(() => {
318
- const container = containerRef.current;
319
- const chart = chartRef.current;
320
- if (!container || !chart) return;
325
+ if (!container) return;
321
326
  let resizeTimeout;
322
- resizeObserverRef.current = new ResizeObserver(() => {
327
+ const observer = new ResizeObserver(() => {
323
328
  clearTimeout(resizeTimeout);
324
329
  resizeTimeout = setTimeout(() => {
325
- chart.resize();
330
+ const chart = chartRef.current;
331
+ if (chart && !chart.isDisposed()) {
332
+ chart.resize();
333
+ }
326
334
  }, 100);
327
335
  });
328
- resizeObserverRef.current.observe(container);
336
+ observer.observe(container);
329
337
  return () => {
330
338
  clearTimeout(resizeTimeout);
331
- resizeObserverRef.current?.disconnect();
339
+ observer.disconnect();
332
340
  };
333
- }, [chartRef, containerRef]);
341
+ }, [chartRef, container]);
334
342
  }
335
343
 
336
344
  // src/hooks/useReducedMotion.ts
@@ -352,6 +360,13 @@ function useReducedMotion() {
352
360
  }
353
361
 
354
362
  // src/hooks/useChart.ts
363
+ var isComponentType = (mainType) => echarts2.ComponentModel.hasClass(mainType);
364
+ function applyOption(chart, prev, next) {
365
+ chart.setOption(next, {
366
+ replaceMerge: (0, import_charts_core2.getReplaceMerge)(prev, next, isComponentType),
367
+ lazyUpdate: true
368
+ });
369
+ }
355
370
  function useChart({
356
371
  option,
357
372
  theme = "auto",
@@ -359,44 +374,39 @@ function useChart({
359
374
  onReady
360
375
  }) {
361
376
  const containerRef = (0, import_react4.useRef)(null);
377
+ const container = useRefElement(containerRef);
362
378
  const chartRef = (0, import_react4.useRef)(null);
363
379
  const currentTheme = useChartTheme(theme);
364
380
  const reducedMotion = useReducedMotion();
365
381
  const onReadyRef = (0, import_react4.useRef)(onReady);
366
382
  onReadyRef.current = onReady;
383
+ const optionRef = (0, import_react4.useRef)(option);
384
+ optionRef.current = {
385
+ ...option,
386
+ // Reduced motion always wins over the animation prop
387
+ animation: (animation ?? true) && !reducedMotion
388
+ };
389
+ const appliedRef = (0, import_react4.useRef)(null);
367
390
  (0, import_react4.useEffect)(() => {
368
- if (!containerRef.current) return;
369
- if (chartRef.current) {
370
- chartRef.current.dispose();
371
- }
372
- chartRef.current = echarts2.init(containerRef.current, currentTheme);
373
- if (onReadyRef.current && chartRef.current) {
374
- onReadyRef.current(chartRef.current);
375
- }
391
+ if (!container) return;
392
+ const chart = echarts2.init(container, currentTheme);
393
+ chartRef.current = chart;
394
+ applyOption(chart, null, optionRef.current);
395
+ appliedRef.current = optionRef.current;
396
+ onReadyRef.current?.(chart);
376
397
  return () => {
377
- chartRef.current?.dispose();
378
- chartRef.current = null;
398
+ chart.dispose();
399
+ if (chartRef.current === chart) {
400
+ chartRef.current = null;
401
+ }
379
402
  };
380
- }, [currentTheme]);
403
+ }, [container, currentTheme]);
381
404
  (0, import_react4.useEffect)(() => {
382
- if (!chartRef.current) return;
383
- const shouldAnimate = animation ?? !reducedMotion;
384
- const optionWithAnimation = {
385
- ...option,
386
- animation: shouldAnimate
387
- };
388
- chartRef.current.setOption(optionWithAnimation, {
389
- notMerge: false,
390
- lazyUpdate: true
391
- });
405
+ const chart = chartRef.current;
406
+ if (!chart || chart.isDisposed()) return;
407
+ applyOption(chart, appliedRef.current, optionRef.current);
408
+ appliedRef.current = optionRef.current;
392
409
  }, [option, animation, reducedMotion]);
393
- (0, import_react4.useEffect)(() => {
394
- if (!chartRef.current || !containerRef.current) return;
395
- const currentOption = chartRef.current.getOption();
396
- chartRef.current.dispose();
397
- chartRef.current = echarts2.init(containerRef.current, currentTheme);
398
- chartRef.current.setOption(currentOption);
399
- }, [currentTheme]);
400
410
  useChartResize(chartRef, containerRef);
401
411
  return {
402
412
  chartRef,
@@ -405,6 +415,14 @@ function useChart({
405
415
  };
406
416
  }
407
417
 
418
+ // src/hooks/useLatestRef.ts
419
+ var import_react5 = require("react");
420
+ function useLatestRef(value) {
421
+ const ref = (0, import_react5.useRef)(value);
422
+ ref.current = value;
423
+ return ref;
424
+ }
425
+
408
426
  // src/components/core/LineChart.tsx
409
427
  var import_jsx_runtime5 = require("react/jsx-runtime");
410
428
  echarts3.use([
@@ -439,6 +457,8 @@ var LineChart = React5.forwardRef(
439
457
  ...props
440
458
  }, ref) => {
441
459
  const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
460
+ const currentTheme = useChartTheme(theme);
461
+ const chartColors = (0, import_charts_core3.getChartColors)(currentTheme);
442
462
  const option = React5.useMemo(() => {
443
463
  if (isEmpty) return {};
444
464
  return {
@@ -453,7 +473,7 @@ var LineChart = React5.forwardRef(
453
473
  axisPointer: {
454
474
  type: "cross",
455
475
  label: {
456
- backgroundColor: "#6a7985"
476
+ backgroundColor: chartColors.axisPointerLabel
457
477
  }
458
478
  }
459
479
  } : void 0,
@@ -499,44 +519,46 @@ var LineChart = React5.forwardRef(
499
519
  smooth,
500
520
  areaFilled,
501
521
  showDataPoints,
502
- stacked
522
+ stacked,
523
+ chartColors
503
524
  ]);
525
+ const latest = useLatestRef({ onClick, onHover });
504
526
  const { containerRef } = useChart({
505
527
  option,
506
- theme,
528
+ theme: currentTheme === import_charts_core3.THEME_DARK ? "dark" : "light",
507
529
  animation,
508
530
  onReady: (chart) => {
509
- if (onClick) {
510
- chart.on("click", (params) => {
511
- onClick({
512
- type: params.type || "click",
513
- componentType: params.componentType || "series",
514
- seriesIndex: params.seriesIndex,
515
- seriesName: params.seriesName || "",
516
- dataIndex: params.dataIndex || 0,
517
- name: params.name || "",
518
- value: params.value,
519
- color: params.color
520
- });
531
+ chart.on("click", (params) => {
532
+ const { onClick: onClick2 } = latest.current;
533
+ if (!onClick2) return;
534
+ onClick2({
535
+ type: params.type || "click",
536
+ componentType: params.componentType || "series",
537
+ seriesIndex: params.seriesIndex,
538
+ seriesName: params.seriesName || "",
539
+ dataIndex: params.dataIndex || 0,
540
+ name: params.name || "",
541
+ value: params.value,
542
+ color: params.color
521
543
  });
522
- }
523
- if (onHover) {
524
- chart.on("mouseover", (params) => {
525
- onHover({
526
- type: params.type || "mouseover",
527
- componentType: params.componentType || "series",
528
- seriesIndex: params.seriesIndex,
529
- seriesName: params.seriesName || "",
530
- dataIndex: params.dataIndex || 0,
531
- name: params.name || "",
532
- value: params.value,
533
- color: params.color
534
- });
544
+ });
545
+ chart.on("mouseover", (params) => {
546
+ const { onHover: onHover2 } = latest.current;
547
+ if (!onHover2) return;
548
+ onHover2({
549
+ type: params.type || "mouseover",
550
+ componentType: params.componentType || "series",
551
+ seriesIndex: params.seriesIndex,
552
+ seriesName: params.seriesName || "",
553
+ dataIndex: params.dataIndex || 0,
554
+ name: params.name || "",
555
+ value: params.value,
556
+ color: params.color
535
557
  });
536
- }
558
+ });
537
559
  }
538
560
  });
539
- const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core2.generateLineChartDescription)(title, data) : void 0);
561
+ const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core3.generateLineChartDescription)(title, data) : void 0);
540
562
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
541
563
  ChartContainer,
542
564
  {
@@ -563,7 +585,7 @@ var echarts4 = __toESM(require("echarts/core"), 1);
563
585
  var import_charts2 = require("echarts/charts");
564
586
  var import_components2 = require("echarts/components");
565
587
  var import_renderers2 = require("echarts/renderers");
566
- var import_charts_core3 = require("@classic-homes/charts-core");
588
+ var import_charts_core4 = require("@classic-homes/charts-core");
567
589
  var import_jsx_runtime6 = require("react/jsx-runtime");
568
590
  echarts4.use([
569
591
  import_charts2.BarChart,
@@ -646,28 +668,29 @@ var BarChart = React6.forwardRef(
646
668
  }))
647
669
  };
648
670
  }, [data, isEmpty, showTooltip, showLegend, showGrid, isHorizontal, stacked, showValues]);
671
+ const latest = useLatestRef({ onClick });
649
672
  const { containerRef } = useChart({
650
673
  option,
651
674
  theme,
652
675
  animation,
653
676
  onReady: (chart) => {
654
- if (onClick) {
655
- chart.on("click", (params) => {
656
- onClick({
657
- type: params.type || "click",
658
- componentType: params.componentType || "series",
659
- seriesIndex: params.seriesIndex,
660
- seriesName: params.seriesName || "",
661
- dataIndex: params.dataIndex || 0,
662
- name: params.name || "",
663
- value: params.value,
664
- color: params.color
665
- });
677
+ chart.on("click", (params) => {
678
+ const { onClick: onClick2 } = latest.current;
679
+ if (!onClick2) return;
680
+ onClick2({
681
+ type: params.type || "click",
682
+ componentType: params.componentType || "series",
683
+ seriesIndex: params.seriesIndex,
684
+ seriesName: params.seriesName || "",
685
+ dataIndex: params.dataIndex || 0,
686
+ name: params.name || "",
687
+ value: params.value,
688
+ color: params.color
666
689
  });
667
- }
690
+ });
668
691
  }
669
692
  });
670
- const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core3.generateBarChartDescription)(title, data) : void 0);
693
+ const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core4.generateBarChartDescription)(title, data) : void 0);
671
694
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
672
695
  ChartContainer,
673
696
  {
@@ -694,7 +717,7 @@ var echarts5 = __toESM(require("echarts/core"), 1);
694
717
  var import_charts3 = require("echarts/charts");
695
718
  var import_components3 = require("echarts/components");
696
719
  var import_renderers3 = require("echarts/renderers");
697
- var import_charts_core4 = require("@classic-homes/charts-core");
720
+ var import_charts_core5 = require("@classic-homes/charts-core");
698
721
  var import_jsx_runtime7 = require("react/jsx-runtime");
699
722
  echarts5.use([import_charts3.PieChart, import_components3.TooltipComponent, import_components3.LegendComponent, import_components3.TitleComponent, import_renderers3.CanvasRenderer]);
700
723
  var PieChart = React7.forwardRef(
@@ -734,7 +757,7 @@ var PieChart = React7.forwardRef(
734
757
  {
735
758
  name: title,
736
759
  type: "pie",
737
- radius: innerRadius === 0 ? "70%" : ["50%", "70%"],
760
+ radius: innerRadius ? [innerRadius, "70%"] : "70%",
738
761
  center: ["50%", "45%"],
739
762
  data: data.map((item) => ({
740
763
  name: item.name,
@@ -759,26 +782,27 @@ var PieChart = React7.forwardRef(
759
782
  ]
760
783
  };
761
784
  }, [data, isEmpty, showTooltip, showLegend, showLabels, labelPosition, innerRadius, title]);
785
+ const latest = useLatestRef({ onClick });
762
786
  const { containerRef } = useChart({
763
787
  option,
764
788
  theme,
765
789
  animation,
766
790
  onReady: (chart) => {
767
- if (onClick) {
768
- chart.on("click", (params) => {
769
- onClick({
770
- type: params.type || "click",
771
- componentType: params.componentType || "series",
772
- name: params.name || "",
773
- value: params.value,
774
- percent: params.percent,
775
- color: params.color
776
- });
791
+ chart.on("click", (params) => {
792
+ const { onClick: onClick2 } = latest.current;
793
+ if (!onClick2) return;
794
+ onClick2({
795
+ type: params.type || "click",
796
+ componentType: params.componentType || "series",
797
+ name: params.name || "",
798
+ value: params.value,
799
+ percent: params.percent,
800
+ color: params.color
777
801
  });
778
- }
802
+ });
779
803
  }
780
804
  });
781
- const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core4.generatePieChartDescription)(title, data, false) : void 0);
805
+ const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core5.generatePieChartDescription)(title, data, false) : void 0);
782
806
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
783
807
  ChartContainer,
784
808
  {
@@ -805,6 +829,7 @@ var echarts6 = __toESM(require("echarts/core"), 1);
805
829
  var import_charts4 = require("echarts/charts");
806
830
  var import_components4 = require("echarts/components");
807
831
  var import_renderers4 = require("echarts/renderers");
832
+ var import_charts_core6 = require("@classic-homes/charts-core");
808
833
  var import_jsx_runtime8 = require("react/jsx-runtime");
809
834
  echarts6.use([
810
835
  import_charts4.LineChart,
@@ -836,6 +861,8 @@ var AreaChart = React8.forwardRef(
836
861
  ...props
837
862
  }, ref) => {
838
863
  const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
864
+ const currentTheme = useChartTheme(theme);
865
+ const chartColors = (0, import_charts_core6.getChartColors)(currentTheme);
839
866
  const option = React8.useMemo(() => {
840
867
  if (isEmpty) return {};
841
868
  return {
@@ -850,7 +877,7 @@ var AreaChart = React8.forwardRef(
850
877
  axisPointer: {
851
878
  type: "cross",
852
879
  label: {
853
- backgroundColor: "#6a7985"
880
+ backgroundColor: chartColors.axisPointerLabel
854
881
  }
855
882
  }
856
883
  } : void 0,
@@ -869,52 +896,50 @@ var AreaChart = React8.forwardRef(
869
896
  show: showGrid
870
897
  }
871
898
  },
872
- series: data.series.map((series, index) => ({
873
- name: series.name,
874
- type: "line",
875
- data: series.data,
876
- smooth,
877
- stack: stacked ? "Total" : void 0,
878
- areaStyle: gradient ? {
879
- opacity: 0.8,
880
- color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
881
- {
882
- offset: 0,
883
- color: series.color || `rgba(${60 + index * 40}, ${160 - index * 20}, ${180 - index * 30}, 0.8)`
884
- },
885
- {
886
- offset: 1,
887
- color: series.color || `rgba(${60 + index * 40}, ${160 - index * 20}, ${180 - index * 30}, 0.1)`
888
- }
889
- ])
890
- } : { opacity: 0.5 },
891
- itemStyle: series.color ? { color: series.color } : void 0,
892
- emphasis: {
893
- focus: "series"
894
- },
895
- showSymbol: false
896
- }))
899
+ series: data.series.map((series, index) => {
900
+ const base = series.color || chartColors.series[index % chartColors.series.length];
901
+ return {
902
+ name: series.name,
903
+ type: "line",
904
+ data: series.data,
905
+ smooth,
906
+ stack: stacked ? "Total" : void 0,
907
+ areaStyle: gradient ? {
908
+ opacity: 0.8,
909
+ color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
910
+ { offset: 0, color: (0, import_charts_core6.colorWithAlpha)(base, 0.8) },
911
+ { offset: 1, color: (0, import_charts_core6.colorWithAlpha)(base, 0.1) }
912
+ ])
913
+ } : { opacity: 0.5 },
914
+ itemStyle: series.color ? { color: series.color } : void 0,
915
+ emphasis: {
916
+ focus: "series"
917
+ },
918
+ showSymbol: false
919
+ };
920
+ })
897
921
  };
898
- }, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient]);
922
+ }, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient, chartColors]);
923
+ const latest = useLatestRef({ onClick });
899
924
  const { containerRef } = useChart({
900
925
  option,
901
- theme,
926
+ theme: currentTheme === import_charts_core6.THEME_DARK ? "dark" : "light",
902
927
  animation,
903
928
  onReady: (chart) => {
904
- if (onClick) {
905
- chart.on("click", (params) => {
906
- onClick({
907
- type: params.type || "click",
908
- componentType: params.componentType || "series",
909
- seriesIndex: params.seriesIndex,
910
- seriesName: params.seriesName || "",
911
- dataIndex: params.dataIndex || 0,
912
- name: params.name || "",
913
- value: params.value,
914
- color: params.color
915
- });
929
+ chart.on("click", (params) => {
930
+ const { onClick: onClick2 } = latest.current;
931
+ if (!onClick2) return;
932
+ onClick2({
933
+ type: params.type || "click",
934
+ componentType: params.componentType || "series",
935
+ seriesIndex: params.seriesIndex,
936
+ seriesName: params.seriesName || "",
937
+ dataIndex: params.dataIndex || 0,
938
+ name: params.name || "",
939
+ value: params.value,
940
+ color: params.color
916
941
  });
917
- }
942
+ });
918
943
  }
919
944
  });
920
945
  const accessibilityDescription = description || (!isEmpty ? `${title}. Area chart with ${data.categories.length} data points across ${data.series.length} series.` : void 0);
@@ -944,10 +969,12 @@ var echarts7 = __toESM(require("echarts/core"), 1);
944
969
  var import_charts5 = require("echarts/charts");
945
970
  var import_components5 = require("echarts/components");
946
971
  var import_renderers5 = require("echarts/renderers");
947
- var import_charts_core5 = require("@classic-homes/charts-core");
972
+ var import_charts_core7 = require("@classic-homes/charts-core");
948
973
  var import_jsx_runtime9 = require("react/jsx-runtime");
949
974
  echarts7.use([
950
975
  import_charts5.ScatterChart,
976
+ // Trend lines are line series
977
+ import_charts5.LineChart,
951
978
  import_components5.GridComponent,
952
979
  import_components5.TooltipComponent,
953
980
  import_components5.LegendComponent,
@@ -1004,9 +1031,12 @@ var ScatterChart = React9.forwardRef(
1004
1031
  });
1005
1032
  const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
1006
1033
  const intercept = (sumY - slope * sumX) / n;
1007
- const xValues = s.data.map(([x]) => x);
1008
- const minX = Math.min(...xValues);
1009
- const maxX = Math.max(...xValues);
1034
+ let minX = Infinity;
1035
+ let maxX = -Infinity;
1036
+ for (const [x] of s.data) {
1037
+ if (x < minX) minX = x;
1038
+ if (x > maxX) maxX = x;
1039
+ }
1010
1040
  series.push({
1011
1041
  name: `${s.name} Trend`,
1012
1042
  type: "line",
@@ -1039,7 +1069,7 @@ var ScatterChart = React9.forwardRef(
1039
1069
  formatter: (params) => {
1040
1070
  const p = params;
1041
1071
  if (!p.value) return "";
1042
- return `${p.seriesName}<br/>X: ${p.value[0]}<br/>Y: ${p.value[1]}`;
1072
+ return `${(0, import_charts_core7.escapeHtml)(p.seriesName)}<br/>X: ${(0, import_charts_core7.escapeHtml)(p.value[0])}<br/>Y: ${(0, import_charts_core7.escapeHtml)(p.value[1])}`;
1043
1073
  }
1044
1074
  } : void 0,
1045
1075
  legend: showLegend ? {
@@ -1061,28 +1091,29 @@ var ScatterChart = React9.forwardRef(
1061
1091
  series
1062
1092
  };
1063
1093
  }, [data, isEmpty, showTooltip, showLegend, showGrid, showTrendLine, symbolSize]);
1094
+ const latest = useLatestRef({ onClick });
1064
1095
  const { containerRef } = useChart({
1065
1096
  option,
1066
1097
  theme,
1067
1098
  animation,
1068
1099
  onReady: (chart) => {
1069
- if (onClick) {
1070
- chart.on("click", (params) => {
1071
- onClick({
1072
- type: params.type || "click",
1073
- componentType: params.componentType || "series",
1074
- seriesIndex: params.seriesIndex,
1075
- seriesName: params.seriesName || "",
1076
- dataIndex: params.dataIndex || 0,
1077
- name: params.name || "",
1078
- value: params.value,
1079
- color: params.color
1080
- });
1100
+ chart.on("click", (params) => {
1101
+ const { onClick: onClick2 } = latest.current;
1102
+ if (!onClick2) return;
1103
+ onClick2({
1104
+ type: params.type || "click",
1105
+ componentType: params.componentType || "series",
1106
+ seriesIndex: params.seriesIndex,
1107
+ seriesName: params.seriesName || "",
1108
+ dataIndex: params.dataIndex || 0,
1109
+ name: params.name || "",
1110
+ value: params.value,
1111
+ color: params.color
1081
1112
  });
1082
- }
1113
+ });
1083
1114
  }
1084
1115
  });
1085
- const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core5.generateScatterChartDescription)(title, data) : void 0);
1116
+ const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core7.generateScatterChartDescription)(title, data) : void 0);
1086
1117
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1087
1118
  ChartContainer,
1088
1119
  {
@@ -1109,7 +1140,7 @@ var echarts8 = __toESM(require("echarts/core"), 1);
1109
1140
  var import_charts6 = require("echarts/charts");
1110
1141
  var import_components6 = require("echarts/components");
1111
1142
  var import_renderers6 = require("echarts/renderers");
1112
- var import_charts_core6 = require("@classic-homes/charts-core");
1143
+ var import_charts_core8 = require("@classic-homes/charts-core");
1113
1144
  var import_jsx_runtime10 = require("react/jsx-runtime");
1114
1145
  echarts8.use([import_charts6.PieChart, import_components6.TooltipComponent, import_components6.LegendComponent, import_components6.TitleComponent, import_renderers6.CanvasRenderer]);
1115
1146
  var DonutChart = React10.forwardRef(
@@ -1135,6 +1166,8 @@ var DonutChart = React10.forwardRef(
1135
1166
  ...props
1136
1167
  }, ref) => {
1137
1168
  const isEmpty = !data?.length;
1169
+ const currentTheme = useChartTheme(theme);
1170
+ const chartColors = (0, import_charts_core8.getChartColors)(currentTheme);
1138
1171
  const option = React10.useMemo(() => {
1139
1172
  if (isEmpty) return {};
1140
1173
  const graphicElements = [];
@@ -1151,7 +1184,7 @@ var DonutChart = React10.forwardRef(
1151
1184
  text: String(centerValue),
1152
1185
  fontSize: 28,
1153
1186
  fontWeight: "bold",
1154
- fill: "currentColor",
1187
+ fill: chartColors.foreground,
1155
1188
  textAlign: "center"
1156
1189
  },
1157
1190
  top: 0,
@@ -1164,7 +1197,7 @@ var DonutChart = React10.forwardRef(
1164
1197
  style: {
1165
1198
  text: centerLabel,
1166
1199
  fontSize: 14,
1167
- fill: "#888",
1200
+ fill: chartColors.mutedForeground,
1168
1201
  textAlign: "center"
1169
1202
  },
1170
1203
  top: centerValue !== void 0 ? 35 : 0,
@@ -1227,28 +1260,30 @@ var DonutChart = React10.forwardRef(
1227
1260
  innerRadius,
1228
1261
  centerLabel,
1229
1262
  centerValue,
1230
- title
1263
+ title,
1264
+ chartColors
1231
1265
  ]);
1266
+ const latest = useLatestRef({ onClick });
1232
1267
  const { containerRef } = useChart({
1233
1268
  option,
1234
- theme,
1269
+ theme: currentTheme === import_charts_core8.THEME_DARK ? "dark" : "light",
1235
1270
  animation,
1236
1271
  onReady: (chart) => {
1237
- if (onClick) {
1238
- chart.on("click", (params) => {
1239
- onClick({
1240
- type: params.type || "click",
1241
- componentType: params.componentType || "series",
1242
- name: params.name || "",
1243
- value: params.value,
1244
- percent: params.percent,
1245
- color: params.color
1246
- });
1272
+ chart.on("click", (params) => {
1273
+ const { onClick: onClick2 } = latest.current;
1274
+ if (!onClick2) return;
1275
+ onClick2({
1276
+ type: params.type || "click",
1277
+ componentType: params.componentType || "series",
1278
+ name: params.name || "",
1279
+ value: params.value,
1280
+ percent: params.percent,
1281
+ color: params.color
1247
1282
  });
1248
- }
1283
+ });
1249
1284
  }
1250
1285
  });
1251
- const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core6.generatePieChartDescription)(title, data, true) : void 0);
1286
+ const accessibilityDescription = description || (!isEmpty ? (0, import_charts_core8.generatePieChartDescription)(title, data, true) : void 0);
1252
1287
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1253
1288
  ChartContainer,
1254
1289
  {
@@ -1417,7 +1452,8 @@ var FunnelChart = React12.forwardRef(
1417
1452
  bottom: 60,
1418
1453
  width: "80%",
1419
1454
  min: 0,
1420
- max: Math.max(...data.map((d) => d.value)),
1455
+ // reduce, not Math.max(...): spreading large arrays overflows the stack
1456
+ max: data.reduce((m, d) => d.value > m ? d.value : m, -Infinity),
1421
1457
  minSize: "0%",
1422
1458
  maxSize: "100%",
1423
1459
  sort,
@@ -1447,22 +1483,23 @@ var FunnelChart = React12.forwardRef(
1447
1483
  ]
1448
1484
  };
1449
1485
  }, [data, isEmpty, showTooltip, showLegend, sort, orientation, showLabels, title]);
1486
+ const latest = useLatestRef({ onClick });
1450
1487
  const { containerRef } = useChart({
1451
1488
  option,
1452
1489
  theme,
1453
1490
  animation,
1454
1491
  onReady: (chart) => {
1455
- if (onClick) {
1456
- chart.on("click", (params) => {
1457
- onClick({
1458
- type: params.type || "click",
1459
- componentType: params.componentType || "series",
1460
- name: params.name || "",
1461
- value: params.value,
1462
- color: params.color
1463
- });
1492
+ chart.on("click", (params) => {
1493
+ const { onClick: onClick2 } = latest.current;
1494
+ if (!onClick2) return;
1495
+ onClick2({
1496
+ type: params.type || "click",
1497
+ componentType: params.componentType || "series",
1498
+ name: params.name || "",
1499
+ value: params.value,
1500
+ color: params.color
1464
1501
  });
1465
- }
1502
+ });
1466
1503
  }
1467
1504
  });
1468
1505
  const accessibilityDescription = description || (!isEmpty ? `${title}. Funnel chart with ${data.length} stages.` : void 0);
@@ -1492,6 +1529,7 @@ var echarts11 = __toESM(require("echarts/core"), 1);
1492
1529
  var import_charts9 = require("echarts/charts");
1493
1530
  var import_components9 = require("echarts/components");
1494
1531
  var import_renderers9 = require("echarts/renderers");
1532
+ var import_charts_core9 = require("@classic-homes/charts-core");
1495
1533
  var import_jsx_runtime13 = require("react/jsx-runtime");
1496
1534
  echarts11.use([import_charts9.GaugeChart, import_components9.TitleComponent, import_renderers9.CanvasRenderer]);
1497
1535
  var GaugeChart = React13.forwardRef(
@@ -1513,6 +1551,9 @@ var GaugeChart = React13.forwardRef(
1513
1551
  class: className,
1514
1552
  ...props
1515
1553
  }, ref) => {
1554
+ const currentTheme = useChartTheme(theme);
1555
+ const chartColors = (0, import_charts_core9.getChartColors)(currentTheme);
1556
+ const reducedMotion = useReducedMotion();
1516
1557
  const option = React13.useMemo(() => {
1517
1558
  return {
1518
1559
  series: [
@@ -1537,7 +1578,7 @@ var GaugeChart = React13.forwardRef(
1537
1578
  splitNumber: 5,
1538
1579
  lineStyle: {
1539
1580
  width: 2,
1540
- color: "#999"
1581
+ color: chartColors.mutedForeground
1541
1582
  }
1542
1583
  },
1543
1584
  splitLine: {
@@ -1545,12 +1586,12 @@ var GaugeChart = React13.forwardRef(
1545
1586
  length: 10,
1546
1587
  lineStyle: {
1547
1588
  width: 3,
1548
- color: "#999"
1589
+ color: chartColors.mutedForeground
1549
1590
  }
1550
1591
  },
1551
1592
  axisLabel: {
1552
1593
  distance: -20,
1553
- color: "#999",
1594
+ color: chartColors.mutedForeground,
1554
1595
  fontSize: 12
1555
1596
  },
1556
1597
  anchor: {
@@ -1570,7 +1611,7 @@ var GaugeChart = React13.forwardRef(
1570
1611
  fontSize: 14
1571
1612
  },
1572
1613
  detail: {
1573
- valueAnimation: animation,
1614
+ valueAnimation: animation && !reducedMotion,
1574
1615
  fontSize: 28,
1575
1616
  fontWeight: "bold",
1576
1617
  offsetCenter: [0, "40%"],
@@ -1585,10 +1626,21 @@ var GaugeChart = React13.forwardRef(
1585
1626
  }
1586
1627
  ]
1587
1628
  };
1588
- }, [value, min, max, splitNumber, showProgress, formatValue, title, animation]);
1629
+ }, [
1630
+ value,
1631
+ min,
1632
+ max,
1633
+ splitNumber,
1634
+ showProgress,
1635
+ formatValue,
1636
+ title,
1637
+ animation,
1638
+ reducedMotion,
1639
+ chartColors
1640
+ ]);
1589
1641
  const { containerRef } = useChart({
1590
1642
  option,
1591
- theme,
1643
+ theme: currentTheme === import_charts_core9.THEME_DARK ? "dark" : "light",
1592
1644
  animation
1593
1645
  });
1594
1646
  const accessibilityDescription = description || `${title}. Gauge showing value ${value} on scale from ${min} to ${max}.`;
@@ -1617,6 +1669,7 @@ var echarts12 = __toESM(require("echarts/core"), 1);
1617
1669
  var import_charts10 = require("echarts/charts");
1618
1670
  var import_components10 = require("echarts/components");
1619
1671
  var import_renderers10 = require("echarts/renderers");
1672
+ var import_charts_core10 = require("@classic-homes/charts-core");
1620
1673
  var import_jsx_runtime14 = require("react/jsx-runtime");
1621
1674
  echarts12.use([
1622
1675
  import_charts10.HeatmapChart,
@@ -1646,9 +1699,14 @@ var HeatmapChart = React14.forwardRef(
1646
1699
  ...props
1647
1700
  }, ref) => {
1648
1701
  const isEmpty = !data?.data?.length || !xAxis?.length || !yAxis?.length;
1649
- const values = data?.data?.map(([, , value]) => value) || [];
1650
- const minValue = data?.min ?? Math.min(...values);
1651
- const maxValue = data?.max ?? Math.max(...values);
1702
+ let dataMin = Infinity;
1703
+ let dataMax = -Infinity;
1704
+ for (const [, , value] of data?.data ?? []) {
1705
+ if (value < dataMin) dataMin = value;
1706
+ if (value > dataMax) dataMax = value;
1707
+ }
1708
+ const minValue = data?.min ?? dataMin;
1709
+ const maxValue = data?.max ?? dataMax;
1652
1710
  const option = React14.useMemo(() => {
1653
1711
  if (isEmpty) return {};
1654
1712
  return {
@@ -1658,7 +1716,7 @@ var HeatmapChart = React14.forwardRef(
1658
1716
  const p = params;
1659
1717
  if (!p.value) return "";
1660
1718
  const [xIdx, yIdx, value] = p.value;
1661
- return `${xAxis[xIdx]} / ${yAxis[yIdx]}: ${value}`;
1719
+ return `${(0, import_charts_core10.escapeHtml)(xAxis[xIdx])} / ${(0, import_charts_core10.escapeHtml)(yAxis[yIdx])}: ${(0, import_charts_core10.escapeHtml)(value)}`;
1662
1720
  }
1663
1721
  } : void 0,
1664
1722
  grid: {
@@ -1707,25 +1765,26 @@ var HeatmapChart = React14.forwardRef(
1707
1765
  ]
1708
1766
  };
1709
1767
  }, [data, xAxis, yAxis, isEmpty, showTooltip, showValues, minValue, maxValue, title]);
1768
+ const latest = useLatestRef({ onClick, xAxis, yAxis });
1710
1769
  const { containerRef } = useChart({
1711
1770
  option,
1712
1771
  theme,
1713
1772
  animation,
1714
1773
  onReady: (chart) => {
1715
- if (onClick) {
1716
- chart.on("click", (params) => {
1717
- const [xIdx, yIdx, value] = params.value || [0, 0, 0];
1718
- onClick({
1719
- type: params.type || "click",
1720
- componentType: params.componentType || "series",
1721
- xIndex: xIdx,
1722
- yIndex: yIdx,
1723
- xLabel: xAxis[xIdx],
1724
- yLabel: yAxis[yIdx],
1725
- value
1726
- });
1774
+ chart.on("click", (params) => {
1775
+ const { onClick: onClick2, xAxis: xAxis2, yAxis: yAxis2 } = latest.current;
1776
+ if (!onClick2) return;
1777
+ const [xIdx, yIdx, value] = params.value || [0, 0, 0];
1778
+ onClick2({
1779
+ type: params.type || "click",
1780
+ componentType: params.componentType || "series",
1781
+ xIndex: xIdx,
1782
+ yIndex: yIdx,
1783
+ xLabel: xAxis2[xIdx],
1784
+ yLabel: yAxis2[yIdx],
1785
+ value
1727
1786
  });
1728
- }
1787
+ });
1729
1788
  }
1730
1789
  });
1731
1790
  const accessibilityDescription = description || (!isEmpty ? `${title}. Heatmap with ${xAxis.length} columns and ${yAxis.length} rows.` : void 0);
@@ -1755,6 +1814,7 @@ var echarts13 = __toESM(require("echarts/core"), 1);
1755
1814
  var import_charts11 = require("echarts/charts");
1756
1815
  var import_components11 = require("echarts/components");
1757
1816
  var import_renderers11 = require("echarts/renderers");
1817
+ var import_charts_core11 = require("@classic-homes/charts-core");
1758
1818
  var import_jsx_runtime15 = require("react/jsx-runtime");
1759
1819
  echarts13.use([import_charts11.TreemapChart, import_components11.TooltipComponent, import_components11.TitleComponent, import_renderers11.CanvasRenderer]);
1760
1820
  var TreemapChart = React15.forwardRef(
@@ -1775,13 +1835,15 @@ var TreemapChart = React15.forwardRef(
1775
1835
  ...props
1776
1836
  }, ref) => {
1777
1837
  const isEmpty = !data?.length;
1838
+ const currentTheme = useChartTheme(theme);
1839
+ const chartColors = (0, import_charts_core11.getChartColors)(currentTheme);
1778
1840
  const option = React15.useMemo(() => {
1779
1841
  if (isEmpty) return {};
1780
1842
  return {
1781
1843
  tooltip: showTooltip ? {
1782
1844
  formatter: (params) => {
1783
1845
  const p = params;
1784
- return `${p.name}: ${p.value}`;
1846
+ return `${(0, import_charts_core11.escapeHtml)(p.name)}: ${(0, import_charts_core11.escapeHtml)(p.value)}`;
1785
1847
  }
1786
1848
  } : void 0,
1787
1849
  series: [
@@ -1792,7 +1854,7 @@ var TreemapChart = React15.forwardRef(
1792
1854
  levels: levels || [
1793
1855
  {
1794
1856
  itemStyle: {
1795
- borderColor: "#555",
1857
+ borderColor: chartColors.divider,
1796
1858
  borderWidth: 4,
1797
1859
  gapWidth: 4
1798
1860
  }
@@ -1830,25 +1892,26 @@ var TreemapChart = React15.forwardRef(
1830
1892
  }
1831
1893
  ]
1832
1894
  };
1833
- }, [data, levels, isEmpty, showTooltip]);
1895
+ }, [data, levels, isEmpty, showTooltip, chartColors]);
1896
+ const latest = useLatestRef({ onClick });
1834
1897
  const { containerRef } = useChart({
1835
1898
  option,
1836
- theme,
1899
+ theme: currentTheme === import_charts_core11.THEME_DARK ? "dark" : "light",
1837
1900
  animation,
1838
1901
  onReady: (chart) => {
1839
- if (onClick) {
1840
- chart.on("click", (params) => {
1841
- const treePathInfo = params.treePathInfo || [];
1842
- onClick({
1843
- type: params.type || "click",
1844
- componentType: params.componentType || "series",
1845
- name: params.name || "",
1846
- value: params.value,
1847
- path: treePathInfo.map((item) => item.name || ""),
1848
- depth: treePathInfo.length - 1
1849
- });
1902
+ chart.on("click", (params) => {
1903
+ const { onClick: onClick2 } = latest.current;
1904
+ if (!onClick2) return;
1905
+ const treePathInfo = params.treePathInfo || [];
1906
+ onClick2({
1907
+ type: params.type || "click",
1908
+ componentType: params.componentType || "series",
1909
+ name: params.name || "",
1910
+ value: params.value,
1911
+ path: treePathInfo.map((item) => item.name || ""),
1912
+ depth: treePathInfo.length - 1
1850
1913
  });
1851
- }
1914
+ });
1852
1915
  }
1853
1916
  });
1854
1917
  const accessibilityDescription = description || (!isEmpty ? `${title}. Treemap chart showing hierarchical data.` : void 0);
@@ -1878,6 +1941,7 @@ var echarts14 = __toESM(require("echarts/core"), 1);
1878
1941
  var import_charts12 = require("echarts/charts");
1879
1942
  var import_components12 = require("echarts/components");
1880
1943
  var import_renderers12 = require("echarts/renderers");
1944
+ var import_charts_core12 = require("@classic-homes/charts-core");
1881
1945
  var import_jsx_runtime16 = require("react/jsx-runtime");
1882
1946
  echarts14.use([
1883
1947
  import_charts12.CandlestickChart,
@@ -1906,6 +1970,8 @@ var CandlestickChart = React16.forwardRef(
1906
1970
  ...props
1907
1971
  }, ref) => {
1908
1972
  const isEmpty = !data?.dates?.length || !data?.data?.length;
1973
+ const currentTheme = useChartTheme(theme);
1974
+ const chartColors = (0, import_charts_core12.getChartColors)(currentTheme);
1909
1975
  const option = React16.useMemo(() => {
1910
1976
  if (isEmpty) return {};
1911
1977
  const candlestickData = data.data.map((item) => [item.open, item.close, item.low, item.high]);
@@ -1915,12 +1981,12 @@ var CandlestickChart = React16.forwardRef(
1915
1981
  type: "candlestick",
1916
1982
  data: candlestickData,
1917
1983
  itemStyle: {
1918
- color: "#ef4444",
1984
+ color: chartColors.destructive,
1919
1985
  // Up color (red for bearish in some markets)
1920
- color0: "#22c55e",
1986
+ color0: chartColors.success,
1921
1987
  // Down color (green for bullish)
1922
- borderColor: "#ef4444",
1923
- borderColor0: "#22c55e"
1988
+ borderColor: chartColors.destructive,
1989
+ borderColor0: chartColors.success
1924
1990
  }
1925
1991
  }
1926
1992
  ];
@@ -1986,7 +2052,7 @@ var CandlestickChart = React16.forwardRef(
1986
2052
  yAxisIndex: 1,
1987
2053
  data: data.volume,
1988
2054
  itemStyle: {
1989
- color: "#6b7280"
2055
+ color: chartColors.mutedForeground
1990
2056
  }
1991
2057
  });
1992
2058
  }
@@ -2016,28 +2082,30 @@ var CandlestickChart = React16.forwardRef(
2016
2082
  ],
2017
2083
  series: seriesArr
2018
2084
  };
2019
- }, [data, isEmpty, showTooltip, showVolume, title]);
2085
+ }, [data, isEmpty, showTooltip, showVolume, title, chartColors]);
2086
+ const latest = useLatestRef({ onClick, data });
2020
2087
  const { containerRef } = useChart({
2021
2088
  option,
2022
- theme,
2089
+ theme: currentTheme === import_charts_core12.THEME_DARK ? "dark" : "light",
2023
2090
  animation,
2024
2091
  onReady: (chart) => {
2025
- if (onClick) {
2026
- chart.on("click", (params) => {
2027
- const dataIndex = params.dataIndex || 0;
2028
- const item = data.data[dataIndex];
2029
- onClick({
2030
- type: params.type || "click",
2031
- componentType: params.componentType || "series",
2032
- date: data.dates[dataIndex],
2033
- open: item.open,
2034
- close: item.close,
2035
- high: item.high,
2036
- low: item.low,
2037
- volume: data.volume?.[dataIndex]
2038
- });
2092
+ chart.on("click", (params) => {
2093
+ const { onClick: onClick2, data: data2 } = latest.current;
2094
+ if (!onClick2) return;
2095
+ const dataIndex = params.dataIndex || 0;
2096
+ const item = data2.data[dataIndex];
2097
+ if (!item) return;
2098
+ onClick2({
2099
+ type: params.type || "click",
2100
+ componentType: params.componentType || "series",
2101
+ date: data2.dates[dataIndex],
2102
+ open: item.open,
2103
+ close: item.close,
2104
+ high: item.high,
2105
+ low: item.low,
2106
+ volume: data2.volume?.[dataIndex]
2039
2107
  });
2040
- }
2108
+ });
2041
2109
  }
2042
2110
  });
2043
2111
  const accessibilityDescription = description || (!isEmpty ? `${title}. Candlestick chart with ${data.dates.length} data points.` : void 0);
@@ -2121,25 +2189,26 @@ var SankeyChart = React17.forwardRef(
2121
2189
  ]
2122
2190
  };
2123
2191
  }, [data, isEmpty, showTooltip, orient]);
2192
+ const latest = useLatestRef({ onClick });
2124
2193
  const { containerRef } = useChart({
2125
2194
  option,
2126
2195
  theme,
2127
2196
  animation,
2128
2197
  onReady: (chart) => {
2129
- if (onClick) {
2130
- chart.on("click", (params) => {
2131
- const isEdge = params.dataType === "edge";
2132
- onClick({
2133
- type: params.type || "click",
2134
- componentType: params.componentType || "series",
2135
- dataType: isEdge ? "edge" : "node",
2136
- name: params.name || "",
2137
- value: isEdge ? params.value : void 0,
2138
- source: isEdge ? params.data?.source : void 0,
2139
- target: isEdge ? params.data?.target : void 0
2140
- });
2198
+ chart.on("click", (params) => {
2199
+ const { onClick: onClick2 } = latest.current;
2200
+ if (!onClick2) return;
2201
+ const isEdge = params.dataType === "edge";
2202
+ onClick2({
2203
+ type: params.type || "click",
2204
+ componentType: params.componentType || "series",
2205
+ dataType: isEdge ? "edge" : "node",
2206
+ name: params.name || "",
2207
+ value: isEdge ? params.value : void 0,
2208
+ source: isEdge ? params.data?.source : void 0,
2209
+ target: isEdge ? params.data?.target : void 0
2141
2210
  });
2142
- }
2211
+ });
2143
2212
  }
2144
2213
  });
2145
2214
  const accessibilityDescription = description || (!isEmpty ? `${title}. Sankey diagram with ${data.nodes.length} nodes and ${data.links.length} links.` : void 0);