@thebuoyant-tsdev/mui-ts-library 3.14.1 → 3.15.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.de.md +14 -0
- package/README.md +14 -0
- package/dist/components/radial-stacked-bar-chart/RadialStackedBarChart.d.ts +5 -0
- package/dist/components/radial-stacked-bar-chart/RadialStackedBarChart.js +285 -0
- package/dist/components/radial-stacked-bar-chart/RadialStackedBarChart.types.d.ts +91 -0
- package/dist/components/radial-stacked-bar-chart/RadialStackedBarChart.types.js +4 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/package.json +2 -2
package/README.de.md
CHANGED
|
@@ -434,6 +434,20 @@ Dieses Projekt folgt [Semantic Versioning](https://semver.org/). In der Praxis b
|
|
|
434
434
|
|
|
435
435
|
## Changelog
|
|
436
436
|
|
|
437
|
+
### [3.15.0] — 2026-07-03
|
|
438
|
+
|
|
439
|
+
**Hinzugefügt**
|
|
440
|
+
- Neue Komponente: `RadialStackedBarChart` — Mehrreihige Stapelbalken im radialen Layout (6. D3-Chart). Features: 20+ Props, konzentrische Gitterringe mit eigenem Formatter, automatisch zentrierte Legende mit Overflow-Schutz, `sortBy`, `colorConfig`, `onBarClick`, `zoomable` und volle Dark-Mode-Unterstützung. Siehe [Vollständiger Changelog](https://github.com/thebuoyant/mui-ts-library/blob/main/CHANGELOG.md) für Details.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
### [3.14.1] — 2026-07-02
|
|
445
|
+
|
|
446
|
+
**Behoben**
|
|
447
|
+
- README: fehlender Changelog-Eintrag für 3.14.0 — keine Code-Änderungen.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
437
451
|
### [3.14.0] — 2026-07-02
|
|
438
452
|
|
|
439
453
|
**Hinzugefügt**
|
package/README.md
CHANGED
|
@@ -434,6 +434,20 @@ This project follows [Semantic Versioning](https://semver.org/). In practice:
|
|
|
434
434
|
|
|
435
435
|
## Changelog
|
|
436
436
|
|
|
437
|
+
### [3.15.0] — 2026-07-03
|
|
438
|
+
|
|
439
|
+
**Added**
|
|
440
|
+
- New component: `RadialStackedBarChart` — multi-series stacked bars in a radial layout (6th D3 chart). Features: 20+ props, concentric grid rings with custom formatter, auto-centered legend with overflow protection, `sortBy`, `colorConfig`, `onBarClick`, `zoomable`, and full dark-mode support. See [Full Changelog](https://github.com/thebuoyant/mui-ts-library/blob/main/CHANGELOG.md) for details.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
### [3.14.1] — 2026-07-02
|
|
445
|
+
|
|
446
|
+
**Fixed**
|
|
447
|
+
- README: missing changelog entry for 3.14.0 — no code changes.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
437
451
|
### [3.14.0] — 2026-07-02
|
|
438
452
|
|
|
439
453
|
**Added**
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type RadialStackedBarChartProps } from "./RadialStackedBarChart.types";
|
|
2
|
+
export declare function RadialStackedBarChart({ data, keys, size, innerRadius, barPadding, chartColors, colorConfig, showLabels, showGridLines, gridLineCount, showGridValues, showLegend, sortBy, valueDecimalCount, valueDecimalSeparator, valueThousandsSeparator, gridValueFormatter, zoomable, onBarClick, disabled, translation, }: RadialStackedBarChartProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare namespace RadialStackedBarChart {
|
|
4
|
+
var displayName: string;
|
|
5
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { DEFAULT_RADIAL_STACKED_BAR_CHART_TRANSLATION as e } from "./RadialStackedBarChart.types.js";
|
|
2
|
+
import { useCallback as t, useLayoutEffect as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
3
|
+
import { Box as o, Tooltip as s, Typography as c, useTheme as l } from "@mui/material";
|
|
4
|
+
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
5
|
+
import * as p from "d3";
|
|
6
|
+
//#region src/components/radial-stacked-bar-chart/RadialStackedBarChart.tsx
|
|
7
|
+
function m(e, t = 0, n = ".", r = ",") {
|
|
8
|
+
let [i, a] = e.toFixed(Math.max(0, t)).split("."), o = i.replace(/\B(?=(\d{3})+(?!\d))/g, r);
|
|
9
|
+
return a ? `${o}${n}${a}` : o;
|
|
10
|
+
}
|
|
11
|
+
function ee(e) {
|
|
12
|
+
return Math.abs(e) >= 1e9 ? `${(e / 1e9).toFixed(1).replace(/\.0$/, "")}B` : Math.abs(e) >= 1e6 ? `${(e / 1e6).toFixed(1).replace(/\.0$/, "")}M` : Math.abs(e) >= 1e3 ? `${(e / 1e3).toFixed(1).replace(/\.0$/, "")}k` : String(e);
|
|
13
|
+
}
|
|
14
|
+
function te(e) {
|
|
15
|
+
return e.map((e) => typeof e == "string" ? {
|
|
16
|
+
key: e,
|
|
17
|
+
label: e
|
|
18
|
+
} : e);
|
|
19
|
+
}
|
|
20
|
+
function ne({ barData: e, seriesKey: t, seriesLabel: n, decimals: r, decimalSep: i, thousandSep: a }) {
|
|
21
|
+
let s = e.values[t] ?? 0, l = p.sum(Object.values(e.values)), u = l > 0 ? Math.round(s / l * 1e3) / 10 : 0;
|
|
22
|
+
return /* @__PURE__ */ f(o, {
|
|
23
|
+
sx: { py: .25 },
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ d(c, {
|
|
26
|
+
variant: "caption",
|
|
27
|
+
sx: {
|
|
28
|
+
fontWeight: "bold",
|
|
29
|
+
display: "block"
|
|
30
|
+
},
|
|
31
|
+
children: e.label
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ f(c, {
|
|
34
|
+
variant: "caption",
|
|
35
|
+
sx: {
|
|
36
|
+
display: "block",
|
|
37
|
+
opacity: .85
|
|
38
|
+
},
|
|
39
|
+
children: [
|
|
40
|
+
n,
|
|
41
|
+
": ",
|
|
42
|
+
m(s, r, i, a)
|
|
43
|
+
]
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ f(c, {
|
|
46
|
+
variant: "caption",
|
|
47
|
+
sx: {
|
|
48
|
+
display: "block",
|
|
49
|
+
opacity: .65,
|
|
50
|
+
mt: .25
|
|
51
|
+
},
|
|
52
|
+
children: [
|
|
53
|
+
u,
|
|
54
|
+
"% · Total: ",
|
|
55
|
+
m(l, r, i, a)
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function h({ data: c, keys: m, size: h = 500, innerRadius: g, barPadding: _ = .12, chartColors: v, colorConfig: y, showLabels: b = !0, showGridLines: x = !0, gridLineCount: S = 3, showGridValues: re = !0, showLegend: C = !0, sortBy: w = "none", valueDecimalCount: ie = 0, valueDecimalSeparator: ae = ".", valueThousandsSeparator: oe = ",", gridValueFormatter: se, zoomable: T = !1, onBarClick: ce, disabled: E = !1, translation: D }) {
|
|
62
|
+
let O = l(), k = {
|
|
63
|
+
...e,
|
|
64
|
+
...D
|
|
65
|
+
}, A = r(() => te(m), [m]), j = r(() => A.map((e) => e.key), [A]), M = c.length === 0 || A.length === 0, le = b ? 63 : 16, N = h / 2 - le, P = g == null ? Math.round(h * .18) : Math.max(0, Math.min(g, N - 1)), ue = [
|
|
66
|
+
O.palette.primary.main,
|
|
67
|
+
O.palette.secondary.main,
|
|
68
|
+
O.palette.success.main,
|
|
69
|
+
O.palette.warning.main,
|
|
70
|
+
O.palette.error.main,
|
|
71
|
+
O.palette.info.main,
|
|
72
|
+
"#8e24aa",
|
|
73
|
+
"#00897b",
|
|
74
|
+
"#f06292",
|
|
75
|
+
"#a1887f"
|
|
76
|
+
], F = v && v.length > 0 ? v : ue, I = t((e, t) => {
|
|
77
|
+
let n = y?.[e];
|
|
78
|
+
return n?.fill ? n.fill : F[t % F.length];
|
|
79
|
+
}, [y, F]), L = r(() => w === "value" ? [...c].sort((e, t) => p.sum(j, (e) => t.values[e] ?? 0) - p.sum(j, (t) => e.values[t] ?? 0)) : w === "label" ? [...c].sort((e, t) => e.label.localeCompare(t.label, void 0, {
|
|
80
|
+
numeric: !0,
|
|
81
|
+
sensitivity: "base"
|
|
82
|
+
})) : c, [
|
|
83
|
+
c,
|
|
84
|
+
w,
|
|
85
|
+
j
|
|
86
|
+
]), R = r(() => p.max(L, (e) => p.sum(j, (t) => e.values[t] ?? 0)) ?? 0, [L, j]), z = r(() => p.scaleBand().domain(L.map((e) => e.id)).range([0, 2 * Math.PI]).padding(_), [L, _]), B = r(() => p.scaleLinear().domain([0, R]).range([P, N]), [
|
|
87
|
+
P,
|
|
88
|
+
N,
|
|
89
|
+
R
|
|
90
|
+
]), V = r(() => M ? [] : p.stack().keys(j).value((e, t) => e.values[t] ?? 0).order(p.stackOrderNone).offset(p.stackOffsetNone)(L), [
|
|
91
|
+
M,
|
|
92
|
+
L,
|
|
93
|
+
j
|
|
94
|
+
]), H = r(() => p.arc().startAngle((e) => e.x0).endAngle((e) => e.x1).innerRadius((e) => e.y0).outerRadius((e) => e.y1).padAngle(.008).padRadius(P + 10), [P]), U = r(() => R > 0 ? p.ticks(0, R, S).filter((e) => e > 0) : [], [R, S]), de = se ?? ee, [W, G] = a(1), K = i(null), [q, J] = a(`-${h / 2} -${h / 2} ${h} ${h}`), fe = r(() => {
|
|
95
|
+
if (W === 1) return q;
|
|
96
|
+
let [e, t, n, r] = q.split(" ").map(Number), i = n / W, a = r / W;
|
|
97
|
+
return `${e + (n - i) / 2} ${t + (r - a) / 2} ${i} ${a}`;
|
|
98
|
+
}, [q, W]);
|
|
99
|
+
n(() => {
|
|
100
|
+
let e = K.current;
|
|
101
|
+
if (!e) return;
|
|
102
|
+
let t = requestAnimationFrame(() => {
|
|
103
|
+
try {
|
|
104
|
+
let t = e.getBBox();
|
|
105
|
+
J(`${t.x - 4} ${t.y - 4} ${t.width + 8} ${t.height + 8}`);
|
|
106
|
+
} catch {
|
|
107
|
+
J(`-${h / 2} -${h / 2} ${h} ${h}`);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return () => cancelAnimationFrame(t);
|
|
111
|
+
}, [
|
|
112
|
+
h,
|
|
113
|
+
c,
|
|
114
|
+
m,
|
|
115
|
+
P,
|
|
116
|
+
N,
|
|
117
|
+
b,
|
|
118
|
+
x
|
|
119
|
+
]), n(() => {
|
|
120
|
+
if (E) return;
|
|
121
|
+
let e = (e) => {
|
|
122
|
+
e.key === "Escape" && G(1);
|
|
123
|
+
};
|
|
124
|
+
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
125
|
+
}, [E]);
|
|
126
|
+
let pe = t((e) => {
|
|
127
|
+
if (!T || E || !e.ctrlKey) return;
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
let t = e.deltaY < 0 ? 1.15 : 1 / 1.15;
|
|
130
|
+
G((e) => Math.max(.25, Math.min(8, e * t)));
|
|
131
|
+
}, [T, E]), me = -(A.length * 16) / 2, Y = Math.max(0, P * 2 - 10 - 5 - 10), X = 9 * .57, he = A.reduce((e, t) => Math.max(e, (t.label ?? t.key).length), 0), ge = -((15 + Math.min(he * X, Y)) / 2), Z = Math.max(1, Math.floor(Y / X)), _e = (e) => e.length <= Z ? e : `${e.slice(0, Z - 1)}…`, ve = {
|
|
132
|
+
followCursor: !0,
|
|
133
|
+
enterDelay: 50,
|
|
134
|
+
enterNextDelay: 0,
|
|
135
|
+
disableHoverListener: E,
|
|
136
|
+
slotProps: { tooltip: { sx: { maxWidth: 240 } } }
|
|
137
|
+
}, Q = O.palette.text.primary, $ = O.palette.divider, ye = O.typography.fontFamily;
|
|
138
|
+
return /* @__PURE__ */ d(o, {
|
|
139
|
+
style: { opacity: E ? .5 : 1 },
|
|
140
|
+
sx: {
|
|
141
|
+
display: "inline-flex",
|
|
142
|
+
cursor: E ? "not-allowed" : "default",
|
|
143
|
+
userSelect: "none"
|
|
144
|
+
},
|
|
145
|
+
children: /* @__PURE__ */ d("svg", {
|
|
146
|
+
width: h,
|
|
147
|
+
height: h,
|
|
148
|
+
viewBox: fe,
|
|
149
|
+
onWheel: pe,
|
|
150
|
+
style: {
|
|
151
|
+
fontFamily: ye ?? "sans-serif",
|
|
152
|
+
overflow: T && W > 1 ? "hidden" : "visible"
|
|
153
|
+
},
|
|
154
|
+
role: "img",
|
|
155
|
+
"aria-label": "Radial stacked bar chart",
|
|
156
|
+
children: /* @__PURE__ */ f("g", {
|
|
157
|
+
ref: K,
|
|
158
|
+
children: [M && /* @__PURE__ */ d("text", {
|
|
159
|
+
textAnchor: "middle",
|
|
160
|
+
dy: "0.35em",
|
|
161
|
+
fontSize: 13,
|
|
162
|
+
fill: O.palette.text.secondary,
|
|
163
|
+
children: k.noData
|
|
164
|
+
}), !M && /* @__PURE__ */ f(u, { children: [
|
|
165
|
+
x && U.map((e) => /* @__PURE__ */ d("circle", {
|
|
166
|
+
r: B(e),
|
|
167
|
+
fill: "none",
|
|
168
|
+
stroke: $,
|
|
169
|
+
strokeWidth: .5,
|
|
170
|
+
strokeDasharray: "3 2"
|
|
171
|
+
}, `grid-${e}`)),
|
|
172
|
+
x && /* @__PURE__ */ d("circle", {
|
|
173
|
+
r: P,
|
|
174
|
+
fill: "none",
|
|
175
|
+
stroke: $,
|
|
176
|
+
strokeWidth: .75
|
|
177
|
+
}),
|
|
178
|
+
x && re && U.map((e) => /* @__PURE__ */ d("text", {
|
|
179
|
+
x: 0,
|
|
180
|
+
y: -B(e),
|
|
181
|
+
textAnchor: "middle",
|
|
182
|
+
dy: "-3",
|
|
183
|
+
fontSize: 9,
|
|
184
|
+
fill: O.palette.text.secondary,
|
|
185
|
+
pointerEvents: "none",
|
|
186
|
+
children: de(e)
|
|
187
|
+
}, `gv-${e}`)),
|
|
188
|
+
V.map((e, t) => {
|
|
189
|
+
let n = e.key, r = A[t]?.label ?? n, i = I(n, t);
|
|
190
|
+
return e.map((e, t) => {
|
|
191
|
+
let a = e.data, o = z(a.id) ?? 0, c = o + z.bandwidth(), l = B(e[0]), u = B(e[1]);
|
|
192
|
+
if (u - l < .5) return null;
|
|
193
|
+
let f = H({
|
|
194
|
+
x0: o,
|
|
195
|
+
x1: c,
|
|
196
|
+
y0: l,
|
|
197
|
+
y1: u
|
|
198
|
+
}) ?? "";
|
|
199
|
+
return /* @__PURE__ */ d(s, {
|
|
200
|
+
...ve,
|
|
201
|
+
placement: "top",
|
|
202
|
+
title: /* @__PURE__ */ d(ne, {
|
|
203
|
+
barData: a,
|
|
204
|
+
seriesKey: n,
|
|
205
|
+
seriesLabel: r,
|
|
206
|
+
decimals: ie,
|
|
207
|
+
decimalSep: ae,
|
|
208
|
+
thousandSep: oe
|
|
209
|
+
}),
|
|
210
|
+
children: /* @__PURE__ */ d("path", {
|
|
211
|
+
d: f,
|
|
212
|
+
fill: i,
|
|
213
|
+
style: {
|
|
214
|
+
cursor: E ? "not-allowed" : "pointer",
|
|
215
|
+
transition: "opacity 0.15s"
|
|
216
|
+
},
|
|
217
|
+
onMouseEnter: (e) => {
|
|
218
|
+
E || (e.currentTarget.style.opacity = "0.75");
|
|
219
|
+
},
|
|
220
|
+
onMouseLeave: (e) => {
|
|
221
|
+
e.currentTarget.style.opacity = "1";
|
|
222
|
+
},
|
|
223
|
+
onClick: (e) => {
|
|
224
|
+
if (E) return;
|
|
225
|
+
let t = p.sum(j, (e) => a.values[e] ?? 0), r = {
|
|
226
|
+
id: a.id,
|
|
227
|
+
label: a.label,
|
|
228
|
+
seriesKey: n,
|
|
229
|
+
value: a.values[n] ?? 0,
|
|
230
|
+
total: t,
|
|
231
|
+
values: a.values
|
|
232
|
+
};
|
|
233
|
+
ce?.(r, e);
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
}, `${n}-${t}`);
|
|
237
|
+
});
|
|
238
|
+
}),
|
|
239
|
+
b && L.map((e) => {
|
|
240
|
+
let t = (z(e.id) ?? 0) + z.bandwidth() / 2, n = N + 8, r = n * Math.sin(t), i = -n * Math.cos(t), a = t * 180 / Math.PI;
|
|
241
|
+
return /* @__PURE__ */ d("text", {
|
|
242
|
+
x: r,
|
|
243
|
+
y: i,
|
|
244
|
+
transform: `rotate(${a < 180 ? a - 90 : a + 90},${r},${i})`,
|
|
245
|
+
textAnchor: "middle",
|
|
246
|
+
dominantBaseline: "central",
|
|
247
|
+
fontSize: 11,
|
|
248
|
+
fill: Q,
|
|
249
|
+
pointerEvents: "none",
|
|
250
|
+
children: e.label
|
|
251
|
+
}, `lbl-${e.id}`);
|
|
252
|
+
}),
|
|
253
|
+
C && /* @__PURE__ */ d("g", {
|
|
254
|
+
pointerEvents: "none",
|
|
255
|
+
transform: `translate(${ge},0)`,
|
|
256
|
+
children: A.map((e, t) => {
|
|
257
|
+
let n = I(e.key, t), r = me + t * 16, i = _e(e.label ?? e.key);
|
|
258
|
+
return /* @__PURE__ */ f("g", {
|
|
259
|
+
transform: `translate(0,${r})`,
|
|
260
|
+
children: [/* @__PURE__ */ d("rect", {
|
|
261
|
+
x: 0,
|
|
262
|
+
y: 0,
|
|
263
|
+
width: 10,
|
|
264
|
+
height: 10,
|
|
265
|
+
fill: n,
|
|
266
|
+
rx: 2
|
|
267
|
+
}), /* @__PURE__ */ d("text", {
|
|
268
|
+
x: 15,
|
|
269
|
+
y: 10 / 2,
|
|
270
|
+
dominantBaseline: "central",
|
|
271
|
+
fontSize: 9,
|
|
272
|
+
fill: Q,
|
|
273
|
+
children: i
|
|
274
|
+
})]
|
|
275
|
+
}, `leg-${e.key}`);
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
] })]
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
h.displayName = "RadialStackedBarChart";
|
|
284
|
+
//#endregion
|
|
285
|
+
export { h as RadialStackedBarChart };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** One series (stack layer) — key is the data field name, label overrides the legend text */
|
|
2
|
+
export type RadialStackedBarSeries = {
|
|
3
|
+
key: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
};
|
|
6
|
+
/** One bar (e.g. one country, state, or category) */
|
|
7
|
+
export type RadialStackedBarData = {
|
|
8
|
+
/** Unique identifier — used as React key and in callback payloads */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Outer-edge label shown next to the bar */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Value per series key — missing keys are treated as 0 */
|
|
13
|
+
values: Record<string, number>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Per-series color overrides.
|
|
17
|
+
* Key = series key. Value = color config — null / omit = use palette.
|
|
18
|
+
* Example: `{ "65 Years and Over": { fill: "#1565C0" } }`
|
|
19
|
+
*/
|
|
20
|
+
export type RadialStackedBarColorConfigs = Record<string, {
|
|
21
|
+
fill?: string;
|
|
22
|
+
} | null>;
|
|
23
|
+
/** Payload delivered to `onBarClick` */
|
|
24
|
+
export type RadialStackedBarBarInfo = {
|
|
25
|
+
id: string;
|
|
26
|
+
label: string;
|
|
27
|
+
/** Series key that was clicked */
|
|
28
|
+
seriesKey: string;
|
|
29
|
+
/** Value of the clicked segment */
|
|
30
|
+
value: number;
|
|
31
|
+
/** Total bar value (sum of all series) */
|
|
32
|
+
total: number;
|
|
33
|
+
/** All values for this bar */
|
|
34
|
+
values: Record<string, number>;
|
|
35
|
+
};
|
|
36
|
+
export type RadialStackedBarChartTranslation = {
|
|
37
|
+
noData: string;
|
|
38
|
+
};
|
|
39
|
+
export declare const DEFAULT_RADIAL_STACKED_BAR_CHART_TRANSLATION: RadialStackedBarChartTranslation;
|
|
40
|
+
export type RadialStackedBarChartProps = {
|
|
41
|
+
/** Array of bars — each bar has a label and a value per series key */
|
|
42
|
+
data: RadialStackedBarData[];
|
|
43
|
+
/**
|
|
44
|
+
* Series definitions in stack order (innermost first).
|
|
45
|
+
* Pass `string[]` for quick setup — the string becomes both key and legend label.
|
|
46
|
+
* Pass `RadialStackedBarSeries[]` to customize the legend label independently from the key.
|
|
47
|
+
*/
|
|
48
|
+
keys: RadialStackedBarSeries[] | string[];
|
|
49
|
+
/** Width and height of the SVG in pixels (default: 500) */
|
|
50
|
+
size?: number;
|
|
51
|
+
/** Inner radius of the bar area in px — controls the center hole size (default: size * 0.18) */
|
|
52
|
+
innerRadius?: number;
|
|
53
|
+
/** Fractional gap between adjacent bars — 0 = no gap, 1 = all gap (default: 0.12) */
|
|
54
|
+
barPadding?: number;
|
|
55
|
+
/** Custom color palette for the series — falls back to MUI theme palette when omitted */
|
|
56
|
+
chartColors?: string[];
|
|
57
|
+
/** Per-series color overrides keyed by series key — takes precedence over `chartColors` */
|
|
58
|
+
colorConfig?: RadialStackedBarColorConfigs;
|
|
59
|
+
/** Show bar labels on the outer edge (default: true) */
|
|
60
|
+
showLabels?: boolean;
|
|
61
|
+
/** Show concentric grid rings (default: true) */
|
|
62
|
+
showGridLines?: boolean;
|
|
63
|
+
/** Number of concentric grid rings (default: 3) */
|
|
64
|
+
gridLineCount?: number;
|
|
65
|
+
/** Show value labels on the outermost grid ring (default: true) */
|
|
66
|
+
showGridValues?: boolean;
|
|
67
|
+
/** Show the series legend (default: true) */
|
|
68
|
+
showLegend?: boolean;
|
|
69
|
+
/** Sort bars by total descending ('value'), by label ascending ('label'), or keep original order ('none') — default: 'none' */
|
|
70
|
+
sortBy?: 'value' | 'label' | 'none';
|
|
71
|
+
/** Decimal places for values in tooltips (default: 0) */
|
|
72
|
+
valueDecimalCount?: number;
|
|
73
|
+
/** Decimal separator for values (default: '.') */
|
|
74
|
+
valueDecimalSeparator?: string;
|
|
75
|
+
/** Thousands separator for values (default: ',') */
|
|
76
|
+
valueThousandsSeparator?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Custom formatter for the grid ring value labels.
|
|
79
|
+
* Defaults to compact notation (e.g. 30000 → "30k", 3000000 → "3M").
|
|
80
|
+
* Example: `(v) => \`${(v / 1e6).toFixed(0)}M\``
|
|
81
|
+
*/
|
|
82
|
+
gridValueFormatter?: (value: number) => string;
|
|
83
|
+
/** Enable Ctrl/Cmd+Scroll visual zoom — content outside `size` is clipped (default: false) */
|
|
84
|
+
zoomable?: boolean;
|
|
85
|
+
/** Fired on click of any bar segment */
|
|
86
|
+
onBarClick?: (info: RadialStackedBarBarInfo, event: React.MouseEvent<SVGPathElement>) => void;
|
|
87
|
+
/** Disables all interactions (default: false) */
|
|
88
|
+
disabled?: boolean;
|
|
89
|
+
/** Override any translation string */
|
|
90
|
+
translation?: Partial<RadialStackedBarChartTranslation>;
|
|
91
|
+
};
|