@classic-homes/charts-react 0.1.37 → 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 +328 -252
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +339 -255
- package/package.json +11 -6
package/dist/index.js
CHANGED
|
@@ -77,10 +77,11 @@ var ChartError = React2.forwardRef(
|
|
|
77
77
|
)
|
|
78
78
|
}
|
|
79
79
|
),
|
|
80
|
-
/* @__PURE__ */ jsx2("p", { className: "mb-2 text-sm font-medium text-
|
|
80
|
+
/* @__PURE__ */ jsx2("p", { className: "mb-2 text-sm font-medium text-foreground", children: message }),
|
|
81
81
|
onRetry && /* @__PURE__ */ jsx2(
|
|
82
82
|
"button",
|
|
83
83
|
{
|
|
84
|
+
type: "button",
|
|
84
85
|
onClick: onRetry,
|
|
85
86
|
className: "rounded-md bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground transition-colors hover:bg-destructive/90",
|
|
86
87
|
children: "Retry"
|
|
@@ -156,6 +157,7 @@ var ChartContainer = React4.forwardRef(
|
|
|
156
157
|
...props
|
|
157
158
|
}, ref) => {
|
|
158
159
|
const heightStyle = typeof height === "number" ? `${height}px` : height;
|
|
160
|
+
const descriptionId = `${React4.useId()}-desc`;
|
|
159
161
|
if (loading) {
|
|
160
162
|
return /* @__PURE__ */ jsx4(ChartSkeleton, { height, className: wrapperClassName });
|
|
161
163
|
}
|
|
@@ -179,12 +181,12 @@ var ChartContainer = React4.forwardRef(
|
|
|
179
181
|
ref,
|
|
180
182
|
role: "img",
|
|
181
183
|
"aria-label": title,
|
|
182
|
-
"aria-describedby": description ?
|
|
184
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
183
185
|
"data-testid": "chart-container",
|
|
184
186
|
className: cn("rounded-lg border border-border bg-card", wrapperClassName),
|
|
185
187
|
...props,
|
|
186
188
|
children: [
|
|
187
|
-
description && /* @__PURE__ */ jsx4("span", { id:
|
|
189
|
+
description && /* @__PURE__ */ jsx4("span", { id: descriptionId, className: "sr-only", children: description }),
|
|
188
190
|
/* @__PURE__ */ jsx4("div", { className: cn("h-full w-full", className), style: { height: heightStyle }, children })
|
|
189
191
|
]
|
|
190
192
|
}
|
|
@@ -204,14 +206,19 @@ import {
|
|
|
204
206
|
TitleComponent
|
|
205
207
|
} from "echarts/components";
|
|
206
208
|
import { CanvasRenderer } from "echarts/renderers";
|
|
207
|
-
import {
|
|
209
|
+
import {
|
|
210
|
+
generateLineChartDescription,
|
|
211
|
+
getChartColors,
|
|
212
|
+
THEME_DARK as THEME_DARK2
|
|
213
|
+
} from "@classic-homes/charts-core";
|
|
208
214
|
|
|
209
215
|
// src/hooks/useChart.ts
|
|
210
|
-
import { useEffect as useEffect4, useRef
|
|
216
|
+
import { useEffect as useEffect4, useRef } from "react";
|
|
211
217
|
import * as echarts2 from "echarts/core";
|
|
218
|
+
import { getReplaceMerge } from "@classic-homes/charts-core";
|
|
212
219
|
|
|
213
220
|
// src/hooks/useChartTheme.ts
|
|
214
|
-
import { useEffect, useState
|
|
221
|
+
import { useEffect, useState } from "react";
|
|
215
222
|
import * as echarts from "echarts/core";
|
|
216
223
|
import { lightTheme, darkTheme, THEME_LIGHT, THEME_DARK } from "@classic-homes/charts-core";
|
|
217
224
|
var themesRegistered = false;
|
|
@@ -221,18 +228,18 @@ function registerClassicThemes() {
|
|
|
221
228
|
echarts.registerTheme(THEME_DARK, darkTheme);
|
|
222
229
|
themesRegistered = true;
|
|
223
230
|
}
|
|
231
|
+
function resolveTheme(preference) {
|
|
232
|
+
if (preference !== "auto") {
|
|
233
|
+
return preference === "dark" ? THEME_DARK : THEME_LIGHT;
|
|
234
|
+
}
|
|
235
|
+
if (typeof document === "undefined") return THEME_LIGHT;
|
|
236
|
+
return document.documentElement.classList.contains("dark") ? THEME_DARK : THEME_LIGHT;
|
|
237
|
+
}
|
|
224
238
|
function useChartTheme(preference = "auto") {
|
|
225
|
-
const [currentTheme, setCurrentTheme] = useState(
|
|
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]);
|
|
239
|
+
const [currentTheme, setCurrentTheme] = useState(() => resolveTheme(preference));
|
|
234
240
|
useEffect(() => {
|
|
235
241
|
registerClassicThemes();
|
|
242
|
+
const updateTheme = () => setCurrentTheme(resolveTheme(preference));
|
|
236
243
|
updateTheme();
|
|
237
244
|
if (preference !== "auto") return;
|
|
238
245
|
const observer = new MutationObserver((mutations) => {
|
|
@@ -246,26 +253,29 @@ function useChartTheme(preference = "auto") {
|
|
|
246
253
|
attributes: true,
|
|
247
254
|
attributeFilter: ["class"]
|
|
248
255
|
});
|
|
249
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
250
|
-
const handleMediaChange = () => updateTheme();
|
|
251
|
-
mediaQuery.addEventListener("change", handleMediaChange);
|
|
252
256
|
return () => {
|
|
253
257
|
observer.disconnect();
|
|
254
|
-
mediaQuery.removeEventListener("change", handleMediaChange);
|
|
255
258
|
};
|
|
256
|
-
}, [preference
|
|
259
|
+
}, [preference]);
|
|
257
260
|
return currentTheme;
|
|
258
261
|
}
|
|
259
262
|
|
|
260
263
|
// src/hooks/useChartResize.ts
|
|
261
|
-
import { useEffect as useEffect2,
|
|
264
|
+
import { useEffect as useEffect2, useLayoutEffect, useState as useState2 } from "react";
|
|
265
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect2 : useLayoutEffect;
|
|
266
|
+
function useRefElement(ref) {
|
|
267
|
+
const [element, setElement] = useState2(null);
|
|
268
|
+
useIsomorphicLayoutEffect(() => {
|
|
269
|
+
setElement(ref.current);
|
|
270
|
+
});
|
|
271
|
+
return element;
|
|
272
|
+
}
|
|
262
273
|
function useChartResize(chartRef, containerRef) {
|
|
263
|
-
const
|
|
274
|
+
const container = useRefElement(containerRef);
|
|
264
275
|
useEffect2(() => {
|
|
265
|
-
const container = containerRef.current;
|
|
266
276
|
if (!container) return;
|
|
267
277
|
let resizeTimeout;
|
|
268
|
-
|
|
278
|
+
const observer = new ResizeObserver(() => {
|
|
269
279
|
clearTimeout(resizeTimeout);
|
|
270
280
|
resizeTimeout = setTimeout(() => {
|
|
271
281
|
const chart = chartRef.current;
|
|
@@ -274,18 +284,18 @@ function useChartResize(chartRef, containerRef) {
|
|
|
274
284
|
}
|
|
275
285
|
}, 100);
|
|
276
286
|
});
|
|
277
|
-
|
|
287
|
+
observer.observe(container);
|
|
278
288
|
return () => {
|
|
279
289
|
clearTimeout(resizeTimeout);
|
|
280
|
-
|
|
290
|
+
observer.disconnect();
|
|
281
291
|
};
|
|
282
|
-
}, [chartRef,
|
|
292
|
+
}, [chartRef, container]);
|
|
283
293
|
}
|
|
284
294
|
|
|
285
295
|
// src/hooks/useReducedMotion.ts
|
|
286
|
-
import { useState as
|
|
296
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
287
297
|
function useReducedMotion() {
|
|
288
|
-
const [reducedMotion, setReducedMotion] =
|
|
298
|
+
const [reducedMotion, setReducedMotion] = useState3(false);
|
|
289
299
|
useEffect3(() => {
|
|
290
300
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
291
301
|
setReducedMotion(mediaQuery.matches);
|
|
@@ -301,29 +311,39 @@ function useReducedMotion() {
|
|
|
301
311
|
}
|
|
302
312
|
|
|
303
313
|
// src/hooks/useChart.ts
|
|
304
|
-
var
|
|
314
|
+
var isComponentType = (mainType) => echarts2.ComponentModel.hasClass(mainType);
|
|
315
|
+
function applyOption(chart, prev, next) {
|
|
316
|
+
chart.setOption(next, {
|
|
317
|
+
replaceMerge: getReplaceMerge(prev, next, isComponentType),
|
|
318
|
+
lazyUpdate: true
|
|
319
|
+
});
|
|
320
|
+
}
|
|
305
321
|
function useChart({
|
|
306
322
|
option,
|
|
307
323
|
theme = "auto",
|
|
308
324
|
animation,
|
|
309
325
|
onReady
|
|
310
326
|
}) {
|
|
311
|
-
const containerRef =
|
|
312
|
-
const
|
|
327
|
+
const containerRef = useRef(null);
|
|
328
|
+
const container = useRefElement(containerRef);
|
|
329
|
+
const chartRef = useRef(null);
|
|
313
330
|
const currentTheme = useChartTheme(theme);
|
|
314
331
|
const reducedMotion = useReducedMotion();
|
|
315
|
-
const onReadyRef =
|
|
332
|
+
const onReadyRef = useRef(onReady);
|
|
316
333
|
onReadyRef.current = onReady;
|
|
317
|
-
const optionRef =
|
|
334
|
+
const optionRef = useRef(option);
|
|
318
335
|
optionRef.current = {
|
|
319
336
|
...option,
|
|
320
|
-
|
|
337
|
+
// Reduced motion always wins over the animation prop
|
|
338
|
+
animation: (animation ?? true) && !reducedMotion
|
|
321
339
|
};
|
|
340
|
+
const appliedRef = useRef(null);
|
|
322
341
|
useEffect4(() => {
|
|
323
|
-
if (!
|
|
324
|
-
const chart = echarts2.init(
|
|
342
|
+
if (!container) return;
|
|
343
|
+
const chart = echarts2.init(container, currentTheme);
|
|
325
344
|
chartRef.current = chart;
|
|
326
|
-
chart
|
|
345
|
+
applyOption(chart, null, optionRef.current);
|
|
346
|
+
appliedRef.current = optionRef.current;
|
|
327
347
|
onReadyRef.current?.(chart);
|
|
328
348
|
return () => {
|
|
329
349
|
chart.dispose();
|
|
@@ -331,11 +351,12 @@ function useChart({
|
|
|
331
351
|
chartRef.current = null;
|
|
332
352
|
}
|
|
333
353
|
};
|
|
334
|
-
}, [currentTheme]);
|
|
354
|
+
}, [container, currentTheme]);
|
|
335
355
|
useEffect4(() => {
|
|
336
356
|
const chart = chartRef.current;
|
|
337
357
|
if (!chart || chart.isDisposed()) return;
|
|
338
|
-
chart.
|
|
358
|
+
applyOption(chart, appliedRef.current, optionRef.current);
|
|
359
|
+
appliedRef.current = optionRef.current;
|
|
339
360
|
}, [option, animation, reducedMotion]);
|
|
340
361
|
useChartResize(chartRef, containerRef);
|
|
341
362
|
return {
|
|
@@ -345,6 +366,14 @@ function useChart({
|
|
|
345
366
|
};
|
|
346
367
|
}
|
|
347
368
|
|
|
369
|
+
// src/hooks/useLatestRef.ts
|
|
370
|
+
import { useRef as useRef2 } from "react";
|
|
371
|
+
function useLatestRef(value) {
|
|
372
|
+
const ref = useRef2(value);
|
|
373
|
+
ref.current = value;
|
|
374
|
+
return ref;
|
|
375
|
+
}
|
|
376
|
+
|
|
348
377
|
// src/components/core/LineChart.tsx
|
|
349
378
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
350
379
|
echarts3.use([
|
|
@@ -379,6 +408,8 @@ var LineChart = React5.forwardRef(
|
|
|
379
408
|
...props
|
|
380
409
|
}, ref) => {
|
|
381
410
|
const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
|
|
411
|
+
const currentTheme = useChartTheme(theme);
|
|
412
|
+
const chartColors = getChartColors(currentTheme);
|
|
382
413
|
const option = React5.useMemo(() => {
|
|
383
414
|
if (isEmpty) return {};
|
|
384
415
|
return {
|
|
@@ -393,7 +424,7 @@ var LineChart = React5.forwardRef(
|
|
|
393
424
|
axisPointer: {
|
|
394
425
|
type: "cross",
|
|
395
426
|
label: {
|
|
396
|
-
backgroundColor:
|
|
427
|
+
backgroundColor: chartColors.axisPointerLabel
|
|
397
428
|
}
|
|
398
429
|
}
|
|
399
430
|
} : void 0,
|
|
@@ -439,41 +470,43 @@ var LineChart = React5.forwardRef(
|
|
|
439
470
|
smooth,
|
|
440
471
|
areaFilled,
|
|
441
472
|
showDataPoints,
|
|
442
|
-
stacked
|
|
473
|
+
stacked,
|
|
474
|
+
chartColors
|
|
443
475
|
]);
|
|
476
|
+
const latest = useLatestRef({ onClick, onHover });
|
|
444
477
|
const { containerRef } = useChart({
|
|
445
478
|
option,
|
|
446
|
-
theme,
|
|
479
|
+
theme: currentTheme === THEME_DARK2 ? "dark" : "light",
|
|
447
480
|
animation,
|
|
448
481
|
onReady: (chart) => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
482
|
+
chart.on("click", (params) => {
|
|
483
|
+
const { onClick: onClick2 } = latest.current;
|
|
484
|
+
if (!onClick2) return;
|
|
485
|
+
onClick2({
|
|
486
|
+
type: params.type || "click",
|
|
487
|
+
componentType: params.componentType || "series",
|
|
488
|
+
seriesIndex: params.seriesIndex,
|
|
489
|
+
seriesName: params.seriesName || "",
|
|
490
|
+
dataIndex: params.dataIndex || 0,
|
|
491
|
+
name: params.name || "",
|
|
492
|
+
value: params.value,
|
|
493
|
+
color: params.color
|
|
461
494
|
});
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
495
|
+
});
|
|
496
|
+
chart.on("mouseover", (params) => {
|
|
497
|
+
const { onHover: onHover2 } = latest.current;
|
|
498
|
+
if (!onHover2) return;
|
|
499
|
+
onHover2({
|
|
500
|
+
type: params.type || "mouseover",
|
|
501
|
+
componentType: params.componentType || "series",
|
|
502
|
+
seriesIndex: params.seriesIndex,
|
|
503
|
+
seriesName: params.seriesName || "",
|
|
504
|
+
dataIndex: params.dataIndex || 0,
|
|
505
|
+
name: params.name || "",
|
|
506
|
+
value: params.value,
|
|
507
|
+
color: params.color
|
|
475
508
|
});
|
|
476
|
-
}
|
|
509
|
+
});
|
|
477
510
|
}
|
|
478
511
|
});
|
|
479
512
|
const accessibilityDescription = description || (!isEmpty ? generateLineChartDescription(title, data) : void 0);
|
|
@@ -591,25 +624,26 @@ var BarChart = React6.forwardRef(
|
|
|
591
624
|
}))
|
|
592
625
|
};
|
|
593
626
|
}, [data, isEmpty, showTooltip, showLegend, showGrid, isHorizontal, stacked, showValues]);
|
|
627
|
+
const latest = useLatestRef({ onClick });
|
|
594
628
|
const { containerRef } = useChart({
|
|
595
629
|
option,
|
|
596
630
|
theme,
|
|
597
631
|
animation,
|
|
598
632
|
onReady: (chart) => {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
633
|
+
chart.on("click", (params) => {
|
|
634
|
+
const { onClick: onClick2 } = latest.current;
|
|
635
|
+
if (!onClick2) return;
|
|
636
|
+
onClick2({
|
|
637
|
+
type: params.type || "click",
|
|
638
|
+
componentType: params.componentType || "series",
|
|
639
|
+
seriesIndex: params.seriesIndex,
|
|
640
|
+
seriesName: params.seriesName || "",
|
|
641
|
+
dataIndex: params.dataIndex || 0,
|
|
642
|
+
name: params.name || "",
|
|
643
|
+
value: params.value,
|
|
644
|
+
color: params.color
|
|
611
645
|
});
|
|
612
|
-
}
|
|
646
|
+
});
|
|
613
647
|
}
|
|
614
648
|
});
|
|
615
649
|
const accessibilityDescription = description || (!isEmpty ? generateBarChartDescription(title, data) : void 0);
|
|
@@ -679,7 +713,7 @@ var PieChart = React7.forwardRef(
|
|
|
679
713
|
{
|
|
680
714
|
name: title,
|
|
681
715
|
type: "pie",
|
|
682
|
-
radius: innerRadius
|
|
716
|
+
radius: innerRadius ? [innerRadius, "70%"] : "70%",
|
|
683
717
|
center: ["50%", "45%"],
|
|
684
718
|
data: data.map((item) => ({
|
|
685
719
|
name: item.name,
|
|
@@ -704,23 +738,24 @@ var PieChart = React7.forwardRef(
|
|
|
704
738
|
]
|
|
705
739
|
};
|
|
706
740
|
}, [data, isEmpty, showTooltip, showLegend, showLabels, labelPosition, innerRadius, title]);
|
|
741
|
+
const latest = useLatestRef({ onClick });
|
|
707
742
|
const { containerRef } = useChart({
|
|
708
743
|
option,
|
|
709
744
|
theme,
|
|
710
745
|
animation,
|
|
711
746
|
onReady: (chart) => {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
747
|
+
chart.on("click", (params) => {
|
|
748
|
+
const { onClick: onClick2 } = latest.current;
|
|
749
|
+
if (!onClick2) return;
|
|
750
|
+
onClick2({
|
|
751
|
+
type: params.type || "click",
|
|
752
|
+
componentType: params.componentType || "series",
|
|
753
|
+
name: params.name || "",
|
|
754
|
+
value: params.value,
|
|
755
|
+
percent: params.percent,
|
|
756
|
+
color: params.color
|
|
722
757
|
});
|
|
723
|
-
}
|
|
758
|
+
});
|
|
724
759
|
}
|
|
725
760
|
});
|
|
726
761
|
const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription(title, data, false) : void 0);
|
|
@@ -755,6 +790,7 @@ import {
|
|
|
755
790
|
TitleComponent as TitleComponent4
|
|
756
791
|
} from "echarts/components";
|
|
757
792
|
import { CanvasRenderer as CanvasRenderer4 } from "echarts/renderers";
|
|
793
|
+
import { colorWithAlpha, getChartColors as getChartColors2, THEME_DARK as THEME_DARK3 } from "@classic-homes/charts-core";
|
|
758
794
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
759
795
|
echarts6.use([
|
|
760
796
|
EChartsLineChart2,
|
|
@@ -786,6 +822,8 @@ var AreaChart = React8.forwardRef(
|
|
|
786
822
|
...props
|
|
787
823
|
}, ref) => {
|
|
788
824
|
const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
|
|
825
|
+
const currentTheme = useChartTheme(theme);
|
|
826
|
+
const chartColors = getChartColors2(currentTheme);
|
|
789
827
|
const option = React8.useMemo(() => {
|
|
790
828
|
if (isEmpty) return {};
|
|
791
829
|
return {
|
|
@@ -800,7 +838,7 @@ var AreaChart = React8.forwardRef(
|
|
|
800
838
|
axisPointer: {
|
|
801
839
|
type: "cross",
|
|
802
840
|
label: {
|
|
803
|
-
backgroundColor:
|
|
841
|
+
backgroundColor: chartColors.axisPointerLabel
|
|
804
842
|
}
|
|
805
843
|
}
|
|
806
844
|
} : void 0,
|
|
@@ -819,52 +857,50 @@ var AreaChart = React8.forwardRef(
|
|
|
819
857
|
show: showGrid
|
|
820
858
|
}
|
|
821
859
|
},
|
|
822
|
-
series: data.series.map((series, index) =>
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
},
|
|
845
|
-
showSymbol: false
|
|
846
|
-
}))
|
|
860
|
+
series: data.series.map((series, index) => {
|
|
861
|
+
const base = series.color || chartColors.series[index % chartColors.series.length];
|
|
862
|
+
return {
|
|
863
|
+
name: series.name,
|
|
864
|
+
type: "line",
|
|
865
|
+
data: series.data,
|
|
866
|
+
smooth,
|
|
867
|
+
stack: stacked ? "Total" : void 0,
|
|
868
|
+
areaStyle: gradient ? {
|
|
869
|
+
opacity: 0.8,
|
|
870
|
+
color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
|
|
871
|
+
{ offset: 0, color: colorWithAlpha(base, 0.8) },
|
|
872
|
+
{ offset: 1, color: colorWithAlpha(base, 0.1) }
|
|
873
|
+
])
|
|
874
|
+
} : { opacity: 0.5 },
|
|
875
|
+
itemStyle: series.color ? { color: series.color } : void 0,
|
|
876
|
+
emphasis: {
|
|
877
|
+
focus: "series"
|
|
878
|
+
},
|
|
879
|
+
showSymbol: false
|
|
880
|
+
};
|
|
881
|
+
})
|
|
847
882
|
};
|
|
848
|
-
}, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient]);
|
|
883
|
+
}, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient, chartColors]);
|
|
884
|
+
const latest = useLatestRef({ onClick });
|
|
849
885
|
const { containerRef } = useChart({
|
|
850
886
|
option,
|
|
851
|
-
theme,
|
|
887
|
+
theme: currentTheme === THEME_DARK3 ? "dark" : "light",
|
|
852
888
|
animation,
|
|
853
889
|
onReady: (chart) => {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
890
|
+
chart.on("click", (params) => {
|
|
891
|
+
const { onClick: onClick2 } = latest.current;
|
|
892
|
+
if (!onClick2) return;
|
|
893
|
+
onClick2({
|
|
894
|
+
type: params.type || "click",
|
|
895
|
+
componentType: params.componentType || "series",
|
|
896
|
+
seriesIndex: params.seriesIndex,
|
|
897
|
+
seriesName: params.seriesName || "",
|
|
898
|
+
dataIndex: params.dataIndex || 0,
|
|
899
|
+
name: params.name || "",
|
|
900
|
+
value: params.value,
|
|
901
|
+
color: params.color
|
|
866
902
|
});
|
|
867
|
-
}
|
|
903
|
+
});
|
|
868
904
|
}
|
|
869
905
|
});
|
|
870
906
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Area chart with ${data.categories.length} data points across ${data.series.length} series.` : void 0);
|
|
@@ -891,7 +927,7 @@ AreaChart.displayName = "AreaChart";
|
|
|
891
927
|
// src/components/core/ScatterChart.tsx
|
|
892
928
|
import * as React9 from "react";
|
|
893
929
|
import * as echarts7 from "echarts/core";
|
|
894
|
-
import { ScatterChart as EChartsScatterChart } from "echarts/charts";
|
|
930
|
+
import { ScatterChart as EChartsScatterChart, LineChart as EChartsLineChart3 } from "echarts/charts";
|
|
895
931
|
import {
|
|
896
932
|
GridComponent as GridComponent4,
|
|
897
933
|
TooltipComponent as TooltipComponent5,
|
|
@@ -899,10 +935,12 @@ import {
|
|
|
899
935
|
TitleComponent as TitleComponent5
|
|
900
936
|
} from "echarts/components";
|
|
901
937
|
import { CanvasRenderer as CanvasRenderer5 } from "echarts/renderers";
|
|
902
|
-
import { generateScatterChartDescription } from "@classic-homes/charts-core";
|
|
938
|
+
import { escapeHtml, generateScatterChartDescription } from "@classic-homes/charts-core";
|
|
903
939
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
904
940
|
echarts7.use([
|
|
905
941
|
EChartsScatterChart,
|
|
942
|
+
// Trend lines are line series
|
|
943
|
+
EChartsLineChart3,
|
|
906
944
|
GridComponent4,
|
|
907
945
|
TooltipComponent5,
|
|
908
946
|
LegendComponent5,
|
|
@@ -959,9 +997,12 @@ var ScatterChart = React9.forwardRef(
|
|
|
959
997
|
});
|
|
960
998
|
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
|
|
961
999
|
const intercept = (sumY - slope * sumX) / n;
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
const
|
|
1000
|
+
let minX = Infinity;
|
|
1001
|
+
let maxX = -Infinity;
|
|
1002
|
+
for (const [x] of s.data) {
|
|
1003
|
+
if (x < minX) minX = x;
|
|
1004
|
+
if (x > maxX) maxX = x;
|
|
1005
|
+
}
|
|
965
1006
|
series.push({
|
|
966
1007
|
name: `${s.name} Trend`,
|
|
967
1008
|
type: "line",
|
|
@@ -994,7 +1035,7 @@ var ScatterChart = React9.forwardRef(
|
|
|
994
1035
|
formatter: (params) => {
|
|
995
1036
|
const p = params;
|
|
996
1037
|
if (!p.value) return "";
|
|
997
|
-
return `${p.seriesName}<br/>X: ${p.value[0]}<br/>Y: ${p.value[1]}`;
|
|
1038
|
+
return `${escapeHtml(p.seriesName)}<br/>X: ${escapeHtml(p.value[0])}<br/>Y: ${escapeHtml(p.value[1])}`;
|
|
998
1039
|
}
|
|
999
1040
|
} : void 0,
|
|
1000
1041
|
legend: showLegend ? {
|
|
@@ -1016,25 +1057,26 @@ var ScatterChart = React9.forwardRef(
|
|
|
1016
1057
|
series
|
|
1017
1058
|
};
|
|
1018
1059
|
}, [data, isEmpty, showTooltip, showLegend, showGrid, showTrendLine, symbolSize]);
|
|
1060
|
+
const latest = useLatestRef({ onClick });
|
|
1019
1061
|
const { containerRef } = useChart({
|
|
1020
1062
|
option,
|
|
1021
1063
|
theme,
|
|
1022
1064
|
animation,
|
|
1023
1065
|
onReady: (chart) => {
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1066
|
+
chart.on("click", (params) => {
|
|
1067
|
+
const { onClick: onClick2 } = latest.current;
|
|
1068
|
+
if (!onClick2) return;
|
|
1069
|
+
onClick2({
|
|
1070
|
+
type: params.type || "click",
|
|
1071
|
+
componentType: params.componentType || "series",
|
|
1072
|
+
seriesIndex: params.seriesIndex,
|
|
1073
|
+
seriesName: params.seriesName || "",
|
|
1074
|
+
dataIndex: params.dataIndex || 0,
|
|
1075
|
+
name: params.name || "",
|
|
1076
|
+
value: params.value,
|
|
1077
|
+
color: params.color
|
|
1036
1078
|
});
|
|
1037
|
-
}
|
|
1079
|
+
});
|
|
1038
1080
|
}
|
|
1039
1081
|
});
|
|
1040
1082
|
const accessibilityDescription = description || (!isEmpty ? generateScatterChartDescription(title, data) : void 0);
|
|
@@ -1064,7 +1106,11 @@ import * as echarts8 from "echarts/core";
|
|
|
1064
1106
|
import { PieChart as EChartsPieChart2 } from "echarts/charts";
|
|
1065
1107
|
import { TooltipComponent as TooltipComponent6, LegendComponent as LegendComponent6, TitleComponent as TitleComponent6 } from "echarts/components";
|
|
1066
1108
|
import { CanvasRenderer as CanvasRenderer6 } from "echarts/renderers";
|
|
1067
|
-
import {
|
|
1109
|
+
import {
|
|
1110
|
+
generatePieChartDescription as generatePieChartDescription2,
|
|
1111
|
+
getChartColors as getChartColors3,
|
|
1112
|
+
THEME_DARK as THEME_DARK4
|
|
1113
|
+
} from "@classic-homes/charts-core";
|
|
1068
1114
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1069
1115
|
echarts8.use([EChartsPieChart2, TooltipComponent6, LegendComponent6, TitleComponent6, CanvasRenderer6]);
|
|
1070
1116
|
var DonutChart = React10.forwardRef(
|
|
@@ -1090,6 +1136,8 @@ var DonutChart = React10.forwardRef(
|
|
|
1090
1136
|
...props
|
|
1091
1137
|
}, ref) => {
|
|
1092
1138
|
const isEmpty = !data?.length;
|
|
1139
|
+
const currentTheme = useChartTheme(theme);
|
|
1140
|
+
const chartColors = getChartColors3(currentTheme);
|
|
1093
1141
|
const option = React10.useMemo(() => {
|
|
1094
1142
|
if (isEmpty) return {};
|
|
1095
1143
|
const graphicElements = [];
|
|
@@ -1106,7 +1154,7 @@ var DonutChart = React10.forwardRef(
|
|
|
1106
1154
|
text: String(centerValue),
|
|
1107
1155
|
fontSize: 28,
|
|
1108
1156
|
fontWeight: "bold",
|
|
1109
|
-
fill:
|
|
1157
|
+
fill: chartColors.foreground,
|
|
1110
1158
|
textAlign: "center"
|
|
1111
1159
|
},
|
|
1112
1160
|
top: 0,
|
|
@@ -1119,7 +1167,7 @@ var DonutChart = React10.forwardRef(
|
|
|
1119
1167
|
style: {
|
|
1120
1168
|
text: centerLabel,
|
|
1121
1169
|
fontSize: 14,
|
|
1122
|
-
fill:
|
|
1170
|
+
fill: chartColors.mutedForeground,
|
|
1123
1171
|
textAlign: "center"
|
|
1124
1172
|
},
|
|
1125
1173
|
top: centerValue !== void 0 ? 35 : 0,
|
|
@@ -1182,25 +1230,27 @@ var DonutChart = React10.forwardRef(
|
|
|
1182
1230
|
innerRadius,
|
|
1183
1231
|
centerLabel,
|
|
1184
1232
|
centerValue,
|
|
1185
|
-
title
|
|
1233
|
+
title,
|
|
1234
|
+
chartColors
|
|
1186
1235
|
]);
|
|
1236
|
+
const latest = useLatestRef({ onClick });
|
|
1187
1237
|
const { containerRef } = useChart({
|
|
1188
1238
|
option,
|
|
1189
|
-
theme,
|
|
1239
|
+
theme: currentTheme === THEME_DARK4 ? "dark" : "light",
|
|
1190
1240
|
animation,
|
|
1191
1241
|
onReady: (chart) => {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1242
|
+
chart.on("click", (params) => {
|
|
1243
|
+
const { onClick: onClick2 } = latest.current;
|
|
1244
|
+
if (!onClick2) return;
|
|
1245
|
+
onClick2({
|
|
1246
|
+
type: params.type || "click",
|
|
1247
|
+
componentType: params.componentType || "series",
|
|
1248
|
+
name: params.name || "",
|
|
1249
|
+
value: params.value,
|
|
1250
|
+
percent: params.percent,
|
|
1251
|
+
color: params.color
|
|
1202
1252
|
});
|
|
1203
|
-
}
|
|
1253
|
+
});
|
|
1204
1254
|
}
|
|
1205
1255
|
});
|
|
1206
1256
|
const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription2(title, data, true) : void 0);
|
|
@@ -1377,7 +1427,8 @@ var FunnelChart = React12.forwardRef(
|
|
|
1377
1427
|
bottom: 60,
|
|
1378
1428
|
width: "80%",
|
|
1379
1429
|
min: 0,
|
|
1380
|
-
|
|
1430
|
+
// reduce, not Math.max(...): spreading large arrays overflows the stack
|
|
1431
|
+
max: data.reduce((m, d) => d.value > m ? d.value : m, -Infinity),
|
|
1381
1432
|
minSize: "0%",
|
|
1382
1433
|
maxSize: "100%",
|
|
1383
1434
|
sort,
|
|
@@ -1407,22 +1458,23 @@ var FunnelChart = React12.forwardRef(
|
|
|
1407
1458
|
]
|
|
1408
1459
|
};
|
|
1409
1460
|
}, [data, isEmpty, showTooltip, showLegend, sort, orientation, showLabels, title]);
|
|
1461
|
+
const latest = useLatestRef({ onClick });
|
|
1410
1462
|
const { containerRef } = useChart({
|
|
1411
1463
|
option,
|
|
1412
1464
|
theme,
|
|
1413
1465
|
animation,
|
|
1414
1466
|
onReady: (chart) => {
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1467
|
+
chart.on("click", (params) => {
|
|
1468
|
+
const { onClick: onClick2 } = latest.current;
|
|
1469
|
+
if (!onClick2) return;
|
|
1470
|
+
onClick2({
|
|
1471
|
+
type: params.type || "click",
|
|
1472
|
+
componentType: params.componentType || "series",
|
|
1473
|
+
name: params.name || "",
|
|
1474
|
+
value: params.value,
|
|
1475
|
+
color: params.color
|
|
1424
1476
|
});
|
|
1425
|
-
}
|
|
1477
|
+
});
|
|
1426
1478
|
}
|
|
1427
1479
|
});
|
|
1428
1480
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Funnel chart with ${data.length} stages.` : void 0);
|
|
@@ -1452,6 +1504,7 @@ import * as echarts11 from "echarts/core";
|
|
|
1452
1504
|
import { GaugeChart as EChartsGaugeChart } from "echarts/charts";
|
|
1453
1505
|
import { TitleComponent as TitleComponent9 } from "echarts/components";
|
|
1454
1506
|
import { CanvasRenderer as CanvasRenderer9 } from "echarts/renderers";
|
|
1507
|
+
import { getChartColors as getChartColors4, THEME_DARK as THEME_DARK5 } from "@classic-homes/charts-core";
|
|
1455
1508
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1456
1509
|
echarts11.use([EChartsGaugeChart, TitleComponent9, CanvasRenderer9]);
|
|
1457
1510
|
var GaugeChart = React13.forwardRef(
|
|
@@ -1473,6 +1526,9 @@ var GaugeChart = React13.forwardRef(
|
|
|
1473
1526
|
class: className,
|
|
1474
1527
|
...props
|
|
1475
1528
|
}, ref) => {
|
|
1529
|
+
const currentTheme = useChartTheme(theme);
|
|
1530
|
+
const chartColors = getChartColors4(currentTheme);
|
|
1531
|
+
const reducedMotion = useReducedMotion();
|
|
1476
1532
|
const option = React13.useMemo(() => {
|
|
1477
1533
|
return {
|
|
1478
1534
|
series: [
|
|
@@ -1497,7 +1553,7 @@ var GaugeChart = React13.forwardRef(
|
|
|
1497
1553
|
splitNumber: 5,
|
|
1498
1554
|
lineStyle: {
|
|
1499
1555
|
width: 2,
|
|
1500
|
-
color:
|
|
1556
|
+
color: chartColors.mutedForeground
|
|
1501
1557
|
}
|
|
1502
1558
|
},
|
|
1503
1559
|
splitLine: {
|
|
@@ -1505,12 +1561,12 @@ var GaugeChart = React13.forwardRef(
|
|
|
1505
1561
|
length: 10,
|
|
1506
1562
|
lineStyle: {
|
|
1507
1563
|
width: 3,
|
|
1508
|
-
color:
|
|
1564
|
+
color: chartColors.mutedForeground
|
|
1509
1565
|
}
|
|
1510
1566
|
},
|
|
1511
1567
|
axisLabel: {
|
|
1512
1568
|
distance: -20,
|
|
1513
|
-
color:
|
|
1569
|
+
color: chartColors.mutedForeground,
|
|
1514
1570
|
fontSize: 12
|
|
1515
1571
|
},
|
|
1516
1572
|
anchor: {
|
|
@@ -1530,7 +1586,7 @@ var GaugeChart = React13.forwardRef(
|
|
|
1530
1586
|
fontSize: 14
|
|
1531
1587
|
},
|
|
1532
1588
|
detail: {
|
|
1533
|
-
valueAnimation: animation,
|
|
1589
|
+
valueAnimation: animation && !reducedMotion,
|
|
1534
1590
|
fontSize: 28,
|
|
1535
1591
|
fontWeight: "bold",
|
|
1536
1592
|
offsetCenter: [0, "40%"],
|
|
@@ -1545,10 +1601,21 @@ var GaugeChart = React13.forwardRef(
|
|
|
1545
1601
|
}
|
|
1546
1602
|
]
|
|
1547
1603
|
};
|
|
1548
|
-
}, [
|
|
1604
|
+
}, [
|
|
1605
|
+
value,
|
|
1606
|
+
min,
|
|
1607
|
+
max,
|
|
1608
|
+
splitNumber,
|
|
1609
|
+
showProgress,
|
|
1610
|
+
formatValue,
|
|
1611
|
+
title,
|
|
1612
|
+
animation,
|
|
1613
|
+
reducedMotion,
|
|
1614
|
+
chartColors
|
|
1615
|
+
]);
|
|
1549
1616
|
const { containerRef } = useChart({
|
|
1550
1617
|
option,
|
|
1551
|
-
theme,
|
|
1618
|
+
theme: currentTheme === THEME_DARK5 ? "dark" : "light",
|
|
1552
1619
|
animation
|
|
1553
1620
|
});
|
|
1554
1621
|
const accessibilityDescription = description || `${title}. Gauge showing value ${value} on scale from ${min} to ${max}.`;
|
|
@@ -1582,6 +1649,7 @@ import {
|
|
|
1582
1649
|
VisualMapComponent
|
|
1583
1650
|
} from "echarts/components";
|
|
1584
1651
|
import { CanvasRenderer as CanvasRenderer10 } from "echarts/renderers";
|
|
1652
|
+
import { escapeHtml as escapeHtml2 } from "@classic-homes/charts-core";
|
|
1585
1653
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1586
1654
|
echarts12.use([
|
|
1587
1655
|
EChartsHeatmapChart,
|
|
@@ -1611,9 +1679,14 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1611
1679
|
...props
|
|
1612
1680
|
}, ref) => {
|
|
1613
1681
|
const isEmpty = !data?.data?.length || !xAxis?.length || !yAxis?.length;
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
const
|
|
1682
|
+
let dataMin = Infinity;
|
|
1683
|
+
let dataMax = -Infinity;
|
|
1684
|
+
for (const [, , value] of data?.data ?? []) {
|
|
1685
|
+
if (value < dataMin) dataMin = value;
|
|
1686
|
+
if (value > dataMax) dataMax = value;
|
|
1687
|
+
}
|
|
1688
|
+
const minValue = data?.min ?? dataMin;
|
|
1689
|
+
const maxValue = data?.max ?? dataMax;
|
|
1617
1690
|
const option = React14.useMemo(() => {
|
|
1618
1691
|
if (isEmpty) return {};
|
|
1619
1692
|
return {
|
|
@@ -1623,7 +1696,7 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1623
1696
|
const p = params;
|
|
1624
1697
|
if (!p.value) return "";
|
|
1625
1698
|
const [xIdx, yIdx, value] = p.value;
|
|
1626
|
-
return `${xAxis[xIdx]} / ${yAxis[yIdx]}: ${value}`;
|
|
1699
|
+
return `${escapeHtml2(xAxis[xIdx])} / ${escapeHtml2(yAxis[yIdx])}: ${escapeHtml2(value)}`;
|
|
1627
1700
|
}
|
|
1628
1701
|
} : void 0,
|
|
1629
1702
|
grid: {
|
|
@@ -1672,25 +1745,26 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1672
1745
|
]
|
|
1673
1746
|
};
|
|
1674
1747
|
}, [data, xAxis, yAxis, isEmpty, showTooltip, showValues, minValue, maxValue, title]);
|
|
1748
|
+
const latest = useLatestRef({ onClick, xAxis, yAxis });
|
|
1675
1749
|
const { containerRef } = useChart({
|
|
1676
1750
|
option,
|
|
1677
1751
|
theme,
|
|
1678
1752
|
animation,
|
|
1679
1753
|
onReady: (chart) => {
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1754
|
+
chart.on("click", (params) => {
|
|
1755
|
+
const { onClick: onClick2, xAxis: xAxis2, yAxis: yAxis2 } = latest.current;
|
|
1756
|
+
if (!onClick2) return;
|
|
1757
|
+
const [xIdx, yIdx, value] = params.value || [0, 0, 0];
|
|
1758
|
+
onClick2({
|
|
1759
|
+
type: params.type || "click",
|
|
1760
|
+
componentType: params.componentType || "series",
|
|
1761
|
+
xIndex: xIdx,
|
|
1762
|
+
yIndex: yIdx,
|
|
1763
|
+
xLabel: xAxis2[xIdx],
|
|
1764
|
+
yLabel: yAxis2[yIdx],
|
|
1765
|
+
value
|
|
1692
1766
|
});
|
|
1693
|
-
}
|
|
1767
|
+
});
|
|
1694
1768
|
}
|
|
1695
1769
|
});
|
|
1696
1770
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Heatmap with ${xAxis.length} columns and ${yAxis.length} rows.` : void 0);
|
|
@@ -1720,6 +1794,7 @@ import * as echarts13 from "echarts/core";
|
|
|
1720
1794
|
import { TreemapChart as EChartsTreemapChart } from "echarts/charts";
|
|
1721
1795
|
import { TooltipComponent as TooltipComponent10, TitleComponent as TitleComponent11 } from "echarts/components";
|
|
1722
1796
|
import { CanvasRenderer as CanvasRenderer11 } from "echarts/renderers";
|
|
1797
|
+
import { escapeHtml as escapeHtml3, getChartColors as getChartColors5, THEME_DARK as THEME_DARK6 } from "@classic-homes/charts-core";
|
|
1723
1798
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1724
1799
|
echarts13.use([EChartsTreemapChart, TooltipComponent10, TitleComponent11, CanvasRenderer11]);
|
|
1725
1800
|
var TreemapChart = React15.forwardRef(
|
|
@@ -1740,13 +1815,15 @@ var TreemapChart = React15.forwardRef(
|
|
|
1740
1815
|
...props
|
|
1741
1816
|
}, ref) => {
|
|
1742
1817
|
const isEmpty = !data?.length;
|
|
1818
|
+
const currentTheme = useChartTheme(theme);
|
|
1819
|
+
const chartColors = getChartColors5(currentTheme);
|
|
1743
1820
|
const option = React15.useMemo(() => {
|
|
1744
1821
|
if (isEmpty) return {};
|
|
1745
1822
|
return {
|
|
1746
1823
|
tooltip: showTooltip ? {
|
|
1747
1824
|
formatter: (params) => {
|
|
1748
1825
|
const p = params;
|
|
1749
|
-
return `${p.name}: ${p.value}`;
|
|
1826
|
+
return `${escapeHtml3(p.name)}: ${escapeHtml3(p.value)}`;
|
|
1750
1827
|
}
|
|
1751
1828
|
} : void 0,
|
|
1752
1829
|
series: [
|
|
@@ -1757,7 +1834,7 @@ var TreemapChart = React15.forwardRef(
|
|
|
1757
1834
|
levels: levels || [
|
|
1758
1835
|
{
|
|
1759
1836
|
itemStyle: {
|
|
1760
|
-
borderColor:
|
|
1837
|
+
borderColor: chartColors.divider,
|
|
1761
1838
|
borderWidth: 4,
|
|
1762
1839
|
gapWidth: 4
|
|
1763
1840
|
}
|
|
@@ -1795,25 +1872,26 @@ var TreemapChart = React15.forwardRef(
|
|
|
1795
1872
|
}
|
|
1796
1873
|
]
|
|
1797
1874
|
};
|
|
1798
|
-
}, [data, levels, isEmpty, showTooltip]);
|
|
1875
|
+
}, [data, levels, isEmpty, showTooltip, chartColors]);
|
|
1876
|
+
const latest = useLatestRef({ onClick });
|
|
1799
1877
|
const { containerRef } = useChart({
|
|
1800
1878
|
option,
|
|
1801
|
-
theme,
|
|
1879
|
+
theme: currentTheme === THEME_DARK6 ? "dark" : "light",
|
|
1802
1880
|
animation,
|
|
1803
1881
|
onReady: (chart) => {
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1882
|
+
chart.on("click", (params) => {
|
|
1883
|
+
const { onClick: onClick2 } = latest.current;
|
|
1884
|
+
if (!onClick2) return;
|
|
1885
|
+
const treePathInfo = params.treePathInfo || [];
|
|
1886
|
+
onClick2({
|
|
1887
|
+
type: params.type || "click",
|
|
1888
|
+
componentType: params.componentType || "series",
|
|
1889
|
+
name: params.name || "",
|
|
1890
|
+
value: params.value,
|
|
1891
|
+
path: treePathInfo.map((item) => item.name || ""),
|
|
1892
|
+
depth: treePathInfo.length - 1
|
|
1815
1893
|
});
|
|
1816
|
-
}
|
|
1894
|
+
});
|
|
1817
1895
|
}
|
|
1818
1896
|
});
|
|
1819
1897
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Treemap chart showing hierarchical data.` : void 0);
|
|
@@ -1851,6 +1929,7 @@ import {
|
|
|
1851
1929
|
DataZoomComponent
|
|
1852
1930
|
} from "echarts/components";
|
|
1853
1931
|
import { CanvasRenderer as CanvasRenderer12 } from "echarts/renderers";
|
|
1932
|
+
import { getChartColors as getChartColors6, THEME_DARK as THEME_DARK7 } from "@classic-homes/charts-core";
|
|
1854
1933
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1855
1934
|
echarts14.use([
|
|
1856
1935
|
EChartsCandlestickChart,
|
|
@@ -1879,6 +1958,8 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1879
1958
|
...props
|
|
1880
1959
|
}, ref) => {
|
|
1881
1960
|
const isEmpty = !data?.dates?.length || !data?.data?.length;
|
|
1961
|
+
const currentTheme = useChartTheme(theme);
|
|
1962
|
+
const chartColors = getChartColors6(currentTheme);
|
|
1882
1963
|
const option = React16.useMemo(() => {
|
|
1883
1964
|
if (isEmpty) return {};
|
|
1884
1965
|
const candlestickData = data.data.map((item) => [item.open, item.close, item.low, item.high]);
|
|
@@ -1888,12 +1969,12 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1888
1969
|
type: "candlestick",
|
|
1889
1970
|
data: candlestickData,
|
|
1890
1971
|
itemStyle: {
|
|
1891
|
-
color:
|
|
1972
|
+
color: chartColors.destructive,
|
|
1892
1973
|
// Up color (red for bearish in some markets)
|
|
1893
|
-
color0:
|
|
1974
|
+
color0: chartColors.success,
|
|
1894
1975
|
// Down color (green for bullish)
|
|
1895
|
-
borderColor:
|
|
1896
|
-
borderColor0:
|
|
1976
|
+
borderColor: chartColors.destructive,
|
|
1977
|
+
borderColor0: chartColors.success
|
|
1897
1978
|
}
|
|
1898
1979
|
}
|
|
1899
1980
|
];
|
|
@@ -1959,7 +2040,7 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1959
2040
|
yAxisIndex: 1,
|
|
1960
2041
|
data: data.volume,
|
|
1961
2042
|
itemStyle: {
|
|
1962
|
-
color:
|
|
2043
|
+
color: chartColors.mutedForeground
|
|
1963
2044
|
}
|
|
1964
2045
|
});
|
|
1965
2046
|
}
|
|
@@ -1989,28 +2070,30 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1989
2070
|
],
|
|
1990
2071
|
series: seriesArr
|
|
1991
2072
|
};
|
|
1992
|
-
}, [data, isEmpty, showTooltip, showVolume, title]);
|
|
2073
|
+
}, [data, isEmpty, showTooltip, showVolume, title, chartColors]);
|
|
2074
|
+
const latest = useLatestRef({ onClick, data });
|
|
1993
2075
|
const { containerRef } = useChart({
|
|
1994
2076
|
option,
|
|
1995
|
-
theme,
|
|
2077
|
+
theme: currentTheme === THEME_DARK7 ? "dark" : "light",
|
|
1996
2078
|
animation,
|
|
1997
2079
|
onReady: (chart) => {
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2080
|
+
chart.on("click", (params) => {
|
|
2081
|
+
const { onClick: onClick2, data: data2 } = latest.current;
|
|
2082
|
+
if (!onClick2) return;
|
|
2083
|
+
const dataIndex = params.dataIndex || 0;
|
|
2084
|
+
const item = data2.data[dataIndex];
|
|
2085
|
+
if (!item) return;
|
|
2086
|
+
onClick2({
|
|
2087
|
+
type: params.type || "click",
|
|
2088
|
+
componentType: params.componentType || "series",
|
|
2089
|
+
date: data2.dates[dataIndex],
|
|
2090
|
+
open: item.open,
|
|
2091
|
+
close: item.close,
|
|
2092
|
+
high: item.high,
|
|
2093
|
+
low: item.low,
|
|
2094
|
+
volume: data2.volume?.[dataIndex]
|
|
2012
2095
|
});
|
|
2013
|
-
}
|
|
2096
|
+
});
|
|
2014
2097
|
}
|
|
2015
2098
|
});
|
|
2016
2099
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Candlestick chart with ${data.dates.length} data points.` : void 0);
|
|
@@ -2094,25 +2177,26 @@ var SankeyChart = React17.forwardRef(
|
|
|
2094
2177
|
]
|
|
2095
2178
|
};
|
|
2096
2179
|
}, [data, isEmpty, showTooltip, orient]);
|
|
2180
|
+
const latest = useLatestRef({ onClick });
|
|
2097
2181
|
const { containerRef } = useChart({
|
|
2098
2182
|
option,
|
|
2099
2183
|
theme,
|
|
2100
2184
|
animation,
|
|
2101
2185
|
onReady: (chart) => {
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2186
|
+
chart.on("click", (params) => {
|
|
2187
|
+
const { onClick: onClick2 } = latest.current;
|
|
2188
|
+
if (!onClick2) return;
|
|
2189
|
+
const isEdge = params.dataType === "edge";
|
|
2190
|
+
onClick2({
|
|
2191
|
+
type: params.type || "click",
|
|
2192
|
+
componentType: params.componentType || "series",
|
|
2193
|
+
dataType: isEdge ? "edge" : "node",
|
|
2194
|
+
name: params.name || "",
|
|
2195
|
+
value: isEdge ? params.value : void 0,
|
|
2196
|
+
source: isEdge ? params.data?.source : void 0,
|
|
2197
|
+
target: isEdge ? params.data?.target : void 0
|
|
2114
2198
|
});
|
|
2115
|
-
}
|
|
2199
|
+
});
|
|
2116
2200
|
}
|
|
2117
2201
|
});
|
|
2118
2202
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Sankey diagram with ${data.nodes.length} nodes and ${data.links.length} links.` : void 0);
|