@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 +345 -276
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +355 -278
- 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,44 +253,49 @@ 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
|
-
|
|
266
|
-
const chart = chartRef.current;
|
|
267
|
-
if (!container || !chart) return;
|
|
276
|
+
if (!container) return;
|
|
268
277
|
let resizeTimeout;
|
|
269
|
-
|
|
278
|
+
const observer = new ResizeObserver(() => {
|
|
270
279
|
clearTimeout(resizeTimeout);
|
|
271
280
|
resizeTimeout = setTimeout(() => {
|
|
272
|
-
chart.
|
|
281
|
+
const chart = chartRef.current;
|
|
282
|
+
if (chart && !chart.isDisposed()) {
|
|
283
|
+
chart.resize();
|
|
284
|
+
}
|
|
273
285
|
}, 100);
|
|
274
286
|
});
|
|
275
|
-
|
|
287
|
+
observer.observe(container);
|
|
276
288
|
return () => {
|
|
277
289
|
clearTimeout(resizeTimeout);
|
|
278
|
-
|
|
290
|
+
observer.disconnect();
|
|
279
291
|
};
|
|
280
|
-
}, [chartRef,
|
|
292
|
+
}, [chartRef, container]);
|
|
281
293
|
}
|
|
282
294
|
|
|
283
295
|
// src/hooks/useReducedMotion.ts
|
|
284
|
-
import { useState as
|
|
296
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
285
297
|
function useReducedMotion() {
|
|
286
|
-
const [reducedMotion, setReducedMotion] =
|
|
298
|
+
const [reducedMotion, setReducedMotion] = useState3(false);
|
|
287
299
|
useEffect3(() => {
|
|
288
300
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
289
301
|
setReducedMotion(mediaQuery.matches);
|
|
@@ -299,51 +311,53 @@ function useReducedMotion() {
|
|
|
299
311
|
}
|
|
300
312
|
|
|
301
313
|
// src/hooks/useChart.ts
|
|
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
|
+
}
|
|
302
321
|
function useChart({
|
|
303
322
|
option,
|
|
304
323
|
theme = "auto",
|
|
305
324
|
animation,
|
|
306
325
|
onReady
|
|
307
326
|
}) {
|
|
308
|
-
const containerRef =
|
|
309
|
-
const
|
|
327
|
+
const containerRef = useRef(null);
|
|
328
|
+
const container = useRefElement(containerRef);
|
|
329
|
+
const chartRef = useRef(null);
|
|
310
330
|
const currentTheme = useChartTheme(theme);
|
|
311
331
|
const reducedMotion = useReducedMotion();
|
|
312
|
-
const onReadyRef =
|
|
332
|
+
const onReadyRef = useRef(onReady);
|
|
313
333
|
onReadyRef.current = onReady;
|
|
334
|
+
const optionRef = useRef(option);
|
|
335
|
+
optionRef.current = {
|
|
336
|
+
...option,
|
|
337
|
+
// Reduced motion always wins over the animation prop
|
|
338
|
+
animation: (animation ?? true) && !reducedMotion
|
|
339
|
+
};
|
|
340
|
+
const appliedRef = useRef(null);
|
|
314
341
|
useEffect4(() => {
|
|
315
|
-
if (!
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
onReadyRef.current(chartRef.current);
|
|
322
|
-
}
|
|
342
|
+
if (!container) return;
|
|
343
|
+
const chart = echarts2.init(container, currentTheme);
|
|
344
|
+
chartRef.current = chart;
|
|
345
|
+
applyOption(chart, null, optionRef.current);
|
|
346
|
+
appliedRef.current = optionRef.current;
|
|
347
|
+
onReadyRef.current?.(chart);
|
|
323
348
|
return () => {
|
|
324
|
-
|
|
325
|
-
chartRef.current
|
|
349
|
+
chart.dispose();
|
|
350
|
+
if (chartRef.current === chart) {
|
|
351
|
+
chartRef.current = null;
|
|
352
|
+
}
|
|
326
353
|
};
|
|
327
|
-
}, [currentTheme]);
|
|
354
|
+
}, [container, currentTheme]);
|
|
328
355
|
useEffect4(() => {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
animation: shouldAnimate
|
|
334
|
-
};
|
|
335
|
-
chartRef.current.setOption(optionWithAnimation, {
|
|
336
|
-
notMerge: false,
|
|
337
|
-
lazyUpdate: true
|
|
338
|
-
});
|
|
356
|
+
const chart = chartRef.current;
|
|
357
|
+
if (!chart || chart.isDisposed()) return;
|
|
358
|
+
applyOption(chart, appliedRef.current, optionRef.current);
|
|
359
|
+
appliedRef.current = optionRef.current;
|
|
339
360
|
}, [option, animation, reducedMotion]);
|
|
340
|
-
useEffect4(() => {
|
|
341
|
-
if (!chartRef.current || !containerRef.current) return;
|
|
342
|
-
const currentOption = chartRef.current.getOption();
|
|
343
|
-
chartRef.current.dispose();
|
|
344
|
-
chartRef.current = echarts2.init(containerRef.current, currentTheme);
|
|
345
|
-
chartRef.current.setOption(currentOption);
|
|
346
|
-
}, [currentTheme]);
|
|
347
361
|
useChartResize(chartRef, containerRef);
|
|
348
362
|
return {
|
|
349
363
|
chartRef,
|
|
@@ -352,6 +366,14 @@ function useChart({
|
|
|
352
366
|
};
|
|
353
367
|
}
|
|
354
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
|
+
|
|
355
377
|
// src/components/core/LineChart.tsx
|
|
356
378
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
357
379
|
echarts3.use([
|
|
@@ -386,6 +408,8 @@ var LineChart = React5.forwardRef(
|
|
|
386
408
|
...props
|
|
387
409
|
}, ref) => {
|
|
388
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);
|
|
389
413
|
const option = React5.useMemo(() => {
|
|
390
414
|
if (isEmpty) return {};
|
|
391
415
|
return {
|
|
@@ -400,7 +424,7 @@ var LineChart = React5.forwardRef(
|
|
|
400
424
|
axisPointer: {
|
|
401
425
|
type: "cross",
|
|
402
426
|
label: {
|
|
403
|
-
backgroundColor:
|
|
427
|
+
backgroundColor: chartColors.axisPointerLabel
|
|
404
428
|
}
|
|
405
429
|
}
|
|
406
430
|
} : void 0,
|
|
@@ -446,41 +470,43 @@ var LineChart = React5.forwardRef(
|
|
|
446
470
|
smooth,
|
|
447
471
|
areaFilled,
|
|
448
472
|
showDataPoints,
|
|
449
|
-
stacked
|
|
473
|
+
stacked,
|
|
474
|
+
chartColors
|
|
450
475
|
]);
|
|
476
|
+
const latest = useLatestRef({ onClick, onHover });
|
|
451
477
|
const { containerRef } = useChart({
|
|
452
478
|
option,
|
|
453
|
-
theme,
|
|
479
|
+
theme: currentTheme === THEME_DARK2 ? "dark" : "light",
|
|
454
480
|
animation,
|
|
455
481
|
onReady: (chart) => {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
|
468
494
|
});
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
|
482
508
|
});
|
|
483
|
-
}
|
|
509
|
+
});
|
|
484
510
|
}
|
|
485
511
|
});
|
|
486
512
|
const accessibilityDescription = description || (!isEmpty ? generateLineChartDescription(title, data) : void 0);
|
|
@@ -598,25 +624,26 @@ var BarChart = React6.forwardRef(
|
|
|
598
624
|
}))
|
|
599
625
|
};
|
|
600
626
|
}, [data, isEmpty, showTooltip, showLegend, showGrid, isHorizontal, stacked, showValues]);
|
|
627
|
+
const latest = useLatestRef({ onClick });
|
|
601
628
|
const { containerRef } = useChart({
|
|
602
629
|
option,
|
|
603
630
|
theme,
|
|
604
631
|
animation,
|
|
605
632
|
onReady: (chart) => {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
|
618
645
|
});
|
|
619
|
-
}
|
|
646
|
+
});
|
|
620
647
|
}
|
|
621
648
|
});
|
|
622
649
|
const accessibilityDescription = description || (!isEmpty ? generateBarChartDescription(title, data) : void 0);
|
|
@@ -686,7 +713,7 @@ var PieChart = React7.forwardRef(
|
|
|
686
713
|
{
|
|
687
714
|
name: title,
|
|
688
715
|
type: "pie",
|
|
689
|
-
radius: innerRadius
|
|
716
|
+
radius: innerRadius ? [innerRadius, "70%"] : "70%",
|
|
690
717
|
center: ["50%", "45%"],
|
|
691
718
|
data: data.map((item) => ({
|
|
692
719
|
name: item.name,
|
|
@@ -711,23 +738,24 @@ var PieChart = React7.forwardRef(
|
|
|
711
738
|
]
|
|
712
739
|
};
|
|
713
740
|
}, [data, isEmpty, showTooltip, showLegend, showLabels, labelPosition, innerRadius, title]);
|
|
741
|
+
const latest = useLatestRef({ onClick });
|
|
714
742
|
const { containerRef } = useChart({
|
|
715
743
|
option,
|
|
716
744
|
theme,
|
|
717
745
|
animation,
|
|
718
746
|
onReady: (chart) => {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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
|
|
729
757
|
});
|
|
730
|
-
}
|
|
758
|
+
});
|
|
731
759
|
}
|
|
732
760
|
});
|
|
733
761
|
const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription(title, data, false) : void 0);
|
|
@@ -762,6 +790,7 @@ import {
|
|
|
762
790
|
TitleComponent as TitleComponent4
|
|
763
791
|
} from "echarts/components";
|
|
764
792
|
import { CanvasRenderer as CanvasRenderer4 } from "echarts/renderers";
|
|
793
|
+
import { colorWithAlpha, getChartColors as getChartColors2, THEME_DARK as THEME_DARK3 } from "@classic-homes/charts-core";
|
|
765
794
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
766
795
|
echarts6.use([
|
|
767
796
|
EChartsLineChart2,
|
|
@@ -793,6 +822,8 @@ var AreaChart = React8.forwardRef(
|
|
|
793
822
|
...props
|
|
794
823
|
}, ref) => {
|
|
795
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);
|
|
796
827
|
const option = React8.useMemo(() => {
|
|
797
828
|
if (isEmpty) return {};
|
|
798
829
|
return {
|
|
@@ -807,7 +838,7 @@ var AreaChart = React8.forwardRef(
|
|
|
807
838
|
axisPointer: {
|
|
808
839
|
type: "cross",
|
|
809
840
|
label: {
|
|
810
|
-
backgroundColor:
|
|
841
|
+
backgroundColor: chartColors.axisPointerLabel
|
|
811
842
|
}
|
|
812
843
|
}
|
|
813
844
|
} : void 0,
|
|
@@ -826,52 +857,50 @@ var AreaChart = React8.forwardRef(
|
|
|
826
857
|
show: showGrid
|
|
827
858
|
}
|
|
828
859
|
},
|
|
829
|
-
series: data.series.map((series, index) =>
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
},
|
|
852
|
-
showSymbol: false
|
|
853
|
-
}))
|
|
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
|
+
})
|
|
854
882
|
};
|
|
855
|
-
}, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient]);
|
|
883
|
+
}, [data, isEmpty, showTooltip, showLegend, showGrid, smooth, stacked, gradient, chartColors]);
|
|
884
|
+
const latest = useLatestRef({ onClick });
|
|
856
885
|
const { containerRef } = useChart({
|
|
857
886
|
option,
|
|
858
|
-
theme,
|
|
887
|
+
theme: currentTheme === THEME_DARK3 ? "dark" : "light",
|
|
859
888
|
animation,
|
|
860
889
|
onReady: (chart) => {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
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
|
|
873
902
|
});
|
|
874
|
-
}
|
|
903
|
+
});
|
|
875
904
|
}
|
|
876
905
|
});
|
|
877
906
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Area chart with ${data.categories.length} data points across ${data.series.length} series.` : void 0);
|
|
@@ -898,7 +927,7 @@ AreaChart.displayName = "AreaChart";
|
|
|
898
927
|
// src/components/core/ScatterChart.tsx
|
|
899
928
|
import * as React9 from "react";
|
|
900
929
|
import * as echarts7 from "echarts/core";
|
|
901
|
-
import { ScatterChart as EChartsScatterChart } from "echarts/charts";
|
|
930
|
+
import { ScatterChart as EChartsScatterChart, LineChart as EChartsLineChart3 } from "echarts/charts";
|
|
902
931
|
import {
|
|
903
932
|
GridComponent as GridComponent4,
|
|
904
933
|
TooltipComponent as TooltipComponent5,
|
|
@@ -906,10 +935,12 @@ import {
|
|
|
906
935
|
TitleComponent as TitleComponent5
|
|
907
936
|
} from "echarts/components";
|
|
908
937
|
import { CanvasRenderer as CanvasRenderer5 } from "echarts/renderers";
|
|
909
|
-
import { generateScatterChartDescription } from "@classic-homes/charts-core";
|
|
938
|
+
import { escapeHtml, generateScatterChartDescription } from "@classic-homes/charts-core";
|
|
910
939
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
911
940
|
echarts7.use([
|
|
912
941
|
EChartsScatterChart,
|
|
942
|
+
// Trend lines are line series
|
|
943
|
+
EChartsLineChart3,
|
|
913
944
|
GridComponent4,
|
|
914
945
|
TooltipComponent5,
|
|
915
946
|
LegendComponent5,
|
|
@@ -966,9 +997,12 @@ var ScatterChart = React9.forwardRef(
|
|
|
966
997
|
});
|
|
967
998
|
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
|
|
968
999
|
const intercept = (sumY - slope * sumX) / n;
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
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
|
+
}
|
|
972
1006
|
series.push({
|
|
973
1007
|
name: `${s.name} Trend`,
|
|
974
1008
|
type: "line",
|
|
@@ -1001,7 +1035,7 @@ var ScatterChart = React9.forwardRef(
|
|
|
1001
1035
|
formatter: (params) => {
|
|
1002
1036
|
const p = params;
|
|
1003
1037
|
if (!p.value) return "";
|
|
1004
|
-
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])}`;
|
|
1005
1039
|
}
|
|
1006
1040
|
} : void 0,
|
|
1007
1041
|
legend: showLegend ? {
|
|
@@ -1023,25 +1057,26 @@ var ScatterChart = React9.forwardRef(
|
|
|
1023
1057
|
series
|
|
1024
1058
|
};
|
|
1025
1059
|
}, [data, isEmpty, showTooltip, showLegend, showGrid, showTrendLine, symbolSize]);
|
|
1060
|
+
const latest = useLatestRef({ onClick });
|
|
1026
1061
|
const { containerRef } = useChart({
|
|
1027
1062
|
option,
|
|
1028
1063
|
theme,
|
|
1029
1064
|
animation,
|
|
1030
1065
|
onReady: (chart) => {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
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
|
|
1043
1078
|
});
|
|
1044
|
-
}
|
|
1079
|
+
});
|
|
1045
1080
|
}
|
|
1046
1081
|
});
|
|
1047
1082
|
const accessibilityDescription = description || (!isEmpty ? generateScatterChartDescription(title, data) : void 0);
|
|
@@ -1071,7 +1106,11 @@ import * as echarts8 from "echarts/core";
|
|
|
1071
1106
|
import { PieChart as EChartsPieChart2 } from "echarts/charts";
|
|
1072
1107
|
import { TooltipComponent as TooltipComponent6, LegendComponent as LegendComponent6, TitleComponent as TitleComponent6 } from "echarts/components";
|
|
1073
1108
|
import { CanvasRenderer as CanvasRenderer6 } from "echarts/renderers";
|
|
1074
|
-
import {
|
|
1109
|
+
import {
|
|
1110
|
+
generatePieChartDescription as generatePieChartDescription2,
|
|
1111
|
+
getChartColors as getChartColors3,
|
|
1112
|
+
THEME_DARK as THEME_DARK4
|
|
1113
|
+
} from "@classic-homes/charts-core";
|
|
1075
1114
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1076
1115
|
echarts8.use([EChartsPieChart2, TooltipComponent6, LegendComponent6, TitleComponent6, CanvasRenderer6]);
|
|
1077
1116
|
var DonutChart = React10.forwardRef(
|
|
@@ -1097,6 +1136,8 @@ var DonutChart = React10.forwardRef(
|
|
|
1097
1136
|
...props
|
|
1098
1137
|
}, ref) => {
|
|
1099
1138
|
const isEmpty = !data?.length;
|
|
1139
|
+
const currentTheme = useChartTheme(theme);
|
|
1140
|
+
const chartColors = getChartColors3(currentTheme);
|
|
1100
1141
|
const option = React10.useMemo(() => {
|
|
1101
1142
|
if (isEmpty) return {};
|
|
1102
1143
|
const graphicElements = [];
|
|
@@ -1113,7 +1154,7 @@ var DonutChart = React10.forwardRef(
|
|
|
1113
1154
|
text: String(centerValue),
|
|
1114
1155
|
fontSize: 28,
|
|
1115
1156
|
fontWeight: "bold",
|
|
1116
|
-
fill:
|
|
1157
|
+
fill: chartColors.foreground,
|
|
1117
1158
|
textAlign: "center"
|
|
1118
1159
|
},
|
|
1119
1160
|
top: 0,
|
|
@@ -1126,7 +1167,7 @@ var DonutChart = React10.forwardRef(
|
|
|
1126
1167
|
style: {
|
|
1127
1168
|
text: centerLabel,
|
|
1128
1169
|
fontSize: 14,
|
|
1129
|
-
fill:
|
|
1170
|
+
fill: chartColors.mutedForeground,
|
|
1130
1171
|
textAlign: "center"
|
|
1131
1172
|
},
|
|
1132
1173
|
top: centerValue !== void 0 ? 35 : 0,
|
|
@@ -1189,25 +1230,27 @@ var DonutChart = React10.forwardRef(
|
|
|
1189
1230
|
innerRadius,
|
|
1190
1231
|
centerLabel,
|
|
1191
1232
|
centerValue,
|
|
1192
|
-
title
|
|
1233
|
+
title,
|
|
1234
|
+
chartColors
|
|
1193
1235
|
]);
|
|
1236
|
+
const latest = useLatestRef({ onClick });
|
|
1194
1237
|
const { containerRef } = useChart({
|
|
1195
1238
|
option,
|
|
1196
|
-
theme,
|
|
1239
|
+
theme: currentTheme === THEME_DARK4 ? "dark" : "light",
|
|
1197
1240
|
animation,
|
|
1198
1241
|
onReady: (chart) => {
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
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
|
|
1209
1252
|
});
|
|
1210
|
-
}
|
|
1253
|
+
});
|
|
1211
1254
|
}
|
|
1212
1255
|
});
|
|
1213
1256
|
const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription2(title, data, true) : void 0);
|
|
@@ -1384,7 +1427,8 @@ var FunnelChart = React12.forwardRef(
|
|
|
1384
1427
|
bottom: 60,
|
|
1385
1428
|
width: "80%",
|
|
1386
1429
|
min: 0,
|
|
1387
|
-
|
|
1430
|
+
// reduce, not Math.max(...): spreading large arrays overflows the stack
|
|
1431
|
+
max: data.reduce((m, d) => d.value > m ? d.value : m, -Infinity),
|
|
1388
1432
|
minSize: "0%",
|
|
1389
1433
|
maxSize: "100%",
|
|
1390
1434
|
sort,
|
|
@@ -1414,22 +1458,23 @@ var FunnelChart = React12.forwardRef(
|
|
|
1414
1458
|
]
|
|
1415
1459
|
};
|
|
1416
1460
|
}, [data, isEmpty, showTooltip, showLegend, sort, orientation, showLabels, title]);
|
|
1461
|
+
const latest = useLatestRef({ onClick });
|
|
1417
1462
|
const { containerRef } = useChart({
|
|
1418
1463
|
option,
|
|
1419
1464
|
theme,
|
|
1420
1465
|
animation,
|
|
1421
1466
|
onReady: (chart) => {
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
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
|
|
1431
1476
|
});
|
|
1432
|
-
}
|
|
1477
|
+
});
|
|
1433
1478
|
}
|
|
1434
1479
|
});
|
|
1435
1480
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Funnel chart with ${data.length} stages.` : void 0);
|
|
@@ -1459,6 +1504,7 @@ import * as echarts11 from "echarts/core";
|
|
|
1459
1504
|
import { GaugeChart as EChartsGaugeChart } from "echarts/charts";
|
|
1460
1505
|
import { TitleComponent as TitleComponent9 } from "echarts/components";
|
|
1461
1506
|
import { CanvasRenderer as CanvasRenderer9 } from "echarts/renderers";
|
|
1507
|
+
import { getChartColors as getChartColors4, THEME_DARK as THEME_DARK5 } from "@classic-homes/charts-core";
|
|
1462
1508
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1463
1509
|
echarts11.use([EChartsGaugeChart, TitleComponent9, CanvasRenderer9]);
|
|
1464
1510
|
var GaugeChart = React13.forwardRef(
|
|
@@ -1480,6 +1526,9 @@ var GaugeChart = React13.forwardRef(
|
|
|
1480
1526
|
class: className,
|
|
1481
1527
|
...props
|
|
1482
1528
|
}, ref) => {
|
|
1529
|
+
const currentTheme = useChartTheme(theme);
|
|
1530
|
+
const chartColors = getChartColors4(currentTheme);
|
|
1531
|
+
const reducedMotion = useReducedMotion();
|
|
1483
1532
|
const option = React13.useMemo(() => {
|
|
1484
1533
|
return {
|
|
1485
1534
|
series: [
|
|
@@ -1504,7 +1553,7 @@ var GaugeChart = React13.forwardRef(
|
|
|
1504
1553
|
splitNumber: 5,
|
|
1505
1554
|
lineStyle: {
|
|
1506
1555
|
width: 2,
|
|
1507
|
-
color:
|
|
1556
|
+
color: chartColors.mutedForeground
|
|
1508
1557
|
}
|
|
1509
1558
|
},
|
|
1510
1559
|
splitLine: {
|
|
@@ -1512,12 +1561,12 @@ var GaugeChart = React13.forwardRef(
|
|
|
1512
1561
|
length: 10,
|
|
1513
1562
|
lineStyle: {
|
|
1514
1563
|
width: 3,
|
|
1515
|
-
color:
|
|
1564
|
+
color: chartColors.mutedForeground
|
|
1516
1565
|
}
|
|
1517
1566
|
},
|
|
1518
1567
|
axisLabel: {
|
|
1519
1568
|
distance: -20,
|
|
1520
|
-
color:
|
|
1569
|
+
color: chartColors.mutedForeground,
|
|
1521
1570
|
fontSize: 12
|
|
1522
1571
|
},
|
|
1523
1572
|
anchor: {
|
|
@@ -1537,7 +1586,7 @@ var GaugeChart = React13.forwardRef(
|
|
|
1537
1586
|
fontSize: 14
|
|
1538
1587
|
},
|
|
1539
1588
|
detail: {
|
|
1540
|
-
valueAnimation: animation,
|
|
1589
|
+
valueAnimation: animation && !reducedMotion,
|
|
1541
1590
|
fontSize: 28,
|
|
1542
1591
|
fontWeight: "bold",
|
|
1543
1592
|
offsetCenter: [0, "40%"],
|
|
@@ -1552,10 +1601,21 @@ var GaugeChart = React13.forwardRef(
|
|
|
1552
1601
|
}
|
|
1553
1602
|
]
|
|
1554
1603
|
};
|
|
1555
|
-
}, [
|
|
1604
|
+
}, [
|
|
1605
|
+
value,
|
|
1606
|
+
min,
|
|
1607
|
+
max,
|
|
1608
|
+
splitNumber,
|
|
1609
|
+
showProgress,
|
|
1610
|
+
formatValue,
|
|
1611
|
+
title,
|
|
1612
|
+
animation,
|
|
1613
|
+
reducedMotion,
|
|
1614
|
+
chartColors
|
|
1615
|
+
]);
|
|
1556
1616
|
const { containerRef } = useChart({
|
|
1557
1617
|
option,
|
|
1558
|
-
theme,
|
|
1618
|
+
theme: currentTheme === THEME_DARK5 ? "dark" : "light",
|
|
1559
1619
|
animation
|
|
1560
1620
|
});
|
|
1561
1621
|
const accessibilityDescription = description || `${title}. Gauge showing value ${value} on scale from ${min} to ${max}.`;
|
|
@@ -1589,6 +1649,7 @@ import {
|
|
|
1589
1649
|
VisualMapComponent
|
|
1590
1650
|
} from "echarts/components";
|
|
1591
1651
|
import { CanvasRenderer as CanvasRenderer10 } from "echarts/renderers";
|
|
1652
|
+
import { escapeHtml as escapeHtml2 } from "@classic-homes/charts-core";
|
|
1592
1653
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1593
1654
|
echarts12.use([
|
|
1594
1655
|
EChartsHeatmapChart,
|
|
@@ -1618,9 +1679,14 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1618
1679
|
...props
|
|
1619
1680
|
}, ref) => {
|
|
1620
1681
|
const isEmpty = !data?.data?.length || !xAxis?.length || !yAxis?.length;
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
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;
|
|
1624
1690
|
const option = React14.useMemo(() => {
|
|
1625
1691
|
if (isEmpty) return {};
|
|
1626
1692
|
return {
|
|
@@ -1630,7 +1696,7 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1630
1696
|
const p = params;
|
|
1631
1697
|
if (!p.value) return "";
|
|
1632
1698
|
const [xIdx, yIdx, value] = p.value;
|
|
1633
|
-
return `${xAxis[xIdx]} / ${yAxis[yIdx]}: ${value}`;
|
|
1699
|
+
return `${escapeHtml2(xAxis[xIdx])} / ${escapeHtml2(yAxis[yIdx])}: ${escapeHtml2(value)}`;
|
|
1634
1700
|
}
|
|
1635
1701
|
} : void 0,
|
|
1636
1702
|
grid: {
|
|
@@ -1679,25 +1745,26 @@ var HeatmapChart = React14.forwardRef(
|
|
|
1679
1745
|
]
|
|
1680
1746
|
};
|
|
1681
1747
|
}, [data, xAxis, yAxis, isEmpty, showTooltip, showValues, minValue, maxValue, title]);
|
|
1748
|
+
const latest = useLatestRef({ onClick, xAxis, yAxis });
|
|
1682
1749
|
const { containerRef } = useChart({
|
|
1683
1750
|
option,
|
|
1684
1751
|
theme,
|
|
1685
1752
|
animation,
|
|
1686
1753
|
onReady: (chart) => {
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
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
|
|
1699
1766
|
});
|
|
1700
|
-
}
|
|
1767
|
+
});
|
|
1701
1768
|
}
|
|
1702
1769
|
});
|
|
1703
1770
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Heatmap with ${xAxis.length} columns and ${yAxis.length} rows.` : void 0);
|
|
@@ -1727,6 +1794,7 @@ import * as echarts13 from "echarts/core";
|
|
|
1727
1794
|
import { TreemapChart as EChartsTreemapChart } from "echarts/charts";
|
|
1728
1795
|
import { TooltipComponent as TooltipComponent10, TitleComponent as TitleComponent11 } from "echarts/components";
|
|
1729
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";
|
|
1730
1798
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1731
1799
|
echarts13.use([EChartsTreemapChart, TooltipComponent10, TitleComponent11, CanvasRenderer11]);
|
|
1732
1800
|
var TreemapChart = React15.forwardRef(
|
|
@@ -1747,13 +1815,15 @@ var TreemapChart = React15.forwardRef(
|
|
|
1747
1815
|
...props
|
|
1748
1816
|
}, ref) => {
|
|
1749
1817
|
const isEmpty = !data?.length;
|
|
1818
|
+
const currentTheme = useChartTheme(theme);
|
|
1819
|
+
const chartColors = getChartColors5(currentTheme);
|
|
1750
1820
|
const option = React15.useMemo(() => {
|
|
1751
1821
|
if (isEmpty) return {};
|
|
1752
1822
|
return {
|
|
1753
1823
|
tooltip: showTooltip ? {
|
|
1754
1824
|
formatter: (params) => {
|
|
1755
1825
|
const p = params;
|
|
1756
|
-
return `${p.name}: ${p.value}`;
|
|
1826
|
+
return `${escapeHtml3(p.name)}: ${escapeHtml3(p.value)}`;
|
|
1757
1827
|
}
|
|
1758
1828
|
} : void 0,
|
|
1759
1829
|
series: [
|
|
@@ -1764,7 +1834,7 @@ var TreemapChart = React15.forwardRef(
|
|
|
1764
1834
|
levels: levels || [
|
|
1765
1835
|
{
|
|
1766
1836
|
itemStyle: {
|
|
1767
|
-
borderColor:
|
|
1837
|
+
borderColor: chartColors.divider,
|
|
1768
1838
|
borderWidth: 4,
|
|
1769
1839
|
gapWidth: 4
|
|
1770
1840
|
}
|
|
@@ -1802,25 +1872,26 @@ var TreemapChart = React15.forwardRef(
|
|
|
1802
1872
|
}
|
|
1803
1873
|
]
|
|
1804
1874
|
};
|
|
1805
|
-
}, [data, levels, isEmpty, showTooltip]);
|
|
1875
|
+
}, [data, levels, isEmpty, showTooltip, chartColors]);
|
|
1876
|
+
const latest = useLatestRef({ onClick });
|
|
1806
1877
|
const { containerRef } = useChart({
|
|
1807
1878
|
option,
|
|
1808
|
-
theme,
|
|
1879
|
+
theme: currentTheme === THEME_DARK6 ? "dark" : "light",
|
|
1809
1880
|
animation,
|
|
1810
1881
|
onReady: (chart) => {
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
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
|
|
1822
1893
|
});
|
|
1823
|
-
}
|
|
1894
|
+
});
|
|
1824
1895
|
}
|
|
1825
1896
|
});
|
|
1826
1897
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Treemap chart showing hierarchical data.` : void 0);
|
|
@@ -1858,6 +1929,7 @@ import {
|
|
|
1858
1929
|
DataZoomComponent
|
|
1859
1930
|
} from "echarts/components";
|
|
1860
1931
|
import { CanvasRenderer as CanvasRenderer12 } from "echarts/renderers";
|
|
1932
|
+
import { getChartColors as getChartColors6, THEME_DARK as THEME_DARK7 } from "@classic-homes/charts-core";
|
|
1861
1933
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1862
1934
|
echarts14.use([
|
|
1863
1935
|
EChartsCandlestickChart,
|
|
@@ -1886,6 +1958,8 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1886
1958
|
...props
|
|
1887
1959
|
}, ref) => {
|
|
1888
1960
|
const isEmpty = !data?.dates?.length || !data?.data?.length;
|
|
1961
|
+
const currentTheme = useChartTheme(theme);
|
|
1962
|
+
const chartColors = getChartColors6(currentTheme);
|
|
1889
1963
|
const option = React16.useMemo(() => {
|
|
1890
1964
|
if (isEmpty) return {};
|
|
1891
1965
|
const candlestickData = data.data.map((item) => [item.open, item.close, item.low, item.high]);
|
|
@@ -1895,12 +1969,12 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1895
1969
|
type: "candlestick",
|
|
1896
1970
|
data: candlestickData,
|
|
1897
1971
|
itemStyle: {
|
|
1898
|
-
color:
|
|
1972
|
+
color: chartColors.destructive,
|
|
1899
1973
|
// Up color (red for bearish in some markets)
|
|
1900
|
-
color0:
|
|
1974
|
+
color0: chartColors.success,
|
|
1901
1975
|
// Down color (green for bullish)
|
|
1902
|
-
borderColor:
|
|
1903
|
-
borderColor0:
|
|
1976
|
+
borderColor: chartColors.destructive,
|
|
1977
|
+
borderColor0: chartColors.success
|
|
1904
1978
|
}
|
|
1905
1979
|
}
|
|
1906
1980
|
];
|
|
@@ -1966,7 +2040,7 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1966
2040
|
yAxisIndex: 1,
|
|
1967
2041
|
data: data.volume,
|
|
1968
2042
|
itemStyle: {
|
|
1969
|
-
color:
|
|
2043
|
+
color: chartColors.mutedForeground
|
|
1970
2044
|
}
|
|
1971
2045
|
});
|
|
1972
2046
|
}
|
|
@@ -1996,28 +2070,30 @@ var CandlestickChart = React16.forwardRef(
|
|
|
1996
2070
|
],
|
|
1997
2071
|
series: seriesArr
|
|
1998
2072
|
};
|
|
1999
|
-
}, [data, isEmpty, showTooltip, showVolume, title]);
|
|
2073
|
+
}, [data, isEmpty, showTooltip, showVolume, title, chartColors]);
|
|
2074
|
+
const latest = useLatestRef({ onClick, data });
|
|
2000
2075
|
const { containerRef } = useChart({
|
|
2001
2076
|
option,
|
|
2002
|
-
theme,
|
|
2077
|
+
theme: currentTheme === THEME_DARK7 ? "dark" : "light",
|
|
2003
2078
|
animation,
|
|
2004
2079
|
onReady: (chart) => {
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
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]
|
|
2019
2095
|
});
|
|
2020
|
-
}
|
|
2096
|
+
});
|
|
2021
2097
|
}
|
|
2022
2098
|
});
|
|
2023
2099
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Candlestick chart with ${data.dates.length} data points.` : void 0);
|
|
@@ -2101,25 +2177,26 @@ var SankeyChart = React17.forwardRef(
|
|
|
2101
2177
|
]
|
|
2102
2178
|
};
|
|
2103
2179
|
}, [data, isEmpty, showTooltip, orient]);
|
|
2180
|
+
const latest = useLatestRef({ onClick });
|
|
2104
2181
|
const { containerRef } = useChart({
|
|
2105
2182
|
option,
|
|
2106
2183
|
theme,
|
|
2107
2184
|
animation,
|
|
2108
2185
|
onReady: (chart) => {
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
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
|
|
2121
2198
|
});
|
|
2122
|
-
}
|
|
2199
|
+
});
|
|
2123
2200
|
}
|
|
2124
2201
|
});
|
|
2125
2202
|
const accessibilityDescription = description || (!isEmpty ? `${title}. Sankey diagram with ${data.nodes.length} nodes and ${data.links.length} links.` : void 0);
|