@gfazioli/mantine-rings-progress 3.0.0 → 4.1.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.
- package/README.md +6 -1
- package/dist/cjs/RingsProgress.cjs +197 -26
- package/dist/cjs/RingsProgress.cjs.map +1 -1
- package/dist/cjs/RingsProgress.module.css.cjs +1 -1
- package/dist/esm/RingsProgress.mjs +198 -27
- package/dist/esm/RingsProgress.mjs.map +1 -1
- package/dist/esm/RingsProgress.module.css.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.layer.css +1 -1
- package/dist/types/RingsProgress.d.ts +31 -2
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -18,19 +18,24 @@
|
|
|
18
18
|
## Overview
|
|
19
19
|
|
|
20
20
|
This component is created on top of the [Mantine](https://mantine.dev/) library.
|
|
21
|
+
It requires **Mantine 9.x** and **React 19**.
|
|
21
22
|
|
|
22
23
|
[Mantine Rings Progress](https://gfazioli.github.io/mantine-rings-progress/) is a Mantine UI extension that renders multiple concentric ring progress indicators — inspired by the Apple Watch activity rings. Each ring is defined by a value and color, and the component wraps native Mantine `RingProgress` instances with rich customization options.
|
|
23
24
|
|
|
24
25
|
### Features
|
|
25
26
|
|
|
26
27
|
- **Per-ring customization** — Override `thickness`, `roundCaps`, and `rootColor` on individual rings
|
|
28
|
+
- **Per-ring linear gradients** — Paint a ring's stroke with a two-stop gradient via `gradient: { from, to, deg? }`
|
|
29
|
+
- **Per-ring value labels** — `showValues` (or per-ring `showValue`) drops a styled pill at the endpoint of each arc, with custom `formatValue`
|
|
30
|
+
- **Per-ring interactions** — `onClick` and `onHover` callbacks with **geometric hit-testing**, so the right ring fires even when their wrappers overlap
|
|
27
31
|
- **Entrance animation** — Animate rings from 0 to their target values on mount
|
|
28
32
|
- **Staggered animation** — Animate rings one after another with configurable delay
|
|
33
|
+
- **Animated value changes** — `animateValueChanges` interpolates value updates after mount (great for live dashboards)
|
|
29
34
|
- **Glow / neon effect** — `drop-shadow` glow that follows the ring shape, with per-ring intensity and color
|
|
30
35
|
- **Pulse on completion** — Subtle pulse animation when a ring reaches 100%, with `onRingComplete` callback
|
|
31
36
|
- **Start angle & direction** — Customize where rings start filling and in which direction (clockwise/counterclockwise)
|
|
32
37
|
- **Unified tooltip** — `withTooltip` shows a chart-like tooltip with color swatches for all rings
|
|
33
|
-
- **Accessibility** — `role="progressbar"` with ARIA attributes on each ring, `prefers-reduced-motion` support
|
|
38
|
+
- **Accessibility** — `role="progressbar"` with ARIA attributes on each ring, keyboard activation for clickable rings, `prefers-reduced-motion` support
|
|
34
39
|
- **Central label** — Display any React node (text, emoji, component) centered in the rings
|
|
35
40
|
|
|
36
41
|
> [!note]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var React = require('react');
|
|
5
4
|
var core = require('@mantine/core');
|
|
6
5
|
var hooks = require('@mantine/hooks');
|
|
6
|
+
var React = require('react');
|
|
7
7
|
var RingsProgress_module = require('./RingsProgress.module.css.cjs');
|
|
8
8
|
|
|
9
9
|
const defaultProps = {
|
|
@@ -11,7 +11,9 @@ const defaultProps = {
|
|
|
11
11
|
thickness: 12,
|
|
12
12
|
gap: 8,
|
|
13
13
|
animate: false,
|
|
14
|
+
animateValueChanges: false,
|
|
14
15
|
roundCaps: true,
|
|
16
|
+
showValues: false,
|
|
15
17
|
transitionDuration: 0,
|
|
16
18
|
rootColorAlpha: 0.15,
|
|
17
19
|
staggerDelay: 0,
|
|
@@ -21,7 +23,7 @@ const defaultProps = {
|
|
|
21
23
|
direction: "clockwise",
|
|
22
24
|
withTooltip: false
|
|
23
25
|
};
|
|
24
|
-
const RingsProgress = core.factory((_props
|
|
26
|
+
const RingsProgress = core.factory((_props) => {
|
|
25
27
|
const theme = core.useMantineTheme();
|
|
26
28
|
const reduceMotion = hooks.useReducedMotion();
|
|
27
29
|
const props = core.useProps("RingsProgress", defaultProps, _props);
|
|
@@ -33,6 +35,7 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
33
35
|
rootColorAlpha,
|
|
34
36
|
label,
|
|
35
37
|
animate,
|
|
38
|
+
animateValueChanges,
|
|
36
39
|
transitionDuration,
|
|
37
40
|
roundCaps,
|
|
38
41
|
staggerDelay,
|
|
@@ -43,6 +46,8 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
43
46
|
direction,
|
|
44
47
|
onRingComplete,
|
|
45
48
|
withTooltip,
|
|
49
|
+
showValues,
|
|
50
|
+
formatValue,
|
|
46
51
|
classNames,
|
|
47
52
|
styles,
|
|
48
53
|
unstyled,
|
|
@@ -58,6 +63,10 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
58
63
|
unstyled,
|
|
59
64
|
vars
|
|
60
65
|
});
|
|
66
|
+
const [instanceId] = React.useState(() => Math.random().toString(36).slice(2, 9));
|
|
67
|
+
const ringsRef = React.useRef(rings);
|
|
68
|
+
ringsRef.current = rings;
|
|
69
|
+
const ringCount = rings.length;
|
|
61
70
|
const [mountedRings, setMountedRings] = React.useState(
|
|
62
71
|
() => rings.map(() => !animate || reduceMotion)
|
|
63
72
|
);
|
|
@@ -68,13 +77,13 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
68
77
|
}, []);
|
|
69
78
|
React.useEffect(() => {
|
|
70
79
|
if (!animate || reduceMotion) {
|
|
71
|
-
setMountedRings(
|
|
80
|
+
setMountedRings(Array.from({ length: ringCount }, () => true));
|
|
72
81
|
return;
|
|
73
82
|
}
|
|
74
|
-
setMountedRings(
|
|
83
|
+
setMountedRings(Array.from({ length: ringCount }, () => false));
|
|
75
84
|
cleanupTimeouts();
|
|
76
85
|
if (staggerDelay && staggerDelay > 0) {
|
|
77
|
-
|
|
86
|
+
for (let index = 0; index < ringCount; index++) {
|
|
78
87
|
const timeout = setTimeout(() => {
|
|
79
88
|
setMountedRings((prev) => {
|
|
80
89
|
const next = [...prev];
|
|
@@ -83,23 +92,25 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
83
92
|
});
|
|
84
93
|
}, index * staggerDelay);
|
|
85
94
|
timeoutsRef.current.push(timeout);
|
|
86
|
-
}
|
|
95
|
+
}
|
|
87
96
|
} else {
|
|
88
97
|
requestAnimationFrame(() => {
|
|
89
|
-
setMountedRings(
|
|
98
|
+
setMountedRings(Array.from({ length: ringCount }, () => true));
|
|
90
99
|
});
|
|
91
100
|
}
|
|
92
101
|
return cleanupTimeouts;
|
|
93
|
-
}, [animate, reduceMotion,
|
|
102
|
+
}, [animate, reduceMotion, ringCount, staggerDelay, cleanupTimeouts]);
|
|
94
103
|
const prevValuesRef = React.useRef(rings.map((r) => r.value));
|
|
95
104
|
const [pulsingRings, setPulsingRings] = React.useState(rings.map(() => false));
|
|
96
105
|
const ringValuesKey = rings.map((r) => r.value).join(",");
|
|
97
106
|
React.useEffect(() => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
const current = ringsRef.current;
|
|
108
|
+
prevValuesRef.current = current.map((r) => r.value);
|
|
109
|
+
setPulsingRings(current.map(() => false));
|
|
110
|
+
}, [ringCount]);
|
|
101
111
|
React.useEffect(() => {
|
|
102
|
-
const
|
|
112
|
+
const current = ringsRef.current;
|
|
113
|
+
const currentValues = current.map((r) => r.value);
|
|
103
114
|
const crossedComplete = currentValues.map((value, i) => {
|
|
104
115
|
const prev = prevValuesRef.current[i] ?? 0;
|
|
105
116
|
return value >= 100 && prev < 100;
|
|
@@ -107,7 +118,7 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
107
118
|
if (onRingComplete) {
|
|
108
119
|
crossedComplete.forEach((crossed, i) => {
|
|
109
120
|
if (crossed) {
|
|
110
|
-
onRingComplete(i,
|
|
121
|
+
onRingComplete(i, current[i]);
|
|
111
122
|
}
|
|
112
123
|
});
|
|
113
124
|
}
|
|
@@ -115,7 +126,20 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
115
126
|
setPulsingRings(crossedComplete);
|
|
116
127
|
}
|
|
117
128
|
prevValuesRef.current = currentValues;
|
|
118
|
-
}, [ringValuesKey, pulseOnComplete, reduceMotion, onRingComplete
|
|
129
|
+
}, [ringValuesKey, pulseOnComplete, reduceMotion, onRingComplete]);
|
|
130
|
+
const gradientDefs = rings.map((ring, index) => {
|
|
131
|
+
if (!ring.gradient) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const id = `rp-grad-${instanceId}-${index}`;
|
|
135
|
+
const cssDeg = ring.gradient.deg ?? 0;
|
|
136
|
+
const svgDeg = cssDeg - 90;
|
|
137
|
+
const fromColor = core.parseThemeColor({ color: ring.gradient.from, theme }).value;
|
|
138
|
+
const toColor = core.parseThemeColor({ color: ring.gradient.to, theme }).value;
|
|
139
|
+
return { id, fromColor, toColor, svgDeg };
|
|
140
|
+
}).filter(
|
|
141
|
+
(g) => g !== null
|
|
142
|
+
);
|
|
119
143
|
const handleAnimationEnd = React.useCallback((index) => {
|
|
120
144
|
setPulsingRings((prev) => {
|
|
121
145
|
const next = [...prev];
|
|
@@ -124,25 +148,115 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
124
148
|
});
|
|
125
149
|
}, []);
|
|
126
150
|
const allMounted = mountedRings.every(Boolean);
|
|
127
|
-
const effectiveTransitionDuration = reduceMotion ? 0 : animate && !allMounted ? transitionDuration || 1e3 : transitionDuration;
|
|
151
|
+
const effectiveTransitionDuration = reduceMotion ? 0 : animate && !allMounted ? transitionDuration || 1e3 : animateValueChanges ? transitionDuration || 500 : transitionDuration;
|
|
128
152
|
const offsets = [];
|
|
129
153
|
let cumulativeOffset = 0;
|
|
130
154
|
for (let i = 0; i < rings.length; i++) {
|
|
131
155
|
offsets.push(cumulativeOffset);
|
|
132
156
|
const ringThickness = rings[i].thickness ?? thickness;
|
|
133
|
-
cumulativeOffset += ringThickness + gap;
|
|
157
|
+
cumulativeOffset += (ringThickness ?? 0) + (gap ?? 0);
|
|
134
158
|
}
|
|
159
|
+
const hasInteractive = rings.some((r) => r.onClick || r.onHover);
|
|
160
|
+
const [hoveredIndex, setHoveredIndex] = React.useState(null);
|
|
161
|
+
const hoveredIndexRef = React.useRef(null);
|
|
162
|
+
hoveredIndexRef.current = hoveredIndex;
|
|
163
|
+
const ringAtPoint = React.useCallback(
|
|
164
|
+
(clientX, clientY, rect) => {
|
|
165
|
+
const cx = rect.left + rect.width / 2;
|
|
166
|
+
const cy = rect.top + rect.height / 2;
|
|
167
|
+
const r = Math.hypot(clientX - cx, clientY - cy);
|
|
168
|
+
const current = ringsRef.current;
|
|
169
|
+
for (let i = 0; i < current.length; i++) {
|
|
170
|
+
const t = current[i].thickness ?? thickness ?? 12;
|
|
171
|
+
const ringSize = (size ?? 120) - offsets[i] * 2;
|
|
172
|
+
const centerR = (ringSize * 0.9 - t * 2) / 2;
|
|
173
|
+
if (Math.abs(r - centerR) <= t / 2) {
|
|
174
|
+
return i;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
},
|
|
179
|
+
// offsets is recomputed every render; capture by closure rather than listing it
|
|
180
|
+
// (size/thickness are stable refs through props).
|
|
181
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
182
|
+
[size, thickness, ringCount]
|
|
183
|
+
);
|
|
184
|
+
const handleContainerClick = React.useCallback(
|
|
185
|
+
(event) => {
|
|
186
|
+
if (!hasInteractive) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
190
|
+
const idx = ringAtPoint(event.clientX, event.clientY, rect);
|
|
191
|
+
if (idx === null) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const ring = ringsRef.current[idx];
|
|
195
|
+
ring.onClick?.(ring, idx);
|
|
196
|
+
},
|
|
197
|
+
[hasInteractive, ringAtPoint]
|
|
198
|
+
);
|
|
199
|
+
const handleContainerMouseMove = React.useCallback(
|
|
200
|
+
(event) => {
|
|
201
|
+
if (!hasInteractive) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
205
|
+
const idx = ringAtPoint(event.clientX, event.clientY, rect);
|
|
206
|
+
if (idx === hoveredIndexRef.current) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const prev = hoveredIndexRef.current;
|
|
210
|
+
if (prev !== null) {
|
|
211
|
+
const prevRing = ringsRef.current[prev];
|
|
212
|
+
prevRing.onHover?.(prevRing, prev, false);
|
|
213
|
+
}
|
|
214
|
+
setHoveredIndex(idx);
|
|
215
|
+
if (idx !== null) {
|
|
216
|
+
const newRing = ringsRef.current[idx];
|
|
217
|
+
newRing.onHover?.(newRing, idx, true);
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
[hasInteractive, ringAtPoint]
|
|
221
|
+
);
|
|
222
|
+
const handleContainerMouseLeave = React.useCallback(() => {
|
|
223
|
+
if (hoveredIndexRef.current === null) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const prev = hoveredIndexRef.current;
|
|
227
|
+
const prevRing = ringsRef.current[prev];
|
|
228
|
+
prevRing.onHover?.(prevRing, prev, false);
|
|
229
|
+
setHoveredIndex(null);
|
|
230
|
+
}, []);
|
|
231
|
+
const containerCursor = hoveredIndex !== null && rings[hoveredIndex]?.onClick ? "pointer" : void 0;
|
|
135
232
|
const glowBlur = glow === true ? 6 : typeof glow === "number" ? glow : 0;
|
|
136
|
-
const svgTransform = startAngle !== 0 || direction === "counterclockwise" ? `rotate(${ -90 + startAngle}deg)${direction === "counterclockwise" ? " scaleX(-1)" : ""}` : void 0;
|
|
233
|
+
const svgTransform = startAngle !== 0 || direction === "counterclockwise" ? `rotate(${ -90 + (startAngle ?? 0)}deg)${direction === "counterclockwise" ? " scaleX(-1)" : ""}` : void 0;
|
|
137
234
|
const content = /* @__PURE__ */ React.createElement(
|
|
138
235
|
core.Box,
|
|
139
236
|
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
237
|
+
...getStyles("root", {
|
|
238
|
+
style: { width: size, height: size, cursor: containerCursor }
|
|
239
|
+
}),
|
|
240
|
+
...others,
|
|
241
|
+
role: others.role ?? "group",
|
|
242
|
+
"aria-label": others["aria-label"] ?? (others["aria-labelledby"] ? void 0 : "Progress rings"),
|
|
243
|
+
onClick: hasInteractive ? handleContainerClick : others.onClick,
|
|
244
|
+
onMouseMove: hasInteractive ? handleContainerMouseMove : others.onMouseMove,
|
|
245
|
+
onMouseLeave: hasInteractive ? handleContainerMouseLeave : others.onMouseLeave,
|
|
246
|
+
"data-interactive": hasInteractive || void 0,
|
|
247
|
+
"data-hovered-ring": hoveredIndex ?? void 0
|
|
145
248
|
},
|
|
249
|
+
gradientDefs.length > 0 && /* @__PURE__ */ React.createElement("svg", { "aria-hidden": true, style: { position: "absolute", width: 0, height: 0, overflow: "hidden" } }, /* @__PURE__ */ React.createElement("defs", null, gradientDefs.map((g) => /* @__PURE__ */ React.createElement(
|
|
250
|
+
"linearGradient",
|
|
251
|
+
{
|
|
252
|
+
key: g.id,
|
|
253
|
+
id: g.id,
|
|
254
|
+
gradientUnits: "objectBoundingBox",
|
|
255
|
+
gradientTransform: `rotate(${g.svgDeg}, 0.5, 0.5)`
|
|
256
|
+
},
|
|
257
|
+
/* @__PURE__ */ React.createElement("stop", { offset: "0%", stopColor: g.fromColor }),
|
|
258
|
+
/* @__PURE__ */ React.createElement("stop", { offset: "100%", stopColor: g.toColor })
|
|
259
|
+
)))),
|
|
146
260
|
rings.map((ring, index) => {
|
|
147
261
|
const {
|
|
148
262
|
thickness: ringThicknessOverride,
|
|
@@ -151,6 +265,11 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
151
265
|
glowIntensity,
|
|
152
266
|
glowColor,
|
|
153
267
|
rootColor: ringRootColor,
|
|
268
|
+
onClick: ringOnClick,
|
|
269
|
+
onHover: _ringOnHover,
|
|
270
|
+
showValue: _ringShowValue,
|
|
271
|
+
formatValue: _ringFormatValue,
|
|
272
|
+
gradient: _ringGradient,
|
|
154
273
|
...ringSection
|
|
155
274
|
} = ring;
|
|
156
275
|
const parsedColor = core.parseThemeColor({ color: ring.color, theme });
|
|
@@ -162,22 +281,38 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
162
281
|
const ringGlowColor = glowColor ? core.parseThemeColor({ color: glowColor, theme }).value : parsedColor.value;
|
|
163
282
|
const glowFilter = ringGlowBlur > 0 ? `drop-shadow(0 0 ${ringGlowBlur}px ${ringGlowColor})` : void 0;
|
|
164
283
|
const { tooltip: _tooltip, ...sectionWithoutTooltip } = ringSection;
|
|
284
|
+
const sectionColor = ring.gradient ? `url(#rp-grad-${instanceId}-${index})` : sectionWithoutTooltip.color;
|
|
165
285
|
const isPulsing = pulseOnComplete && pulsingRings[index];
|
|
286
|
+
const interactive = Boolean(ringOnClick);
|
|
287
|
+
const handleKeyDown = ringOnClick ? (event) => {
|
|
288
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
289
|
+
event.preventDefault();
|
|
290
|
+
ringOnClick(ring, index);
|
|
291
|
+
}
|
|
292
|
+
} : void 0;
|
|
166
293
|
return /* @__PURE__ */ React.createElement(
|
|
167
294
|
core.RingProgress,
|
|
168
295
|
{
|
|
169
296
|
key: index,
|
|
170
|
-
rootColor: ringRootColor ? core.parseThemeColor({ color: ringRootColor, theme }).value : core.alpha(parsedColor.value, rootColorAlpha),
|
|
171
|
-
size: size - offsets[index] * 2,
|
|
297
|
+
rootColor: ringRootColor ? core.parseThemeColor({ color: ringRootColor, theme }).value : core.alpha(parsedColor.value, rootColorAlpha ?? 0.1),
|
|
298
|
+
size: (size ?? 0) - offsets[index] * 2,
|
|
172
299
|
thickness: ringThickness,
|
|
173
300
|
roundCaps: ringRoundCaps,
|
|
174
301
|
transitionDuration: effectiveTransitionDuration,
|
|
175
|
-
sections: [
|
|
176
|
-
|
|
302
|
+
sections: [
|
|
303
|
+
{
|
|
304
|
+
...sectionWithoutTooltip,
|
|
305
|
+
value: effectiveValue,
|
|
306
|
+
color: sectionColor
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
role: interactive ? "button" : "progressbar",
|
|
177
310
|
"aria-valuenow": Math.round(ring.value),
|
|
178
311
|
"aria-valuemin": 0,
|
|
179
312
|
"aria-valuemax": 100,
|
|
180
313
|
"aria-label": ringAriaLabel,
|
|
314
|
+
tabIndex: interactive ? 0 : void 0,
|
|
315
|
+
onKeyDown: handleKeyDown,
|
|
181
316
|
styles: glowFilter || svgTransform ? {
|
|
182
317
|
svg: {
|
|
183
318
|
...glowFilter ? { filter: glowFilter } : {},
|
|
@@ -196,6 +331,42 @@ const RingsProgress = core.factory((_props, ref) => {
|
|
|
196
331
|
}
|
|
197
332
|
);
|
|
198
333
|
}),
|
|
334
|
+
(showValues || rings.some((r) => r.showValue)) && rings.map((ring, index) => {
|
|
335
|
+
const shouldShow = ring.showValue ?? showValues;
|
|
336
|
+
if (!shouldShow) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
const ringT = ring.thickness ?? thickness ?? 12;
|
|
340
|
+
const ringSize = (size ?? 120) - offsets[index] * 2;
|
|
341
|
+
const ringR = (ringSize * 0.9 - ringT * 2) / 2;
|
|
342
|
+
const clampedValue = Math.max(0, Math.min(100, ring.value));
|
|
343
|
+
const directionMultiplier = direction === "counterclockwise" ? -1 : 1;
|
|
344
|
+
const endAngleDeg = (startAngle ?? 0) + clampedValue / 100 * 360 * directionMultiplier;
|
|
345
|
+
const angleRad = endAngleDeg * Math.PI / 180;
|
|
346
|
+
const center = (size ?? 120) / 2;
|
|
347
|
+
const x = center + ringR * Math.sin(angleRad);
|
|
348
|
+
const y = center - ringR * Math.cos(angleRad);
|
|
349
|
+
const formatter = ring.formatValue ?? formatValue ?? ((v) => `${Math.round(v)}%`);
|
|
350
|
+
const labelColor = core.parseThemeColor({ color: ring.color, theme }).value;
|
|
351
|
+
return /* @__PURE__ */ React.createElement(
|
|
352
|
+
core.Box,
|
|
353
|
+
{
|
|
354
|
+
key: `value-${index}`,
|
|
355
|
+
...getStyles("valueLabel", {
|
|
356
|
+
style: {
|
|
357
|
+
position: "absolute",
|
|
358
|
+
left: x,
|
|
359
|
+
top: y,
|
|
360
|
+
transform: "translate(-50%, -50%)",
|
|
361
|
+
pointerEvents: "none",
|
|
362
|
+
color: labelColor
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
"data-ring-index": index
|
|
366
|
+
},
|
|
367
|
+
formatter(ring.value)
|
|
368
|
+
);
|
|
369
|
+
}),
|
|
199
370
|
label && /* @__PURE__ */ React.createElement(core.Box, { ...getStyles("label") }, label)
|
|
200
371
|
);
|
|
201
372
|
if (withTooltip) {
|