@sesionario/blocks 1.27.0 → 1.28.0

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.
@@ -0,0 +1,1904 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var responsive = require('@visx/responsive');
5
+ var react$1 = require('motion/react');
6
+ var react = require('react');
7
+ var clsx = require('clsx');
8
+ var tailwindMerge = require('tailwind-merge');
9
+ var NumberFlow = require('@number-flow/react');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+ var d3Shape = require('d3-shape');
12
+ var group = require('@visx/group');
13
+ var shape = require('@visx/shape');
14
+
15
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
+
17
+ var NumberFlow__default = /*#__PURE__*/_interopDefault(NumberFlow);
18
+
19
+ function cn(...inputs) {
20
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
21
+ }
22
+ var defaultChartStatFlowFormat = {
23
+ notation: "standard",
24
+ maximumFractionDigits: 0
25
+ };
26
+ function formatStatValue(value, formatOptions, prefix, suffix) {
27
+ const formatted = new Intl.NumberFormat(void 0, formatOptions).format(
28
+ value
29
+ );
30
+ return `${prefix ?? ""}${formatted}${suffix ?? ""}`;
31
+ }
32
+ function useNumberFlowElementReady() {
33
+ const [ready, setReady] = react.useState(
34
+ () => typeof customElements !== "undefined" && Boolean(customElements.get("number-flow-react"))
35
+ );
36
+ react.useEffect(() => {
37
+ if (ready) {
38
+ return;
39
+ }
40
+ let cancelled = false;
41
+ customElements.whenDefined("number-flow-react").then(() => {
42
+ if (!cancelled) {
43
+ setReady(true);
44
+ }
45
+ });
46
+ return () => {
47
+ cancelled = true;
48
+ };
49
+ }, [ready]);
50
+ return ready;
51
+ }
52
+ function ChartStatFlow({
53
+ value,
54
+ label,
55
+ formatOptions = defaultChartStatFlowFormat,
56
+ prefix,
57
+ suffix,
58
+ valueClassName = "text-2xl font-bold",
59
+ labelClassName = "text-xs",
60
+ icon
61
+ }) {
62
+ const numberFlowReady = useNumberFlowElementReady();
63
+ const staticValue = react.useMemo(
64
+ () => formatStatValue(value, formatOptions, prefix, suffix),
65
+ [value, formatOptions, prefix, suffix]
66
+ );
67
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
68
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 flex h-12 w-12 items-center justify-center rounded-full bg-muted/50", children: icon }) : null,
69
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-foreground tabular-nums", valueClassName), children: numberFlowReady ? /* @__PURE__ */ jsxRuntime.jsx(
70
+ NumberFlow__default.default,
71
+ {
72
+ format: formatOptions,
73
+ isolate: true,
74
+ prefix,
75
+ suffix,
76
+ value,
77
+ willChange: true
78
+ }
79
+ ) : staticValue }),
80
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("mt-0.5 text-chart-label", labelClassName), children: label })
81
+ ] });
82
+ }
83
+ ChartStatFlow.displayName = "ChartStatFlow";
84
+
85
+ // src/components/charts/chart-center-typography.ts
86
+ var chartCenterContainerClassName = "@container/chart-center size-full min-w-0";
87
+ var chartCenterValueClassName = "font-bold tabular-nums leading-none text-[clamp(0.75rem,22cqw,1.875rem)]";
88
+ var chartCenterLabelClassName = "max-w-full truncate leading-tight text-[clamp(0.625rem,9cqw,0.75rem)]";
89
+ var labelAlignClass = {
90
+ start: "items-start text-left",
91
+ center: "items-center text-center",
92
+ end: "items-end text-right"
93
+ };
94
+ function GaugeLabelShell({
95
+ centerValue,
96
+ defaultLabel = "Total",
97
+ prefix,
98
+ suffix,
99
+ formatOptions = defaultChartStatFlowFormat,
100
+ align = "center",
101
+ className
102
+ }) {
103
+ return /* @__PURE__ */ jsxRuntime.jsx(
104
+ "div",
105
+ {
106
+ className: cn(
107
+ chartCenterContainerClassName,
108
+ "flex min-w-0 flex-col",
109
+ labelAlignClass[align],
110
+ className
111
+ ),
112
+ children: /* @__PURE__ */ jsxRuntime.jsx(
113
+ ChartStatFlow,
114
+ {
115
+ formatOptions,
116
+ label: defaultLabel,
117
+ labelClassName: cn(
118
+ chartCenterLabelClassName,
119
+ "text-[length:var(--chart-foreground-muted)]"
120
+ ),
121
+ prefix,
122
+ suffix,
123
+ value: centerValue,
124
+ valueClassName: cn(
125
+ chartCenterValueClassName,
126
+ "text-[length:var(--chart-foreground)]"
127
+ )
128
+ }
129
+ )
130
+ }
131
+ );
132
+ }
133
+ var crossAxisSelf = {
134
+ start: "self-start",
135
+ center: "self-center",
136
+ end: "self-end"
137
+ };
138
+ var crossAxisAlign = {
139
+ start: "items-start",
140
+ center: "items-center",
141
+ end: "items-end"
142
+ };
143
+ var inlineAxisAlign = {
144
+ start: "justify-start",
145
+ center: "justify-center",
146
+ end: "justify-end"
147
+ };
148
+ function GaugeLabelLayout({
149
+ placement,
150
+ align,
151
+ label,
152
+ children,
153
+ className
154
+ }) {
155
+ if (!label) {
156
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full min-w-0", className), children });
157
+ }
158
+ if (placement === "top") {
159
+ return /* @__PURE__ */ jsxRuntime.jsxs(
160
+ "div",
161
+ {
162
+ className: cn(
163
+ "flex w-full min-w-0 flex-col gap-3",
164
+ crossAxisAlign[align],
165
+ className
166
+ ),
167
+ children: [
168
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: crossAxisSelf[align], children: label }),
169
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full min-w-0", children })
170
+ ]
171
+ }
172
+ );
173
+ }
174
+ if (placement === "bottom") {
175
+ return /* @__PURE__ */ jsxRuntime.jsxs(
176
+ "div",
177
+ {
178
+ className: cn(
179
+ "flex w-full min-w-0 flex-col gap-3",
180
+ crossAxisAlign[align],
181
+ className
182
+ ),
183
+ children: [
184
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full min-w-0", children }),
185
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: crossAxisSelf[align], children: label })
186
+ ]
187
+ }
188
+ );
189
+ }
190
+ if (placement === "left") {
191
+ return /* @__PURE__ */ jsxRuntime.jsxs(
192
+ "div",
193
+ {
194
+ className: cn(
195
+ "flex w-full min-w-0 items-center gap-4",
196
+ inlineAxisAlign[align],
197
+ className
198
+ ),
199
+ children: [
200
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: label }),
201
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children })
202
+ ]
203
+ }
204
+ );
205
+ }
206
+ return /* @__PURE__ */ jsxRuntime.jsxs(
207
+ "div",
208
+ {
209
+ className: cn(
210
+ "flex w-full min-w-0 items-center gap-4",
211
+ inlineAxisAlign[align],
212
+ className
213
+ ),
214
+ children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children }),
216
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: label })
217
+ ]
218
+ }
219
+ );
220
+ }
221
+ var DEFAULT_ACTIVE_GRADIENT = [
222
+ "#bef264",
223
+ "#10b981"
224
+ ];
225
+ var DEFAULT_ACTIVE_FILL_OPACITY = 1;
226
+ var DEFAULT_INACTIVE_FILL_OPACITY = 0.8;
227
+ var DEFAULT_LINEAR_GAUGE_HEIGHT = 24;
228
+ function isDefsComponent(child) {
229
+ const typeLabel = child.type?.displayName || child.type?.name || "";
230
+ return typeLabel.includes("Gradient") || typeLabel.includes("Pattern") || typeLabel === "LinearGradient" || typeLabel === "RadialGradient" || typeLabel === "Lines" || typeLabel === "PatternLines" || typeLabel === "Circles" || typeLabel === "Hexagons" || typeLabel === "Waves";
231
+ }
232
+ function collectGaugeDefsElements(nodes) {
233
+ const out = [];
234
+ react.Children.forEach(nodes, (child) => {
235
+ if (!react.isValidElement(child)) {
236
+ return;
237
+ }
238
+ if (child.type === react.Fragment) {
239
+ out.push(
240
+ ...collectGaugeDefsElements(
241
+ child.props.children
242
+ )
243
+ );
244
+ return;
245
+ }
246
+ if (isDefsComponent(child)) {
247
+ out.push(child);
248
+ }
249
+ });
250
+ return out;
251
+ }
252
+ function interpolateGaugeHex(color1, color2, factor) {
253
+ const hex = (c) => Number.parseInt(c, 16);
254
+ const r1 = hex(color1.slice(1, 3));
255
+ const g1 = hex(color1.slice(3, 5));
256
+ const b1 = hex(color1.slice(5, 7));
257
+ const r2 = hex(color2.slice(1, 3));
258
+ const g2 = hex(color2.slice(3, 5));
259
+ const b2 = hex(color2.slice(5, 7));
260
+ const r = Math.round(r1 + (r2 - r1) * factor);
261
+ const g = Math.round(g1 + (g2 - g1) * factor);
262
+ const b = Math.round(b1 + (b2 - b1) * factor);
263
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
264
+ }
265
+ function createNotchPath(points, cornerRadiusPx, verticalDepth) {
266
+ const { x1, y1, x2, y2, x3, y3, x4, y4 } = points;
267
+ const lerp = (a, b, t) => a + (b - a) * t;
268
+ const dist = (ax, ay, bx, by) => Math.hypot(bx - ax, by - ay);
269
+ const d12 = dist(x1, y1, x2, y2);
270
+ const d23 = dist(x2, y2, x3, y3);
271
+ const d34 = dist(x3, y3, x4, y4);
272
+ const d41 = dist(x4, y4, x1, y1);
273
+ if (cornerRadiusPx <= 0) {
274
+ return `M ${x1} ${y1} L ${x2} ${y2} L ${x3} ${y3} L ${x4} ${y4} Z`;
275
+ }
276
+ const minEdge = Math.min(d12, d23, d34, d41);
277
+ const cr = Math.min(
278
+ cornerRadiusPx,
279
+ verticalDepth * 0.48,
280
+ d12 * 0.49,
281
+ d23 * 0.49,
282
+ d34 * 0.49,
283
+ d41 * 0.49,
284
+ minEdge * 0.49
285
+ );
286
+ const r1 = Math.min(cr / d12, 0.49);
287
+ const r2 = Math.min(cr / d23, 0.49);
288
+ const r3 = Math.min(cr / d34, 0.49);
289
+ const r4 = Math.min(cr / d41, 0.49);
290
+ const p1a = { x: lerp(x1, x4, r4), y: lerp(y1, y4, r4) };
291
+ const p1b = { x: lerp(x1, x2, r1), y: lerp(y1, y2, r1) };
292
+ const p2a = { x: lerp(x2, x1, r1), y: lerp(y2, y1, r1) };
293
+ const p2b = { x: lerp(x2, x3, r2), y: lerp(y2, y3, r2) };
294
+ const p3a = { x: lerp(x3, x2, r2), y: lerp(y3, y2, r2) };
295
+ const p3b = { x: lerp(x3, x4, r3), y: lerp(y3, y4, r3) };
296
+ const p4a = { x: lerp(x4, x3, r3), y: lerp(y4, y3, r3) };
297
+ const p4b = { x: lerp(x4, x1, r4), y: lerp(y4, y1, r4) };
298
+ return `M ${p1a.x} ${p1a.y} Q ${x1} ${y1} ${p1b.x} ${p1b.y} L ${p2a.x} ${p2a.y} Q ${x2} ${y2} ${p2b.x} ${p2b.y} L ${p3a.x} ${p3a.y} Q ${x3} ${y3} ${p3b.x} ${p3b.y} L ${p4a.x} ${p4a.y} Q ${x4} ${y4} ${p4b.x} ${p4b.y} Z`;
299
+ }
300
+ function resolveGaugeBgFill(options) {
301
+ const {
302
+ notchIndex,
303
+ totalNotches,
304
+ hasCustomInactive,
305
+ inactiveFill,
306
+ useThemePaletteGradient,
307
+ useGradient,
308
+ inactiveGrad0,
309
+ inactiveGrad1,
310
+ arcTrackFill,
311
+ linearTrackFill,
312
+ linearMode
313
+ } = options;
314
+ if (hasCustomInactive) {
315
+ return inactiveFill;
316
+ }
317
+ if (useThemePaletteGradient) {
318
+ return linearMode ? "var(--chart-1)" : arcTrackFill;
319
+ }
320
+ if (useGradient) {
321
+ const denom = totalNotches > 1 ? totalNotches - 1 : 1;
322
+ return interpolateGaugeHex(
323
+ inactiveGrad0,
324
+ inactiveGrad1,
325
+ notchIndex / denom
326
+ );
327
+ }
328
+ return linearMode ? linearTrackFill : arcTrackFill;
329
+ }
330
+ function resolveGaugeActiveFill(options) {
331
+ const {
332
+ notch,
333
+ hasCustomActive,
334
+ activeFill,
335
+ useThemePaletteGradient,
336
+ themeActiveGradientId,
337
+ useGradient,
338
+ activeFillSolid
339
+ } = options;
340
+ if (hasCustomActive) {
341
+ return activeFill;
342
+ }
343
+ if (useThemePaletteGradient) {
344
+ return `url(#${themeActiveGradientId})`;
345
+ }
346
+ if (useGradient) {
347
+ return notch.gradientColor;
348
+ }
349
+ return activeFillSolid;
350
+ }
351
+ var pieCssVars = {
352
+ // Default slice colors from chart palette
353
+ slice1: "var(--chart-1)",
354
+ slice2: "var(--chart-2)",
355
+ slice3: "var(--chart-3)",
356
+ slice4: "var(--chart-4)",
357
+ slice5: "var(--chart-5)"
358
+ };
359
+ var defaultPieColors = [
360
+ pieCssVars.slice1,
361
+ pieCssVars.slice2,
362
+ pieCssVars.slice3,
363
+ pieCssVars.slice4,
364
+ pieCssVars.slice5
365
+ ];
366
+ var PieStableContext = react.createContext(null);
367
+ var PieHoverContext = react.createContext(null);
368
+ function PieProvider({
369
+ children,
370
+ value
371
+ }) {
372
+ const stable = react.useMemo(
373
+ () => ({
374
+ data: value.data,
375
+ arcs: value.arcs,
376
+ size: value.size,
377
+ center: value.center,
378
+ outerRadius: value.outerRadius,
379
+ innerRadius: value.innerRadius,
380
+ padAngle: value.padAngle,
381
+ cornerRadius: value.cornerRadius,
382
+ hoverOffset: value.hoverOffset,
383
+ animationKey: value.animationKey,
384
+ isLoaded: value.isLoaded,
385
+ enterTransition: value.enterTransition,
386
+ enterStaggerScale: value.enterStaggerScale,
387
+ containerRef: value.containerRef,
388
+ totalValue: value.totalValue,
389
+ getColor: value.getColor,
390
+ getFill: value.getFill,
391
+ geometryScrubbing: value.geometryScrubbing,
392
+ scrubSlicePaths: value.scrubSlicePaths
393
+ }),
394
+ [
395
+ value.data,
396
+ value.arcs,
397
+ value.size,
398
+ value.center,
399
+ value.outerRadius,
400
+ value.innerRadius,
401
+ value.padAngle,
402
+ value.cornerRadius,
403
+ value.hoverOffset,
404
+ value.animationKey,
405
+ value.isLoaded,
406
+ value.enterTransition,
407
+ value.enterStaggerScale,
408
+ value.containerRef,
409
+ value.totalValue,
410
+ value.getColor,
411
+ value.getFill,
412
+ value.geometryScrubbing,
413
+ value.scrubSlicePaths
414
+ ]
415
+ );
416
+ const hover = react.useMemo(
417
+ () => ({
418
+ hoveredIndex: value.hoveredIndex,
419
+ setHoveredIndex: value.setHoveredIndex
420
+ }),
421
+ [value.hoveredIndex, value.setHoveredIndex]
422
+ );
423
+ return /* @__PURE__ */ jsxRuntime.jsx(PieStableContext.Provider, { value: stable, children: /* @__PURE__ */ jsxRuntime.jsx(PieHoverContext.Provider, { value: hover, children }) });
424
+ }
425
+ function usePieStable() {
426
+ const context = react.useContext(PieStableContext);
427
+ if (!context) {
428
+ throw new Error(
429
+ "usePieStable must be used within a PieProvider. Make sure your component is wrapped in <PieChart>."
430
+ );
431
+ }
432
+ return context;
433
+ }
434
+ function usePieHover() {
435
+ const context = react.useContext(PieHoverContext);
436
+ if (!context) {
437
+ throw new Error(
438
+ "usePieHover must be used within a PieProvider. Make sure your component is wrapped in <PieChart>."
439
+ );
440
+ }
441
+ return context;
442
+ }
443
+ function PieCenter({
444
+ defaultLabel = "Total",
445
+ formatOptions = defaultChartStatFlowFormat,
446
+ children,
447
+ className = "",
448
+ valueClassName = chartCenterValueClassName,
449
+ labelClassName = chartCenterLabelClassName,
450
+ prefix,
451
+ suffix
452
+ }) {
453
+ const { data, totalValue, innerRadius, geometryScrubbing } = usePieStable();
454
+ const { hoveredIndex } = usePieHover();
455
+ const effectiveHoveredIndex = geometryScrubbing ? null : hoveredIndex;
456
+ const hoveredData = effectiveHoveredIndex === null ? null : data[effectiveHoveredIndex];
457
+ const displayValue = hoveredData ? hoveredData.value : totalValue;
458
+ const displayLabel = hoveredData ? hoveredData.label : defaultLabel;
459
+ const centerSize = innerRadius * 2 - 16;
460
+ if (innerRadius <= 0) {
461
+ return null;
462
+ }
463
+ if (children && hoveredData) {
464
+ return /* @__PURE__ */ jsxRuntime.jsx(
465
+ "div",
466
+ {
467
+ className: cn(
468
+ chartCenterContainerClassName,
469
+ "flex items-center justify-center",
470
+ className
471
+ ),
472
+ style: { width: centerSize, height: centerSize },
473
+ children: children({
474
+ value: displayValue,
475
+ label: displayLabel,
476
+ isHovered: effectiveHoveredIndex !== null,
477
+ data: hoveredData
478
+ })
479
+ }
480
+ );
481
+ }
482
+ return /* @__PURE__ */ jsxRuntime.jsx(
483
+ "div",
484
+ {
485
+ className: cn(
486
+ chartCenterContainerClassName,
487
+ "flex flex-col items-center justify-center text-center",
488
+ className
489
+ ),
490
+ style: { width: centerSize, height: centerSize },
491
+ children: /* @__PURE__ */ jsxRuntime.jsx(
492
+ ChartStatFlow,
493
+ {
494
+ formatOptions,
495
+ label: displayLabel,
496
+ labelClassName,
497
+ prefix,
498
+ suffix,
499
+ value: displayValue,
500
+ valueClassName
501
+ }
502
+ )
503
+ }
504
+ );
505
+ }
506
+ PieCenter.displayName = "PieCenter";
507
+ var SHELL_HOVER_OFFSET = 10;
508
+ function PieCenterShell({
509
+ centerValue,
510
+ contextSize,
511
+ innerRadiusPx,
512
+ animateEntrance = true,
513
+ ...pieCenterProps
514
+ }) {
515
+ const containerRef = react.useRef(null);
516
+ const introStartedRef = react.useRef(false);
517
+ const [flowTotal, setFlowTotal] = react.useState(
518
+ () => animateEntrance ? 0 : centerValue
519
+ );
520
+ react.useEffect(() => {
521
+ if (!animateEntrance) {
522
+ setFlowTotal(centerValue);
523
+ return;
524
+ }
525
+ if (!introStartedRef.current) {
526
+ introStartedRef.current = true;
527
+ setFlowTotal(0);
528
+ let innerRaf = 0;
529
+ const outerRaf = requestAnimationFrame(() => {
530
+ innerRaf = requestAnimationFrame(() => setFlowTotal(centerValue));
531
+ });
532
+ return () => {
533
+ cancelAnimationFrame(outerRaf);
534
+ cancelAnimationFrame(innerRaf);
535
+ introStartedRef.current = false;
536
+ };
537
+ }
538
+ setFlowTotal(centerValue);
539
+ }, [animateEntrance, centerValue]);
540
+ const data = react.useMemo(
541
+ () => [{ label: "_pieCenterShell", value: Math.max(flowTotal, 0) }],
542
+ [flowTotal]
543
+ );
544
+ const totalValue = flowTotal;
545
+ const arcs = react.useMemo(() => {
546
+ const v = data[0]?.value ?? 0;
547
+ if (v > 0) {
548
+ const pieGenerator = d3Shape.pie().value((d) => d.value).startAngle(-Math.PI / 2).endAngle(3 * Math.PI / 2).padAngle(0).sort(null);
549
+ const computed = pieGenerator(data);
550
+ return computed.map((arc, index) => ({
551
+ data: arc.data,
552
+ index,
553
+ startAngle: arc.startAngle,
554
+ endAngle: arc.endAngle,
555
+ padAngle: arc.padAngle,
556
+ value: arc.value
557
+ }));
558
+ }
559
+ const d0 = data[0];
560
+ if (!d0) {
561
+ return [];
562
+ }
563
+ return [
564
+ {
565
+ data: d0,
566
+ index: 0,
567
+ startAngle: -Math.PI / 2,
568
+ endAngle: 3 * Math.PI / 2,
569
+ padAngle: 0,
570
+ value: 0
571
+ }
572
+ ];
573
+ }, [data]);
574
+ const getColor = react.useCallback((index) => {
575
+ return defaultPieColors[index % defaultPieColors.length];
576
+ }, []);
577
+ const getFill = react.useCallback(
578
+ (index) => {
579
+ const item = data[index];
580
+ if (item?.fill) {
581
+ return item.fill;
582
+ }
583
+ return getColor(index);
584
+ },
585
+ [data, getColor]
586
+ );
587
+ const center = contextSize / 2;
588
+ const outerRadius = center - SHELL_HOVER_OFFSET;
589
+ const contextValue = react.useMemo(
590
+ () => ({
591
+ data,
592
+ arcs,
593
+ size: contextSize,
594
+ center,
595
+ outerRadius,
596
+ innerRadius: innerRadiusPx,
597
+ padAngle: 0,
598
+ cornerRadius: 0,
599
+ hoverOffset: SHELL_HOVER_OFFSET,
600
+ hoveredIndex: null,
601
+ setHoveredIndex: () => void 0,
602
+ animationKey: 0,
603
+ isLoaded: true,
604
+ enterStaggerScale: 1,
605
+ containerRef,
606
+ totalValue,
607
+ getColor,
608
+ getFill,
609
+ geometryScrubbing: false,
610
+ scrubSlicePaths: null
611
+ }),
612
+ [
613
+ data,
614
+ arcs,
615
+ contextSize,
616
+ center,
617
+ outerRadius,
618
+ innerRadiusPx,
619
+ totalValue,
620
+ getColor,
621
+ getFill
622
+ ]
623
+ );
624
+ return /* @__PURE__ */ jsxRuntime.jsx(PieProvider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(PieCenter, { ...pieCenterProps }) });
625
+ }
626
+ PieCenterShell.displayName = "PieCenterShell";
627
+ var DEFAULT_NOTCH_ENTER_TRANSITION = {
628
+ type: "spring",
629
+ stiffness: 300,
630
+ damping: 20
631
+ };
632
+ function GaugeNotchSvg({
633
+ notches,
634
+ width,
635
+ height,
636
+ notchCornerRadius,
637
+ cornerDepth,
638
+ geometryScrubbing,
639
+ notchTransition,
640
+ stagger,
641
+ defsChildren,
642
+ useThemePaletteGradient,
643
+ themeActiveGradientId,
644
+ resolvedInactiveFillOpacity,
645
+ resolvedActiveFillOpacity,
646
+ resolveBgFill,
647
+ resolveActiveFill
648
+ }) {
649
+ return /* @__PURE__ */ jsxRuntime.jsxs(
650
+ "svg",
651
+ {
652
+ "aria-hidden": "true",
653
+ className: "block w-full overflow-visible",
654
+ height,
655
+ viewBox: `0 0 ${width} ${height}`,
656
+ width,
657
+ children: [
658
+ defsChildren.length > 0 || useThemePaletteGradient ? /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
659
+ useThemePaletteGradient ? /* @__PURE__ */ jsxRuntime.jsxs(
660
+ "linearGradient",
661
+ {
662
+ id: themeActiveGradientId,
663
+ x1: "0%",
664
+ x2: "100%",
665
+ y1: "0%",
666
+ y2: "0%",
667
+ children: [
668
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "var(--chart-1)" }),
669
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "var(--chart-5)" })
670
+ ]
671
+ }
672
+ ) : null,
673
+ defsChildren
674
+ ] }) : null,
675
+ notches.map((notch) => {
676
+ const pathD = createNotchPath(
677
+ notch.points,
678
+ notchCornerRadius,
679
+ cornerDepth
680
+ );
681
+ if (geometryScrubbing) {
682
+ return /* @__PURE__ */ jsxRuntime.jsx(
683
+ "path",
684
+ {
685
+ d: pathD,
686
+ fill: resolveBgFill(notch.index),
687
+ fillOpacity: resolvedInactiveFillOpacity
688
+ },
689
+ `bg-${notch.index}`
690
+ );
691
+ }
692
+ return /* @__PURE__ */ jsxRuntime.jsx(
693
+ react$1.motion.path,
694
+ {
695
+ animate: { opacity: 1, scale: 1 },
696
+ d: pathD,
697
+ fill: resolveBgFill(notch.index),
698
+ fillOpacity: resolvedInactiveFillOpacity,
699
+ initial: { opacity: 0, scale: 0 },
700
+ style: {
701
+ transformOrigin: `${notch.xCenter}px ${notch.yCenter}px`
702
+ },
703
+ transition: {
704
+ ...notchTransition,
705
+ delay: notch.index * 0.015 * stagger
706
+ }
707
+ },
708
+ `bg-${notch.index}`
709
+ );
710
+ }),
711
+ notches.filter((n) => n.isActive).map((notch) => {
712
+ const pathD = createNotchPath(
713
+ notch.points,
714
+ notchCornerRadius,
715
+ cornerDepth
716
+ );
717
+ if (geometryScrubbing) {
718
+ return /* @__PURE__ */ jsxRuntime.jsx(
719
+ "path",
720
+ {
721
+ d: pathD,
722
+ fill: resolveActiveFill(notch),
723
+ fillOpacity: resolvedActiveFillOpacity
724
+ },
725
+ `active-${notch.index}`
726
+ );
727
+ }
728
+ return /* @__PURE__ */ jsxRuntime.jsx(
729
+ react$1.motion.path,
730
+ {
731
+ animate: { opacity: 1, scale: 1 },
732
+ d: pathD,
733
+ fill: resolveActiveFill(notch),
734
+ fillOpacity: resolvedActiveFillOpacity,
735
+ initial: { opacity: 0, scale: 0 },
736
+ style: {
737
+ transformOrigin: `${notch.xCenter}px ${notch.yCenter}px`
738
+ },
739
+ transition: {
740
+ ...notchTransition,
741
+ delay: (0.3 + notch.index * 0.02) * stagger
742
+ }
743
+ },
744
+ `active-${notch.index}`
745
+ );
746
+ })
747
+ ]
748
+ }
749
+ );
750
+ }
751
+ function useGaugeFillState(props) {
752
+ const {
753
+ useGradient = false,
754
+ activeGradient,
755
+ inactiveGradient,
756
+ inactiveFill,
757
+ activeFill,
758
+ inactiveFillOpacity,
759
+ activeFillOpacity,
760
+ children,
761
+ totalNotches = 40
762
+ } = props;
763
+ const themeActiveGradientId = `gauge-theme-active-${react.useId().replace(/:/g, "")}`;
764
+ const defsChildren = react.useMemo(
765
+ () => collectGaugeDefsElements(children),
766
+ [children]
767
+ );
768
+ const hasCustomInactive = inactiveFill !== void 0 && inactiveFill.length > 0;
769
+ const hasCustomActive = activeFill !== void 0 && activeFill.length > 0;
770
+ const activeGrad0 = activeGradient?.[0] ?? DEFAULT_ACTIVE_GRADIENT[0];
771
+ const activeGrad1 = activeGradient?.[1] ?? DEFAULT_ACTIVE_GRADIENT[1];
772
+ const inactiveGrad0 = inactiveGradient?.[0] ?? activeGrad0;
773
+ const inactiveGrad1 = inactiveGradient?.[1] ?? activeGrad1;
774
+ const useThemePaletteGradient = useGradient && activeGradient === void 0;
775
+ return {
776
+ themeActiveGradientId,
777
+ defsChildren,
778
+ hasCustomInactive,
779
+ hasCustomActive,
780
+ activeGrad0,
781
+ activeGrad1,
782
+ inactiveGrad0,
783
+ inactiveGrad1,
784
+ useThemePaletteGradient,
785
+ resolvedActiveFillOpacity: activeFillOpacity ?? DEFAULT_ACTIVE_FILL_OPACITY,
786
+ resolvedInactiveFillOpacity: inactiveFillOpacity ?? DEFAULT_INACTIVE_FILL_OPACITY,
787
+ totalNotches
788
+ };
789
+ }
790
+ function GaugeArcInner(props) {
791
+ const {
792
+ value,
793
+ totalNotches = 40,
794
+ spacing = 25,
795
+ notchCornerRadius = 0,
796
+ uniformWidth = false,
797
+ width,
798
+ height,
799
+ startAngle = 135,
800
+ endAngle = 405,
801
+ useGradient = false,
802
+ centerValue,
803
+ defaultLabel = "Total",
804
+ prefix,
805
+ suffix,
806
+ formatOptions = defaultChartStatFlowFormat,
807
+ inactiveFill,
808
+ activeFill,
809
+ notchLengthPercent = 100,
810
+ enterTransition,
811
+ enterStaggerScale = 1
812
+ } = props;
813
+ const prefersReducedMotion = react$1.useReducedMotion();
814
+ const fillState = useGaugeFillState(props);
815
+ const notchTransition = prefersReducedMotion ? { duration: 0 } : enterTransition ?? DEFAULT_NOTCH_ENTER_TRANSITION;
816
+ const stagger = Math.max(0.25, Math.min(2.5, enterStaggerScale));
817
+ const size = Math.min(width, height);
818
+ const centerX = width / 2;
819
+ const centerY = height / 2;
820
+ const outerRadius = size * 0.42;
821
+ const innerRadiusBase = size * 0.28;
822
+ const defaultRadialDepth = outerRadius - innerRadiusBase;
823
+ const depthFactor = Math.min(100, Math.max(5, notchLengthPercent)) / 100;
824
+ const notchLength = defaultRadialDepth * depthFactor;
825
+ const innerRadius = outerRadius - notchLength;
826
+ const activeNotches = Math.round(value / 100 * totalNotches);
827
+ const totalAngle = endAngle - startAngle;
828
+ const availableAngle = totalAngle * (1 - spacing / 100);
829
+ const notchAngle = totalNotches > 0 ? availableAngle / totalNotches : 0;
830
+ const gapDen = totalNotches - 1 > 0 ? totalNotches - 1 : 1;
831
+ const gapAngle = totalAngle * (spacing / 100) / gapDen;
832
+ const notches = react.useMemo(() => {
833
+ return Array.from({ length: totalNotches }, (_, i) => {
834
+ const angle = startAngle + i * (notchAngle + gapAngle) + notchAngle / 2;
835
+ const radians = angle * Math.PI / 180;
836
+ const arcNotchWidth = notchAngle * 0.8;
837
+ const halfWidth = arcNotchWidth * Math.PI / 180 / 2;
838
+ const x1 = centerX + Math.cos(radians - halfWidth) * outerRadius;
839
+ const y1 = centerY + Math.sin(radians - halfWidth) * outerRadius;
840
+ const x2 = centerX + Math.cos(radians + halfWidth) * outerRadius;
841
+ const y2 = centerY + Math.sin(radians + halfWidth) * outerRadius;
842
+ let x3;
843
+ let y3;
844
+ let x4;
845
+ let y4;
846
+ if (uniformWidth) {
847
+ const perpX = Math.cos(radians);
848
+ const perpY = Math.sin(radians);
849
+ x3 = x2 - perpX * notchLength;
850
+ y3 = y2 - perpY * notchLength;
851
+ x4 = x1 - perpX * notchLength;
852
+ y4 = y1 - perpY * notchLength;
853
+ } else {
854
+ x3 = centerX + Math.cos(radians + halfWidth) * innerRadius;
855
+ y3 = centerY + Math.sin(radians + halfWidth) * innerRadius;
856
+ x4 = centerX + Math.cos(radians - halfWidth) * innerRadius;
857
+ y4 = centerY + Math.sin(radians - halfWidth) * innerRadius;
858
+ }
859
+ const denom = totalNotches > 1 ? totalNotches - 1 : 1;
860
+ const gradientColor = useGradient && !fillState.useThemePaletteGradient ? interpolateGaugeHex(
861
+ fillState.activeGrad0,
862
+ fillState.activeGrad1,
863
+ i / denom
864
+ ) : "var(--chart-1)";
865
+ return {
866
+ index: i,
867
+ points: { x1, y1, x2, y2, x3, y3, x4, y4 },
868
+ isActive: i < activeNotches,
869
+ gradientColor,
870
+ xCenter: centerX,
871
+ yCenter: centerY
872
+ };
873
+ });
874
+ }, [
875
+ totalNotches,
876
+ notchAngle,
877
+ gapAngle,
878
+ centerX,
879
+ centerY,
880
+ outerRadius,
881
+ innerRadius,
882
+ activeNotches,
883
+ startAngle,
884
+ uniformWidth,
885
+ notchLength,
886
+ useGradient,
887
+ fillState.useThemePaletteGradient,
888
+ fillState.activeGrad0,
889
+ fillState.activeGrad1
890
+ ]);
891
+ const resolveBgFill = (notchIndex) => resolveGaugeBgFill({
892
+ notchIndex,
893
+ totalNotches,
894
+ hasCustomInactive: fillState.hasCustomInactive,
895
+ inactiveFill,
896
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
897
+ useGradient,
898
+ inactiveGrad0: fillState.inactiveGrad0,
899
+ inactiveGrad1: fillState.inactiveGrad1,
900
+ arcTrackFill: "var(--border)",
901
+ linearTrackFill: "var(--chart-background)",
902
+ linearMode: false
903
+ });
904
+ const resolveActiveFill = (notch) => resolveGaugeActiveFill({
905
+ notch,
906
+ hasCustomActive: fillState.hasCustomActive,
907
+ activeFill,
908
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
909
+ themeActiveGradientId: fillState.themeActiveGradientId,
910
+ useGradient,
911
+ activeFillSolid: "var(--chart-1)"
912
+ });
913
+ const showCenter = centerValue != null;
914
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", style: { height, width }, children: [
915
+ /* @__PURE__ */ jsxRuntime.jsx(
916
+ GaugeNotchSvg,
917
+ {
918
+ cornerDepth: notchLength,
919
+ defsChildren: fillState.defsChildren,
920
+ geometryScrubbing: false,
921
+ height,
922
+ notchCornerRadius,
923
+ notches,
924
+ notchTransition,
925
+ resolveActiveFill,
926
+ resolveBgFill,
927
+ resolvedActiveFillOpacity: fillState.resolvedActiveFillOpacity,
928
+ resolvedInactiveFillOpacity: fillState.resolvedInactiveFillOpacity,
929
+ stagger,
930
+ themeActiveGradientId: fillState.themeActiveGradientId,
931
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
932
+ width
933
+ }
934
+ ),
935
+ showCenter ? /* @__PURE__ */ jsxRuntime.jsx(
936
+ "div",
937
+ {
938
+ className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center",
939
+ style: { paddingTop: size * 0.08 },
940
+ children: /* @__PURE__ */ jsxRuntime.jsx(
941
+ PieCenterShell,
942
+ {
943
+ centerValue,
944
+ contextSize: size,
945
+ defaultLabel,
946
+ formatOptions,
947
+ innerRadiusPx: Math.max(size * 0.2, 52),
948
+ prefix,
949
+ suffix
950
+ }
951
+ )
952
+ }
953
+ ) : null
954
+ ] });
955
+ }
956
+ function GaugeLinearInner(props) {
957
+ const {
958
+ value,
959
+ totalNotches = 40,
960
+ spacing = 25,
961
+ notchCornerRadius = 0,
962
+ uniformWidth = true,
963
+ width,
964
+ height,
965
+ useGradient = false,
966
+ centerValue,
967
+ defaultLabel = "Total",
968
+ prefix,
969
+ suffix,
970
+ formatOptions = defaultChartStatFlowFormat,
971
+ labelPlacement = "top",
972
+ labelAlign = "start",
973
+ inactiveFill,
974
+ activeFill,
975
+ notchLengthPercent = 100,
976
+ notchWidthPercent = 80,
977
+ enterTransition,
978
+ enterStaggerScale = 1,
979
+ geometryScrubbing = false
980
+ } = props;
981
+ const prefersReducedMotion = react$1.useReducedMotion();
982
+ const fillState = useGaugeFillState(props);
983
+ const notchTransition = prefersReducedMotion ? { duration: 0 } : enterTransition ?? DEFAULT_NOTCH_ENTER_TRANSITION;
984
+ const stagger = Math.max(0.25, Math.min(2.5, enterStaggerScale));
985
+ const centerY = height / 2;
986
+ const depthFactor = Math.min(100, Math.max(5, notchLengthPercent)) / 100;
987
+ const outerOffset = height / 2 * depthFactor;
988
+ const taperRatio = 28 / 42;
989
+ const innerOffset = uniformWidth ? outerOffset : outerOffset * taperRatio;
990
+ const notchDepth = uniformWidth ? outerOffset * 2 : outerOffset - innerOffset;
991
+ const cornerVerticalDepth = uniformWidth ? notchDepth : outerOffset * 2;
992
+ const widthFactor = Math.min(100, Math.max(10, notchWidthPercent)) / 100;
993
+ const activeNotches = Math.round(value / 100 * totalNotches);
994
+ const availableWidth = width * (1 - spacing / 100);
995
+ const slotWidth = totalNotches > 0 ? availableWidth / totalNotches : 0;
996
+ const gapDen = totalNotches - 1 > 0 ? totalNotches - 1 : 1;
997
+ const gapWidth = width * (spacing / 100) / gapDen;
998
+ const notches = react.useMemo(() => {
999
+ return Array.from({ length: totalNotches }, (_, i) => {
1000
+ const xCenter = i * (slotWidth + gapWidth) + slotWidth / 2;
1001
+ const halfWidth = slotWidth * widthFactor / 2;
1002
+ let x1;
1003
+ let y1;
1004
+ let x2;
1005
+ let y2;
1006
+ let x3;
1007
+ let y3;
1008
+ let x4;
1009
+ let y4;
1010
+ if (uniformWidth) {
1011
+ const halfHeight = notchDepth / 2;
1012
+ x1 = xCenter - halfWidth;
1013
+ y1 = centerY - halfHeight;
1014
+ x2 = xCenter + halfWidth;
1015
+ y2 = centerY - halfHeight;
1016
+ x3 = xCenter + halfWidth;
1017
+ y3 = centerY + halfHeight;
1018
+ x4 = xCenter - halfWidth;
1019
+ y4 = centerY + halfHeight;
1020
+ } else {
1021
+ x1 = xCenter - halfWidth;
1022
+ y1 = centerY - outerOffset;
1023
+ x2 = xCenter + halfWidth;
1024
+ y2 = centerY - outerOffset;
1025
+ const innerHalfWidth = halfWidth * (innerOffset / outerOffset);
1026
+ x3 = xCenter + innerHalfWidth;
1027
+ y3 = centerY + outerOffset;
1028
+ x4 = xCenter - innerHalfWidth;
1029
+ y4 = centerY + outerOffset;
1030
+ }
1031
+ const denom = totalNotches > 1 ? totalNotches - 1 : 1;
1032
+ const gradientColor = useGradient && !fillState.useThemePaletteGradient ? interpolateGaugeHex(
1033
+ fillState.activeGrad0,
1034
+ fillState.activeGrad1,
1035
+ i / denom
1036
+ ) : "var(--chart-1)";
1037
+ return {
1038
+ index: i,
1039
+ points: { x1, y1, x2, y2, x3, y3, x4, y4 },
1040
+ isActive: i < activeNotches,
1041
+ gradientColor,
1042
+ xCenter,
1043
+ yCenter: centerY
1044
+ };
1045
+ });
1046
+ }, [
1047
+ totalNotches,
1048
+ slotWidth,
1049
+ gapWidth,
1050
+ centerY,
1051
+ outerOffset,
1052
+ innerOffset,
1053
+ activeNotches,
1054
+ uniformWidth,
1055
+ notchDepth,
1056
+ widthFactor,
1057
+ useGradient,
1058
+ fillState.useThemePaletteGradient,
1059
+ fillState.activeGrad0,
1060
+ fillState.activeGrad1
1061
+ ]);
1062
+ const resolveBgFill = (notchIndex) => resolveGaugeBgFill({
1063
+ notchIndex,
1064
+ totalNotches,
1065
+ hasCustomInactive: fillState.hasCustomInactive,
1066
+ inactiveFill,
1067
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
1068
+ useGradient,
1069
+ inactiveGrad0: fillState.inactiveGrad0,
1070
+ inactiveGrad1: fillState.inactiveGrad1,
1071
+ arcTrackFill: "var(--border)",
1072
+ linearTrackFill: "var(--chart-background)",
1073
+ linearMode: true
1074
+ });
1075
+ const resolveActiveFill = (notch) => resolveGaugeActiveFill({
1076
+ notch,
1077
+ hasCustomActive: fillState.hasCustomActive,
1078
+ activeFill,
1079
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
1080
+ themeActiveGradientId: fillState.themeActiveGradientId,
1081
+ useGradient,
1082
+ activeFillSolid: "var(--chart-1)"
1083
+ });
1084
+ const label = centerValue == null ? null : /* @__PURE__ */ jsxRuntime.jsx(
1085
+ GaugeLabelShell,
1086
+ {
1087
+ align: labelAlign,
1088
+ centerValue,
1089
+ defaultLabel,
1090
+ formatOptions,
1091
+ prefix,
1092
+ suffix
1093
+ }
1094
+ );
1095
+ const track = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full", style: { height, width }, children: /* @__PURE__ */ jsxRuntime.jsx(
1096
+ GaugeNotchSvg,
1097
+ {
1098
+ cornerDepth: cornerVerticalDepth,
1099
+ defsChildren: fillState.defsChildren,
1100
+ geometryScrubbing,
1101
+ height,
1102
+ notchCornerRadius,
1103
+ notches,
1104
+ notchTransition,
1105
+ resolveActiveFill,
1106
+ resolveBgFill,
1107
+ resolvedActiveFillOpacity: fillState.resolvedActiveFillOpacity,
1108
+ resolvedInactiveFillOpacity: fillState.resolvedInactiveFillOpacity,
1109
+ stagger,
1110
+ themeActiveGradientId: fillState.themeActiveGradientId,
1111
+ useThemePaletteGradient: fillState.useThemePaletteGradient,
1112
+ width
1113
+ }
1114
+ ) });
1115
+ return /* @__PURE__ */ jsxRuntime.jsx(
1116
+ GaugeLabelLayout,
1117
+ {
1118
+ align: labelAlign,
1119
+ label,
1120
+ placement: labelPlacement,
1121
+ children: track
1122
+ }
1123
+ );
1124
+ }
1125
+ function GaugeInner(props) {
1126
+ if (props.orientation === "linear") {
1127
+ return /* @__PURE__ */ jsxRuntime.jsx(GaugeLinearInner, { ...props });
1128
+ }
1129
+ return /* @__PURE__ */ jsxRuntime.jsx(GaugeArcInner, { ...props });
1130
+ }
1131
+ function Gauge({
1132
+ width: widthProp,
1133
+ height: heightProp,
1134
+ className,
1135
+ minWidth,
1136
+ orientation = "arc",
1137
+ linearHeight,
1138
+ ...props
1139
+ }) {
1140
+ const isLinear = orientation === "linear";
1141
+ const resolvedMinWidth = minWidth ?? (isLinear ? 200 : 300);
1142
+ const resolvedLinearHeight = linearHeight ?? DEFAULT_LINEAR_GAUGE_HEIGHT;
1143
+ if (isLinear) {
1144
+ if (widthProp != null) {
1145
+ return /* @__PURE__ */ jsxRuntime.jsx(
1146
+ "div",
1147
+ {
1148
+ className: cn("relative w-full max-w-full", className),
1149
+ style: { width: widthProp },
1150
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1151
+ GaugeInner,
1152
+ {
1153
+ height: heightProp ?? resolvedLinearHeight,
1154
+ orientation: "linear",
1155
+ width: widthProp,
1156
+ ...props
1157
+ }
1158
+ )
1159
+ }
1160
+ );
1161
+ }
1162
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative w-full min-w-0 max-w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full min-w-0", style: { minWidth: resolvedMinWidth }, children: /* @__PURE__ */ jsxRuntime.jsx(responsive.ParentSize, { debounceTime: 10, children: ({ width }) => width > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1163
+ GaugeInner,
1164
+ {
1165
+ height: resolvedLinearHeight,
1166
+ orientation: "linear",
1167
+ width,
1168
+ ...props
1169
+ }
1170
+ ) : null }) }) });
1171
+ }
1172
+ if (widthProp != null && heightProp != null) {
1173
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative inline-flex max-w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
1174
+ GaugeInner,
1175
+ {
1176
+ height: heightProp,
1177
+ orientation: "arc",
1178
+ width: widthProp,
1179
+ ...props
1180
+ }
1181
+ ) });
1182
+ }
1183
+ return /* @__PURE__ */ jsxRuntime.jsx(
1184
+ "div",
1185
+ {
1186
+ className: cn("relative w-full max-w-full", className),
1187
+ style: { minWidth: resolvedMinWidth },
1188
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto aspect-[21/16] w-full max-w-[560px]", children: /* @__PURE__ */ jsxRuntime.jsx(responsive.ParentSize, { debounceTime: 10, children: ({ width, height }) => width > 0 && height > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1189
+ GaugeInner,
1190
+ {
1191
+ height,
1192
+ orientation: "arc",
1193
+ width,
1194
+ ...props
1195
+ }
1196
+ ) : null }) })
1197
+ }
1198
+ );
1199
+ }
1200
+ Gauge.displayName = "Gauge";
1201
+ var ringCssVars = {
1202
+ background: "var(--chart-background)",
1203
+ foreground: "var(--chart-foreground)",
1204
+ foregroundMuted: "var(--chart-foreground-muted)",
1205
+ label: "var(--chart-label)",
1206
+ ringBackground: "var(--border)",
1207
+ // Default ring colors from chart palette
1208
+ ring1: "var(--chart-1)",
1209
+ ring2: "var(--chart-2)",
1210
+ ring3: "var(--chart-3)",
1211
+ ring4: "var(--chart-4)",
1212
+ ring5: "var(--chart-5)"
1213
+ };
1214
+ var defaultRingColors = [
1215
+ ringCssVars.ring1,
1216
+ ringCssVars.ring2,
1217
+ ringCssVars.ring3,
1218
+ ringCssVars.ring4,
1219
+ ringCssVars.ring5
1220
+ ];
1221
+ var RingStableContext = react.createContext(null);
1222
+ var RingHoverContext = react.createContext(null);
1223
+ function RingProvider({
1224
+ children,
1225
+ value
1226
+ }) {
1227
+ const stable = react.useMemo(
1228
+ () => ({
1229
+ data: value.data,
1230
+ size: value.size,
1231
+ center: value.center,
1232
+ strokeWidth: value.strokeWidth,
1233
+ ringGap: value.ringGap,
1234
+ baseInnerRadius: value.baseInnerRadius,
1235
+ animationKey: value.animationKey,
1236
+ isLoaded: value.isLoaded,
1237
+ enterTransition: value.enterTransition,
1238
+ enterStaggerScale: value.enterStaggerScale,
1239
+ containerRef: value.containerRef,
1240
+ totalValue: value.totalValue,
1241
+ getColor: value.getColor,
1242
+ getRingRadii: value.getRingRadii,
1243
+ startAngle: value.startAngle,
1244
+ endAngle: value.endAngle,
1245
+ geometryScrubbing: value.geometryScrubbing
1246
+ }),
1247
+ [
1248
+ value.data,
1249
+ value.size,
1250
+ value.center,
1251
+ value.strokeWidth,
1252
+ value.ringGap,
1253
+ value.baseInnerRadius,
1254
+ value.animationKey,
1255
+ value.isLoaded,
1256
+ value.enterTransition,
1257
+ value.enterStaggerScale,
1258
+ value.containerRef,
1259
+ value.totalValue,
1260
+ value.getColor,
1261
+ value.getRingRadii,
1262
+ value.startAngle,
1263
+ value.endAngle,
1264
+ value.geometryScrubbing
1265
+ ]
1266
+ );
1267
+ const hover = react.useMemo(
1268
+ () => ({
1269
+ hoveredIndex: value.hoveredIndex,
1270
+ setHoveredIndex: value.setHoveredIndex
1271
+ }),
1272
+ [value.hoveredIndex, value.setHoveredIndex]
1273
+ );
1274
+ return /* @__PURE__ */ jsxRuntime.jsx(RingStableContext.Provider, { value: stable, children: /* @__PURE__ */ jsxRuntime.jsx(RingHoverContext.Provider, { value: hover, children }) });
1275
+ }
1276
+ function useRingStable() {
1277
+ const context = react.useContext(RingStableContext);
1278
+ if (!context) {
1279
+ throw new Error(
1280
+ "useRingStable must be used within a RingProvider. Make sure your component is wrapped in <RingChart>."
1281
+ );
1282
+ }
1283
+ return context;
1284
+ }
1285
+ function useRingHover() {
1286
+ const context = react.useContext(RingHoverContext);
1287
+ if (!context) {
1288
+ throw new Error(
1289
+ "useRingHover must be used within a RingProvider. Make sure your component is wrapped in <RingChart>."
1290
+ );
1291
+ }
1292
+ return context;
1293
+ }
1294
+ function useRing() {
1295
+ return { ...useRingStable(), ...useRingHover() };
1296
+ }
1297
+ function generateRingArcPath(innerRadius, outerRadius, startAngle, endAngle, cornerRadius) {
1298
+ const generator = shape.arc({
1299
+ innerRadius,
1300
+ outerRadius,
1301
+ cornerRadius
1302
+ });
1303
+ return generator({ startAngle, endAngle }) || "";
1304
+ }
1305
+ function isRing(child) {
1306
+ return react.isValidElement(child) && typeof child.type === "function" && (child.type.displayName === "Ring" || child.type.name === "Ring");
1307
+ }
1308
+ function isRingCenter(child) {
1309
+ return react.isValidElement(child) && typeof child.type === "function" && (child.type.displayName === "RingCenter" || child.type.name === "RingCenter");
1310
+ }
1311
+ function RingChartInner(props) {
1312
+ const size = Math.min(props.width, props.height);
1313
+ if (size < 10) {
1314
+ return null;
1315
+ }
1316
+ return /* @__PURE__ */ jsxRuntime.jsx(RingChartCore, { ...props });
1317
+ }
1318
+ var RingChartCore = react.memo(function RingChartCore2({
1319
+ width,
1320
+ height,
1321
+ data,
1322
+ strokeWidth: strokeWidthProp,
1323
+ ringGap: ringGapProp,
1324
+ baseInnerRadius: baseInnerRadiusProp,
1325
+ children,
1326
+ containerRef,
1327
+ hoveredIndexProp,
1328
+ onHoverChange,
1329
+ startAngle,
1330
+ endAngle,
1331
+ enterTransition,
1332
+ enterStaggerScale,
1333
+ geometryScrubbing
1334
+ }) {
1335
+ const [internalHoveredIndex, setInternalHoveredIndex] = react.useState(null);
1336
+ const [animationKey] = react.useState(0);
1337
+ const [isLoaded, setIsLoaded] = react.useState(false);
1338
+ const isControlled = hoveredIndexProp !== void 0;
1339
+ const hoveredIndex = isControlled ? hoveredIndexProp : internalHoveredIndex;
1340
+ const setHoveredIndex = react.useCallback(
1341
+ (index) => {
1342
+ if (isControlled) {
1343
+ onHoverChange?.(index);
1344
+ } else {
1345
+ setInternalHoveredIndex(index);
1346
+ }
1347
+ },
1348
+ [isControlled, onHoverChange]
1349
+ );
1350
+ const size = Math.min(width, height);
1351
+ const center = size / 2;
1352
+ const ringCount = data.length;
1353
+ const padding = 8;
1354
+ const availableRadius = center - padding;
1355
+ const designOuterRadius = baseInnerRadiusProp + (ringCount - 1) * (strokeWidthProp + ringGapProp) + strokeWidthProp;
1356
+ const scale = Math.min(1, availableRadius / designOuterRadius);
1357
+ const strokeWidth = strokeWidthProp * scale;
1358
+ const ringGap = ringGapProp * scale;
1359
+ const baseInnerRadius = baseInnerRadiusProp * scale;
1360
+ const totalValue = react.useMemo(
1361
+ () => data.reduce((sum, d) => sum + d.value, 0),
1362
+ [data]
1363
+ );
1364
+ const getColor = react.useCallback(
1365
+ (index) => {
1366
+ const item = data[index];
1367
+ if (item?.color) {
1368
+ return item.color;
1369
+ }
1370
+ return defaultRingColors[index % defaultRingColors.length];
1371
+ },
1372
+ [data]
1373
+ );
1374
+ const getRingRadii = react.useCallback(
1375
+ (index) => {
1376
+ const innerRadius = baseInnerRadius + index * (strokeWidth + ringGap);
1377
+ const outerRadius = innerRadius + strokeWidth;
1378
+ return { innerRadius, outerRadius };
1379
+ },
1380
+ [baseInnerRadius, strokeWidth, ringGap]
1381
+ );
1382
+ const arcRange = endAngle - startAngle;
1383
+ const scrubRingLayers = react.useMemo(() => {
1384
+ if (!geometryScrubbing) {
1385
+ return null;
1386
+ }
1387
+ return data.map((ringData, index) => {
1388
+ const { innerRadius, outerRadius } = getRingRadii(index);
1389
+ const cornerRadius = (outerRadius - innerRadius) / 2;
1390
+ const progress = ringData.value / ringData.maxValue;
1391
+ const progressEndAngle = startAngle + arcRange * progress;
1392
+ return {
1393
+ bgPath: generateRingArcPath(
1394
+ innerRadius,
1395
+ outerRadius,
1396
+ startAngle,
1397
+ endAngle,
1398
+ cornerRadius
1399
+ ),
1400
+ progressPath: progressEndAngle <= startAngle + 0.01 ? "" : generateRingArcPath(
1401
+ innerRadius,
1402
+ outerRadius,
1403
+ startAngle,
1404
+ progressEndAngle,
1405
+ cornerRadius
1406
+ ),
1407
+ color: getColor(index)
1408
+ };
1409
+ });
1410
+ }, [
1411
+ geometryScrubbing,
1412
+ data,
1413
+ getRingRadii,
1414
+ getColor,
1415
+ startAngle,
1416
+ endAngle,
1417
+ arcRange
1418
+ ]);
1419
+ const effectiveIsLoaded = geometryScrubbing || isLoaded;
1420
+ react.useEffect(() => {
1421
+ if (geometryScrubbing) {
1422
+ return;
1423
+ }
1424
+ setIsLoaded(false);
1425
+ const timer = setTimeout(() => {
1426
+ setIsLoaded(true);
1427
+ }, 100);
1428
+ return () => clearTimeout(timer);
1429
+ }, [enterTransition, enterStaggerScale, geometryScrubbing]);
1430
+ const { svgChildren, centerChildren } = react.useMemo(() => {
1431
+ const svgNodes = [];
1432
+ const centerNodes = [];
1433
+ react.Children.forEach(children, (child) => {
1434
+ if (isRingCenter(child)) {
1435
+ centerNodes.push(child);
1436
+ } else if (geometryScrubbing && isRing(child)) {
1437
+ return;
1438
+ } else {
1439
+ svgNodes.push(child);
1440
+ }
1441
+ });
1442
+ return { svgChildren: svgNodes, centerChildren: centerNodes };
1443
+ }, [children, geometryScrubbing]);
1444
+ const contextValue = react.useMemo(
1445
+ () => ({
1446
+ data,
1447
+ size,
1448
+ center,
1449
+ strokeWidth,
1450
+ ringGap,
1451
+ baseInnerRadius,
1452
+ hoveredIndex,
1453
+ setHoveredIndex,
1454
+ animationKey,
1455
+ isLoaded: effectiveIsLoaded,
1456
+ enterTransition,
1457
+ enterStaggerScale,
1458
+ containerRef,
1459
+ totalValue,
1460
+ getColor,
1461
+ getRingRadii,
1462
+ startAngle,
1463
+ endAngle,
1464
+ geometryScrubbing
1465
+ }),
1466
+ [
1467
+ data,
1468
+ size,
1469
+ center,
1470
+ strokeWidth,
1471
+ ringGap,
1472
+ baseInnerRadius,
1473
+ hoveredIndex,
1474
+ setHoveredIndex,
1475
+ animationKey,
1476
+ effectiveIsLoaded,
1477
+ enterTransition,
1478
+ enterStaggerScale,
1479
+ containerRef,
1480
+ totalValue,
1481
+ getColor,
1482
+ getRingRadii,
1483
+ startAngle,
1484
+ endAngle,
1485
+ geometryScrubbing
1486
+ ]
1487
+ );
1488
+ return /* @__PURE__ */ jsxRuntime.jsx(RingProvider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
1489
+ "div",
1490
+ {
1491
+ className: "grid",
1492
+ style: {
1493
+ gridTemplateColumns: "1fr",
1494
+ gridTemplateRows: "1fr",
1495
+ width: size,
1496
+ height: size
1497
+ },
1498
+ children: [
1499
+ /* @__PURE__ */ jsxRuntime.jsx(
1500
+ "svg",
1501
+ {
1502
+ "aria-hidden": "true",
1503
+ height: size,
1504
+ style: { gridArea: "1 / 1", contain: "layout style paint" },
1505
+ width: size,
1506
+ children: /* @__PURE__ */ jsxRuntime.jsxs(group.Group, { left: center, top: center, children: [
1507
+ scrubRingLayers ? scrubRingLayers.map((layer, index) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1508
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: layer.bgPath, fill: ringCssVars.ringBackground }),
1509
+ layer.progressPath ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: layer.progressPath, fill: layer.color }) : null
1510
+ ] }, data[index]?.label ?? index)) : null,
1511
+ svgChildren
1512
+ ] })
1513
+ }
1514
+ ),
1515
+ centerChildren.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1516
+ "div",
1517
+ {
1518
+ className: "pointer-events-none flex items-center justify-center",
1519
+ style: { gridArea: "1 / 1" },
1520
+ children: centerChildren
1521
+ }
1522
+ )
1523
+ ]
1524
+ }
1525
+ ) });
1526
+ }, ringChartCorePropsEqual);
1527
+ function ringChartCorePropsEqual(prev, next) {
1528
+ return prev.width === next.width && prev.height === next.height && prev.data === next.data && prev.strokeWidth === next.strokeWidth && prev.ringGap === next.ringGap && prev.baseInnerRadius === next.baseInnerRadius && prev.hoveredIndexProp === next.hoveredIndexProp && prev.onHoverChange === next.onHoverChange && prev.startAngle === next.startAngle && prev.endAngle === next.endAngle && prev.enterTransition === next.enterTransition && prev.enterStaggerScale === next.enterStaggerScale && prev.geometryScrubbing === next.geometryScrubbing && prev.children === next.children;
1529
+ }
1530
+ function RingChart({
1531
+ data,
1532
+ size: fixedSize,
1533
+ strokeWidth = 12,
1534
+ ringGap = 6,
1535
+ baseInnerRadius = 60,
1536
+ className = "",
1537
+ hoveredIndex,
1538
+ onHoverChange,
1539
+ startAngle = -Math.PI / 2,
1540
+ endAngle = 3 * Math.PI / 2,
1541
+ enterTransition,
1542
+ enterStaggerScale = 1,
1543
+ geometryScrubbing = false,
1544
+ children
1545
+ }) {
1546
+ const containerRef = react.useRef(null);
1547
+ if (fixedSize) {
1548
+ return /* @__PURE__ */ jsxRuntime.jsx(
1549
+ "div",
1550
+ {
1551
+ className: cn("relative flex items-center justify-center", className),
1552
+ ref: containerRef,
1553
+ style: { width: fixedSize, height: fixedSize },
1554
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1555
+ RingChartInner,
1556
+ {
1557
+ baseInnerRadius,
1558
+ containerRef,
1559
+ data,
1560
+ endAngle,
1561
+ enterStaggerScale,
1562
+ enterTransition,
1563
+ geometryScrubbing,
1564
+ height: fixedSize,
1565
+ hoveredIndexProp: hoveredIndex,
1566
+ onHoverChange,
1567
+ ringGap,
1568
+ startAngle,
1569
+ strokeWidth,
1570
+ width: fixedSize,
1571
+ children
1572
+ }
1573
+ )
1574
+ }
1575
+ );
1576
+ }
1577
+ return /* @__PURE__ */ jsxRuntime.jsx(
1578
+ "div",
1579
+ {
1580
+ className: cn("relative aspect-square w-full", className),
1581
+ ref: containerRef,
1582
+ children: /* @__PURE__ */ jsxRuntime.jsx(responsive.ParentSize, { debounceTime: 10, children: ({ width, height }) => /* @__PURE__ */ jsxRuntime.jsx(
1583
+ RingChartInner,
1584
+ {
1585
+ baseInnerRadius,
1586
+ containerRef,
1587
+ data,
1588
+ endAngle,
1589
+ enterStaggerScale,
1590
+ enterTransition,
1591
+ geometryScrubbing,
1592
+ height,
1593
+ hoveredIndexProp: hoveredIndex,
1594
+ onHoverChange,
1595
+ ringGap,
1596
+ startAngle,
1597
+ strokeWidth,
1598
+ width,
1599
+ children
1600
+ }
1601
+ ) })
1602
+ }
1603
+ );
1604
+ }
1605
+ function useEnterComplete(mountProgress) {
1606
+ const [complete, setComplete] = react.useState(() => mountProgress.get() >= 1);
1607
+ react.useEffect(() => {
1608
+ if (mountProgress.get() >= 1) {
1609
+ setComplete(true);
1610
+ return;
1611
+ }
1612
+ return mountProgress.on("change", (value) => {
1613
+ if (value >= 1) {
1614
+ setComplete(true);
1615
+ }
1616
+ });
1617
+ }, [mountProgress]);
1618
+ return complete;
1619
+ }
1620
+
1621
+ // src/components/charts/animation.ts
1622
+ var DEFAULT_ANIMATION_DURATION_MS = 1100;
1623
+ var DEFAULT_CHART_ENTER_TRANSITION = {
1624
+ type: "tween",
1625
+ duration: DEFAULT_ANIMATION_DURATION_MS / 1e3,
1626
+ ease: [0.85, 0, 0.15, 1]
1627
+ };
1628
+
1629
+ // src/components/charts/use-mount-progress.ts
1630
+ function useMountProgress(enterTransition, delaySeconds, replayKey) {
1631
+ const progress = react$1.useMotionValue(0);
1632
+ const transitionRef = react.useRef(enterTransition);
1633
+ transitionRef.current = enterTransition;
1634
+ react.useEffect(() => {
1635
+ progress.set(0);
1636
+ const controls = react$1.animate(progress, 1, {
1637
+ ...transitionRef.current ?? DEFAULT_CHART_ENTER_TRANSITION,
1638
+ delay: delaySeconds
1639
+ });
1640
+ return () => controls.stop();
1641
+ }, [delaySeconds, replayKey, progress]);
1642
+ return progress;
1643
+ }
1644
+ function generateArcPath(innerRadius, outerRadius, startAngle, endAngle, cornerRadius) {
1645
+ const generator = shape.arc({
1646
+ innerRadius,
1647
+ outerRadius,
1648
+ cornerRadius
1649
+ });
1650
+ return generator({ startAngle, endAngle }) || "";
1651
+ }
1652
+ function ringHoverScale(isHovered, isPushedOut) {
1653
+ if (isHovered) {
1654
+ return 1.03;
1655
+ }
1656
+ if (isPushedOut) {
1657
+ return 1.02;
1658
+ }
1659
+ return 1;
1660
+ }
1661
+ function RingProgressPath({
1662
+ progressComplete,
1663
+ progressPath,
1664
+ animatedProgressPath,
1665
+ color
1666
+ }) {
1667
+ if (progressComplete) {
1668
+ if (!progressPath) {
1669
+ return null;
1670
+ }
1671
+ return /* @__PURE__ */ jsxRuntime.jsx("path", { d: progressPath, fill: color });
1672
+ }
1673
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.motion.path, { d: animatedProgressPath, fill: color });
1674
+ }
1675
+ var Ring = react.memo(function Ring2({
1676
+ index,
1677
+ color: colorProp,
1678
+ animate: animate2 = true,
1679
+ showGlow = true,
1680
+ lineCap = "round"
1681
+ }) {
1682
+ const {
1683
+ data,
1684
+ getColor,
1685
+ getRingRadii,
1686
+ startAngle,
1687
+ endAngle,
1688
+ enterTransition,
1689
+ enterStaggerScale,
1690
+ animationKey
1691
+ } = useRingStable();
1692
+ const { hoveredIndex, setHoveredIndex } = useRingHover();
1693
+ const expandDelay = index * 0.08 * enterStaggerScale;
1694
+ const expandProgress = useMountProgress(
1695
+ enterTransition,
1696
+ expandDelay,
1697
+ `${animationKey}-expand-${index}`
1698
+ );
1699
+ const expandComplete = useEnterComplete(expandProgress);
1700
+ const progressDelay = (0.6 + index * 0.1) * enterStaggerScale;
1701
+ const progressMount = useMountProgress(
1702
+ enterTransition,
1703
+ progressDelay,
1704
+ `${animationKey}-progress-${index}`
1705
+ );
1706
+ const progressComplete = useEnterComplete(progressMount);
1707
+ const ringData = data[index];
1708
+ const progress = ringData ? ringData.value / ringData.maxValue : 0;
1709
+ const arcRange = endAngle - startAngle;
1710
+ const animatedProgressPath = react$1.useTransform(progressMount, (v) => {
1711
+ if (!ringData) {
1712
+ return "";
1713
+ }
1714
+ const currentEndAngle = startAngle + arcRange * progress * v;
1715
+ if (currentEndAngle <= startAngle + 0.01) {
1716
+ return "";
1717
+ }
1718
+ const radii = getRingRadii(index);
1719
+ const corner = lineCap === "round" ? (radii.outerRadius - radii.innerRadius) / 2 : 0;
1720
+ return generateArcPath(
1721
+ radii.innerRadius,
1722
+ radii.outerRadius,
1723
+ startAngle,
1724
+ currentEndAngle,
1725
+ corner
1726
+ );
1727
+ });
1728
+ const enterScale = react$1.useTransform(expandProgress, [0, 1], [0, 1]);
1729
+ const handleMouseEnter = react.useCallback(
1730
+ () => setHoveredIndex(index),
1731
+ [index, setHoveredIndex]
1732
+ );
1733
+ const handleMouseLeave = react.useCallback(
1734
+ () => setHoveredIndex(null),
1735
+ [setHoveredIndex]
1736
+ );
1737
+ if (!ringData) {
1738
+ return null;
1739
+ }
1740
+ const { innerRadius, outerRadius } = getRingRadii(index);
1741
+ const color = colorProp || getColor(index);
1742
+ const isHovered = hoveredIndex === index;
1743
+ const isFaded = hoveredIndex !== null && hoveredIndex !== index;
1744
+ const isPushedOut = hoveredIndex !== null && hoveredIndex < index;
1745
+ const cornerRadius = lineCap === "round" ? (outerRadius - innerRadius) / 2 : 0;
1746
+ const bgPath = generateArcPath(
1747
+ innerRadius,
1748
+ outerRadius,
1749
+ startAngle,
1750
+ endAngle,
1751
+ cornerRadius
1752
+ );
1753
+ const progressEndAngle = startAngle + arcRange * progress;
1754
+ const progressPath = progressEndAngle <= startAngle + 0.01 ? "" : generateArcPath(
1755
+ innerRadius,
1756
+ outerRadius,
1757
+ startAngle,
1758
+ progressEndAngle,
1759
+ cornerRadius
1760
+ );
1761
+ const hoverScale = ringHoverScale(isHovered, isPushedOut);
1762
+ const layerOpacity = isFaded ? 0.35 : 1;
1763
+ const enterDone = !animate2 || expandComplete && progressComplete;
1764
+ const groupStyle = {
1765
+ cursor: "pointer",
1766
+ transformOrigin: "0px 0px",
1767
+ filter: showGlow && isHovered ? `drop-shadow(0 0 12px ${color})` : "none"
1768
+ };
1769
+ if (enterDone) {
1770
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1771
+ react$1.motion.g,
1772
+ {
1773
+ animate: { scale: hoverScale, opacity: layerOpacity },
1774
+ onMouseEnter: handleMouseEnter,
1775
+ onMouseLeave: handleMouseLeave,
1776
+ style: groupStyle,
1777
+ transition: {
1778
+ scale: { type: "spring", stiffness: 400, damping: 25 },
1779
+ opacity: { duration: 0.15 }
1780
+ },
1781
+ children: [
1782
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: bgPath, fill: ringCssVars.ringBackground }),
1783
+ progressPath ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: progressPath, fill: color }) : null
1784
+ ]
1785
+ }
1786
+ );
1787
+ }
1788
+ if (!expandComplete) {
1789
+ return /* @__PURE__ */ jsxRuntime.jsx(
1790
+ react$1.motion.g,
1791
+ {
1792
+ onMouseEnter: handleMouseEnter,
1793
+ onMouseLeave: handleMouseLeave,
1794
+ style: {
1795
+ ...groupStyle,
1796
+ scale: enterScale,
1797
+ opacity: layerOpacity
1798
+ },
1799
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: bgPath, fill: ringCssVars.ringBackground })
1800
+ }
1801
+ );
1802
+ }
1803
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1804
+ react$1.motion.g,
1805
+ {
1806
+ animate: { scale: hoverScale, opacity: layerOpacity },
1807
+ onMouseEnter: handleMouseEnter,
1808
+ onMouseLeave: handleMouseLeave,
1809
+ style: groupStyle,
1810
+ transition: {
1811
+ scale: { type: "spring", stiffness: 400, damping: 25 },
1812
+ opacity: { duration: 0.15 }
1813
+ },
1814
+ children: [
1815
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: bgPath, fill: ringCssVars.ringBackground }),
1816
+ /* @__PURE__ */ jsxRuntime.jsx(
1817
+ RingProgressPath,
1818
+ {
1819
+ animatedProgressPath,
1820
+ color,
1821
+ progressComplete,
1822
+ progressPath
1823
+ }
1824
+ )
1825
+ ]
1826
+ }
1827
+ );
1828
+ });
1829
+ Ring.displayName = "Ring";
1830
+ function RingCenter({
1831
+ defaultLabel = "Total",
1832
+ formatOptions = defaultChartStatFlowFormat,
1833
+ children,
1834
+ className = "",
1835
+ valueClassName = chartCenterValueClassName,
1836
+ labelClassName = chartCenterLabelClassName,
1837
+ prefix,
1838
+ suffix
1839
+ }) {
1840
+ const { data, totalValue, baseInnerRadius } = useRingStable();
1841
+ const { hoveredIndex } = useRingHover();
1842
+ const hoveredData = hoveredIndex === null ? null : data[hoveredIndex];
1843
+ const displayValue = hoveredData ? hoveredData.value : totalValue;
1844
+ const displayLabel = hoveredData ? hoveredData.label : defaultLabel;
1845
+ const centerSize = baseInnerRadius * 2 - 16;
1846
+ if (children && hoveredData) {
1847
+ return /* @__PURE__ */ jsxRuntime.jsx(
1848
+ "div",
1849
+ {
1850
+ className: cn(
1851
+ chartCenterContainerClassName,
1852
+ "flex items-center justify-center",
1853
+ className
1854
+ ),
1855
+ style: { width: centerSize, height: centerSize },
1856
+ children: children({
1857
+ value: displayValue,
1858
+ label: displayLabel,
1859
+ isHovered: hoveredIndex !== null,
1860
+ data: hoveredData
1861
+ })
1862
+ }
1863
+ );
1864
+ }
1865
+ return /* @__PURE__ */ jsxRuntime.jsx(
1866
+ "div",
1867
+ {
1868
+ className: cn(
1869
+ chartCenterContainerClassName,
1870
+ "flex flex-col items-center justify-center text-center",
1871
+ className
1872
+ ),
1873
+ style: { width: centerSize, height: centerSize },
1874
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1875
+ ChartStatFlow,
1876
+ {
1877
+ formatOptions,
1878
+ label: displayLabel,
1879
+ labelClassName,
1880
+ prefix,
1881
+ suffix,
1882
+ value: displayValue,
1883
+ valueClassName
1884
+ }
1885
+ )
1886
+ }
1887
+ );
1888
+ }
1889
+ RingCenter.displayName = "RingCenter";
1890
+
1891
+ exports.ChartStatFlow = ChartStatFlow;
1892
+ exports.Gauge = Gauge;
1893
+ exports.Ring = Ring;
1894
+ exports.RingCenter = RingCenter;
1895
+ exports.RingChart = RingChart;
1896
+ exports.RingProvider = RingProvider;
1897
+ exports.defaultChartStatFlowFormat = defaultChartStatFlowFormat;
1898
+ exports.defaultRingColors = defaultRingColors;
1899
+ exports.ringCssVars = ringCssVars;
1900
+ exports.useRing = useRing;
1901
+ exports.useRingHover = useRingHover;
1902
+ exports.useRingStable = useRingStable;
1903
+ //# sourceMappingURL=charts.cjs.map
1904
+ //# sourceMappingURL=charts.cjs.map