@carto/ps-react-ui 4.12.0 → 4.12.1

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.
Files changed (38) hide show
  1. package/dist/{echart-BMPpj7n_.js → echart-Bdvbfx9s.js} +2 -2
  2. package/dist/echart-Bdvbfx9s.js.map +1 -0
  3. package/dist/{option-builders-F-c9ELi1.js → option-builders-DPeoyQaM.js} +41 -33
  4. package/dist/option-builders-DPeoyQaM.js.map +1 -0
  5. package/dist/types/widgets/utils/chart-config/index.d.ts +1 -1
  6. package/dist/types/widgets-v2/pie/skeleton.d.ts +9 -0
  7. package/dist/widgets/bar.js +1 -1
  8. package/dist/widgets/histogram.js +1 -1
  9. package/dist/widgets/pie.js +1 -1
  10. package/dist/widgets/scatterplot.js +5 -5
  11. package/dist/widgets/timeseries.js +1 -1
  12. package/dist/widgets/utils.js +1 -1
  13. package/dist/widgets-v2/bar.js +64 -64
  14. package/dist/widgets-v2/bar.js.map +1 -1
  15. package/dist/widgets-v2/echart.js +1 -1
  16. package/dist/widgets-v2/histogram.js +89 -89
  17. package/dist/widgets-v2/histogram.js.map +1 -1
  18. package/dist/widgets-v2/pie.js +149 -95
  19. package/dist/widgets-v2/pie.js.map +1 -1
  20. package/dist/widgets-v2/scatterplot.js +153 -157
  21. package/dist/widgets-v2/scatterplot.js.map +1 -1
  22. package/dist/widgets-v2/timeseries.js +74 -74
  23. package/dist/widgets-v2/timeseries.js.map +1 -1
  24. package/dist/widgets-v2.js +2 -2
  25. package/package.json +1 -1
  26. package/src/widgets/utils/chart-config/index.ts +1 -0
  27. package/src/widgets/utils/chart-config/option-builders.test.ts +34 -0
  28. package/src/widgets/utils/chart-config/option-builders.ts +21 -0
  29. package/src/widgets-v2/bar/options.ts +3 -2
  30. package/src/widgets-v2/echart/edge-label-clamp.ts +7 -4
  31. package/src/widgets-v2/histogram/options.ts +3 -2
  32. package/src/widgets-v2/pie/skeleton.test.tsx +6 -3
  33. package/src/widgets-v2/pie/skeleton.tsx +69 -7
  34. package/src/widgets-v2/scatterplot/options.ts +3 -6
  35. package/src/widgets-v2/timeseries/options.ts +3 -2
  36. package/dist/echart-BMPpj7n_.js.map +0 -1
  37. package/dist/option-builders-F-c9ELi1.js.map +0 -1
  38. package/dist/types/widgets/utils/chart-config/option-builders.d.ts +0 -124
@@ -1,8 +1,8 @@
1
- import * as w from "echarts";
2
- import { g as k, d as N, h as j, c as T, f as I, n as A } from "../option-builders-F-c9ELi1.js";
3
- import { jsx as C } from "react/jsx-runtime";
4
- import { c as O } from "react/compiler-runtime";
5
- import { Box as P, Skeleton as $ } from "@mui/material";
1
+ import * as N from "echarts";
2
+ import { g as O, d as D, i as P, c as $, f as T, n as F } from "../option-builders-DPeoyQaM.js";
3
+ import { jsx as x, jsxs as A } from "react/jsx-runtime";
4
+ import { c as z } from "react/compiler-runtime";
5
+ import { Skeleton as I, Box as w } from "@mui/material";
6
6
  import "../widget-store-Bw5zRUGg.js";
7
7
  import "zustand/shallow";
8
8
  import "@mui/icons-material";
@@ -15,23 +15,23 @@ import "@dnd-kit/core";
15
15
  import "@dnd-kit/sortable";
16
16
  import "@dnd-kit/utilities";
17
17
  import "react-dom";
18
- import { m as D, r as M } from "../resolve-theme-color-BdojIw0K.js";
18
+ import { m as E, r as M } from "../resolve-theme-color-BdojIw0K.js";
19
19
  import "../widget-context-DTGO0Yta.js";
20
20
  import "zustand";
21
21
  import "zustand/vanilla";
22
22
  import "zustand/middleware";
23
23
  import "zustand/react/shallow";
24
24
  import { b as V } from "../png-item-9dNbB37T.js";
25
- import { b as z } from "../csv-item-hH_Gt7ur.js";
26
- const B = ["58%", "74%"];
27
- function _({
25
+ import { b as B } from "../csv-item-hH_Gt7ur.js";
26
+ const R = ["58%", "74%"];
27
+ function H({
28
28
  theme: e,
29
29
  formatter: r,
30
30
  labelFormatter: t
31
31
  }) {
32
32
  return {
33
33
  legend: {
34
- ...N({
34
+ ...D({
35
35
  hasLegend: !0,
36
36
  labelFormatter: t
37
37
  }),
@@ -60,8 +60,8 @@ function _({
60
60
  fontSize: 11,
61
61
  fontFamily: e.typography.caption.fontFamily
62
62
  },
63
- position: k(e),
64
- formatter: F(r, t)
63
+ position: O(e),
64
+ formatter: _(r, t)
65
65
  },
66
66
  // V1 used `qualitative.bold` only (no `secondary.main` prefix) because
67
67
  // pie slices are categorical — each slice deserves a distinct palette
@@ -101,59 +101,59 @@ function _({
101
101
  }]
102
102
  };
103
103
  }
104
- function ye(e) {
104
+ function ve(e) {
105
105
  const {
106
106
  theme: r,
107
107
  formatter: t,
108
- labelFormatter: n,
108
+ labelFormatter: a,
109
109
  optionsOverride: o,
110
- series: s
111
- } = e, c = e.radius ?? B, u = e.selection, g = u && u.length > 0 ? new Set(u) : null;
110
+ series: n
111
+ } = e, c = e.radius ?? R, u = e.selection, g = u && u.length > 0 ? new Set(u) : null;
112
112
  return (d, f, b) => {
113
113
  if (d == null) {
114
- const v = _({
114
+ const h = H({
115
115
  theme: r,
116
116
  formatter: t,
117
- labelFormatter: n
117
+ labelFormatter: a
118
118
  });
119
- return o ? D(v, o) : v;
119
+ return o ? E(h, o) : h;
120
120
  }
121
121
  const p = Array.isArray(f) ? f : [];
122
122
  return p.length === 0 ? {
123
123
  ...d,
124
124
  dataset: [],
125
125
  series: []
126
- } : p.length > 1 ? W(d, p, r, s, b, g) : R(d, p, c, s, b, g);
126
+ } : p.length > 1 ? G(d, p, r, n, b, g) : W(d, p, c, n, b, g);
127
127
  };
128
128
  }
129
- function R(e, r, t, n, o, s) {
130
- const c = Array.isArray(e.series) ? e.series : [], u = c[0] ?? {}, g = typeof e.tooltip == "object" && !Array.isArray(e.tooltip) ? e.tooltip : {}, d = typeof e.legend == "object" && !Array.isArray(e.legend) ? e.legend : {}, f = o?.formatter, b = o?.labelFormatter, p = Array.isArray(e.color) ? e.color : [], v = (a) => (p.length > 0 ? p[a.dataIndex % p.length] : void 0) ?? a.color, x = (a) => {
131
- const l = v(a);
132
- if (!s) return l;
133
- const m = a.value?.name ?? a.name;
134
- return m != null && s.has(m) ? l : w.color.modifyAlpha(l, 0.15);
135
- }, i = (a) => {
129
+ function W(e, r, t, a, o, n) {
130
+ const c = Array.isArray(e.series) ? e.series : [], u = c[0] ?? {}, g = typeof e.tooltip == "object" && !Array.isArray(e.tooltip) ? e.tooltip : {}, d = typeof e.legend == "object" && !Array.isArray(e.legend) ? e.legend : {}, f = o?.formatter, b = o?.labelFormatter, p = Array.isArray(e.color) ? e.color : [], h = (i) => (p.length > 0 ? p[i.dataIndex % p.length] : void 0) ?? i.color, C = (i) => {
131
+ const l = h(i);
132
+ if (!n) return l;
133
+ const m = i.value?.name ?? i.name;
134
+ return m != null && n.has(m) ? l : N.color.modifyAlpha(l, 0.15);
135
+ }, s = (i) => {
136
136
  const {
137
137
  name: l
138
- } = a, y = a.encode?.value?.[0];
138
+ } = i, y = i.encode?.value?.[0];
139
139
  if (y === void 0) return "";
140
- const m = Object.values(a.data ?? {}).at(y), h = typeof m == "number" ? f ? f(m) : String(m) : typeof m == "string" ? m : "", S = String(b ? b(l ?? "") : l ?? "");
141
- return `{c|${h}}
140
+ const m = Object.values(i.data ?? {}).at(y), S = typeof m == "number" ? f ? f(m) : String(m) : typeof m == "string" ? m : "", j = String(b ? b(l ?? "") : l ?? "");
141
+ return `{c|${S}}
142
142
 
143
- {b|${S}}`;
143
+ {b|${j}}`;
144
144
  };
145
145
  return {
146
146
  ...e,
147
- dataset: r.map((a) => ({
148
- source: a
147
+ dataset: r.map((i) => ({
148
+ source: i
149
149
  })),
150
- series: r.map((a, l) => {
151
- const y = c[l] ?? u, m = typeof y == "object" ? y : {}, h = m.label ?? {}, S = m.itemStyle ?? {};
150
+ series: r.map((i, l) => {
151
+ const y = c[l] ?? u, m = typeof y == "object" ? y : {}, S = m.label ?? {}, j = m.itemStyle ?? {};
152
152
  return {
153
153
  ...m,
154
154
  type: "pie",
155
155
  datasetIndex: l,
156
- name: n?.[l]?.name ?? `Series ${l + 1}`,
156
+ name: a?.[l]?.name ?? `Series ${l + 1}`,
157
157
  radius: [...t],
158
158
  // Lift the donut up so the bottom-anchored legend has the
159
159
  // vertical real estate to wrap to multiple rows for long
@@ -166,12 +166,12 @@ function R(e, r, t, n, o, s) {
166
166
  value: "value"
167
167
  },
168
168
  label: {
169
- ...h,
170
- formatter: i
169
+ ...S,
170
+ formatter: s
171
171
  },
172
172
  itemStyle: {
173
- ...S,
174
- color: x
173
+ ...j,
174
+ color: C
175
175
  }
176
176
  };
177
177
  }),
@@ -183,47 +183,47 @@ function R(e, r, t, n, o, s) {
183
183
  },
184
184
  tooltip: {
185
185
  ...g,
186
- formatter: F(f, b)
186
+ formatter: _(f, b)
187
187
  }
188
188
  };
189
189
  }
190
- function W(e, r, t, n, o, s) {
190
+ function G(e, r, t, a, o, n) {
191
191
  const c = typeof e.tooltip == "object" && !Array.isArray(e.tooltip) ? e.tooltip : {}, u = typeof e.legend == "object" && !Array.isArray(e.legend) ? e.legend : {}, g = typeof e.grid == "object" && !Array.isArray(e.grid) ? e.grid : {}, d = o?.formatter, f = o?.labelFormatter, {
192
192
  niceMinVal: b,
193
193
  niceMaxVal: p
194
- } = H(r), v = Array.isArray(e.color) ? e.color : [], x = (i) => {
195
- const a = i.seriesIndex ?? 0, y = (v.length > 0 ? v[a % v.length] : void 0) ?? i.color;
196
- if (!s) return y;
197
- const h = i.value?.name ?? i.name;
198
- return h != null && s.has(h) ? y : w.color.modifyAlpha(y, 0.15);
194
+ } = Z(r), h = Array.isArray(e.color) ? e.color : [], C = (s) => {
195
+ const i = s.seriesIndex ?? 0, y = (h.length > 0 ? h[i % h.length] : void 0) ?? s.color;
196
+ if (!n) return y;
197
+ const S = s.value?.name ?? s.name;
198
+ return S != null && n.has(S) ? y : N.color.modifyAlpha(y, 0.15);
199
199
  };
200
200
  return {
201
201
  ...e,
202
- dataset: r.map((i) => ({
203
- source: i
202
+ dataset: r.map((s) => ({
203
+ source: s
204
204
  })),
205
205
  grid: {
206
206
  ...g,
207
- ...T(!0, t),
207
+ ...$(!0, t),
208
208
  right: parseInt(t.spacing(4)),
209
209
  containLabel: !0
210
210
  },
211
211
  // Drop pie-specific structural keys that shouldn't render in the
212
212
  // bar fallback. ECharts ignores undefined keys, so this is a clean
213
213
  // override.
214
- series: r.map((i, a) => {
215
- const l = M(t, n?.[a]?.color);
214
+ series: r.map((s, i) => {
215
+ const l = M(t, a?.[i]?.color);
216
216
  return {
217
- datasetIndex: a,
217
+ datasetIndex: i,
218
218
  type: "bar",
219
- name: n?.[a]?.name ?? `Series ${a + 1}`,
219
+ name: a?.[i]?.name ?? `Series ${i + 1}`,
220
220
  barMaxWidth: 100,
221
221
  emphasis: {
222
222
  focus: "series"
223
223
  },
224
- ...j(d, "x"),
224
+ ...P(d, "x"),
225
225
  itemStyle: {
226
- color: x
226
+ color: C
227
227
  },
228
228
  ...l ? {
229
229
  color: l
@@ -262,7 +262,7 @@ function W(e, r, t, n, o, s) {
262
262
  margin: parseInt(t.spacing(1)),
263
263
  showMaxLabel: !0,
264
264
  showMinLabel: !0,
265
- formatter: (i) => i !== p && i !== b || i === 0 ? "" : d ? d(i) : String(i)
265
+ formatter: (s) => s !== p && s !== b || s === 0 ? "" : d ? d(s) : String(s)
266
266
  }
267
267
  },
268
268
  yAxis: {
@@ -276,7 +276,7 @@ function W(e, r, t, n, o, s) {
276
276
  axisLabel: {
277
277
  padding: [parseInt(t.spacing(0.5)), 0, 0, 0],
278
278
  ...f && {
279
- formatter: (i) => String(f(i))
279
+ formatter: (s) => String(f(s))
280
280
  }
281
281
  }
282
282
  },
@@ -287,13 +287,13 @@ function W(e, r, t, n, o, s) {
287
287
  tooltip: {
288
288
  ...c,
289
289
  trigger: "axis",
290
- formatter: E(d, f)
290
+ formatter: U(d, f)
291
291
  }
292
292
  };
293
293
  }
294
- function E(e, r) {
295
- return I((t) => {
296
- const n = t.encode?.x?.at(0), o = n !== void 0 ? t.dimensionNames?.[n] : void 0, s = t.value && typeof t.value == "object" && !Array.isArray(t.value) ? t.value : void 0, c = o && s ? s[o] : void 0, u = typeof c == "number" && e ? e(c) : c ?? "", g = typeof t.marker == "string" ? t.marker : "", d = t.seriesName ? `${t.seriesName}: ` : "";
294
+ function U(e, r) {
295
+ return T((t) => {
296
+ const a = t.encode?.x?.at(0), o = a !== void 0 ? t.dimensionNames?.[a] : void 0, n = t.value && typeof t.value == "object" && !Array.isArray(t.value) ? t.value : void 0, c = o && n ? n[o] : void 0, u = typeof c == "number" && e ? e(c) : c ?? "", g = typeof t.marker == "string" ? t.marker : "", d = t.seriesName ? `${t.seriesName}: ` : "";
297
297
  return {
298
298
  name: String(r ? r(t.name ?? "") : t.name ?? ""),
299
299
  seriesName: d,
@@ -302,19 +302,19 @@ function E(e, r) {
302
302
  };
303
303
  });
304
304
  }
305
- function H(e) {
305
+ function Z(e) {
306
306
  let r = 0, t = -1 / 0;
307
- for (const n of e)
308
- for (const o of n)
307
+ for (const a of e)
308
+ for (const o of a)
309
309
  typeof o?.value != "number" || !Number.isFinite(o.value) || (o.value < r && (r = o.value), o.value > t && (t = o.value));
310
310
  return {
311
- niceMinVal: r < 0 ? A(r) : 0,
312
- niceMaxVal: t <= 0 ? 1 : A(t)
311
+ niceMinVal: r < 0 ? F(r) : 0,
312
+ niceMaxVal: t <= 0 ? 1 : F(t)
313
313
  };
314
314
  }
315
- function F(e, r) {
316
- return I((t) => {
317
- const n = t.encode?.value?.at(0) ?? 1, s = (t.value && typeof t.value == "object" && !Array.isArray(t.value) ? Object.values(t.value) : [])[n], c = typeof s == "number" && e ? e(s) : s ?? "", u = typeof t.marker == "string" ? t.marker : "", g = t.seriesName ? `${t.seriesName}: ` : "";
315
+ function _(e, r) {
316
+ return T((t) => {
317
+ const a = t.encode?.value?.at(0) ?? 1, n = (t.value && typeof t.value == "object" && !Array.isArray(t.value) ? Object.values(t.value) : [])[a], c = typeof n == "number" && e ? e(n) : n ?? "", u = typeof t.marker == "string" ? t.marker : "", g = t.seriesName ? `${t.seriesName}: ` : "";
318
318
  return {
319
319
  name: String(r ? r(t.name ?? "") : t.name ?? ""),
320
320
  seriesName: g,
@@ -323,57 +323,111 @@ function F(e, r) {
323
323
  };
324
324
  });
325
325
  }
326
- const L = {
326
+ const L = 160, k = 96, v = {
327
327
  root: {
328
328
  display: "flex",
329
+ flexDirection: "column",
329
330
  alignItems: "center",
330
331
  justifyContent: "center",
331
332
  minHeight: 200,
332
333
  py: 1,
333
- gap: 2
334
+ gap: ({
335
+ spacing: e
336
+ }) => e(2)
334
337
  },
335
338
  donut: {
336
- width: 160,
337
- height: 160,
338
- borderRadius: "50%"
339
+ position: "relative",
340
+ display: "flex",
341
+ alignItems: "center",
342
+ justifyContent: "center"
343
+ },
344
+ ring: {
345
+ width: L,
346
+ height: L
347
+ },
348
+ hole: {
349
+ position: "absolute",
350
+ zIndex: 1,
351
+ width: k,
352
+ height: k,
353
+ borderRadius: "50%",
354
+ bgcolor: "background.paper"
355
+ },
356
+ label: {
357
+ position: "absolute",
358
+ zIndex: 2,
359
+ display: "flex",
360
+ flexDirection: "column",
361
+ alignItems: "center",
362
+ justifyContent: "center",
363
+ gap: ({
364
+ spacing: e
365
+ }) => e(0.5)
366
+ },
367
+ legend: {
368
+ display: "flex",
369
+ alignItems: "center",
370
+ gap: ({
371
+ spacing: e
372
+ }) => e(2)
373
+ },
374
+ legendItem: {
375
+ display: "flex",
376
+ alignItems: "center",
377
+ gap: ({
378
+ spacing: e
379
+ }) => e(1.5)
339
380
  }
340
381
  };
341
- function be(e) {
342
- const r = O(2), {
343
- count: t
344
- } = e, n = t === void 0 ? 1 : t;
382
+ function xe(e) {
383
+ const r = z(4);
384
+ let t, a;
385
+ r[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t = /* @__PURE__ */ x(I, { variant: "circular", sx: v.ring }), a = /* @__PURE__ */ x(w, { sx: v.hole }), r[0] = t, r[1] = a) : (t = r[0], a = r[1]);
345
386
  let o;
346
- return r[0] !== n ? (o = /* @__PURE__ */ C(P, { sx: L.root, children: Array.from({
347
- length: n
348
- }).map(G) }), r[0] = n, r[1] = o) : o = r[1], o;
387
+ r[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (o = /* @__PURE__ */ A(w, { sx: v.donut, children: [
388
+ t,
389
+ a,
390
+ /* @__PURE__ */ A(w, { sx: v.label, children: [
391
+ /* @__PURE__ */ x(I, { width: 56, height: 18 }),
392
+ /* @__PURE__ */ x(I, { width: 36, height: 8 })
393
+ ] })
394
+ ] }), r[2] = o) : o = r[2];
395
+ let n;
396
+ return r[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (n = /* @__PURE__ */ A(w, { sx: v.root, children: [
397
+ o,
398
+ /* @__PURE__ */ x(w, { sx: v.legend, children: [0, 1].map(q) })
399
+ ] }), r[3] = n) : n = r[3], n;
349
400
  }
350
- function G(e, r) {
351
- return /* @__PURE__ */ C($, { variant: "circular", sx: L.donut }, `donut-${r}`);
401
+ function q(e) {
402
+ return /* @__PURE__ */ A(w, { sx: v.legendItem, children: [
403
+ /* @__PURE__ */ x(I, { variant: "circular", width: 8, height: 8 }),
404
+ /* @__PURE__ */ x(I, { width: 48, height: 8 })
405
+ ] }, `legend-${e}`);
352
406
  }
353
- function ve(e) {
407
+ function Se(e) {
354
408
  const r = [];
355
409
  return e.getCaptureEl && r.push(V({
356
410
  filename: e.filename,
357
411
  getCaptureEl: e.getCaptureEl,
358
412
  pixelRatio: e.pngPixelRatio,
359
413
  backgroundColor: e.pngBackgroundColor
360
- })), r.push(z({
414
+ })), r.push(B({
361
415
  filename: e.filename,
362
416
  getRows: () => {
363
- const t = e.getData(), n = [["series", "name", "value"]];
364
- for (const [o, s] of t.entries()) {
417
+ const t = e.getData(), a = [["series", "name", "value"]];
418
+ for (const [o, n] of t.entries()) {
365
419
  const c = e.seriesNames?.[o] ?? `series_${o + 1}`;
366
- for (const u of s)
367
- n.push([c, u.name, u.value]);
420
+ for (const u of n)
421
+ a.push([c, u.name, u.value]);
368
422
  }
369
- return n;
423
+ return a;
370
424
  }
371
425
  })), r;
372
426
  }
373
427
  export {
374
- be as PieSkeleton,
375
- ve as createPieDownloadConfig,
376
- ye as createPieOptionFactory,
377
- _ as pieOptions
428
+ xe as PieSkeleton,
429
+ Se as createPieDownloadConfig,
430
+ ve as createPieOptionFactory,
431
+ H as pieOptions
378
432
  };
379
433
  //# sourceMappingURL=pie.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pie.js","sources":["../../src/widgets-v2/pie/options.ts","../../src/widgets-v2/pie/skeleton.tsx","../../src/widgets-v2/pie/download.ts"],"sourcesContent":["import type { Theme } from '@mui/material'\nimport type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildGridConfig,\n buildLegendConfig,\n buildSeriesLabelConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport type { OptionFactory, OptionFactoryContext } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport type { WidgetSeries } from '../types'\nimport type {\n PieEChartsOption,\n PieOptionFactoryInput,\n PieOptionsInput,\n PieWidgetData,\n} from './types'\n\nconst DEFAULT_RADIUS: readonly [string, string] = ['58%', '74%']\n\n/**\n * Builds the **structural** ECharts option for a pie / donut widget.\n * Mirrors v1's pie look-and-feel: themed legend (`buildLegendConfig`),\n * themed tooltip via `createTooltipPositioner` / `createTooltipFormatter`,\n * `qualitative.bold` color palette, slice borders against the paper\n * background, hover-emphasis disabled, and a centered rich-text label.\n *\n * Layered like Bar / Histogram:\n * - **Theme-aware bits** live here on a series template (slice border,\n * center-label rich style sizes, emphasis-disabled).\n * - **Reactive bits** (tooltip value formatter, center-label text,\n * selection-driven dim) are re-emitted by\n * {@link createPieOptionFactory} at fusion time so RelativeData's\n * percent override flows through.\n */\nexport function pieOptions({\n theme,\n formatter,\n labelFormatter,\n}: PieOptionsInput): PieEChartsOption {\n return {\n legend: {\n ...buildLegendConfig({ hasLegend: true, labelFormatter }),\n // Pie reads better with a centered legend (the donut is radially\n // symmetric — left-aligning the legend below it visually unbalances\n // the chart). Override `buildLegendConfig`'s `type: 'scroll'` with\n // `'plain'` so long category lists wrap to multiple rows instead\n // of clipping the last visible item against the chart container.\n // The wider `itemGap` gives chips breathing room in the typical\n // 3–6 category case.\n left: 'center',\n type: 'scroll',\n itemGap: 16,\n },\n tooltip: {\n // Pie uses item-trigger (no axis); the rest of the styling mirrors\n // bar/histogram so the dashboard reads consistently — dark\n // grey[900] bg, white caption-font text, padded, with the shared\n // overflow-aware positioner.\n trigger: 'item',\n backgroundColor: theme.palette.grey[900],\n borderWidth: 0,\n padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],\n textStyle: {\n color: theme.palette.common.white,\n fontSize: 11,\n fontFamily: theme.typography.caption.fontFamily,\n },\n position: createTooltipPositioner(theme),\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n // V1 used `qualitative.bold` only (no `secondary.main` prefix) because\n // pie slices are categorical — each slice deserves a distinct palette\n // entry from the start, not a primary highlight.\n color: Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n // Pie template. The merger spreads this into each per-data series it\n // emits — borderColor / borderWidth / emphasis-disabled / label rich\n // sizes all survive through.\n series: [\n {\n type: 'pie',\n colorBy: 'data',\n avoidLabelOverlap: true,\n selectedOffset: 0,\n emphasis: { disabled: true },\n itemStyle: {\n borderColor: theme.palette.background.paper,\n borderWidth: 1,\n },\n label: {\n show: true,\n position: 'center',\n rich: {\n b: { fontSize: 16, fontWeight: 'normal', lineHeight: 20 },\n c: { fontSize: 28, fontWeight: 'bold', lineHeight: 27 },\n },\n },\n },\n ],\n }\n}\n\n/**\n * Returns the pie widget's {@link OptionFactory} — one closure that owns\n * BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link pieOptions}, optionally merging the\n * consumer-supplied `optionsOverride` on top. Called once by Provider\n * to seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`PieWidgetData`) into the option via the dataset API. Single-series\n * → donut (one dataset, `series[i].encode = { itemName: 'name', value: 'value' }`).\n * Multi-series → horizontal-bar fallback (mirrors v1 pie). Reactive\n * formatters from `ctx` drive the tooltip + center label at fusion\n * time so RelativeData's percent formatter flows through without a\n * structural rebuild.\n */\nexport function createPieOptionFactory(\n options: PieOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride, series } = options\n const radius = options.radius ?? DEFAULT_RADIUS\n const selection = options.selection\n const selectionSet =\n selection && selection.length > 0\n ? new Set<string | number>(selection)\n : null\n return (option, data, ctx) => {\n if (option == null) {\n const structural = pieOptions({ theme, formatter, labelFormatter })\n return optionsOverride\n ? (mergeOptions(\n structural as unknown as Record<string, unknown>,\n optionsOverride as Partial<Record<string, unknown>>,\n ) as EChartsOption)\n : structural\n }\n\n const seriesArr = Array.isArray(data) ? (data as PieWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n if (seriesArr.length > 1) {\n return buildMultiSeriesBarFusion(\n option,\n seriesArr,\n theme,\n series,\n ctx,\n selectionSet,\n )\n }\n return buildSingleSeriesPieFusion(\n option,\n seriesArr,\n radius,\n series,\n ctx,\n selectionSet,\n )\n }\n}\n\n/**\n * Single-series donut fusion. Spreads the structural pie series template\n * into per-data series with center/radius/encoding, wires the reactive\n * center-label / tooltip formatters and the per-data palette-aware\n * selection-dim callback.\n */\nfunction buildSingleSeriesPieFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n radius: readonly [string, string],\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n // Pie wants `colorBy: 'data'` — each slice draws from the option's\n // `color` palette by data index. But installing an `itemStyle.color`\n // callback disables ECharts' automatic per-data cycling, and\n // `params.color` collapses to the series color (so every slice goes\n // the same color). We re-implement the per-data palette resolution\n // here so the multicolor look survives selection-driven dimming.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const resolvePaletteColor = (params: CallbackDataParams): string => {\n const swatch =\n palette.length > 0\n ? palette[params.dataIndex % palette.length]\n : undefined\n return swatch ?? (params.color as string)\n }\n\n // Always emit `itemStyle.color` (passthrough when nothing is selected),\n // not conditionally — same anti-stale-callback rationale as bar /\n // histogram. The slice border + width come from the structural\n // template's `itemStyle` and survive via the spread below.\n const colorFn = (params: CallbackDataParams): string => {\n const base = resolvePaletteColor(params)\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n // Center label formatter — lives in the merger because it reads\n // reactive `formatter` / `labelFormatter` from ctx. The rich tags\n // `{c|…}` and `{b|…}` reference the rich styles baked into the\n // structural label template.\n const labelTextFormatter = (params: CallbackDataParams): string => {\n const { name } = params\n const encodeIndex = params.encode?.value?.[0]\n if (encodeIndex === undefined) return ''\n const value = (Object.values(params.data ?? {}) as unknown[]).at(\n encodeIndex,\n )\n // `value` here is the resolved dataset cell — for pie data it's a\n // `string | number` primitive. Anything else is a misuse we won't\n // dress up with `String(...)` (would render \"[object Object]\").\n const formattedValue =\n typeof value === 'number'\n ? formatter\n ? formatter(value)\n : String(value)\n : typeof value === 'string'\n ? value\n : ''\n const formattedName = labelFormatter\n ? String(labelFormatter(name ?? ''))\n : String(name ?? '')\n return `{c|${formattedValue}}\\n\\n{b|${formattedName}}`\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n series: seriesArr.map((_, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const templateObj = typeof template === 'object' ? template : {}\n const templateLabel = (templateObj as { label?: object }).label ?? {}\n const templateItemStyle =\n (templateObj as { itemStyle?: object }).itemStyle ?? {}\n return {\n ...templateObj,\n type: 'pie' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n radius: [...radius],\n // Lift the donut up so the bottom-anchored legend has the\n // vertical real estate to wrap to multiple rows for long\n // category lists — at exactly `50%` the bottom slices crowd\n // the chips and `type: 'plain'` legends can't expand upward\n // without overlapping the donut.\n center: ['50%', '38%'] as [string, string],\n encode: { itemName: 'name', value: 'value' },\n label: {\n ...templateLabel,\n formatter: labelTextFormatter,\n },\n itemStyle: {\n ...templateItemStyle,\n color: colorFn,\n },\n }\n }),\n // Legend always shows for pie (mirrors v1) — slice names drive the\n // entries, so even a single donut benefits from a category list.\n legend: { ...baseLegend, show: true },\n tooltip: {\n ...baseTooltip,\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n }\n}\n\n/**\n * Multi-series horizontal-bar fusion. Mirrors v1 pie's \"pie data with\n * >1 series collapses into a horizontal bar chart\" behavior — side-by-\n * side donuts don't read well when you're comparing the same categories\n * across cohorts, so swap to a value-on-x / category-on-y bar layout.\n *\n * Pie data shape is identical to bar's (`{ name, value }[][]`), so the\n * same dataset feeds either layout without transformation.\n */\nfunction buildMultiSeriesBarFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n theme: Theme,\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n const { niceMinVal, niceMaxVal } = computeNiceBounds(seriesArr)\n\n // Per-series palette — multi-series bars take one color per series\n // (not per-data, unlike donut slices). Same anti-stale-callback rule:\n // always emit the callback so a transition to/from a selection\n // replaces the previous closure cleanly.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const barColorFn = (params: CallbackDataParams): string => {\n const seriesIdx = params.seriesIndex ?? 0\n const seriesSwatch =\n palette.length > 0 ? palette[seriesIdx % palette.length] : undefined\n const base = (seriesSwatch ?? params.color) as string\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n grid: {\n ...baseGrid,\n ...buildGridConfig(true, theme),\n right: parseInt(theme.spacing(4)),\n containLabel: true,\n },\n // Drop pie-specific structural keys that shouldn't render in the\n // bar fallback. ECharts ignores undefined keys, so this is a clean\n // override.\n series: seriesArr.map((_, i) => {\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n datasetIndex: i,\n type: 'bar' as const,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n barMaxWidth: 100,\n emphasis: { focus: 'series' },\n ...buildSeriesLabelConfig(formatter, 'x'),\n itemStyle: { color: barColorFn },\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n xAxis: {\n type: 'value',\n // Closures over the pre-computed nice bounds — ECharts calls them\n // once per render to resolve the axis extents.\n min: () => niceMinVal,\n max: () => niceMaxVal,\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: { color: theme.palette.black?.[4] ?? theme.palette.divider },\n },\n // Value labels render BELOW the axis line (default placement),\n // NOT inside the plot. Bar/histogram use `inside: true` +\n // `verticalAlign: 'bottom'` for their *vertical* y-axis where the\n // axis is the left wall — labels inside read like grid annotations.\n // A horizontal bar chart's value axis is the x-axis, and `inside`\n // there pushes the max label *behind* the bar (it visually\n // disappears once a bar reaches the right edge). Use the default\n // below-the-axis placement so the rounded extents stay readable.\n axisLabel: {\n fontSize: theme.typography.overlineDelicate?.fontSize,\n fontFamily: theme.typography.overlineDelicate?.fontFamily,\n margin: parseInt(theme.spacing(1)),\n showMaxLabel: true,\n showMinLabel: true,\n formatter: (value: number) => {\n if (value !== niceMaxVal && value !== niceMinVal) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n yAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n ...(labelFormatter && {\n formatter: (value: string | number) => String(labelFormatter(value)),\n }),\n },\n },\n legend: { ...baseLegend, show: true },\n tooltip: {\n ...baseTooltip,\n trigger: 'axis',\n formatter: buildHorizontalBarTooltipFormatter(formatter, labelFormatter),\n },\n } as EChartsOption\n}\n\n/**\n * Tooltip formatter for the horizontal-bar fallback. Reads the value by\n * `encode.x` dimension index (v1 parity) so it stays robust to\n * downstream changes that rename dataset columns.\n */\nfunction buildHorizontalBarTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.x?.at(0)\n const dimName =\n encodeIndex !== undefined ? item.dimensionNames?.[encodeIndex] : undefined\n const row =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (item.value as Record<string, string | number>)\n : undefined\n const raw = dimName && row ? row[dimName] : undefined\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n\n/**\n * Min/max bounds over every datum's `.value` across all series. Used by\n * the horizontal-bar fallback's x-axis label formatter so we only render\n * labels at the rounded extents (matches v1 + bar / histogram).\n */\nfunction computeNiceBounds(seriesArr: PieWidgetData): {\n niceMinVal: number\n niceMaxVal: number\n} {\n let min = 0\n let max = -Infinity\n for (const series of seriesArr) {\n for (const d of series) {\n if (typeof d?.value !== 'number' || !Number.isFinite(d.value)) continue\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n }\n return {\n niceMinVal: min < 0 ? niceNum(min) : 0,\n niceMaxVal: max <= 0 ? 1 : niceNum(max),\n }\n}\n\n/**\n * Tooltip formatter for pie slices. `item.value` is the dataset row\n * object (e.g. `{ name: 'A', value: 10 }`); we pull the value by\n * `encode.value`'s dimension index, formatted via the reactive `formatter`\n * if present. Slice name passes through `labelFormatter`.\n */\nfunction buildPieTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.value?.at(0) ?? 1\n const values =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (Object.values(item.value) as (string | number)[])\n : []\n const raw = values[encodeIndex]\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n","import { Box, Skeleton } from '@mui/material'\nimport type { SxProps, Theme } from '@mui/material'\n\nconst styles = {\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 200,\n py: 1,\n gap: 2,\n },\n donut: {\n width: 160,\n height: 160,\n borderRadius: '50%',\n },\n} satisfies Record<string, SxProps<Theme>>\n\nexport interface PieSkeletonProps {\n count?: number\n}\n\nexport function PieSkeleton({ count = 1 }: PieSkeletonProps) {\n return (\n <Box sx={styles.root}>\n {Array.from({ length: count }).map((_, i) => (\n <Skeleton key={`donut-${i}`} variant='circular' sx={styles.donut} />\n ))}\n </Box>\n )\n}\n","import {\n buildCsvDownloadItem,\n buildPngDownloadItem,\n type DownloadItem,\n} from '../actions/download'\nimport type { PieWidgetData } from './types'\n\n/**\n * Download menu items for the Pie widget. Always includes a CSV item with\n * `series, name, value` columns (one row per slice; series labels come from\n * `seriesNames` if provided, else `series_<n>`). When `getCaptureEl` is\n * supplied, prepends a PNG item that rasterises the captured element via\n * `html2canvas`.\n */\nexport function createPieDownloadConfig(args: {\n filename: string\n getData: () => PieWidgetData\n seriesNames?: readonly string[]\n getCaptureEl?: () => HTMLElement | null\n pngPixelRatio?: number\n pngBackgroundColor?: string | null\n}): DownloadItem[] {\n const items: DownloadItem[] = []\n if (args.getCaptureEl) {\n items.push(\n buildPngDownloadItem({\n filename: args.filename,\n getCaptureEl: args.getCaptureEl,\n pixelRatio: args.pngPixelRatio,\n backgroundColor: args.pngBackgroundColor,\n }),\n )\n }\n items.push(\n buildCsvDownloadItem({\n filename: args.filename,\n getRows: () => {\n const data = args.getData()\n const rows: unknown[][] = [['series', 'name', 'value']]\n for (const [i, series] of data.entries()) {\n const seriesName = args.seriesNames?.[i] ?? `series_${i + 1}`\n for (const slice of series) {\n rows.push([seriesName, slice.name, slice.value])\n }\n }\n return rows\n },\n }),\n )\n return items\n}\n"],"names":["DEFAULT_RADIUS","pieOptions","theme","formatter","labelFormatter","legend","buildLegendConfig","hasLegend","left","type","itemGap","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","parseInt","spacing","textStyle","color","common","white","fontSize","fontFamily","typography","caption","position","createTooltipPositioner","buildPieTooltipFormatter","Object","values","qualitative","bold","series","colorBy","avoidLabelOverlap","selectedOffset","emphasis","disabled","itemStyle","borderColor","background","paper","label","show","rich","b","fontWeight","lineHeight","c","createPieOptionFactory","options","optionsOverride","radius","selection","selectionSet","length","Set","option","data","ctx","structural","mergeOptions","seriesArr","Array","isArray","dataset","buildMultiSeriesBarFusion","buildSingleSeriesPieFusion","seriesTemplates","broadcastTemplate","baseTooltip","baseLegend","resolvePaletteColor","params","dataIndex","undefined","colorFn","base","name","value","has","echarts","modifyAlpha","labelTextFormatter","encodeIndex","encode","at","formattedValue","String","formattedName","map","s","source","_","i","template","templateObj","templateLabel","templateItemStyle","datasetIndex","center","itemName","baseGrid","grid","niceMinVal","niceMaxVal","computeNiceBounds","barColorFn","seriesIdx","seriesIndex","buildGridConfig","right","containLabel","overrideColor","resolveThemeColor","barMaxWidth","focus","buildSeriesLabelConfig","xAxis","min","max","axisLine","axisTick","splitLine","lineStyle","black","divider","axisLabel","overlineDelicate","margin","showMaxLabel","showMinLabel","yAxis","buildHorizontalBarTooltipFormatter","createTooltipFormatter","item","x","dimName","dimensionNames","row","raw","marker","seriesName","d","Number","isFinite","niceNum","styles","root","display","alignItems","justifyContent","minHeight","py","gap","donut","width","height","borderRadius","PieSkeleton","t0","$","_c","count","t1","t2","Box","from","_temp","jsx","Skeleton","createPieDownloadConfig","args","items","getCaptureEl","push","buildPngDownloadItem","filename","pixelRatio","pngPixelRatio","pngBackgroundColor","buildCsvDownloadItem","getRows","getData","rows","entries","seriesNames","slice"],"mappings":"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"}
1
+ {"version":3,"file":"pie.js","sources":["../../src/widgets-v2/pie/options.ts","../../src/widgets-v2/pie/skeleton.tsx","../../src/widgets-v2/pie/download.ts"],"sourcesContent":["import type { Theme } from '@mui/material'\nimport type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildGridConfig,\n buildLegendConfig,\n buildSeriesLabelConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport type { OptionFactory, OptionFactoryContext } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport type { WidgetSeries } from '../types'\nimport type {\n PieEChartsOption,\n PieOptionFactoryInput,\n PieOptionsInput,\n PieWidgetData,\n} from './types'\n\nconst DEFAULT_RADIUS: readonly [string, string] = ['58%', '74%']\n\n/**\n * Builds the **structural** ECharts option for a pie / donut widget.\n * Mirrors v1's pie look-and-feel: themed legend (`buildLegendConfig`),\n * themed tooltip via `createTooltipPositioner` / `createTooltipFormatter`,\n * `qualitative.bold` color palette, slice borders against the paper\n * background, hover-emphasis disabled, and a centered rich-text label.\n *\n * Layered like Bar / Histogram:\n * - **Theme-aware bits** live here on a series template (slice border,\n * center-label rich style sizes, emphasis-disabled).\n * - **Reactive bits** (tooltip value formatter, center-label text,\n * selection-driven dim) are re-emitted by\n * {@link createPieOptionFactory} at fusion time so RelativeData's\n * percent override flows through.\n */\nexport function pieOptions({\n theme,\n formatter,\n labelFormatter,\n}: PieOptionsInput): PieEChartsOption {\n return {\n legend: {\n ...buildLegendConfig({ hasLegend: true, labelFormatter }),\n // Pie reads better with a centered legend (the donut is radially\n // symmetric — left-aligning the legend below it visually unbalances\n // the chart). Override `buildLegendConfig`'s `type: 'scroll'` with\n // `'plain'` so long category lists wrap to multiple rows instead\n // of clipping the last visible item against the chart container.\n // The wider `itemGap` gives chips breathing room in the typical\n // 3–6 category case.\n left: 'center',\n type: 'scroll',\n itemGap: 16,\n },\n tooltip: {\n // Pie uses item-trigger (no axis); the rest of the styling mirrors\n // bar/histogram so the dashboard reads consistently — dark\n // grey[900] bg, white caption-font text, padded, with the shared\n // overflow-aware positioner.\n trigger: 'item',\n backgroundColor: theme.palette.grey[900],\n borderWidth: 0,\n padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],\n textStyle: {\n color: theme.palette.common.white,\n fontSize: 11,\n fontFamily: theme.typography.caption.fontFamily,\n },\n position: createTooltipPositioner(theme),\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n // V1 used `qualitative.bold` only (no `secondary.main` prefix) because\n // pie slices are categorical — each slice deserves a distinct palette\n // entry from the start, not a primary highlight.\n color: Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n // Pie template. The merger spreads this into each per-data series it\n // emits — borderColor / borderWidth / emphasis-disabled / label rich\n // sizes all survive through.\n series: [\n {\n type: 'pie',\n colorBy: 'data',\n avoidLabelOverlap: true,\n selectedOffset: 0,\n emphasis: { disabled: true },\n itemStyle: {\n borderColor: theme.palette.background.paper,\n borderWidth: 1,\n },\n label: {\n show: true,\n position: 'center',\n rich: {\n b: { fontSize: 16, fontWeight: 'normal', lineHeight: 20 },\n c: { fontSize: 28, fontWeight: 'bold', lineHeight: 27 },\n },\n },\n },\n ],\n }\n}\n\n/**\n * Returns the pie widget's {@link OptionFactory} — one closure that owns\n * BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link pieOptions}, optionally merging the\n * consumer-supplied `optionsOverride` on top. Called once by Provider\n * to seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`PieWidgetData`) into the option via the dataset API. Single-series\n * → donut (one dataset, `series[i].encode = { itemName: 'name', value: 'value' }`).\n * Multi-series → horizontal-bar fallback (mirrors v1 pie). Reactive\n * formatters from `ctx` drive the tooltip + center label at fusion\n * time so RelativeData's percent formatter flows through without a\n * structural rebuild.\n */\nexport function createPieOptionFactory(\n options: PieOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride, series } = options\n const radius = options.radius ?? DEFAULT_RADIUS\n const selection = options.selection\n const selectionSet =\n selection && selection.length > 0\n ? new Set<string | number>(selection)\n : null\n return (option, data, ctx) => {\n if (option == null) {\n const structural = pieOptions({ theme, formatter, labelFormatter })\n return optionsOverride\n ? (mergeOptions(\n structural as unknown as Record<string, unknown>,\n optionsOverride as Partial<Record<string, unknown>>,\n ) as EChartsOption)\n : structural\n }\n\n const seriesArr = Array.isArray(data) ? (data as PieWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n if (seriesArr.length > 1) {\n return buildMultiSeriesBarFusion(\n option,\n seriesArr,\n theme,\n series,\n ctx,\n selectionSet,\n )\n }\n return buildSingleSeriesPieFusion(\n option,\n seriesArr,\n radius,\n series,\n ctx,\n selectionSet,\n )\n }\n}\n\n/**\n * Single-series donut fusion. Spreads the structural pie series template\n * into per-data series with center/radius/encoding, wires the reactive\n * center-label / tooltip formatters and the per-data palette-aware\n * selection-dim callback.\n */\nfunction buildSingleSeriesPieFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n radius: readonly [string, string],\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n // Pie wants `colorBy: 'data'` — each slice draws from the option's\n // `color` palette by data index. But installing an `itemStyle.color`\n // callback disables ECharts' automatic per-data cycling, and\n // `params.color` collapses to the series color (so every slice goes\n // the same color). We re-implement the per-data palette resolution\n // here so the multicolor look survives selection-driven dimming.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const resolvePaletteColor = (params: CallbackDataParams): string => {\n const swatch =\n palette.length > 0\n ? palette[params.dataIndex % palette.length]\n : undefined\n return swatch ?? (params.color as string)\n }\n\n // Always emit `itemStyle.color` (passthrough when nothing is selected),\n // not conditionally — same anti-stale-callback rationale as bar /\n // histogram. The slice border + width come from the structural\n // template's `itemStyle` and survive via the spread below.\n const colorFn = (params: CallbackDataParams): string => {\n const base = resolvePaletteColor(params)\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n // Center label formatter — lives in the merger because it reads\n // reactive `formatter` / `labelFormatter` from ctx. The rich tags\n // `{c|…}` and `{b|…}` reference the rich styles baked into the\n // structural label template.\n const labelTextFormatter = (params: CallbackDataParams): string => {\n const { name } = params\n const encodeIndex = params.encode?.value?.[0]\n if (encodeIndex === undefined) return ''\n const value = (Object.values(params.data ?? {}) as unknown[]).at(\n encodeIndex,\n )\n // `value` here is the resolved dataset cell — for pie data it's a\n // `string | number` primitive. Anything else is a misuse we won't\n // dress up with `String(...)` (would render \"[object Object]\").\n const formattedValue =\n typeof value === 'number'\n ? formatter\n ? formatter(value)\n : String(value)\n : typeof value === 'string'\n ? value\n : ''\n const formattedName = labelFormatter\n ? String(labelFormatter(name ?? ''))\n : String(name ?? '')\n return `{c|${formattedValue}}\\n\\n{b|${formattedName}}`\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n series: seriesArr.map((_, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const templateObj = typeof template === 'object' ? template : {}\n const templateLabel = (templateObj as { label?: object }).label ?? {}\n const templateItemStyle =\n (templateObj as { itemStyle?: object }).itemStyle ?? {}\n return {\n ...templateObj,\n type: 'pie' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n radius: [...radius],\n // Lift the donut up so the bottom-anchored legend has the\n // vertical real estate to wrap to multiple rows for long\n // category lists — at exactly `50%` the bottom slices crowd\n // the chips and `type: 'plain'` legends can't expand upward\n // without overlapping the donut.\n center: ['50%', '38%'] as [string, string],\n encode: { itemName: 'name', value: 'value' },\n label: {\n ...templateLabel,\n formatter: labelTextFormatter,\n },\n itemStyle: {\n ...templateItemStyle,\n color: colorFn,\n },\n }\n }),\n // Legend always shows for pie (mirrors v1) — slice names drive the\n // entries, so even a single donut benefits from a category list.\n legend: { ...baseLegend, show: true },\n tooltip: {\n ...baseTooltip,\n formatter: buildPieTooltipFormatter(formatter, labelFormatter),\n },\n }\n}\n\n/**\n * Multi-series horizontal-bar fusion. Mirrors v1 pie's \"pie data with\n * >1 series collapses into a horizontal bar chart\" behavior — side-by-\n * side donuts don't read well when you're comparing the same categories\n * across cohorts, so swap to a value-on-x / category-on-y bar layout.\n *\n * Pie data shape is identical to bar's (`{ name, value }[][]`), so the\n * same dataset feeds either layout without transformation.\n */\nfunction buildMultiSeriesBarFusion(\n option: EChartsOption,\n seriesArr: PieWidgetData,\n theme: Theme,\n series: readonly WidgetSeries[] | undefined,\n ctx: OptionFactoryContext | undefined,\n selectionSet: Set<string | number> | null,\n): EChartsOption {\n const baseTooltip =\n typeof option.tooltip === 'object' && !Array.isArray(option.tooltip)\n ? option.tooltip\n : {}\n const baseLegend =\n typeof option.legend === 'object' && !Array.isArray(option.legend)\n ? option.legend\n : {}\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\n const formatter = ctx?.formatter\n const labelFormatter = ctx?.labelFormatter\n\n const { niceMinVal, niceMaxVal } = computeNiceBounds(seriesArr)\n\n // Per-series palette — multi-series bars take one color per series\n // (not per-data, unlike donut slices). Same anti-stale-callback rule:\n // always emit the callback so a transition to/from a selection\n // replaces the previous closure cleanly.\n const palette = Array.isArray(option.color)\n ? (option.color as readonly (string | undefined)[])\n : []\n const barColorFn = (params: CallbackDataParams): string => {\n const seriesIdx = params.seriesIndex ?? 0\n const seriesSwatch =\n palette.length > 0 ? palette[seriesIdx % palette.length] : undefined\n const base = (seriesSwatch ?? params.color) as string\n if (!selectionSet) return base\n const datum = params.value as { name?: string | number } | undefined\n const name = datum?.name ?? params.name\n return name != null && selectionSet.has(name)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n }\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n grid: {\n ...baseGrid,\n ...buildGridConfig(true, theme),\n right: parseInt(theme.spacing(4)),\n containLabel: true,\n },\n // Drop pie-specific structural keys that shouldn't render in the\n // bar fallback. ECharts ignores undefined keys, so this is a clean\n // override.\n series: seriesArr.map((_, i) => {\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n datasetIndex: i,\n type: 'bar' as const,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n barMaxWidth: 100,\n emphasis: { focus: 'series' },\n ...buildSeriesLabelConfig(formatter, 'x'),\n itemStyle: { color: barColorFn },\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n xAxis: {\n type: 'value',\n // Closures over the pre-computed nice bounds — ECharts calls them\n // once per render to resolve the axis extents.\n min: () => niceMinVal,\n max: () => niceMaxVal,\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: { color: theme.palette.black?.[4] ?? theme.palette.divider },\n },\n // Value labels render BELOW the axis line (default placement),\n // NOT inside the plot. Bar/histogram use `inside: true` +\n // `verticalAlign: 'bottom'` for their *vertical* y-axis where the\n // axis is the left wall — labels inside read like grid annotations.\n // A horizontal bar chart's value axis is the x-axis, and `inside`\n // there pushes the max label *behind* the bar (it visually\n // disappears once a bar reaches the right edge). Use the default\n // below-the-axis placement so the rounded extents stay readable.\n axisLabel: {\n fontSize: theme.typography.overlineDelicate?.fontSize,\n fontFamily: theme.typography.overlineDelicate?.fontFamily,\n margin: parseInt(theme.spacing(1)),\n showMaxLabel: true,\n showMinLabel: true,\n formatter: (value: number) => {\n if (value !== niceMaxVal && value !== niceMinVal) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n yAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n ...(labelFormatter && {\n formatter: (value: string | number) => String(labelFormatter(value)),\n }),\n },\n },\n legend: { ...baseLegend, show: true },\n tooltip: {\n ...baseTooltip,\n trigger: 'axis',\n formatter: buildHorizontalBarTooltipFormatter(formatter, labelFormatter),\n },\n } as EChartsOption\n}\n\n/**\n * Tooltip formatter for the horizontal-bar fallback. Reads the value by\n * `encode.x` dimension index (v1 parity) so it stays robust to\n * downstream changes that rename dataset columns.\n */\nfunction buildHorizontalBarTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.x?.at(0)\n const dimName =\n encodeIndex !== undefined ? item.dimensionNames?.[encodeIndex] : undefined\n const row =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (item.value as Record<string, string | number>)\n : undefined\n const raw = dimName && row ? row[dimName] : undefined\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n\n/**\n * Min/max bounds over every datum's `.value` across all series. Used by\n * the horizontal-bar fallback's x-axis label formatter so we only render\n * labels at the rounded extents (matches v1 + bar / histogram).\n */\nfunction computeNiceBounds(seriesArr: PieWidgetData): {\n niceMinVal: number\n niceMaxVal: number\n} {\n let min = 0\n let max = -Infinity\n for (const series of seriesArr) {\n for (const d of series) {\n if (typeof d?.value !== 'number' || !Number.isFinite(d.value)) continue\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n }\n return {\n niceMinVal: min < 0 ? niceNum(min) : 0,\n niceMaxVal: max <= 0 ? 1 : niceNum(max),\n }\n}\n\n/**\n * Tooltip formatter for pie slices. `item.value` is the dataset row\n * object (e.g. `{ name: 'A', value: 10 }`); we pull the value by\n * `encode.value`'s dimension index, formatted via the reactive `formatter`\n * if present. Slice name passes through `labelFormatter`.\n */\nfunction buildPieTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: string | number) => string | number) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const encodeIndex = item.encode?.value?.at(0) ?? 1\n const values =\n item.value && typeof item.value === 'object' && !Array.isArray(item.value)\n ? (Object.values(item.value) as (string | number)[])\n : []\n const raw = values[encodeIndex]\n const formattedValue =\n typeof raw === 'number' && formatter ? formatter(raw) : (raw ?? '')\n const marker = typeof item.marker === 'string' ? item.marker : ''\n const seriesName = item.seriesName ? `${item.seriesName}: ` : ''\n const name = labelFormatter\n ? String(labelFormatter(item.name ?? ''))\n : String(item.name ?? '')\n return { name, seriesName, marker, value: formattedValue }\n })\n}\n","import { Box, Skeleton } from '@mui/material'\nimport type { SxProps, Theme } from '@mui/material'\n\nconst OUTER_SIZE = 160\nconst HOLE_SIZE = 96\n\nconst styles = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: 200,\n py: 1,\n gap: ({ spacing }) => spacing(2),\n },\n donut: {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n ring: {\n width: OUTER_SIZE,\n height: OUTER_SIZE,\n },\n hole: {\n position: 'absolute',\n zIndex: 1,\n width: HOLE_SIZE,\n height: HOLE_SIZE,\n borderRadius: '50%',\n bgcolor: 'background.paper',\n },\n label: {\n position: 'absolute',\n zIndex: 2,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: ({ spacing }) => spacing(0.5),\n },\n legend: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(2),\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1.5),\n },\n} satisfies Record<string, SxProps<Theme>>\n\nexport interface PieSkeletonProps {\n count?: number\n}\n\n/**\n * Loading state for the Pie widget. Mirrors the donut silhouette — a ring\n * (gray circle with a background-coloured hole punched out), a stacked\n * value/name stub in the centre, and a centered legend stub below — so the\n * skeleton reads as \"a donut chart\" rather than a solid disc.\n *\n * Single donut only: multi-series pie loads as a horizontal bar chart, so\n * rendering one ring stays honest regardless of `count`.\n */\nexport function PieSkeleton({ count }: PieSkeletonProps) {\n // `count` is accepted for API compatibility but intentionally unused: the\n // skeleton always renders a single donut, since multi-series pie loads as a\n // horizontal bar chart rather than multiple donuts.\n void count\n return (\n <Box sx={styles.root}>\n <Box sx={styles.donut}>\n <Skeleton variant='circular' sx={styles.ring} />\n <Box sx={styles.hole} />\n <Box sx={styles.label}>\n <Skeleton width={56} height={18} />\n <Skeleton width={36} height={8} />\n </Box>\n </Box>\n <Box sx={styles.legend}>\n {[0, 1].map((i) => (\n <Box key={`legend-${i}`} sx={styles.legendItem}>\n <Skeleton variant='circular' width={8} height={8} />\n <Skeleton width={48} height={8} />\n </Box>\n ))}\n </Box>\n </Box>\n )\n}\n","import {\n buildCsvDownloadItem,\n buildPngDownloadItem,\n type DownloadItem,\n} from '../actions/download'\nimport type { PieWidgetData } from './types'\n\n/**\n * Download menu items for the Pie widget. Always includes a CSV item with\n * `series, name, value` columns (one row per slice; series labels come from\n * `seriesNames` if provided, else `series_<n>`). When `getCaptureEl` is\n * supplied, prepends a PNG item that rasterises the captured element via\n * `html2canvas`.\n */\nexport function createPieDownloadConfig(args: {\n filename: string\n getData: () => PieWidgetData\n seriesNames?: readonly string[]\n getCaptureEl?: () => HTMLElement | null\n pngPixelRatio?: number\n pngBackgroundColor?: string | null\n}): DownloadItem[] {\n const items: DownloadItem[] = []\n if (args.getCaptureEl) {\n items.push(\n buildPngDownloadItem({\n filename: args.filename,\n getCaptureEl: args.getCaptureEl,\n pixelRatio: args.pngPixelRatio,\n backgroundColor: args.pngBackgroundColor,\n }),\n )\n }\n items.push(\n buildCsvDownloadItem({\n filename: args.filename,\n getRows: () => {\n const data = args.getData()\n const rows: unknown[][] = [['series', 'name', 'value']]\n for (const [i, series] of data.entries()) {\n const seriesName = args.seriesNames?.[i] ?? `series_${i + 1}`\n for (const slice of series) {\n rows.push([seriesName, slice.name, slice.value])\n }\n }\n return rows\n },\n }),\n )\n return items\n}\n"],"names":["DEFAULT_RADIUS","pieOptions","theme","formatter","labelFormatter","legend","buildLegendConfig","hasLegend","left","type","itemGap","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","parseInt","spacing","textStyle","color","common","white","fontSize","fontFamily","typography","caption","position","createTooltipPositioner","buildPieTooltipFormatter","Object","values","qualitative","bold","series","colorBy","avoidLabelOverlap","selectedOffset","emphasis","disabled","itemStyle","borderColor","background","paper","label","show","rich","b","fontWeight","lineHeight","c","createPieOptionFactory","options","optionsOverride","radius","selection","selectionSet","length","Set","option","data","ctx","structural","mergeOptions","seriesArr","Array","isArray","dataset","buildMultiSeriesBarFusion","buildSingleSeriesPieFusion","seriesTemplates","broadcastTemplate","baseTooltip","baseLegend","resolvePaletteColor","params","dataIndex","undefined","colorFn","base","name","value","has","echarts","modifyAlpha","labelTextFormatter","encodeIndex","encode","at","formattedValue","String","formattedName","map","s","source","_","i","template","templateObj","templateLabel","templateItemStyle","datasetIndex","center","itemName","baseGrid","grid","niceMinVal","niceMaxVal","computeNiceBounds","barColorFn","seriesIdx","seriesIndex","buildGridConfig","right","containLabel","overrideColor","resolveThemeColor","barMaxWidth","focus","buildSeriesLabelConfig","xAxis","min","max","axisLine","axisTick","splitLine","lineStyle","black","divider","axisLabel","overlineDelicate","margin","showMaxLabel","showMinLabel","yAxis","buildHorizontalBarTooltipFormatter","createTooltipFormatter","item","x","dimName","dimensionNames","row","raw","marker","seriesName","d","Number","isFinite","niceNum","OUTER_SIZE","HOLE_SIZE","styles","root","display","flexDirection","alignItems","justifyContent","minHeight","py","gap","donut","ring","width","height","hole","zIndex","borderRadius","bgcolor","legendItem","PieSkeleton","t0","$","_c","t1","t2","Symbol","for","Skeleton","jsx","Box","t3","jsxs","t4","_temp","createPieDownloadConfig","args","items","getCaptureEl","push","buildPngDownloadItem","filename","pixelRatio","pngPixelRatio","pngBackgroundColor","buildCsvDownloadItem","getRows","getData","rows","entries","seriesNames","slice"],"mappings":"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"}