react-premium-charts 0.1.6

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 ADDED
@@ -0,0 +1,2087 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var reactDom = require('react-dom');
6
+ var d3Shape = require('d3-shape');
7
+ var d3Scale = require('d3-scale');
8
+ var d3Array = require('d3-array');
9
+
10
+ // src/theme/ThemeProvider.tsx
11
+ var Ctx = react.createContext({
12
+ mode: "light",
13
+ palette: "default",
14
+ isGradientEnabled: true
15
+ });
16
+ function ThemeProvider({
17
+ mode = "light",
18
+ palette = "default",
19
+ isGradientEnabled = true,
20
+ children
21
+ }) {
22
+ const value = react.useMemo(() => ({ mode, palette, isGradientEnabled }), [mode, palette, isGradientEnabled]);
23
+ return /* @__PURE__ */ jsxRuntime.jsx(Ctx.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "msc-root", "data-msc-theme": mode, "data-msc-palette": palette, children }) });
24
+ }
25
+ function useTheme() {
26
+ return react.useContext(Ctx);
27
+ }
28
+ var ChartCtx = react.createContext(null);
29
+ function useChart() {
30
+ const v = react.useContext(ChartCtx);
31
+ if (!v) throw new Error("useChart must be used inside <Chart>");
32
+ return v;
33
+ }
34
+ function Chart({
35
+ width,
36
+ height,
37
+ margin = { top: 16, right: 16, bottom: 28, left: 40 },
38
+ defs,
39
+ children,
40
+ className,
41
+ style
42
+ }) {
43
+ const svgRef = react.useRef(null);
44
+ const [pointer, setPointer] = react.useState(null);
45
+ const clearTooltipFns = react.useRef(/* @__PURE__ */ new Set());
46
+ const registerClearTooltip = react.useCallback((fn) => {
47
+ clearTooltipFns.current.add(fn);
48
+ return () => {
49
+ clearTooltipFns.current.delete(fn);
50
+ };
51
+ }, []);
52
+ const handleChartLeave = react.useCallback(() => {
53
+ setPointer(null);
54
+ clearTooltipFns.current.forEach((fn) => fn());
55
+ }, []);
56
+ const clearAllTooltips = react.useCallback(() => {
57
+ clearTooltipFns.current.forEach((fn) => fn());
58
+ }, []);
59
+ const innerWidth = Math.max(0, width - margin.left - margin.right);
60
+ const innerHeight = Math.max(0, height - margin.top - margin.bottom);
61
+ const value = react.useMemo(
62
+ () => ({
63
+ size: { width, height },
64
+ margin,
65
+ innerWidth,
66
+ innerHeight,
67
+ svgRef,
68
+ pointer,
69
+ setPointer,
70
+ registerClearTooltip,
71
+ clearAllTooltips
72
+ }),
73
+ [width, height, margin, innerWidth, innerHeight, pointer, registerClearTooltip, clearAllTooltips]
74
+ );
75
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartCtx.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(
76
+ "svg",
77
+ {
78
+ ref: svgRef,
79
+ width,
80
+ height,
81
+ viewBox: `0 0 ${width} ${height}`,
82
+ overflow: "visible",
83
+ className,
84
+ style: { background: "var(--msc-panel)", borderRadius: "var(--msc-radius)", ...style },
85
+ onMouseLeave: handleChartLeave,
86
+ onMouseMove: (e) => {
87
+ const svg = svgRef.current;
88
+ if (!svg) return;
89
+ const pt = svg.createSVGPoint();
90
+ pt.x = e.clientX;
91
+ pt.y = e.clientY;
92
+ const screenCTM = svg.getScreenCTM();
93
+ if (!screenCTM) return;
94
+ const local = pt.matrixTransform(screenCTM.inverse());
95
+ setPointer({ x: local.x, y: local.y });
96
+ },
97
+ children: /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${margin.left},${margin.top})`, children: [
98
+ defs,
99
+ children
100
+ ] })
101
+ }
102
+ ) });
103
+ }
104
+ function AxisBottom({
105
+ ticks,
106
+ y = void 0
107
+ }) {
108
+ const { innerHeight } = useChart();
109
+ const yy = y ?? innerHeight;
110
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
111
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: 0, x2: Math.max(...ticks.map((t) => t.x), 0), y1: yy, y2: yy, stroke: "var(--msc-border)" }),
112
+ ticks.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${t.x},${yy})`, children: [
113
+ /* @__PURE__ */ jsxRuntime.jsx("line", { y2: 6, stroke: "var(--msc-border)" }),
114
+ /* @__PURE__ */ jsxRuntime.jsx(
115
+ "text",
116
+ {
117
+ y: 18,
118
+ textAnchor: "middle",
119
+ fontSize: 12,
120
+ fill: "var(--msc-muted)",
121
+ children: t.value
122
+ }
123
+ )
124
+ ] }, t.value))
125
+ ] });
126
+ }
127
+ function AxisLeft({
128
+ ticks
129
+ }) {
130
+ const x = 0;
131
+ const maxY = Math.max(...ticks.map((t) => t.y), 0);
132
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
133
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: x, x2: x, y1: 0, y2: maxY, stroke: "var(--msc-border)" }),
134
+ ticks.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x},${t.y})`, children: [
135
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x2: -6, stroke: "var(--msc-border)" }),
136
+ /* @__PURE__ */ jsxRuntime.jsx(
137
+ "text",
138
+ {
139
+ x: -10,
140
+ dy: "0.32em",
141
+ textAnchor: "end",
142
+ fontSize: 12,
143
+ fill: "var(--msc-muted)",
144
+ children: t.value
145
+ }
146
+ )
147
+ ] }, t.value))
148
+ ] });
149
+ }
150
+ function AxisRight({
151
+ ticks,
152
+ x
153
+ }) {
154
+ const maxY = Math.max(...ticks.map((t) => t.y), 0);
155
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
156
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: x, x2: x, y1: 0, y2: maxY, stroke: "var(--msc-border)" }),
157
+ ticks.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x},${t.y})`, children: [
158
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x2: 6, stroke: "var(--msc-border)" }),
159
+ /* @__PURE__ */ jsxRuntime.jsx(
160
+ "text",
161
+ {
162
+ x: 10,
163
+ dy: "0.32em",
164
+ textAnchor: "start",
165
+ fontSize: 12,
166
+ fill: "var(--msc-muted)",
167
+ children: t.value
168
+ }
169
+ )
170
+ ] }, t.value))
171
+ ] });
172
+ }
173
+ function Grid({
174
+ xTicks,
175
+ yTicks
176
+ }) {
177
+ const { innerWidth, innerHeight } = useChart();
178
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { "aria-hidden": "true", children: [
179
+ xTicks.map((x) => /* @__PURE__ */ jsxRuntime.jsx(
180
+ "line",
181
+ {
182
+ x1: x,
183
+ x2: x,
184
+ y1: 0,
185
+ y2: innerHeight,
186
+ stroke: "var(--msc-grid)",
187
+ strokeDasharray: "3 6"
188
+ },
189
+ `x-${x}`
190
+ )),
191
+ yTicks.map((y) => /* @__PURE__ */ jsxRuntime.jsx(
192
+ "line",
193
+ {
194
+ x1: 0,
195
+ x2: innerWidth,
196
+ y1: y,
197
+ y2: y,
198
+ stroke: "var(--msc-grid)",
199
+ strokeDasharray: "3 6"
200
+ },
201
+ `y-${y}`
202
+ ))
203
+ ] });
204
+ }
205
+ function ThresholdLine({
206
+ value,
207
+ yScale,
208
+ stroke = "var(--msc-s4)",
209
+ strokeWidth = 1.5,
210
+ strokeDasharray = "6 4",
211
+ label
212
+ }) {
213
+ const { innerWidth } = useChart();
214
+ const y = yScale(value);
215
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
216
+ /* @__PURE__ */ jsxRuntime.jsx(
217
+ "line",
218
+ {
219
+ x1: 0,
220
+ x2: innerWidth,
221
+ y1: y,
222
+ y2: y,
223
+ stroke,
224
+ strokeWidth,
225
+ strokeDasharray
226
+ }
227
+ ),
228
+ label && /* @__PURE__ */ jsxRuntime.jsx(
229
+ "text",
230
+ {
231
+ x: innerWidth - 4,
232
+ y: y - 6,
233
+ textAnchor: "end",
234
+ fontSize: 11,
235
+ fill: "var(--msc-muted)",
236
+ children: label
237
+ }
238
+ )
239
+ ] });
240
+ }
241
+ function LinearGradient({
242
+ id,
243
+ x1 = "0%",
244
+ y1 = "0%",
245
+ x2 = "0%",
246
+ y2 = "100%",
247
+ stops
248
+ }) {
249
+ return /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("linearGradient", { id, x1, y1, x2, y2, children: stops.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
250
+ "stop",
251
+ {
252
+ offset: s.offset,
253
+ stopColor: s.color,
254
+ stopOpacity: s.opacity ?? 1
255
+ },
256
+ i
257
+ )) }) });
258
+ }
259
+ function RadialGradient({
260
+ id,
261
+ cx = "50%",
262
+ cy = "50%",
263
+ r = "50%",
264
+ fx,
265
+ fy,
266
+ stops
267
+ }) {
268
+ return /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("radialGradient", { id, cx, cy, r, fx, fy, children: stops.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
269
+ "stop",
270
+ {
271
+ offset: s.offset,
272
+ stopColor: s.color,
273
+ stopOpacity: s.opacity ?? 1
274
+ },
275
+ i
276
+ )) }) });
277
+ }
278
+ function ChartTitle({
279
+ title,
280
+ x = 0,
281
+ y = -8
282
+ }) {
283
+ return /* @__PURE__ */ jsxRuntime.jsx(
284
+ "text",
285
+ {
286
+ x,
287
+ y,
288
+ fontSize: 14,
289
+ fontWeight: 600,
290
+ fill: "var(--msc-muted)",
291
+ children: title
292
+ }
293
+ );
294
+ }
295
+ function Legend({
296
+ items,
297
+ direction = "row"
298
+ }) {
299
+ return /* @__PURE__ */ jsxRuntime.jsx(
300
+ "div",
301
+ {
302
+ className: "msc-legend",
303
+ style: {
304
+ display: "flex",
305
+ flexWrap: "wrap",
306
+ gap: 12,
307
+ flexDirection: direction,
308
+ alignItems: "center",
309
+ justifyContent: "center",
310
+ marginTop: 12
311
+ },
312
+ children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(
313
+ "div",
314
+ {
315
+ style: {
316
+ display: "flex",
317
+ alignItems: "center",
318
+ gap: 6,
319
+ fontSize: 12,
320
+ color: "var(--msc-muted)"
321
+ },
322
+ children: [
323
+ /* @__PURE__ */ jsxRuntime.jsx(
324
+ "span",
325
+ {
326
+ className: "msc-dot",
327
+ style: {
328
+ background: item.color,
329
+ width: 8,
330
+ height: 8,
331
+ marginRight: 0
332
+ }
333
+ }
334
+ ),
335
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
336
+ item.label,
337
+ item.value != null && `: ${item.value}`
338
+ ] })
339
+ ]
340
+ },
341
+ `${item.label}-${i}`
342
+ ))
343
+ }
344
+ );
345
+ }
346
+ var TOOLTIP_WIDTH = 200;
347
+ var TOOLTIP_HEIGHT = 120;
348
+ var OFFSET = 12;
349
+ var PADDING = 8;
350
+ var TOOLTIP_Z_INDEX = 1e4;
351
+ function computeTooltipPosition(anchorX, anchorY, containerWidth, containerHeight, tooltipWidth = TOOLTIP_WIDTH, tooltipHeight = TOOLTIP_HEIGHT) {
352
+ let x = anchorX + OFFSET;
353
+ let y = anchorY - tooltipHeight - OFFSET;
354
+ if (x + tooltipWidth > containerWidth - PADDING) {
355
+ x = anchorX - tooltipWidth - OFFSET;
356
+ }
357
+ if (x < PADDING) {
358
+ x = PADDING;
359
+ }
360
+ if (y < PADDING) {
361
+ y = anchorY + OFFSET;
362
+ }
363
+ if (y + tooltipHeight > containerHeight - PADDING) {
364
+ y = containerHeight - tooltipHeight - PADDING;
365
+ }
366
+ return { x: Math.max(PADDING, x), y: Math.max(PADDING, y) };
367
+ }
368
+ function useScreenPosition(innerX, innerY, svgRef, margin) {
369
+ const [pos, setPos] = react.useState(null);
370
+ react.useEffect(() => {
371
+ const svg = svgRef?.current;
372
+ if (!svg || !margin) return;
373
+ const pt = svg.createSVGPoint();
374
+ pt.x = innerX + margin.left;
375
+ pt.y = innerY + margin.top;
376
+ const ctm = svg.getScreenCTM();
377
+ if (!ctm) return;
378
+ const screen = pt.matrixTransform(ctm);
379
+ setPos({ x: screen.x, y: screen.y });
380
+ }, [innerX, innerY, svgRef, margin]);
381
+ return pos;
382
+ }
383
+ function TooltipPortal({
384
+ x,
385
+ y,
386
+ anchorX,
387
+ anchorY,
388
+ containerWidth,
389
+ containerHeight,
390
+ svgRef,
391
+ margin,
392
+ children
393
+ }) {
394
+ const innerPosition = anchorX != null && anchorY != null && containerWidth != null && containerHeight != null ? computeTooltipPosition(anchorX, anchorY, containerWidth, containerHeight) : { x: x ?? 0, y: y ?? 0 };
395
+ const screenPos = useScreenPosition(
396
+ innerPosition.x,
397
+ innerPosition.y,
398
+ svgRef,
399
+ margin ?? void 0
400
+ );
401
+ const usePortal = svgRef != null && margin != null && screenPos != null;
402
+ if (usePortal && screenPos) {
403
+ return reactDom.createPortal(
404
+ /* @__PURE__ */ jsxRuntime.jsx(
405
+ "div",
406
+ {
407
+ style: {
408
+ position: "fixed",
409
+ left: screenPos.x,
410
+ top: screenPos.y,
411
+ zIndex: TOOLTIP_Z_INDEX,
412
+ pointerEvents: "none",
413
+ width: "max-content",
414
+ maxWidth: TOOLTIP_WIDTH,
415
+ minWidth: 140
416
+ },
417
+ children
418
+ }
419
+ ),
420
+ document.body
421
+ );
422
+ }
423
+ return /* @__PURE__ */ jsxRuntime.jsx(
424
+ "foreignObject",
425
+ {
426
+ x: innerPosition.x,
427
+ y: innerPosition.y,
428
+ width: TOOLTIP_WIDTH + 40,
429
+ height: TOOLTIP_HEIGHT + 40,
430
+ style: { overflow: "visible", pointerEvents: "none" },
431
+ children: /* @__PURE__ */ jsxRuntime.jsx(
432
+ "div",
433
+ {
434
+ style: {
435
+ width: "max-content",
436
+ maxWidth: TOOLTIP_WIDTH,
437
+ minWidth: 140,
438
+ pointerEvents: "none"
439
+ },
440
+ children
441
+ }
442
+ )
443
+ }
444
+ );
445
+ }
446
+ function DefaultTooltip({
447
+ title,
448
+ rows
449
+ }) {
450
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "msc-tooltip", children: [
451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "msc-tooltip-title", children: title }),
452
+ rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "msc-tooltip-row", children: [
453
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "msc-dot", style: { background: r.color } }),
455
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: r.label })
456
+ ] }),
457
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 650 }, children: r.value })
458
+ ] }, r.label))
459
+ ] });
460
+ }
461
+ var HOVER_HIT_RADIUS = 12;
462
+ var HOVER_LEAVE_DELAY = 150;
463
+ function LineSeries({
464
+ data,
465
+ x,
466
+ y,
467
+ xScale,
468
+ yScale,
469
+ stroke = "var(--msc-s1)",
470
+ strokeWidth = 2.5,
471
+ curve = "monotone",
472
+ showMarkers = false,
473
+ animate = true,
474
+ duration = 800,
475
+ hoverDimOpacity = 0.5,
476
+ tooltip
477
+ }) {
478
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
479
+ const leaveTimeoutRef = react.useRef(null);
480
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
481
+ const clearTooltip = () => {
482
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
483
+ leaveTimeoutRef.current = null;
484
+ setHoveredIndex(null);
485
+ };
486
+ react.useEffect(() => {
487
+ return registerClearTooltip(clearTooltip);
488
+ }, [registerClearTooltip]);
489
+ const handleEnter = (i) => {
490
+ if (leaveTimeoutRef.current) {
491
+ clearTimeout(leaveTimeoutRef.current);
492
+ leaveTimeoutRef.current = null;
493
+ }
494
+ clearAllTooltips();
495
+ setHoveredIndex(i);
496
+ };
497
+ const handleLeave = () => {
498
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY);
499
+ };
500
+ const { pathD, points } = react.useMemo(() => {
501
+ const gen = d3Shape.line().x((dd, i) => xScale(x(dd, i))).y((dd, i) => yScale(y(dd, i))).defined((dd, i) => Number.isFinite(x(dd, i)) && Number.isFinite(y(dd, i))).curve(curve === "monotone" ? d3Shape.curveMonotoneX : d3Shape.curveLinear);
502
+ const pathD2 = gen(data) ?? "";
503
+ const points2 = data.map((d, i) => ({
504
+ x: xScale(x(d, i)),
505
+ y: yScale(y(d, i)),
506
+ datum: d,
507
+ index: i
508
+ }));
509
+ return { pathD: pathD2, points: points2 };
510
+ }, [data, x, y, xScale, yScale, curve]);
511
+ const lineOpacity = hoveredIndex === null ? 1 : hoverDimOpacity;
512
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
513
+ /* @__PURE__ */ jsxRuntime.jsx(
514
+ "path",
515
+ {
516
+ d: pathD,
517
+ fill: "none",
518
+ stroke,
519
+ strokeWidth,
520
+ opacity: lineOpacity,
521
+ pathLength: animate ? 1 : void 0,
522
+ strokeDasharray: animate ? "1 1" : void 0,
523
+ strokeDashoffset: animate ? 1 : void 0,
524
+ style: {
525
+ ...animate ? { animation: `msc-line-draw ${duration}ms ease-out forwards` } : {},
526
+ transition: "opacity 0.2s ease"
527
+ }
528
+ }
529
+ ),
530
+ points.map((pt, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
531
+ /* @__PURE__ */ jsxRuntime.jsx(
532
+ "circle",
533
+ {
534
+ cx: pt.x,
535
+ cy: pt.y,
536
+ r: HOVER_HIT_RADIUS,
537
+ fill: "transparent",
538
+ style: { cursor: "pointer" },
539
+ onMouseEnter: () => handleEnter(i),
540
+ onMouseLeave: handleLeave
541
+ }
542
+ ),
543
+ (showMarkers || hoveredIndex === i) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
544
+ /* @__PURE__ */ jsxRuntime.jsx(
545
+ "circle",
546
+ {
547
+ cx: pt.x,
548
+ cy: pt.y,
549
+ r: showMarkers ? 4 : 6,
550
+ fill: showMarkers ? stroke : "var(--msc-panel)",
551
+ stroke: showMarkers ? "var(--msc-panel)" : stroke,
552
+ strokeWidth: showMarkers ? 2 : 2.5,
553
+ style: {
554
+ transition: "opacity 0.15s ease",
555
+ transformOrigin: "center",
556
+ ...animate ? {
557
+ animation: `msc-marker-pop 400ms ease-out ${Math.min(300 + i * 80, duration - 100)}ms both`
558
+ } : {}
559
+ }
560
+ }
561
+ ),
562
+ tooltip && hoveredIndex === i && /* @__PURE__ */ jsxRuntime.jsx(
563
+ TooltipPortal,
564
+ {
565
+ anchorX: pt.x,
566
+ anchorY: pt.y,
567
+ containerWidth: innerWidth,
568
+ containerHeight: innerHeight,
569
+ svgRef,
570
+ margin,
571
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(pt.datum, i) })
572
+ }
573
+ )
574
+ ] })
575
+ ] }, i))
576
+ ] });
577
+ }
578
+ function AreaSeries({
579
+ data,
580
+ x,
581
+ y,
582
+ y0 = 0,
583
+ xScale,
584
+ yScale,
585
+ fill = "var(--msc-s1)",
586
+ fillOpacity = 0.18,
587
+ curve = "monotone",
588
+ animate = true,
589
+ duration = 600
590
+ }) {
591
+ const d = react.useMemo(() => {
592
+ const gen = d3Shape.area().x((dd, i) => xScale(x(dd, i))).y1((dd, i) => yScale(y(dd, i))).y0(() => yScale(y0)).defined((dd, i) => Number.isFinite(x(dd, i)) && Number.isFinite(y(dd, i))).curve(curve === "monotone" ? d3Shape.curveMonotoneX : d3Shape.curveLinear);
593
+ return gen(data) ?? "";
594
+ }, [data, x, y, y0, xScale, yScale, curve]);
595
+ return /* @__PURE__ */ jsxRuntime.jsx(
596
+ "path",
597
+ {
598
+ d,
599
+ fill,
600
+ fillOpacity,
601
+ stroke: "none",
602
+ className: animate ? "msc-area-animate" : void 0,
603
+ style: animate ? {
604
+ animation: `msc-area-reveal ${duration}ms ease-out forwards`
605
+ } : void 0
606
+ }
607
+ );
608
+ }
609
+ var HOVER_LEAVE_DELAY2 = 150;
610
+ function BarSeries({
611
+ data,
612
+ x,
613
+ y,
614
+ xScale,
615
+ yScale,
616
+ fill = "var(--msc-s1)",
617
+ radius = 10,
618
+ animate = true,
619
+ duration = 500,
620
+ hoverDimOpacity = 0.4,
621
+ tooltip
622
+ }) {
623
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
624
+ const leaveTimeoutRef = react.useRef(null);
625
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
626
+ const barW = xScale.bandwidth();
627
+ const clearTooltip = () => {
628
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
629
+ leaveTimeoutRef.current = null;
630
+ setHoveredIndex(null);
631
+ };
632
+ react.useEffect(() => {
633
+ return registerClearTooltip(clearTooltip);
634
+ }, [registerClearTooltip]);
635
+ const handleEnter = (i) => {
636
+ if (leaveTimeoutRef.current) {
637
+ clearTimeout(leaveTimeoutRef.current);
638
+ leaveTimeoutRef.current = null;
639
+ }
640
+ clearAllTooltips();
641
+ setHoveredIndex(i);
642
+ };
643
+ const handleLeave = () => {
644
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY2);
645
+ };
646
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: data.map((d, i) => {
647
+ const xx = xScale(x(d, i));
648
+ if (xx == null) return null;
649
+ const yVal = y(d, i);
650
+ const yy = yScale(yVal);
651
+ const zeroY = yScale(0);
652
+ const h = zeroY - yy;
653
+ const isHovered = hoveredIndex === i;
654
+ const opacity = hoveredIndex === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
655
+ const anchorX = xx + barW / 2;
656
+ const anchorY = yy;
657
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
658
+ /* @__PURE__ */ jsxRuntime.jsx(
659
+ "rect",
660
+ {
661
+ x: xx,
662
+ y: h >= 0 ? yy : zeroY,
663
+ width: barW,
664
+ height: Math.abs(h),
665
+ rx: radius,
666
+ ry: radius,
667
+ fill,
668
+ opacity,
669
+ className: `msc-bar-hoverable ${animate ? "msc-bar-animate" : ""}`.trim(),
670
+ style: {
671
+ ...animate ? { animation: `msc-bar-grow ${duration}ms ease-out ${i * 60}ms both` } : {},
672
+ transition: "opacity 0.2s ease",
673
+ cursor: tooltip ? "pointer" : void 0
674
+ },
675
+ onMouseEnter: () => handleEnter(i),
676
+ onMouseLeave: handleLeave
677
+ }
678
+ ),
679
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
680
+ TooltipPortal,
681
+ {
682
+ anchorX,
683
+ anchorY,
684
+ containerWidth: innerWidth,
685
+ containerHeight: innerHeight,
686
+ svgRef,
687
+ margin,
688
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(d, i) })
689
+ }
690
+ )
691
+ ] }, i);
692
+ }) });
693
+ }
694
+ var HOVER_LEAVE_DELAY3 = 150;
695
+ function HorizontalBarSeries({
696
+ data,
697
+ y,
698
+ x,
699
+ yScale,
700
+ xScale,
701
+ fill = "var(--msc-s1)",
702
+ radius = 6,
703
+ animate = true,
704
+ duration = 500,
705
+ hoverDimOpacity = 0.4,
706
+ tooltip
707
+ }) {
708
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
709
+ const leaveTimeoutRef = react.useRef(null);
710
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
711
+ const barH = yScale.bandwidth();
712
+ const clearTooltip = () => {
713
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
714
+ leaveTimeoutRef.current = null;
715
+ setHoveredIndex(null);
716
+ };
717
+ react.useEffect(() => {
718
+ return registerClearTooltip(clearTooltip);
719
+ }, [registerClearTooltip]);
720
+ const handleEnter = (i) => {
721
+ if (leaveTimeoutRef.current) {
722
+ clearTimeout(leaveTimeoutRef.current);
723
+ leaveTimeoutRef.current = null;
724
+ }
725
+ clearAllTooltips();
726
+ setHoveredIndex(i);
727
+ };
728
+ const handleLeave = () => {
729
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY3);
730
+ };
731
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: data.map((d, i) => {
732
+ const yy = yScale(y(d, i));
733
+ if (yy == null) return null;
734
+ const xVal = x(d, i);
735
+ const xx = xScale(xVal);
736
+ const zeroX = xScale(0);
737
+ const w = xx - zeroX;
738
+ const isHovered = hoveredIndex === i;
739
+ const opacity = hoveredIndex === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
740
+ const anchorX = w >= 0 ? zeroX + Math.abs(w) / 2 : zeroX - Math.abs(w) / 2;
741
+ const anchorY = yy + barH / 2;
742
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
743
+ /* @__PURE__ */ jsxRuntime.jsx(
744
+ "rect",
745
+ {
746
+ x: w >= 0 ? zeroX : xx,
747
+ y: yy,
748
+ width: Math.abs(w),
749
+ height: barH,
750
+ rx: radius,
751
+ ry: radius,
752
+ fill,
753
+ opacity,
754
+ className: `msc-bar-hoverable ${animate ? "msc-bar-animate msc-bar-horizontal" : ""}`.trim(),
755
+ style: {
756
+ ...animate ? { animation: `msc-bar-grow-horizontal ${duration}ms ease-out ${i * 60}ms both` } : {},
757
+ transition: "opacity 0.2s ease",
758
+ cursor: tooltip ? "pointer" : void 0
759
+ },
760
+ onMouseEnter: () => handleEnter(i),
761
+ onMouseLeave: handleLeave
762
+ }
763
+ ),
764
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
765
+ TooltipPortal,
766
+ {
767
+ anchorX,
768
+ anchorY,
769
+ containerWidth: innerWidth,
770
+ containerHeight: innerHeight,
771
+ svgRef,
772
+ margin,
773
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(d, i) })
774
+ }
775
+ )
776
+ ] }, i);
777
+ }) });
778
+ }
779
+ var HOVER_LEAVE_DELAY4 = 150;
780
+ function GroupedBarSeries({
781
+ data,
782
+ x,
783
+ xScale,
784
+ yScale,
785
+ groups,
786
+ radius = 6,
787
+ animate = true,
788
+ duration = 500,
789
+ hoverDimOpacity = 0.4
790
+ }) {
791
+ const [hovered, setHovered] = react.useState(null);
792
+ const leaveTimeoutRef = react.useRef(null);
793
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
794
+ const clearTooltip = () => {
795
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
796
+ leaveTimeoutRef.current = null;
797
+ setHovered(null);
798
+ };
799
+ react.useEffect(() => {
800
+ return registerClearTooltip(clearTooltip);
801
+ }, [registerClearTooltip]);
802
+ const handleEnter = (groupIdx, dataIdx) => {
803
+ if (leaveTimeoutRef.current) {
804
+ clearTimeout(leaveTimeoutRef.current);
805
+ leaveTimeoutRef.current = null;
806
+ }
807
+ clearAllTooltips();
808
+ setHovered({ groupIdx, dataIdx });
809
+ };
810
+ const handleLeave = () => {
811
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY4);
812
+ };
813
+ const groupCount = groups.length;
814
+ const categoryBand = xScale.bandwidth();
815
+ const barGap = 2;
816
+ const barWidth = (categoryBand - barGap * (groupCount - 1)) / groupCount;
817
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: groups.map(
818
+ (group, groupIdx) => data.map((d, i) => {
819
+ const xx = xScale(x(d, i));
820
+ if (xx == null) return null;
821
+ const xOffset = xx + groupIdx * (barWidth + barGap);
822
+ const yVal = group.y(d, i);
823
+ const yy = yScale(yVal);
824
+ const zeroY = yScale(0);
825
+ const h = zeroY - yy;
826
+ const rectY = h >= 0 ? yy : zeroY;
827
+ const isHovered = hovered?.groupIdx === groupIdx && hovered?.dataIdx === i;
828
+ const opacity = hovered === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
829
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
830
+ /* @__PURE__ */ jsxRuntime.jsx(
831
+ "rect",
832
+ {
833
+ x: xOffset,
834
+ y: rectY,
835
+ width: barWidth,
836
+ height: Math.abs(h),
837
+ rx: radius,
838
+ ry: radius,
839
+ fill: group.fill,
840
+ opacity,
841
+ className: `msc-bar-hoverable ${animate ? "msc-bar-animate" : ""}`.trim(),
842
+ style: {
843
+ ...animate ? { animation: `msc-bar-grow ${duration}ms ease-out ${(i * groupCount + groupIdx) * 40}ms both` } : {},
844
+ transition: "opacity 0.2s ease",
845
+ cursor: group.tooltip ? "pointer" : void 0
846
+ },
847
+ onMouseEnter: () => handleEnter(groupIdx, i),
848
+ onMouseLeave: handleLeave
849
+ }
850
+ ),
851
+ group.tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
852
+ TooltipPortal,
853
+ {
854
+ anchorX: xOffset + barWidth / 2,
855
+ anchorY: yy,
856
+ containerWidth: innerWidth,
857
+ containerHeight: innerHeight,
858
+ svgRef,
859
+ margin,
860
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...group.tooltip(d, i) })
861
+ }
862
+ )
863
+ ] }, `${groupIdx}-${i}`);
864
+ })
865
+ ) });
866
+ }
867
+ var HOVER_LEAVE_DELAY5 = 150;
868
+ function StackedBarSeries({
869
+ segments,
870
+ orientation = "horizontal",
871
+ radius = 4,
872
+ animate = true,
873
+ duration = 400,
874
+ hoverDimOpacity = 0.4,
875
+ showValues = true,
876
+ valueFormat = (v) => String(v)
877
+ }) {
878
+ const [hoveredIdx, setHoveredIdx] = react.useState(null);
879
+ const leaveTimeoutRef = react.useRef(null);
880
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
881
+ const clearTooltip = () => {
882
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
883
+ leaveTimeoutRef.current = null;
884
+ setHoveredIdx(null);
885
+ };
886
+ react.useEffect(() => {
887
+ return registerClearTooltip(clearTooltip);
888
+ }, [registerClearTooltip]);
889
+ const handleEnter = (idx) => {
890
+ if (leaveTimeoutRef.current) {
891
+ clearTimeout(leaveTimeoutRef.current);
892
+ leaveTimeoutRef.current = null;
893
+ }
894
+ clearAllTooltips();
895
+ setHoveredIdx(idx);
896
+ };
897
+ const handleLeave = () => {
898
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY5);
899
+ };
900
+ const total = segments.reduce((s, seg) => s + seg.value, 0);
901
+ if (total <= 0) return null;
902
+ const isHorizontal = orientation === "horizontal";
903
+ const barLength = isHorizontal ? innerWidth : innerHeight;
904
+ const barThickness = isHorizontal ? innerHeight : innerWidth;
905
+ const n = segments.length;
906
+ function roundedRectPath(x, y, w, h, r, roundLeft, roundRight) {
907
+ const r2 = Math.min(r, w / 2, h / 2);
908
+ if (r2 <= 0) return `M ${x} ${y} L ${x + w} ${y} L ${x + w} ${y + h} L ${x} ${y + h} Z`;
909
+ if (roundLeft && roundRight) {
910
+ return `M ${x + r2} ${y} L ${x + w - r2} ${y} A ${r2} ${r2} 0 0 1 ${x + w} ${y + r2} L ${x + w} ${y + h - r2} A ${r2} ${r2} 0 0 1 ${x + w - r2} ${y + h} L ${x + r2} ${y + h} A ${r2} ${r2} 0 0 1 ${x} ${y + h - r2} L ${x} ${y + r2} A ${r2} ${r2} 0 0 1 ${x + r2} ${y} Z`;
911
+ }
912
+ if (roundLeft) {
913
+ return `M ${x + r2} ${y} L ${x + w} ${y} L ${x + w} ${y + h} L ${x + r2} ${y + h} A ${r2} ${r2} 0 0 1 ${x} ${y + h - r2} L ${x} ${y + r2} A ${r2} ${r2} 0 0 1 ${x + r2} ${y} Z`;
914
+ }
915
+ if (roundRight) {
916
+ return `M ${x} ${y} L ${x + w - r2} ${y} A ${r2} ${r2} 0 0 1 ${x + w} ${y + r2} L ${x + w} ${y + h - r2} A ${r2} ${r2} 0 0 1 ${x + w - r2} ${y + h} L ${x} ${y + h} Z`;
917
+ }
918
+ return `M ${x} ${y} L ${x + w} ${y} L ${x + w} ${y + h} L ${x} ${y + h} Z`;
919
+ }
920
+ let offset = 0;
921
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: isHorizontal ? void 0 : `translate(0,${innerHeight}) rotate(-90)`, children: segments.map((seg, idx) => {
922
+ const width = seg.value / total * barLength;
923
+ const x = offset;
924
+ offset += width;
925
+ const isHovered = hoveredIdx === idx;
926
+ const opacity = hoveredIdx === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
927
+ const textX = x + width / 2;
928
+ const textY = barThickness / 2;
929
+ const minWidthForLabel = 24;
930
+ const isFirst = idx === 0;
931
+ const isLast = idx === n - 1;
932
+ const roundLeft = isFirst;
933
+ const roundRight = isLast;
934
+ const pathD = roundedRectPath(x, 0, Math.max(0, width), barThickness, radius, roundLeft, roundRight);
935
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
936
+ /* @__PURE__ */ jsxRuntime.jsx(
937
+ "path",
938
+ {
939
+ d: pathD,
940
+ fill: seg.fill,
941
+ opacity,
942
+ style: {
943
+ ...animate ? { animation: `msc-bar-grow ${duration}ms ease-out ${idx * 50}ms both` } : {},
944
+ transition: "opacity 0.2s ease",
945
+ cursor: seg.tooltip ? "pointer" : void 0
946
+ },
947
+ onMouseEnter: () => handleEnter(idx),
948
+ onMouseLeave: handleLeave
949
+ }
950
+ ),
951
+ showValues && width >= minWidthForLabel && /* @__PURE__ */ jsxRuntime.jsx(
952
+ "text",
953
+ {
954
+ x: textX,
955
+ y: textY,
956
+ textAnchor: "middle",
957
+ dominantBaseline: "central",
958
+ fill: "white",
959
+ style: {
960
+ fontSize: 11,
961
+ fontWeight: 600,
962
+ pointerEvents: "none",
963
+ textShadow: "0 1px 1px rgba(0,0,0,0.3)"
964
+ },
965
+ children: seg.label ? `${seg.label}: ${valueFormat(seg.value)}` : valueFormat(seg.value)
966
+ }
967
+ ),
968
+ seg.tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
969
+ TooltipPortal,
970
+ {
971
+ anchorX: x + width / 2,
972
+ anchorY: barThickness / 2,
973
+ containerWidth: innerWidth,
974
+ containerHeight: innerHeight,
975
+ svgRef,
976
+ margin,
977
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...seg.tooltip })
978
+ }
979
+ )
980
+ ] }, idx);
981
+ }) });
982
+ }
983
+ var DEFAULT_COLORS = [
984
+ "var(--msc-s1)",
985
+ "var(--msc-s2)",
986
+ "var(--msc-s3)",
987
+ "var(--msc-s4)",
988
+ "var(--msc-s5)"
989
+ ];
990
+ function PieSeries({
991
+ data,
992
+ value,
993
+ colors = DEFAULT_COLORS,
994
+ innerRadius = 0,
995
+ outerRadius,
996
+ padAngle = 0,
997
+ cornerRadius = 0,
998
+ animate = true,
999
+ duration = 600,
1000
+ hoverDimOpacity = 0.4,
1001
+ tooltip
1002
+ }) {
1003
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
1004
+ const leaveTimeoutRef = react.useRef(null);
1005
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1006
+ const clearTooltip = () => {
1007
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1008
+ leaveTimeoutRef.current = null;
1009
+ setHoveredIndex(null);
1010
+ };
1011
+ react.useEffect(() => {
1012
+ return registerClearTooltip(clearTooltip);
1013
+ }, [registerClearTooltip]);
1014
+ const handleEnter = (i) => {
1015
+ if (leaveTimeoutRef.current) {
1016
+ clearTimeout(leaveTimeoutRef.current);
1017
+ leaveTimeoutRef.current = null;
1018
+ }
1019
+ clearAllTooltips();
1020
+ setHoveredIndex(i);
1021
+ };
1022
+ const handleLeave = () => {
1023
+ leaveTimeoutRef.current = setTimeout(clearTooltip, 150);
1024
+ };
1025
+ const { arcs, arcGen, cx, cy } = react.useMemo(() => {
1026
+ const r = outerRadius ?? Math.min(innerWidth, innerHeight) / 2 - 8;
1027
+ const cx2 = innerWidth / 2;
1028
+ const cy2 = innerHeight / 2;
1029
+ const pieGen = d3Shape.pie().value((d, i) => value(d, i)).sort(null);
1030
+ const arcGen2 = d3Shape.arc().innerRadius(innerRadius).outerRadius(r).padAngle(padAngle).cornerRadius(cornerRadius);
1031
+ const arcs2 = pieGen(data).map((d, i) => ({ ...d, index: i }));
1032
+ return { arcs: arcs2, arcGen: arcGen2, cx: cx2, cy: cy2 };
1033
+ }, [data, value, innerWidth, innerHeight, outerRadius, innerRadius, padAngle, cornerRadius]);
1034
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${cx},${cy})`, children: arcs.map((arc, i) => {
1035
+ const d = arcGen(arc);
1036
+ if (!d) return null;
1037
+ const fill = colors[i % colors.length] ?? colors[0];
1038
+ const isHovered = hoveredIndex === i;
1039
+ const fillOpacity = hoveredIndex === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
1040
+ const [centroidX, centroidY] = arcGen.centroid(arc);
1041
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1042
+ /* @__PURE__ */ jsxRuntime.jsx(
1043
+ "path",
1044
+ {
1045
+ d,
1046
+ fill,
1047
+ fillOpacity,
1048
+ className: `msc-pie-slice-hoverable ${animate ? "msc-pie-slice-animate" : ""}`.trim(),
1049
+ style: {
1050
+ ...animate ? { animation: `msc-pie-draw ${duration}ms ease-out ${i * 40}ms both` } : {},
1051
+ transition: "fill-opacity 0.2s ease",
1052
+ cursor: tooltip ? "pointer" : void 0
1053
+ },
1054
+ onMouseEnter: () => handleEnter(i),
1055
+ onMouseLeave: handleLeave
1056
+ }
1057
+ ),
1058
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
1059
+ TooltipPortal,
1060
+ {
1061
+ anchorX: cx + centroidX,
1062
+ anchorY: cy + centroidY,
1063
+ containerWidth: innerWidth,
1064
+ containerHeight: innerHeight,
1065
+ svgRef,
1066
+ margin,
1067
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(arc.data, i) })
1068
+ }
1069
+ )
1070
+ ] }, i);
1071
+ }) });
1072
+ }
1073
+ var DEFAULT_COLORS2 = [
1074
+ "var(--msc-s1)",
1075
+ "var(--msc-s2)",
1076
+ "var(--msc-s3)",
1077
+ "var(--msc-s4)",
1078
+ "var(--msc-s5)"
1079
+ ];
1080
+ var HOVER_LEAVE_DELAY6 = 150;
1081
+ function PolarAreaSeries({
1082
+ data,
1083
+ value,
1084
+ colors = DEFAULT_COLORS2,
1085
+ innerRadius = 0,
1086
+ padAngle = 0.02,
1087
+ cornerRadius = 4,
1088
+ animate = true,
1089
+ duration = 600,
1090
+ hoverDimOpacity = 0.4,
1091
+ tooltip
1092
+ }) {
1093
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
1094
+ const leaveTimeoutRef = react.useRef(null);
1095
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1096
+ const clearTooltip = () => {
1097
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1098
+ leaveTimeoutRef.current = null;
1099
+ setHoveredIndex(null);
1100
+ };
1101
+ react.useEffect(() => {
1102
+ return registerClearTooltip(clearTooltip);
1103
+ }, [registerClearTooltip]);
1104
+ const handleEnter = (i) => {
1105
+ if (leaveTimeoutRef.current) {
1106
+ clearTimeout(leaveTimeoutRef.current);
1107
+ leaveTimeoutRef.current = null;
1108
+ }
1109
+ clearAllTooltips();
1110
+ setHoveredIndex(i);
1111
+ };
1112
+ const handleLeave = () => {
1113
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY6);
1114
+ };
1115
+ const { arcs, arcGen, cx, cy } = react.useMemo(() => {
1116
+ const r = Math.min(innerWidth, innerHeight) / 2 - 8;
1117
+ const cx2 = innerWidth / 2;
1118
+ const cy2 = innerHeight / 2;
1119
+ const maxVal = Math.max(...data.map((d, i) => value(d, i)), 1);
1120
+ const n = data.length;
1121
+ const angleStep = 2 * Math.PI / n;
1122
+ const arcs2 = data.map((d, i) => {
1123
+ const val = value(d, i);
1124
+ const outerR = innerRadius + val / maxVal * (r - innerRadius);
1125
+ return {
1126
+ data: d,
1127
+ index: i,
1128
+ startAngle: i * angleStep,
1129
+ endAngle: (i + 1) * angleStep,
1130
+ innerRadius,
1131
+ outerRadius: outerR
1132
+ };
1133
+ });
1134
+ const arcGen2 = d3Shape.arc().innerRadius((a) => a.innerRadius).outerRadius((a) => a.outerRadius).padAngle(padAngle).cornerRadius(cornerRadius);
1135
+ return { arcs: arcs2, arcGen: arcGen2, cx: cx2, cy: cy2 };
1136
+ }, [data, value, innerWidth, innerHeight, innerRadius, padAngle, cornerRadius]);
1137
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${cx},${cy})`, children: arcs.map((arc, i) => {
1138
+ const d = arcGen(arc);
1139
+ if (!d) return null;
1140
+ const fill = colors[i % colors.length] ?? colors[0];
1141
+ const isHovered = hoveredIndex === i;
1142
+ const fillOpacity = hoveredIndex === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
1143
+ const [centroidX, centroidY] = arcGen.centroid(arc);
1144
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1145
+ /* @__PURE__ */ jsxRuntime.jsx(
1146
+ "path",
1147
+ {
1148
+ d,
1149
+ fill,
1150
+ fillOpacity,
1151
+ className: `msc-pie-slice-hoverable ${animate ? "msc-pie-slice-animate" : ""}`.trim(),
1152
+ style: {
1153
+ ...animate ? { animation: `msc-pie-draw ${duration}ms ease-out ${i * 40}ms both` } : {},
1154
+ transition: "fill-opacity 0.2s ease",
1155
+ cursor: tooltip ? "pointer" : void 0
1156
+ },
1157
+ onMouseEnter: () => handleEnter(i),
1158
+ onMouseLeave: handleLeave
1159
+ }
1160
+ ),
1161
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
1162
+ TooltipPortal,
1163
+ {
1164
+ anchorX: cx + centroidX,
1165
+ anchorY: cy + centroidY,
1166
+ containerWidth: innerWidth,
1167
+ containerHeight: innerHeight,
1168
+ svgRef,
1169
+ margin,
1170
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(arc.data, i) })
1171
+ }
1172
+ )
1173
+ ] }, i);
1174
+ }) });
1175
+ }
1176
+ var DEFAULT_COLORS3 = [
1177
+ "var(--msc-s1)",
1178
+ "var(--msc-s2)",
1179
+ "var(--msc-s3)",
1180
+ "var(--msc-s4)",
1181
+ "var(--msc-s5)"
1182
+ ];
1183
+ function PieChart({
1184
+ data,
1185
+ value,
1186
+ label,
1187
+ colors = DEFAULT_COLORS3,
1188
+ width = 280,
1189
+ height = 260,
1190
+ margin = { top: 16, right: 16, bottom: 16, left: 16 },
1191
+ showLegend = true,
1192
+ showValues = true,
1193
+ valueFormat = (v) => String(v),
1194
+ innerRadius = 0,
1195
+ padAngle = 0.02,
1196
+ cornerRadius = 4,
1197
+ animate = true,
1198
+ defs,
1199
+ tooltip
1200
+ }) {
1201
+ const getColor = (i) => colors[i % colors.length] ?? colors[0] ?? "var(--msc-s1)";
1202
+ const legendItems = data.map((d, i) => ({
1203
+ label: label ? label(d, i) : `Item ${i + 1}`,
1204
+ value: showValues ? valueFormat(value(d, i)) : void 0,
1205
+ color: getColor(i)
1206
+ }));
1207
+ const defaultTooltip = tooltip ?? ((d, i) => ({
1208
+ title: label ? label(d, i) : `Item ${i + 1}`,
1209
+ rows: [{ label: "Value", value: valueFormat(value(d, i)), color: getColor(i) }]
1210
+ }));
1211
+ const chartMargin = {
1212
+ top: margin.top ?? 16,
1213
+ right: margin.right ?? 16,
1214
+ bottom: margin.bottom ?? 16,
1215
+ left: margin.left ?? 16
1216
+ };
1217
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1218
+ /* @__PURE__ */ jsxRuntime.jsxs(Chart, { width, height, margin: chartMargin, children: [
1219
+ defs,
1220
+ /* @__PURE__ */ jsxRuntime.jsx(
1221
+ PieSeries,
1222
+ {
1223
+ data,
1224
+ value,
1225
+ colors,
1226
+ innerRadius,
1227
+ padAngle,
1228
+ cornerRadius,
1229
+ animate,
1230
+ tooltip: defaultTooltip
1231
+ }
1232
+ )
1233
+ ] }),
1234
+ showLegend && /* @__PURE__ */ jsxRuntime.jsx(Legend, { items: legendItems })
1235
+ ] });
1236
+ }
1237
+ function ComboChart({
1238
+ data,
1239
+ x,
1240
+ bar,
1241
+ line,
1242
+ barLabel = "Bar",
1243
+ lineLabel = "Line",
1244
+ barFill = "var(--msc-s1)",
1245
+ lineStroke = "var(--msc-s2)",
1246
+ width = 320,
1247
+ height = 200,
1248
+ margin = { top: 24, right: 16, bottom: 28, left: 46 },
1249
+ showMarkers = true,
1250
+ animate = true,
1251
+ defs,
1252
+ barTooltip,
1253
+ lineTooltip
1254
+ }) {
1255
+ const chartMargin = {
1256
+ top: margin.top ?? 24,
1257
+ right: margin.right ?? 16,
1258
+ bottom: margin.bottom ?? 28,
1259
+ left: margin.left ?? 46
1260
+ };
1261
+ const innerW = width - (chartMargin.left ?? 0) - (chartMargin.right ?? 0);
1262
+ const innerH = height - (chartMargin.top ?? 0) - (chartMargin.bottom ?? 0);
1263
+ const xScale = react.useMemo(
1264
+ () => d3Scale.scaleBand().domain(data.map((d, i) => x(d, i))).range([0, innerW]).padding(0.25),
1265
+ [data, x, innerW]
1266
+ );
1267
+ const yScale = react.useMemo(() => {
1268
+ const barVals = data.map((d, i) => bar(d, i));
1269
+ const lineVals = data.map((d, i) => line(d, i));
1270
+ const all = [...barVals, ...lineVals];
1271
+ return d3Scale.scaleLinear().domain([Math.min(...all, 0), Math.max(...all)]).nice().range([innerH, 0]);
1272
+ }, [data, bar, line, innerH]);
1273
+ const lineXScale = react.useMemo(() => {
1274
+ const firstD = data[0];
1275
+ const lastD = data[data.length - 1];
1276
+ const first = firstD ? (xScale(x(firstD, 0)) ?? 0) + xScale.bandwidth() / 2 : 0;
1277
+ const last = data.length > 1 && lastD ? (xScale(x(lastD, data.length - 1)) ?? 0) + xScale.bandwidth() / 2 : first;
1278
+ return d3Scale.scaleLinear().domain([0, Math.max(0, data.length - 1)]).range([first, last]);
1279
+ }, [data, x, xScale]);
1280
+ const bottomTicks = react.useMemo(
1281
+ () => data.map((d, i) => ({ value: x(d, i), x: (xScale(x(d, i)) ?? 0) + xScale.bandwidth() / 2, y: innerH })),
1282
+ [data, x, xScale, innerH]
1283
+ );
1284
+ const leftTicks = react.useMemo(() => yScale.ticks(5).map((v) => ({ value: String(v), x: 0, y: yScale(v) })), [yScale]);
1285
+ const xTicks = xScale.domain().map((m) => (xScale(m) ?? 0) + xScale.bandwidth() / 2);
1286
+ const yTicks = yScale.ticks(5).map((v) => yScale(v));
1287
+ const defaultBarTooltip = barTooltip ?? ((d, i) => ({
1288
+ title: x(d, i),
1289
+ rows: [{ label: barLabel, value: String(bar(d, i)), color: barFill }]
1290
+ }));
1291
+ const defaultLineTooltip = lineTooltip ?? ((d, i) => ({
1292
+ title: x(d, i),
1293
+ rows: [{ label: lineLabel, value: String(line(d, i)), color: lineStroke }]
1294
+ }));
1295
+ return /* @__PURE__ */ jsxRuntime.jsxs(Chart, { width, height, margin: chartMargin, children: [
1296
+ defs,
1297
+ /* @__PURE__ */ jsxRuntime.jsx(Grid, { xTicks, yTicks }),
1298
+ /* @__PURE__ */ jsxRuntime.jsx(AxisLeft, { ticks: leftTicks }),
1299
+ /* @__PURE__ */ jsxRuntime.jsx(AxisBottom, { ticks: bottomTicks }),
1300
+ /* @__PURE__ */ jsxRuntime.jsx(
1301
+ BarSeries,
1302
+ {
1303
+ data,
1304
+ x,
1305
+ y: bar,
1306
+ xScale,
1307
+ yScale,
1308
+ fill: barFill,
1309
+ animate,
1310
+ tooltip: defaultBarTooltip
1311
+ }
1312
+ ),
1313
+ /* @__PURE__ */ jsxRuntime.jsx(
1314
+ LineSeries,
1315
+ {
1316
+ data,
1317
+ x: (_, i) => i,
1318
+ y: line,
1319
+ xScale: lineXScale,
1320
+ yScale,
1321
+ stroke: lineStroke,
1322
+ showMarkers,
1323
+ animate,
1324
+ tooltip: defaultLineTooltip
1325
+ }
1326
+ )
1327
+ ] });
1328
+ }
1329
+ var HOVER_LEAVE_DELAY7 = 150;
1330
+ function RadarChart({
1331
+ data,
1332
+ value,
1333
+ label,
1334
+ colors = ["var(--msc-s1)", "var(--msc-s2)", "var(--msc-s3)"],
1335
+ width = 280,
1336
+ height = 280,
1337
+ margin = { top: 24, right: 24, bottom: 24, left: 24 },
1338
+ levels = 5,
1339
+ animate = true,
1340
+ duration = 500,
1341
+ fillOpacity = 0.25,
1342
+ strokeWidth = 2,
1343
+ fill,
1344
+ stroke,
1345
+ defs,
1346
+ tooltip
1347
+ }) {
1348
+ const chartMargin = {
1349
+ top: margin.top ?? 24,
1350
+ right: margin.right ?? 24,
1351
+ bottom: margin.bottom ?? 24,
1352
+ left: margin.left ?? 24
1353
+ };
1354
+ const innerW = width - (chartMargin.left ?? 0) - (chartMargin.right ?? 0);
1355
+ const innerH = height - (chartMargin.top ?? 0) - (chartMargin.bottom ?? 0);
1356
+ const cx = innerW / 2;
1357
+ const cy = innerH / 2;
1358
+ const radius = Math.min(cx, cy) - 16;
1359
+ const n = data.length;
1360
+ const angleStep = 2 * Math.PI / n;
1361
+ const points = react.useMemo(() => {
1362
+ const maxVal = Math.max(...data.map((d, i) => value(d, i)), 1);
1363
+ return data.map((d, i) => {
1364
+ const angle = i * angleStep - Math.PI / 2;
1365
+ const val = value(d, i);
1366
+ const r = val / maxVal * radius;
1367
+ return {
1368
+ x: cx + r * Math.cos(angle),
1369
+ y: cy + r * Math.sin(angle),
1370
+ label: label(d, i),
1371
+ value: val,
1372
+ datum: d,
1373
+ index: i
1374
+ };
1375
+ });
1376
+ }, [data, value, label, angleStep, radius, cx, cy]);
1377
+ const polygonPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
1378
+ const fillColor = fill ?? colors[0] ?? "var(--msc-s1)";
1379
+ const strokeColor = stroke ?? colors[0] ?? "var(--msc-s1)";
1380
+ return /* @__PURE__ */ jsxRuntime.jsxs(Chart, { width, height, margin: chartMargin, children: [
1381
+ defs,
1382
+ /* @__PURE__ */ jsxRuntime.jsx(
1383
+ RadarGrid,
1384
+ {
1385
+ n,
1386
+ levels,
1387
+ cx,
1388
+ cy,
1389
+ radius,
1390
+ angleStep
1391
+ }
1392
+ ),
1393
+ /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1394
+ /* @__PURE__ */ jsxRuntime.jsx(
1395
+ "polygon",
1396
+ {
1397
+ points: polygonPoints,
1398
+ fill: fillColor,
1399
+ fillOpacity,
1400
+ stroke: strokeColor,
1401
+ strokeWidth,
1402
+ style: {
1403
+ ...animate ? { animation: `msc-area-reveal ${duration}ms ease-out forwards` } : {}
1404
+ }
1405
+ }
1406
+ ),
1407
+ points.map((pt, i) => /* @__PURE__ */ jsxRuntime.jsx(
1408
+ RadarPoint,
1409
+ {
1410
+ pt,
1411
+ color: strokeColor,
1412
+ animate,
1413
+ duration,
1414
+ delay: i * 60,
1415
+ tooltip
1416
+ },
1417
+ i
1418
+ ))
1419
+ ] }),
1420
+ points.map((pt, i) => /* @__PURE__ */ jsxRuntime.jsx(
1421
+ "text",
1422
+ {
1423
+ x: pt.x + (pt.x >= cx ? 8 : -8),
1424
+ y: pt.y,
1425
+ textAnchor: pt.x >= cx ? "start" : "end",
1426
+ dominantBaseline: "middle",
1427
+ fontSize: 10,
1428
+ fill: "var(--msc-muted)",
1429
+ children: pt.label
1430
+ },
1431
+ `label-${i}`
1432
+ ))
1433
+ ] });
1434
+ }
1435
+ function RadarGrid({
1436
+ n,
1437
+ levels,
1438
+ cx,
1439
+ cy,
1440
+ radius,
1441
+ angleStep
1442
+ }) {
1443
+ const lines = [];
1444
+ for (let level = 1; level <= levels; level++) {
1445
+ const r = radius * level / levels;
1446
+ const pts = [];
1447
+ for (let i = 0; i <= n; i++) {
1448
+ const angle = i * angleStep - Math.PI / 2;
1449
+ pts.push(`${cx + r * Math.cos(angle)},${cy + r * Math.sin(angle)}`);
1450
+ }
1451
+ lines.push(
1452
+ /* @__PURE__ */ jsxRuntime.jsx(
1453
+ "polygon",
1454
+ {
1455
+ points: pts.join(" "),
1456
+ fill: "none",
1457
+ stroke: "var(--msc-grid)",
1458
+ strokeWidth: 1
1459
+ },
1460
+ `level-${level}`
1461
+ )
1462
+ );
1463
+ }
1464
+ for (let i = 0; i < n; i++) {
1465
+ const angle = i * angleStep - Math.PI / 2;
1466
+ const x2 = cx + radius * Math.cos(angle);
1467
+ const y2 = cy + radius * Math.sin(angle);
1468
+ lines.push(
1469
+ /* @__PURE__ */ jsxRuntime.jsx(
1470
+ "line",
1471
+ {
1472
+ x1: cx,
1473
+ y1: cy,
1474
+ x2,
1475
+ y2,
1476
+ stroke: "var(--msc-grid)",
1477
+ strokeWidth: 1
1478
+ },
1479
+ `axis-${i}`
1480
+ )
1481
+ );
1482
+ }
1483
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: lines });
1484
+ }
1485
+ function RadarPoint({
1486
+ pt,
1487
+ color,
1488
+ animate,
1489
+ duration,
1490
+ delay,
1491
+ tooltip
1492
+ }) {
1493
+ const [hovered, setHovered] = react.useState(false);
1494
+ const leaveTimeoutRef = react.useRef(null);
1495
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1496
+ react.useEffect(() => {
1497
+ const clear = () => {
1498
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1499
+ setHovered(false);
1500
+ };
1501
+ return registerClearTooltip(clear);
1502
+ }, [registerClearTooltip]);
1503
+ const handleEnter = () => {
1504
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1505
+ clearAllTooltips();
1506
+ setHovered(true);
1507
+ };
1508
+ const handleLeave = () => {
1509
+ leaveTimeoutRef.current = setTimeout(() => setHovered(false), HOVER_LEAVE_DELAY7);
1510
+ };
1511
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1512
+ /* @__PURE__ */ jsxRuntime.jsx(
1513
+ "circle",
1514
+ {
1515
+ cx: pt.x,
1516
+ cy: pt.y,
1517
+ r: 5,
1518
+ fill: color,
1519
+ stroke: "var(--msc-panel)",
1520
+ strokeWidth: 2,
1521
+ style: {
1522
+ cursor: tooltip ? "pointer" : void 0,
1523
+ ...animate ? { animation: `msc-marker-pop 400ms ease-out ${delay}ms both` } : {}
1524
+ },
1525
+ onMouseEnter: handleEnter,
1526
+ onMouseLeave: handleLeave
1527
+ }
1528
+ ),
1529
+ tooltip && hovered && /* @__PURE__ */ jsxRuntime.jsx(
1530
+ TooltipPortal,
1531
+ {
1532
+ anchorX: pt.x,
1533
+ anchorY: pt.y,
1534
+ containerWidth: innerWidth,
1535
+ containerHeight: innerHeight,
1536
+ svgRef,
1537
+ margin,
1538
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(pt.datum, pt.index) })
1539
+ }
1540
+ )
1541
+ ] });
1542
+ }
1543
+ var DEFAULT_COLORS4 = [
1544
+ "var(--msc-s1)",
1545
+ "var(--msc-s2)",
1546
+ "var(--msc-s3)",
1547
+ "var(--msc-s4)",
1548
+ "var(--msc-s5)"
1549
+ ];
1550
+ function PolarAreaChart({
1551
+ data,
1552
+ value,
1553
+ label,
1554
+ colors = DEFAULT_COLORS4,
1555
+ width = 280,
1556
+ height = 260,
1557
+ margin = { top: 16, right: 16, bottom: 16, left: 16 },
1558
+ showLegend = true,
1559
+ showValues = true,
1560
+ valueFormat = (v) => String(v),
1561
+ animate = true,
1562
+ defs,
1563
+ tooltip
1564
+ }) {
1565
+ const getColor = (i) => colors[i % colors.length] ?? colors[0] ?? "var(--msc-s1)";
1566
+ const legendItems = data.map((d, i) => ({
1567
+ label: label ? label(d, i) : `Item ${i + 1}`,
1568
+ value: showValues ? valueFormat(value(d, i)) : void 0,
1569
+ color: getColor(i)
1570
+ }));
1571
+ const chartMargin = {
1572
+ top: margin.top ?? 16,
1573
+ right: margin.right ?? 16,
1574
+ bottom: margin.bottom ?? 16,
1575
+ left: margin.left ?? 16
1576
+ };
1577
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1578
+ /* @__PURE__ */ jsxRuntime.jsxs(Chart, { width, height, margin: chartMargin, children: [
1579
+ defs,
1580
+ /* @__PURE__ */ jsxRuntime.jsx(
1581
+ PolarAreaSeries,
1582
+ {
1583
+ data,
1584
+ value,
1585
+ colors,
1586
+ animate,
1587
+ tooltip
1588
+ }
1589
+ )
1590
+ ] }),
1591
+ showLegend && /* @__PURE__ */ jsxRuntime.jsx(Legend, { items: legendItems })
1592
+ ] });
1593
+ }
1594
+ function MultiaxisLineChart({
1595
+ data,
1596
+ x,
1597
+ leftLine,
1598
+ rightLine,
1599
+ leftLabel = "Left",
1600
+ rightLabel = "Right",
1601
+ leftStroke = "var(--msc-s1)",
1602
+ rightStroke = "var(--msc-s2)",
1603
+ width = 400,
1604
+ height = 240,
1605
+ margin = { top: 24, right: 48, bottom: 28, left: 48 },
1606
+ showMarkers = true,
1607
+ defs,
1608
+ leftTooltip,
1609
+ rightTooltip
1610
+ }) {
1611
+ const chartMargin = {
1612
+ top: margin.top ?? 24,
1613
+ right: margin.right ?? 48,
1614
+ bottom: margin.bottom ?? 28,
1615
+ left: margin.left ?? 48
1616
+ };
1617
+ const innerW = width - (chartMargin.left ?? 0) - (chartMargin.right ?? 0);
1618
+ const innerH = height - (chartMargin.top ?? 0) - (chartMargin.bottom ?? 0);
1619
+ const leftVals = data.map((d, i) => leftLine(d, i));
1620
+ const rightVals = data.map((d, i) => rightLine(d, i));
1621
+ const leftYScale = react.useMemo(
1622
+ () => d3Scale.scaleLinear().domain([Math.min(...leftVals, 0), Math.max(...leftVals)]).nice().range([innerH, 0]),
1623
+ [leftVals, innerH]
1624
+ );
1625
+ const rightYScale = react.useMemo(
1626
+ () => d3Scale.scaleLinear().domain([Math.min(...rightVals, 0), Math.max(...rightVals)]).nice().range([innerH, 0]),
1627
+ [rightVals, innerH]
1628
+ );
1629
+ const xScale = react.useMemo(() => {
1630
+ const labels = data.map((d, i) => String(x(d, i)));
1631
+ return d3Scale.scaleBand().domain(labels).range([0, innerW]).padding(0.25);
1632
+ }, [data, x, innerW]);
1633
+ const lineXScale = react.useMemo(() => {
1634
+ const domain = xScale.domain();
1635
+ const firstLabel = domain[0] ?? "";
1636
+ const lastLabel = domain[domain.length - 1] ?? firstLabel;
1637
+ const first = (xScale(firstLabel) ?? 0) + xScale.bandwidth() / 2;
1638
+ const last = (xScale(lastLabel) ?? first) + xScale.bandwidth() / 2;
1639
+ return d3Scale.scaleLinear().domain([0, data.length - 1]).range([first, last]);
1640
+ }, [xScale, data.length]);
1641
+ const bottomTicks = react.useMemo(
1642
+ () => data.map((d, i) => ({
1643
+ value: String(x(d, i)),
1644
+ x: (xScale(String(x(d, i))) ?? 0) + xScale.bandwidth() / 2,
1645
+ y: innerH
1646
+ })),
1647
+ [data, x, xScale, innerH]
1648
+ );
1649
+ const leftTicks = react.useMemo(
1650
+ () => leftYScale.ticks(5).map((v) => ({ value: String(v), x: 0, y: leftYScale(v) })),
1651
+ [leftYScale]
1652
+ );
1653
+ const rightTicks = react.useMemo(
1654
+ () => rightYScale.ticks(5).map((v) => ({
1655
+ value: String(v),
1656
+ x: innerW,
1657
+ y: rightYScale(v)
1658
+ })),
1659
+ [rightYScale, innerW]
1660
+ );
1661
+ const xTicks = xScale.domain().map((m) => (xScale(m) ?? 0) + xScale.bandwidth() / 2);
1662
+ const yTicks = leftYScale.ticks(5).map((v) => leftYScale(v));
1663
+ const defaultLeftTooltip = leftTooltip ?? ((d, i) => ({
1664
+ title: String(x(d, i)),
1665
+ rows: [{ label: leftLabel, value: String(leftLine(d, i)), color: leftStroke }]
1666
+ }));
1667
+ const defaultRightTooltip = rightTooltip ?? ((d, i) => ({
1668
+ title: String(x(d, i)),
1669
+ rows: [{ label: rightLabel, value: String(rightLine(d, i)), color: rightStroke }]
1670
+ }));
1671
+ return /* @__PURE__ */ jsxRuntime.jsxs(Chart, { width, height, margin: chartMargin, children: [
1672
+ defs,
1673
+ /* @__PURE__ */ jsxRuntime.jsx(Grid, { xTicks, yTicks }),
1674
+ /* @__PURE__ */ jsxRuntime.jsx(AxisLeft, { ticks: leftTicks }),
1675
+ /* @__PURE__ */ jsxRuntime.jsx(AxisRight, { ticks: rightTicks, x: innerW }),
1676
+ /* @__PURE__ */ jsxRuntime.jsx(AxisBottom, { ticks: bottomTicks }),
1677
+ /* @__PURE__ */ jsxRuntime.jsx(
1678
+ LineSeries,
1679
+ {
1680
+ data,
1681
+ x: (_, i) => i,
1682
+ y: leftLine,
1683
+ xScale: lineXScale,
1684
+ yScale: leftYScale,
1685
+ stroke: leftStroke,
1686
+ showMarkers,
1687
+ tooltip: defaultLeftTooltip
1688
+ }
1689
+ ),
1690
+ /* @__PURE__ */ jsxRuntime.jsx(
1691
+ LineSeries,
1692
+ {
1693
+ data,
1694
+ x: (_, i) => i,
1695
+ y: rightLine,
1696
+ xScale: lineXScale,
1697
+ yScale: rightYScale,
1698
+ stroke: rightStroke,
1699
+ showMarkers,
1700
+ tooltip: defaultRightTooltip
1701
+ }
1702
+ )
1703
+ ] });
1704
+ }
1705
+ var HOVER_LEAVE_DELAY8 = 150;
1706
+ function ScatterSeries({
1707
+ data,
1708
+ x,
1709
+ y,
1710
+ xScale,
1711
+ yScale,
1712
+ fill = "var(--msc-s1)",
1713
+ stroke = "var(--msc-panel)",
1714
+ strokeWidth = 2,
1715
+ radius = 5,
1716
+ animate = true,
1717
+ duration = 400,
1718
+ hoverDimOpacity = 0.5,
1719
+ tooltip
1720
+ }) {
1721
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
1722
+ const leaveTimeoutRef = react.useRef(null);
1723
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1724
+ const clearTooltip = () => {
1725
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1726
+ leaveTimeoutRef.current = null;
1727
+ setHoveredIndex(null);
1728
+ };
1729
+ react.useEffect(() => {
1730
+ return registerClearTooltip(clearTooltip);
1731
+ }, [registerClearTooltip]);
1732
+ const handleEnter = (i) => {
1733
+ if (leaveTimeoutRef.current) {
1734
+ clearTimeout(leaveTimeoutRef.current);
1735
+ leaveTimeoutRef.current = null;
1736
+ }
1737
+ clearAllTooltips();
1738
+ setHoveredIndex(i);
1739
+ };
1740
+ const handleLeave = () => {
1741
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY8);
1742
+ };
1743
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: data.map((d, i) => {
1744
+ const xx = xScale(x(d, i));
1745
+ const yy = yScale(y(d, i));
1746
+ if (!Number.isFinite(xx) || !Number.isFinite(yy)) return null;
1747
+ const isHovered = hoveredIndex === i;
1748
+ const opacity = hoveredIndex === null ? 0.92 : isHovered ? 1 : hoverDimOpacity;
1749
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1750
+ /* @__PURE__ */ jsxRuntime.jsx(
1751
+ "circle",
1752
+ {
1753
+ cx: xx,
1754
+ cy: yy,
1755
+ r: radius,
1756
+ fill,
1757
+ stroke,
1758
+ strokeWidth,
1759
+ opacity,
1760
+ style: {
1761
+ transition: "opacity 0.2s ease",
1762
+ cursor: tooltip ? "pointer" : void 0,
1763
+ ...animate ? { animation: `msc-marker-pop ${duration}ms ease-out ${i * 50}ms both` } : {}
1764
+ },
1765
+ onMouseEnter: () => handleEnter(i),
1766
+ onMouseLeave: handleLeave
1767
+ }
1768
+ ),
1769
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
1770
+ TooltipPortal,
1771
+ {
1772
+ anchorX: xx,
1773
+ anchorY: yy,
1774
+ containerWidth: innerWidth,
1775
+ containerHeight: innerHeight,
1776
+ svgRef,
1777
+ margin,
1778
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(d, i) })
1779
+ }
1780
+ )
1781
+ ] }, i);
1782
+ }) });
1783
+ }
1784
+ var HOVER_LEAVE_DELAY9 = 150;
1785
+ var MIN_RADIUS = 4;
1786
+ var MAX_RADIUS = 24;
1787
+ function BubbleSeries({
1788
+ data,
1789
+ x,
1790
+ y,
1791
+ size,
1792
+ xScale,
1793
+ yScale,
1794
+ fill = "var(--msc-s1)",
1795
+ stroke = "var(--msc-panel)",
1796
+ strokeWidth = 2,
1797
+ fillOpacity = 0.7,
1798
+ animate = true,
1799
+ duration = 400,
1800
+ hoverDimOpacity = 0.5,
1801
+ tooltip
1802
+ }) {
1803
+ const [hoveredIndex, setHoveredIndex] = react.useState(null);
1804
+ const leaveTimeoutRef = react.useRef(null);
1805
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1806
+ const sizeScale = react.useMemo(() => {
1807
+ const sizes = data.map((d, i) => size(d, i));
1808
+ const min = Math.min(...sizes);
1809
+ const max = Math.max(...sizes);
1810
+ return (v) => {
1811
+ if (max === min) return (MIN_RADIUS + MAX_RADIUS) / 2;
1812
+ const t = (v - min) / (max - min);
1813
+ return MIN_RADIUS + t * (MAX_RADIUS - MIN_RADIUS);
1814
+ };
1815
+ }, [data, size]);
1816
+ const clearTooltip = () => {
1817
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1818
+ leaveTimeoutRef.current = null;
1819
+ setHoveredIndex(null);
1820
+ };
1821
+ react.useEffect(() => {
1822
+ return registerClearTooltip(clearTooltip);
1823
+ }, [registerClearTooltip]);
1824
+ const handleEnter = (i) => {
1825
+ if (leaveTimeoutRef.current) {
1826
+ clearTimeout(leaveTimeoutRef.current);
1827
+ leaveTimeoutRef.current = null;
1828
+ }
1829
+ clearAllTooltips();
1830
+ setHoveredIndex(i);
1831
+ };
1832
+ const handleLeave = () => {
1833
+ leaveTimeoutRef.current = setTimeout(clearTooltip, HOVER_LEAVE_DELAY9);
1834
+ };
1835
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { children: data.map((d, i) => {
1836
+ const xx = xScale(x(d, i));
1837
+ const yy = yScale(y(d, i));
1838
+ if (!Number.isFinite(xx) || !Number.isFinite(yy)) return null;
1839
+ const r = sizeScale(size(d, i));
1840
+ const isHovered = hoveredIndex === i;
1841
+ const opacity = hoveredIndex === null ? fillOpacity : isHovered ? fillOpacity : hoverDimOpacity;
1842
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1843
+ /* @__PURE__ */ jsxRuntime.jsx(
1844
+ "circle",
1845
+ {
1846
+ cx: xx,
1847
+ cy: yy,
1848
+ r,
1849
+ fill,
1850
+ stroke,
1851
+ strokeWidth,
1852
+ fillOpacity: opacity,
1853
+ style: {
1854
+ transition: "opacity 0.2s ease",
1855
+ cursor: tooltip ? "pointer" : void 0,
1856
+ ...animate ? { animation: `msc-marker-pop ${duration}ms ease-out ${i * 50}ms both` } : {}
1857
+ },
1858
+ onMouseEnter: () => handleEnter(i),
1859
+ onMouseLeave: handleLeave
1860
+ }
1861
+ ),
1862
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
1863
+ TooltipPortal,
1864
+ {
1865
+ anchorX: xx,
1866
+ anchorY: yy,
1867
+ containerWidth: innerWidth,
1868
+ containerHeight: innerHeight,
1869
+ svgRef,
1870
+ margin,
1871
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(d, i) })
1872
+ }
1873
+ )
1874
+ ] }, i);
1875
+ }) });
1876
+ }
1877
+ function interpolateColor(t, stops) {
1878
+ if (stops.length === 0) return "var(--msc-grid)";
1879
+ const first = stops[0];
1880
+ if (stops.length === 1 || !first) return first?.color ?? "var(--msc-grid)";
1881
+ t = Math.max(0, Math.min(1, t));
1882
+ for (let i = 0; i < stops.length - 1; i++) {
1883
+ const a = stops[i];
1884
+ const b = stops[i + 1];
1885
+ if (a && b && t >= a.offset && t <= b.offset) {
1886
+ const local = (t - a.offset) / (b.offset - a.offset || 1);
1887
+ return lerpColor(a.color, b.color, local);
1888
+ }
1889
+ }
1890
+ const last = stops[stops.length - 1];
1891
+ return last?.color ?? "var(--msc-grid)";
1892
+ }
1893
+ function lerpColor(a, b, t) {
1894
+ const parse = (hex) => {
1895
+ const m = hex.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
1896
+ return m ? [parseInt(m[1] ?? "0", 16), parseInt(m[2] ?? "0", 16), parseInt(m[3] ?? "0", 16)] : [0, 0, 0];
1897
+ };
1898
+ const [r1, g1, b1] = parse(a);
1899
+ const [r2, g2, b2] = parse(b);
1900
+ const r = Math.round(r1 + (r2 - r1) * t);
1901
+ const g = Math.round(g1 + (g2 - g1) * t);
1902
+ const bl = Math.round(b1 + (b2 - b1) * t);
1903
+ return `rgb(${r},${g},${bl})`;
1904
+ }
1905
+ function HeatmapSeries({
1906
+ rows,
1907
+ columns,
1908
+ data,
1909
+ colorScale = ["#93c5fd", "#3b82f6", "#8b5cf6", "#7c3aed"],
1910
+ gradientStops,
1911
+ animate = true,
1912
+ duration = 300,
1913
+ hoverDimOpacity = 0.7,
1914
+ tooltip
1915
+ }) {
1916
+ const [hovered, setHovered] = react.useState(null);
1917
+ const leaveTimeoutRef = react.useRef(null);
1918
+ const { innerWidth, innerHeight, svgRef, margin, registerClearTooltip, clearAllTooltips } = useChart();
1919
+ const clearTooltip = () => {
1920
+ if (leaveTimeoutRef.current) clearTimeout(leaveTimeoutRef.current);
1921
+ leaveTimeoutRef.current = null;
1922
+ setHovered(null);
1923
+ };
1924
+ react.useEffect(() => {
1925
+ return registerClearTooltip(clearTooltip);
1926
+ }, [registerClearTooltip]);
1927
+ const handleEnter = (r, c) => {
1928
+ if (leaveTimeoutRef.current) {
1929
+ clearTimeout(leaveTimeoutRef.current);
1930
+ leaveTimeoutRef.current = null;
1931
+ }
1932
+ clearAllTooltips();
1933
+ setHovered({ r, c });
1934
+ };
1935
+ const handleLeave = () => {
1936
+ leaveTimeoutRef.current = setTimeout(clearTooltip, 150);
1937
+ };
1938
+ const { cellWidth, cellHeight, minVal, maxVal } = react.useMemo(() => {
1939
+ const cellW = innerWidth / Math.max(columns.length, 1);
1940
+ const cellH = innerHeight / Math.max(rows.length, 1);
1941
+ let min = Infinity;
1942
+ let max = -Infinity;
1943
+ data.forEach(
1944
+ (row) => row.forEach((cell) => {
1945
+ if (cell.value < min) min = cell.value;
1946
+ if (cell.value > max) max = cell.value;
1947
+ })
1948
+ );
1949
+ if (min === Infinity) min = 0;
1950
+ if (max === -Infinity) max = 1;
1951
+ return { cellWidth: cellW, cellHeight: cellH, minVal: min, maxVal: max };
1952
+ }, [innerWidth, innerHeight, columns.length, rows.length, data]);
1953
+ const getColor = (value) => {
1954
+ const t = maxVal === minVal ? 0 : (value - minVal) / (maxVal - minVal);
1955
+ if (gradientStops && gradientStops.length > 0) {
1956
+ return interpolateColor(t, gradientStops);
1957
+ }
1958
+ if (colorScale.length === 0) return "var(--msc-grid)";
1959
+ const idx = Math.min(
1960
+ Math.floor(t * (colorScale.length - 1)),
1961
+ colorScale.length - 1
1962
+ );
1963
+ return colorScale[idx];
1964
+ };
1965
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1966
+ rows.map((rowLabel, r) => /* @__PURE__ */ jsxRuntime.jsx(
1967
+ "text",
1968
+ {
1969
+ x: -8,
1970
+ y: r * cellHeight + cellHeight / 2,
1971
+ textAnchor: "end",
1972
+ fontSize: 10,
1973
+ fill: "var(--msc-muted)",
1974
+ dy: "0.32em",
1975
+ children: rowLabel
1976
+ },
1977
+ `row-${r}`
1978
+ )),
1979
+ columns.map((colLabel, c) => /* @__PURE__ */ jsxRuntime.jsx(
1980
+ "text",
1981
+ {
1982
+ x: c * cellWidth + cellWidth / 2,
1983
+ y: innerHeight + 16,
1984
+ textAnchor: "middle",
1985
+ fontSize: 10,
1986
+ fill: "var(--msc-muted)",
1987
+ children: colLabel
1988
+ },
1989
+ `col-${c}`
1990
+ )),
1991
+ rows.map(
1992
+ (rowLabel, r) => columns.map((colLabel, c) => {
1993
+ const cell = data[r]?.[c] ?? { value: 0 };
1994
+ const x = c * cellWidth;
1995
+ const y = r * cellHeight;
1996
+ const isHovered = hovered?.r === r && hovered?.c === c;
1997
+ const opacity = hovered === null ? 1 : isHovered ? 1 : hoverDimOpacity;
1998
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1999
+ /* @__PURE__ */ jsxRuntime.jsx(
2000
+ "rect",
2001
+ {
2002
+ x: x + 1,
2003
+ y: y + 1,
2004
+ width: cellWidth - 2,
2005
+ height: cellHeight - 2,
2006
+ fill: getColor(cell.value),
2007
+ opacity,
2008
+ rx: 2,
2009
+ style: {
2010
+ ...animate ? { animation: `msc-area-reveal ${duration}ms ease-out ${(r * columns.length + c) * 20}ms both` } : {},
2011
+ transition: "opacity 0.2s ease",
2012
+ cursor: tooltip ? "pointer" : void 0
2013
+ },
2014
+ onMouseEnter: () => handleEnter(r, c),
2015
+ onMouseLeave: handleLeave
2016
+ }
2017
+ ),
2018
+ tooltip && isHovered && /* @__PURE__ */ jsxRuntime.jsx(
2019
+ TooltipPortal,
2020
+ {
2021
+ anchorX: x + cellWidth / 2,
2022
+ anchorY: y + cellHeight / 2,
2023
+ containerWidth: innerWidth,
2024
+ containerHeight: innerHeight,
2025
+ svgRef,
2026
+ margin,
2027
+ children: /* @__PURE__ */ jsxRuntime.jsx(DefaultTooltip, { ...tooltip(rowLabel, colLabel, cell) })
2028
+ }
2029
+ )
2030
+ ] }, `${r}-${c}`);
2031
+ })
2032
+ )
2033
+ ] });
2034
+ }
2035
+ function useNearestPoint(data, xAccessor, xScale, yAccessor, yScale) {
2036
+ d3Array.bisector((d) => xAccessor(d, 0)).center;
2037
+ return function findNearest(pointerX) {
2038
+ if (!data.length) return null;
2039
+ const lastDatum = data[data.length - 1];
2040
+ if (lastDatum === void 0) return null;
2041
+ const approxIndex = Math.round(pointerX / Math.max(xScale(xAccessor(lastDatum, data.length - 1)), 1) * (data.length - 1));
2042
+ const seed = Math.max(0, Math.min(data.length - 1, approxIndex));
2043
+ const idx = Math.max(0, Math.min(data.length - 1, seed));
2044
+ const d = data[idx];
2045
+ if (d === void 0) return null;
2046
+ const x = xScale(xAccessor(d, idx));
2047
+ const y = yScale(yAccessor(d, idx));
2048
+ const distance = Math.abs(pointerX - x);
2049
+ return { index: idx, datum: d, x, y, distance };
2050
+ };
2051
+ }
2052
+
2053
+ exports.AreaSeries = AreaSeries;
2054
+ exports.AxisBottom = AxisBottom;
2055
+ exports.AxisLeft = AxisLeft;
2056
+ exports.AxisRight = AxisRight;
2057
+ exports.BarSeries = BarSeries;
2058
+ exports.BubbleSeries = BubbleSeries;
2059
+ exports.Chart = Chart;
2060
+ exports.ChartTitle = ChartTitle;
2061
+ exports.ComboChart = ComboChart;
2062
+ exports.DefaultTooltip = DefaultTooltip;
2063
+ exports.Grid = Grid;
2064
+ exports.GroupedBarSeries = GroupedBarSeries;
2065
+ exports.HeatmapSeries = HeatmapSeries;
2066
+ exports.HorizontalBarSeries = HorizontalBarSeries;
2067
+ exports.Legend = Legend;
2068
+ exports.LineSeries = LineSeries;
2069
+ exports.LinearGradient = LinearGradient;
2070
+ exports.MultiaxisLineChart = MultiaxisLineChart;
2071
+ exports.PieChart = PieChart;
2072
+ exports.PieSeries = PieSeries;
2073
+ exports.PolarAreaChart = PolarAreaChart;
2074
+ exports.PolarAreaSeries = PolarAreaSeries;
2075
+ exports.RadarChart = RadarChart;
2076
+ exports.RadialGradient = RadialGradient;
2077
+ exports.ScatterSeries = ScatterSeries;
2078
+ exports.StackedBarSeries = StackedBarSeries;
2079
+ exports.ThemeProvider = ThemeProvider;
2080
+ exports.ThresholdLine = ThresholdLine;
2081
+ exports.TooltipPortal = TooltipPortal;
2082
+ exports.computeTooltipPosition = computeTooltipPosition;
2083
+ exports.useChart = useChart;
2084
+ exports.useNearestPoint = useNearestPoint;
2085
+ exports.useTheme = useTheme;
2086
+ //# sourceMappingURL=index.cjs.map
2087
+ //# sourceMappingURL=index.cjs.map