@carto/ps-react-ui 4.26.0 → 4.27.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.
Files changed (47) hide show
  1. package/dist/actions-DON6fSCh.js +1289 -0
  2. package/dist/actions-DON6fSCh.js.map +1 -0
  3. package/dist/category-BoT5FHHp.js +950 -0
  4. package/dist/category-BoT5FHHp.js.map +1 -0
  5. package/dist/scale-0elCv3tk.js +29 -0
  6. package/dist/scale-0elCv3tk.js.map +1 -0
  7. package/dist/types/widgets-v2/actions/index.d.ts +1 -1
  8. package/dist/types/widgets-v2/actions/relative-data/index.d.ts +1 -0
  9. package/dist/types/widgets-v2/actions/relative-data/labels.d.ts +3 -0
  10. package/dist/types/widgets-v2/actions/relative-data/relative-data.d.ts +16 -2
  11. package/dist/types/widgets-v2/actions/relative-data/scale.d.ts +26 -0
  12. package/dist/types/widgets-v2/actions/relative-data/style.d.ts +12 -0
  13. package/dist/types/widgets-v2/category/category.d.ts +2 -1
  14. package/dist/types/widgets-v2/index.d.ts +1 -1
  15. package/dist/widgets-v2/actions.js +1 -1
  16. package/dist/widgets-v2/bar.js +84 -83
  17. package/dist/widgets-v2/bar.js.map +1 -1
  18. package/dist/widgets-v2/category.js +1 -1
  19. package/dist/widgets-v2/histogram.js +108 -107
  20. package/dist/widgets-v2/histogram.js.map +1 -1
  21. package/dist/widgets-v2/scatterplot.js +120 -119
  22. package/dist/widgets-v2/scatterplot.js.map +1 -1
  23. package/dist/widgets-v2/timeseries.js +90 -89
  24. package/dist/widgets-v2/timeseries.js.map +1 -1
  25. package/dist/widgets-v2.js +2 -2
  26. package/dist/widgets-v2.js.map +1 -1
  27. package/package.json +3 -3
  28. package/src/widgets-v2/actions/index.ts +1 -0
  29. package/src/widgets-v2/actions/relative-data/index.ts +1 -0
  30. package/src/widgets-v2/actions/relative-data/labels.ts +6 -0
  31. package/src/widgets-v2/actions/relative-data/relative-data.test.tsx +78 -1
  32. package/src/widgets-v2/actions/relative-data/relative-data.tsx +137 -20
  33. package/src/widgets-v2/actions/relative-data/scale.ts +48 -0
  34. package/src/widgets-v2/actions/relative-data/style.ts +10 -0
  35. package/src/widgets-v2/bar/options.test.ts +16 -0
  36. package/src/widgets-v2/bar/options.ts +6 -2
  37. package/src/widgets-v2/category/category.relative-data.test.tsx +51 -63
  38. package/src/widgets-v2/category/category.tsx +25 -11
  39. package/src/widgets-v2/histogram/options.ts +6 -2
  40. package/src/widgets-v2/index.ts +1 -0
  41. package/src/widgets-v2/scatterplot/options.test.ts +12 -0
  42. package/src/widgets-v2/scatterplot/options.ts +18 -4
  43. package/src/widgets-v2/timeseries/options.ts +6 -2
  44. package/dist/actions-DXfQMrll.js +0 -1177
  45. package/dist/actions-DXfQMrll.js.map +0 -1
  46. package/dist/category-DuKx_CJX.js +0 -933
  47. package/dist/category-DuKx_CJX.js.map +0 -1
@@ -1,23 +1,24 @@
1
1
  import { r as e } from "../zoom-toggle-KA63b6-J.js";
2
- import { n as t, t as n } from "../download--wRRnf19.js";
3
- import { n as r, r as i, t as a } from "../utils-ClB6nn4w.js";
4
- import { a as o, d as s, f as c, i as l, s as u, u as d } from "../chart-config-BWxjodlt.js";
5
- import { t as f } from "../item-color-C1cu6EJd.js";
6
- import { c as p } from "react/compiler-runtime";
7
- import { Box as m, Skeleton as h } from "@mui/material";
8
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
9
- import * as v from "echarts";
2
+ import { n as t } from "../scale-0elCv3tk.js";
3
+ import { n, t as r } from "../download--wRRnf19.js";
4
+ import { n as i, r as a, t as o } from "../utils-ClB6nn4w.js";
5
+ import { a as s, d as c, f as l, i as u, s as d, u as f } from "../chart-config-BWxjodlt.js";
6
+ import { t as p } from "../item-color-C1cu6EJd.js";
7
+ import { c as m } from "react/compiler-runtime";
8
+ import { Box as h, Skeleton as g } from "@mui/material";
9
+ import { jsx as _, jsxs as v } from "react/jsx-runtime";
10
+ import * as y from "echarts";
10
11
  //#region src/widgets-v2/histogram/bins.ts
11
- function y(e) {
12
+ function b(e) {
12
13
  return typeof e == "number" ? e : e.value;
13
14
  }
14
- function b(e) {
15
+ function x(e) {
15
16
  if (typeof e == "number") return Number.isFinite(e);
16
17
  if (typeof e != "object" || !e) return !1;
17
18
  let t = e.value;
18
19
  return typeof t == "number" && Number.isFinite(t);
19
20
  }
20
- function x(e, t) {
21
+ function S(e, t) {
21
22
  return typeof e == "number" ? t : {
22
23
  ...e,
23
24
  value: t
@@ -25,14 +26,14 @@ function x(e, t) {
25
26
  }
26
27
  //#endregion
27
28
  //#region src/widgets-v2/histogram/options.ts
28
- function S({ theme: e, formatter: t }) {
29
+ function C({ theme: e, formatter: t }) {
29
30
  let n = 0, r = 1;
30
31
  return {
31
32
  grid: {
32
33
  left: parseInt(e.spacing(1)),
33
34
  top: parseInt(e.spacing(3)),
34
35
  right: parseInt(e.spacing(1)),
35
- ...o(!1, e),
36
+ ...s(!1, e),
36
37
  containLabel: !0
37
38
  },
38
39
  tooltip: {
@@ -46,10 +47,10 @@ function S({ theme: e, formatter: t }) {
46
47
  fontFamily: e.typography.caption.fontFamily
47
48
  },
48
49
  axisPointer: { type: "line" },
49
- position: s(e),
50
- formatter: w(t)
50
+ position: c(e),
51
+ formatter: T(t)
51
52
  },
52
- legend: { ...u({ hasLegend: !1 }) },
53
+ legend: { ...d({ hasLegend: !1 }) },
53
54
  axisPointer: { lineStyle: { color: e.palette.grey[400] } },
54
55
  color: [e.palette.secondary.main, ...Object.values(e.palette.qualitative?.bold ?? {})],
55
56
  xAxis: {
@@ -57,7 +58,7 @@ function S({ theme: e, formatter: t }) {
57
58
  axisLine: { show: !1 },
58
59
  axisTick: { show: !1 },
59
60
  axisLabel: {
60
- ...l(e),
61
+ ...u(e),
61
62
  padding: [
62
63
  parseInt(e.spacing(.5)),
63
64
  0,
@@ -71,8 +72,8 @@ function S({ theme: e, formatter: t }) {
71
72
  },
72
73
  yAxis: {
73
74
  type: "value",
74
- min: (e) => (n = e.min < 0 ? c(e.min) : 0, n),
75
- max: (e) => (r = e.max <= 0 ? 1 : c(e.max), r),
75
+ min: (e) => (n = e.min < 0 ? l(e.min) : 0, n),
76
+ max: (e) => (r = e.max <= 0 ? 1 : l(e.max), r),
76
77
  axisLine: { show: !1 },
77
78
  axisTick: { show: !1 },
78
79
  splitLine: {
@@ -80,7 +81,7 @@ function S({ theme: e, formatter: t }) {
80
81
  lineStyle: { color: e.palette.black?.[4] ?? e.palette.divider }
81
82
  },
82
83
  axisLabel: {
83
- ...l(e),
84
+ ...u(e),
84
85
  margin: parseInt(e.spacing(1)),
85
86
  show: !0,
86
87
  showMaxLabel: !0,
@@ -92,105 +93,105 @@ function S({ theme: e, formatter: t }) {
92
93
  }
93
94
  };
94
95
  }
95
- function C(t) {
96
- let { theme: n, formatter: o, ticks: s, series: l, labelFormatter: u, selection: d } = t, p = t.optionsOverride, m = t.lockedItems, h = d && d.length > 0 ? new Set(d) : null, g = [];
97
- for (let e = 0; e < s.length - 1; e++) {
98
- let t = s[e], n = s[e + 1], r = `${T(t)}–${T(n)}`;
99
- g.push(u ? u(r) : r);
96
+ function w(n) {
97
+ let { theme: r, formatter: s, ticks: c, series: u, labelFormatter: d, selection: f } = n, m = n.optionsOverride, h = n.lockedItems, g = f && f.length > 0 ? new Set(f) : null, _ = [];
98
+ for (let e = 0; e < c.length - 1; e++) {
99
+ let t = c[e], n = c[e + 1], r = `${E(t)}–${E(n)}`;
100
+ _.push(d ? d(r) : r);
100
101
  }
101
- let _ = m && m.length > 0 ? (() => {
102
- let e = m.map(Number), t = g[Math.min(...e)], n = g[Math.max(...e)];
102
+ let v = h && h.length > 0 ? (() => {
103
+ let e = h.map(Number), t = _[Math.min(...e)], n = _[Math.max(...e)];
103
104
  return t != null && n != null ? {
104
105
  min: t,
105
106
  max: n
106
107
  } : null;
107
108
  })() : null;
108
- return (t, s, u) => {
109
- if (t == null) {
110
- let e = S({
111
- theme: n,
112
- formatter: o
109
+ return (n, c, d) => {
110
+ if (n == null) {
111
+ let e = C({
112
+ theme: r,
113
+ formatter: s
113
114
  });
114
- return p ? i(e, p) : e;
115
+ return m ? a(e, m) : e;
115
116
  }
116
- let d = Array.isArray(s) ? s : [];
117
- if (d.length === 0 || g.length === 0) return {
118
- ...t,
117
+ let f = Array.isArray(c) ? c : [];
118
+ if (f.length === 0 || _.length === 0) return {
119
+ ...n,
119
120
  dataset: [],
120
121
  series: []
121
122
  };
122
- let m = d.length > 1, b = Array.isArray(t.series) ? t.series : [], x = b[0] ?? {}, C = typeof t.yAxis == "object" && !Array.isArray(t.yAxis) ? t.yAxis : {}, T = typeof t.grid == "object" && !Array.isArray(t.grid) ? t.grid : {}, E = typeof t.tooltip == "object" && !Array.isArray(t.tooltip) ? t.tooltip : {}, D = typeof t.legend == "object" && !Array.isArray(t.legend) ? t.legend : {}, O = u?.formatter, k = 0, A = 1, j = r(t.dataZoom, m), M = typeof T.bottom == "number" ? T.bottom : 24, N = m ? 56 : M, P = j ? N + e.sliderHeight + e.sliderGap : N, F = (e, t) => {
123
- let r = f({
124
- theme: n,
123
+ let h = f.length > 1, x = Array.isArray(n.series) ? n.series : [], S = x[0] ?? {}, w = typeof n.yAxis == "object" && !Array.isArray(n.yAxis) ? n.yAxis : {}, E = t(w), D = typeof n.grid == "object" && !Array.isArray(n.grid) ? n.grid : {}, O = typeof n.tooltip == "object" && !Array.isArray(n.tooltip) ? n.tooltip : {}, k = typeof n.legend == "object" && !Array.isArray(n.legend) ? n.legend : {}, A = d?.formatter, j = 0, M = 1, N = i(n.dataZoom, h), P = typeof D.bottom == "number" ? D.bottom : 24, F = h ? 56 : P, I = N ? F + e.sliderHeight + e.sliderGap : F, L = (e, t) => {
124
+ let n = p({
125
+ theme: r,
125
126
  datums: e,
126
127
  template: t,
127
128
  fallback: (e) => e.color
128
129
  });
129
130
  return { color: (e) => {
130
- let t = r(e);
131
- return h ? h.has(e.dataIndex) ? t : v.color.modifyAlpha(t, .15) : t;
131
+ let t = n(e);
132
+ return g ? g.has(e.dataIndex) ? t : y.color.modifyAlpha(t, .15) : t;
132
133
  } };
133
- }, I = Array.isArray(t.xAxis) ? t.xAxis[0] : t.xAxis, L = {
134
- min: _?.min ?? I?.min ?? null,
135
- max: _?.max ?? I?.max ?? null
136
- }, R = Array.isArray(t.xAxis) ? [{
137
- ...t.xAxis[0],
138
- ...L
139
- }, ...t.xAxis.slice(1)] : {
140
- ...typeof t.xAxis == "object" ? t.xAxis : {},
141
- ...L
134
+ }, R = Array.isArray(n.xAxis) ? n.xAxis[0] : n.xAxis, z = {
135
+ min: v?.min ?? R?.min ?? null,
136
+ max: v?.max ?? R?.max ?? null
137
+ }, B = Array.isArray(n.xAxis) ? [{
138
+ ...n.xAxis[0],
139
+ ...z
140
+ }, ...n.xAxis.slice(1)] : {
141
+ ...typeof n.xAxis == "object" ? n.xAxis : {},
142
+ ...z
142
143
  };
143
144
  return {
144
- ...t,
145
- xAxis: R,
146
- dataset: d.map((e) => ({ source: g.map((t, n) => {
145
+ ...n,
146
+ xAxis: B,
147
+ dataset: f.map((e) => ({ source: _.map((t, n) => {
147
148
  let r = e[n];
148
- return [t, r == null ? 0 : y(r)];
149
+ return [t, r == null ? 0 : b(r)];
149
150
  }) })),
150
- series: d.map((e, t) => {
151
- let r = b[t] ?? x, i = a(n, l?.[t]?.color);
151
+ series: f.map((e, t) => {
152
+ let n = x[t] ?? S, i = o(r, u?.[t]?.color);
152
153
  return {
153
- ...typeof r == "object" ? r : {},
154
+ ...typeof n == "object" ? n : {},
154
155
  type: "bar",
155
156
  datasetIndex: t,
156
- name: l?.[t]?.name ?? `Series ${t + 1}`,
157
+ name: u?.[t]?.name ?? `Series ${t + 1}`,
157
158
  encode: {
158
159
  x: 0,
159
160
  y: 1
160
161
  },
161
162
  barCategoryGap: "0%",
162
163
  emphasis: { focus: "series" },
163
- itemStyle: F(e, r),
164
+ itemStyle: L(e, n),
164
165
  ...i ? { color: i } : {}
165
166
  };
166
167
  }),
167
168
  legend: {
168
- ...D,
169
- show: m
169
+ ...k,
170
+ show: h
170
171
  },
171
172
  grid: {
172
- ...T,
173
- bottom: P
173
+ ...D,
174
+ bottom: I
174
175
  },
175
- ...j ? { dataZoom: j } : {},
176
+ ...N ? { dataZoom: N } : {},
176
177
  yAxis: {
177
- ...C,
178
- min: (e) => (k = e.min < 0 ? c(e.min) : 0, k),
179
- max: (e) => (A = e.max <= 0 ? 1 : c(e.max), A),
178
+ ...w,
179
+ min: (e) => (j = e.min < 0 ? E.min ?? l(e.min) : 0, j),
180
+ max: (e) => (M = e.max <= 0 ? 1 : E.max ?? l(e.max), M),
180
181
  axisLabel: {
181
- ...C.axisLabel ?? {},
182
- formatter: (e) => e !== A && e !== k || e === 0 ? "" : O ? O(e) : String(e)
182
+ ...w.axisLabel ?? {},
183
+ formatter: (e) => e !== M && e !== j || e === 0 ? "" : A ? A(e) : String(e)
183
184
  }
184
185
  },
185
186
  tooltip: {
186
- ...E,
187
- formatter: w(O)
187
+ ...O,
188
+ formatter: T(A)
188
189
  }
189
190
  };
190
191
  };
191
192
  }
192
- function w(e) {
193
- return d((t) => {
193
+ function T(e) {
194
+ return f((t) => {
194
195
  let n = t.value?.[1], r = typeof n == "number" && e ? e(n) : n ?? "", i = typeof t.marker == "string" ? t.marker : "", a = t.seriesName ? `${t.seriesName}: ` : "";
195
196
  return {
196
197
  name: String(t.name ?? ""),
@@ -200,12 +201,12 @@ function w(e) {
200
201
  };
201
202
  });
202
203
  }
203
- function T(e) {
204
+ function E(e) {
204
205
  return Number.isInteger(e) ? String(e) : Number(e.toFixed(2)).toString();
205
206
  }
206
207
  //#endregion
207
208
  //#region src/widgets-v2/histogram/skeleton.tsx
208
- var E = {
209
+ var D = {
209
210
  container: {
210
211
  display: "flex",
211
212
  alignItems: "center",
@@ -232,65 +233,65 @@ var E = {
232
233
  alignItems: "center",
233
234
  gap: ({ spacing: e }) => e(1.5)
234
235
  }
235
- }, D = (e) => ({
236
+ }, O = (e) => ({
236
237
  flex: 1,
237
238
  height: `${e}%`,
238
239
  minWidth: 8
239
240
  });
240
- function O(e) {
241
- let t = p(15), { bins: n } = e, r = n === void 0 ? 12 : n, i, a, o, s, c;
241
+ function k(e) {
242
+ let t = m(15), { bins: n } = e, r = n === void 0 ? 12 : n, i, a, o, s, c;
242
243
  if (t[0] !== r) {
243
244
  let e = Array.from({ length: r }, (e, t) => {
244
245
  let n = t / Math.max(1, r - 1);
245
246
  return Math.round(20 + 80 * Math.exp(-((n - .5) ** 2) * 8));
246
247
  });
247
- a = m, c = E.container, i = m, o = E.grid, s = e.map(A), t[0] = r, t[1] = i, t[2] = a, t[3] = o, t[4] = s, t[5] = c;
248
+ a = h, c = D.container, i = h, o = D.grid, s = e.map(j), t[0] = r, t[1] = i, t[2] = a, t[3] = o, t[4] = s, t[5] = c;
248
249
  } else i = t[1], a = t[2], o = t[3], s = t[4], c = t[5];
249
250
  let l;
250
- t[6] !== i || t[7] !== o || t[8] !== s ? (l = /* @__PURE__ */ g(i, {
251
+ t[6] !== i || t[7] !== o || t[8] !== s ? (l = /* @__PURE__ */ _(i, {
251
252
  sx: o,
252
253
  children: s
253
254
  }), t[6] = i, t[7] = o, t[8] = s, t[9] = l) : l = t[9];
254
255
  let u;
255
- t[10] === Symbol.for("react.memo_cache_sentinel") ? (u = /* @__PURE__ */ g(m, {
256
- sx: E.legend,
257
- children: [0, 1].map(k)
256
+ t[10] === Symbol.for("react.memo_cache_sentinel") ? (u = /* @__PURE__ */ _(h, {
257
+ sx: D.legend,
258
+ children: [0, 1].map(A)
258
259
  }), t[10] = u) : u = t[10];
259
260
  let d;
260
- return t[11] !== a || t[12] !== c || t[13] !== l ? (d = /* @__PURE__ */ _(a, {
261
+ return t[11] !== a || t[12] !== c || t[13] !== l ? (d = /* @__PURE__ */ v(a, {
261
262
  sx: c,
262
263
  children: [l, u]
263
264
  }), t[11] = a, t[12] = c, t[13] = l, t[14] = d) : d = t[14], d;
264
265
  }
265
- function k(e) {
266
- return /* @__PURE__ */ _(m, {
267
- sx: E.legendItem,
268
- children: [/* @__PURE__ */ g(h, {
266
+ function A(e) {
267
+ return /* @__PURE__ */ v(h, {
268
+ sx: D.legendItem,
269
+ children: [/* @__PURE__ */ _(g, {
269
270
  variant: "circular",
270
271
  width: 8,
271
272
  height: 8
272
- }), /* @__PURE__ */ g(h, {
273
+ }), /* @__PURE__ */ _(g, {
273
274
  width: 48,
274
275
  height: 8
275
276
  })]
276
277
  }, `legend-${e}`);
277
278
  }
278
- function A(e, t) {
279
- return /* @__PURE__ */ g(h, {
279
+ function j(e, t) {
280
+ return /* @__PURE__ */ _(g, {
280
281
  variant: "rectangular",
281
- sx: D(e)
282
+ sx: O(e)
282
283
  }, `bar-${t}`);
283
284
  }
284
285
  //#endregion
285
286
  //#region src/widgets-v2/histogram/download.ts
286
- function j(e) {
287
- let r = [];
288
- return e.getCaptureEl && r.push(t({
287
+ function M(e) {
288
+ let t = [];
289
+ return e.getCaptureEl && t.push(n({
289
290
  filename: e.filename,
290
291
  getCaptureEl: e.getCaptureEl,
291
292
  pixelRatio: e.pngPixelRatio,
292
293
  backgroundColor: e.pngBackgroundColor
293
- })), r.push(n({
294
+ })), t.push(r({
294
295
  filename: e.filename,
295
296
  getRows: (t) => {
296
297
  let n = e.getData(t), r = e.getTicks(), i = n.length, a = ["bin_low", "bin_high"];
@@ -300,30 +301,30 @@ function j(e) {
300
301
  let t = [r[e], r[e + 1]];
301
302
  for (let r = 0; r < i; r++) {
302
303
  let i = n[r]?.[e];
303
- t.push(i == null ? 0 : y(i));
304
+ t.push(i == null ? 0 : b(i));
304
305
  }
305
306
  o.push(t);
306
307
  }
307
308
  return o;
308
309
  }
309
- })), r;
310
+ })), t;
310
311
  }
311
312
  //#endregion
312
313
  //#region src/widgets-v2/histogram/transforms.ts
313
- var M = (e) => Array.isArray(e) ? e.map((e) => {
314
- if (!N(e)) return e;
315
- let t = e.reduce((e, t) => e + Math.abs(y(t)), 0);
316
- return t <= 0 ? e : e.map((e) => x(e, y(e) / t * 100));
314
+ var N = (e) => Array.isArray(e) ? e.map((e) => {
315
+ if (!P(e)) return e;
316
+ let t = e.reduce((e, t) => e + Math.abs(b(t)), 0);
317
+ return t <= 0 ? e : e.map((e) => S(e, b(e) / t * 100));
317
318
  }) : e;
318
- function N(e) {
319
- return Array.isArray(e) && e.every(b);
319
+ function P(e) {
320
+ return Array.isArray(e) && e.every(x);
320
321
  }
321
- function P(e, t) {
322
+ function F(e, t) {
322
323
  if (t.length === 0 || !Array.isArray(e)) return e;
323
324
  let n = new Set(t.map(Number));
324
- return e.map((e) => N(e) ? e.map((e, t) => n.has(t) ? e : x(e, 0)) : e);
325
+ return e.map((e) => P(e) ? e.map((e, t) => n.has(t) ? e : S(e, 0)) : e);
325
326
  }
326
327
  //#endregion
327
- export { O as HistogramSkeleton, j as createHistogramDownloadConfig, C as createHistogramOptionFactory, P as filterHistogramByLockedBins, y as getHistogramBinValue, S as histogramOptions, M as toRelativeHistogramData };
328
+ export { k as HistogramSkeleton, M as createHistogramDownloadConfig, w as createHistogramOptionFactory, F as filterHistogramByLockedBins, b as getHistogramBinValue, C as histogramOptions, N as toRelativeHistogramData };
328
329
 
329
330
  //# sourceMappingURL=histogram.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"histogram.js","names":["HistogramBin","getHistogramBinValue","bin","value","isHistogramBin","v","Number","isFinite","withHistogramBinValue","EChartsOption","echarts","CallbackDataParams","buildAxisLabelStyle","buildGridConfig","buildLegendConfig","createTooltipFormatter","createTooltipPositioner","niceNum","ZOOM_LAYOUT","OptionFactory","mergeOptions","resolveThemeColor","createItemColorResolver","getHistogramBinValue","positionDataZoomForLegend","HistogramEChartsOption","HistogramOptionFactoryInput","HistogramOptionsInput","HistogramBin","HistogramWidgetData","histogramOptions","theme","formatter","niceMin","niceMax","grid","left","parseInt","spacing","top","right","containLabel","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","textStyle","color","common","white","fontSize","fontFamily","typography","caption","axisPointer","type","position","buildHistogramTooltipFormatter","legend","hasLegend","lineStyle","secondary","main","Object","values","qualitative","bold","Record","xAxis","axisLine","show","axisTick","axisLabel","margin","interval","hideOverlap","yAxis","min","extent","max","splitLine","black","divider","showMaxLabel","showMinLabel","verticalAlign","inside","value","String","createHistogramOptionFactory","options","ticks","series","labelFormatter","selection","optionsOverride","lockedItems","selectionSet","length","Set","binLabels","i","lo","hi","raw","formatNumber","push","lockedRange","indices","map","Number","Math","option","data","ctx","structural","Partial","seriesArr","Array","isArray","dataset","seriesTemplates","broadcastTemplate","baseYAxis","baseGrid","baseTooltip","baseLegend","liveFormatter","dataZoomLayout","dataZoom","fallbackBottom","bottom","baseBottom","gridBottom","sliderHeight","sliderGap","makeDimItemStyle","datums","template","baseColor","fallback","params","base","has","dataIndex","modifyAlpha","currentAxis","lockedRangeAxis","nextXAxis","slice","bins","source","label","bin","overrideColor","const","datasetIndex","name","encode","x","y","barCategoryGap","emphasis","focus","itemStyle","item","row","formattedValue","marker","seriesName","n","isInteger","toFixed","toString","Box","Skeleton","SxProps","Theme","styles","container","display","alignItems","justifyContent","flexDirection","gap","spacing","height","grid","flex","width","legend","legendItem","Record","barSx","minWidth","HistogramSkeletonProps","bins","HistogramSkeleton","t0","$","_c","t1","undefined","T0","T1","t2","t3","t4","heights","Array","from","length","_","i","t","Math","max","round","exp","map","_temp","t5","t6","Symbol","for","_temp2","t7","i_1","h","i_0","buildCsvDownloadItem","buildPngDownloadItem","DownloadContext","DownloadItem","getHistogramBinValue","HistogramBin","HistogramWidgetData","createHistogramDownloadConfig","args","filename","getData","ctx","getTicks","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","ticks","seriesCount","length","header","i","rows","bin","Math","max","row","s","value","getHistogramBinValue","isHistogramBin","withHistogramBinValue","HistogramBin","toRelativeHistogramData","input","Array","isArray","map","series","isBinArray","total","reduce","acc","b","Math","abs","v","every","filterHistogramByLockedBins","lockedItems","length","locked","Set","Number","bin","i","has"],"sources":["../../src/widgets-v2/histogram/bins.ts","../../src/widgets-v2/histogram/options.ts","../../src/widgets-v2/histogram/skeleton.tsx","../../src/widgets-v2/histogram/download.ts","../../src/widgets-v2/histogram/transforms.ts"],"sourcesContent":["import type { HistogramBin } from './types'\n\n/** Count of a {@link HistogramBin}, whichever form it takes. */\nexport function getHistogramBinValue(bin: HistogramBin): number {\n return typeof bin === 'number' ? bin : bin.value\n}\n\n/** Whether `v` is a valid {@link HistogramBin} with a finite count. */\nexport function isHistogramBin(v: unknown): v is HistogramBin {\n if (typeof v === 'number') return Number.isFinite(v)\n if (v == null || typeof v !== 'object') return false\n const value = (v as { value?: unknown }).value\n return typeof value === 'number' && Number.isFinite(value)\n}\n\n/** Same bin with its count replaced; keeps the object form (and `color`). */\nexport function withHistogramBinValue(\n bin: HistogramBin,\n value: number,\n): HistogramBin {\n return typeof bin === 'number' ? value : { ...bin, value }\n}\n","import type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildAxisLabelStyle,\n buildGridConfig,\n buildLegendConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport { ZOOM_LAYOUT } from '../actions/zoom-toggle'\nimport type { OptionFactory } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport { createItemColorResolver } from '../utils/item-color'\nimport { getHistogramBinValue } from './bins'\nimport { positionDataZoomForLegend } from '../utils/data-zoom-layout'\nimport type {\n HistogramEChartsOption,\n HistogramOptionFactoryInput,\n HistogramOptionsInput,\n HistogramBin,\n HistogramWidgetData,\n} from './types'\n\n/**\n * Builds the **structural** ECharts option for a histogram widget — axes,\n * grid, tooltip, value-axis label formatter, themed legend. Mirrors\n * {@link import('../bar/options').barOptions} so the two widgets share v1\n * look-and-feel: themed dark tooltip with positioner, CARTO color palette,\n * structural legend (`show` toggled by the merger based on series count),\n * y-axis labels rendered inside the plot via the `niceNum` closure pattern.\n *\n * Intentional deviations from bar (histogram-specific):\n * - **No `xAxis.axisLabel.formatter`.** Bin labels are pre-formatted in\n * the merger via `formatNumber(lo)–formatNumber(hi)` and optionally\n * the consumer's `labelFormatter`. The strings on the axis are\n * already display-ready, so there's nothing to post-format here.\n * - **Tooltip formatter reads the array-tuple row shape.** The dataset\n * uses positional `encode: { x: 0, y: 1 }`, so `item.value` comes in\n * as `[binLabel, count]` rather than bar's `{ name, value }` object.\n *\n * Intentionally data-agnostic: no series, no dataset, no x-axis category\n * data (those depend on data + ticks and are added by the option factory's\n * merge phase via {@link createHistogramOptionFactory}).\n */\nexport function histogramOptions({\n theme,\n formatter,\n}: HistogramOptionsInput): HistogramEChartsOption {\n // Closure shared between yAxis min/max callbacks and the label formatter,\n // so only the rounded extents are labelled (matches v1 + bar).\n let niceMin = 0\n let niceMax = 1\n\n return {\n grid: {\n left: parseInt(theme.spacing(1)),\n top: parseInt(theme.spacing(3)),\n right: parseInt(theme.spacing(1)),\n // Default: no legend. Merger bumps this when there are >1 series.\n ...buildGridConfig(false, theme),\n containLabel: true,\n },\n tooltip: {\n trigger: 'axis',\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 axisPointer: { type: 'line' },\n position: createTooltipPositioner(theme),\n formatter: buildHistogramTooltipFormatter(formatter),\n },\n // Legend styling baked here; `show` is toggled by the merger based on\n // series count. Histogram doesn't accept `labelFormatter` at the\n // options layer (bin labels are pre-formatted in the merger), so we\n // skip the legend `labelFormatter` argument too.\n legend: {\n ...buildLegendConfig({ hasLegend: false }),\n },\n axisPointer: { lineStyle: { color: theme.palette.grey[400] } },\n color: [\n theme.palette.secondary.main,\n ...Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n ],\n xAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n ...buildAxisLabelStyle(theme),\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n margin: 0,\n // `interval: 0` makes every bin label a candidate so `hideOverlap`\n // can pack the maximum number that physically fit. The category-axis\n // default (`'auto'`) sub-samples first and leaves only one/two labels\n // even when there's room for more.\n interval: 0,\n hideOverlap: true,\n },\n },\n yAxis: {\n type: 'value',\n min: (extent: { min: number }) => {\n niceMin = extent.min < 0 ? niceNum(extent.min) : 0\n return niceMin\n },\n max: (extent: { min: number; max: number }) => {\n niceMax = extent.max <= 0 ? 1 : niceNum(extent.max)\n return niceMax\n },\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 axisLabel: {\n ...buildAxisLabelStyle(theme),\n margin: parseInt(theme.spacing(1)),\n show: true,\n showMaxLabel: true,\n showMinLabel: true,\n verticalAlign: 'bottom',\n inside: true,\n formatter: (value: number) => {\n if (value !== niceMax && value !== niceMin) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n } as HistogramEChartsOption\n}\n\n/**\n * Returns the histogram widget's {@link OptionFactory} — one closure that\n * owns BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link histogramOptions}, optionally merging\n * the consumer-supplied `optionsOverride`. Called once by Provider to\n * seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`HistogramWidgetData` — `HistogramBin[][]`) into the option via the\n * dataset API. Each series gets its own dataset of `[binLabel, count]`\n * pairs derived from `ticks`; series reference their dataset by\n * `datasetIndex` and are encoded by column position. Reactive\n * `ctx.formatter` (driven by RelativeData → `%`) plus `niceMin`/`niceMax`\n * are re-derived here so the y-axis label formatter and the tooltip\n * pick up live store values, mirroring bar.\n */\nexport function createHistogramOptionFactory(\n options: HistogramOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, ticks, series, labelFormatter, selection } = options\n const optionsOverride = options.optionsOverride\n const lockedItems = options.lockedItems\n const selectionSet =\n selection && selection.length > 0 ? new Set<number>(selection) : null\n\n const binLabels: string[] = []\n for (let i = 0; i < ticks.length - 1; i++) {\n const lo = ticks[i]!\n const hi = ticks[i + 1]!\n const raw = `${formatNumber(lo)}–${formatNumber(hi)}`\n binLabels.push(labelFormatter ? labelFormatter(raw) : raw)\n }\n\n // Locked range → x-axis crop. `min`/`max` on a category axis accept a\n // category value (the bin label string), bounding the visible window\n // without touching `dataset`/`series` — the zeroed-out bins from\n // `filterHistogramByLockedBins` stay in the data, just scrolled out of\n // view. `null` (not omitted) on unlock, since ECharts' option merge skips\n // `undefined` keys and would otherwise leave a stale crop in place.\n const lockedRange =\n lockedItems && lockedItems.length > 0\n ? (() => {\n const indices = lockedItems.map(Number)\n const min = binLabels[Math.min(...indices)]\n const max = binLabels[Math.max(...indices)]\n return min != null && max != null ? { min, max } : null\n })()\n : null\n\n return (option, data, ctx) => {\n if (option == null) {\n const structural = histogramOptions({ theme, formatter })\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: HistogramWidgetData<HistogramBin> = Array.isArray(data)\n ? (data as HistogramWidgetData<HistogramBin>)\n : []\n if (seriesArr.length === 0 || binLabels.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n\n const hasLegend = seriesArr.length > 1\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseYAxis =\n typeof option.yAxis === 'object' && !Array.isArray(option.yAxis)\n ? option.yAxis\n : {}\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\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 // Reactive (live store) formatter from ctx — distinct from the\n // closure-time `formatter` captured for the structural-build branch\n // above. RelativeData can install a percent formatter on the store\n // after the factory was constructed; the merge phase reads `ctx` to\n // pick that up.\n const liveFormatter = ctx?.formatter\n\n // Closure shared between the yAxis min/max callbacks and the label\n // formatter, so only the rounded extents are labelled (matches v1 +\n // bar). Delegating the extent to ECharts (rather than precomputing\n // scalars from the raw counts) keeps stacked bins inside the plot:\n // when StackToggle marks the series, ECharts feeds the *post-stack*\n // extent to these callbacks, so `niceNum` rounds the stacked total.\n let niceMin = 0\n let niceMax = 1\n\n // Zoom slider layout: when ZoomToggle has installed `dataZoom`, push\n // the slider above the legend (if any) and reserve room in the grid.\n const dataZoomLayout = positionDataZoomForLegend(option.dataZoom, hasLegend)\n const fallbackBottom =\n typeof baseGrid.bottom === 'number' ? baseGrid.bottom : 24\n const baseBottom = hasLegend ? 56 : fallbackBottom\n const gridBottom = dataZoomLayout\n ? baseBottom + ZOOM_LAYOUT.sliderHeight + ZOOM_LAYOUT.sliderGap\n : baseBottom\n\n // Dim non-selected bins via `series.itemStyle.color`. Per-row\n // `itemStyle` on dataset sources is silently ignored when\n // `series.encode` is in play.\n //\n // We *always* emit `itemStyle.color` (a passthrough when nothing is\n // selected), not conditionally — dropping the key between renders\n // would let ECharts' default merge keep the previous callback alive\n // and bins would stay dimmed forever after an external clear. Always\n // emitting lets normal merge swap the callback in place, no\n // `replaceMerge` and no entry-animation flash on selection on/off.\n //\n // The base colour is the bin's own `color` (object bins), else the\n // template's `itemStyle.color`, else the series colour / palette.\n const makeDimItemStyle = (\n datums: readonly unknown[],\n template: unknown,\n ) => {\n const baseColor = createItemColorResolver({\n theme,\n datums,\n template,\n fallback: (params) => params.color as string,\n })\n return {\n color: (params: CallbackDataParams) => {\n const base = baseColor(params)\n if (!selectionSet) return base\n return selectionSet.has(params.dataIndex)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n },\n }\n }\n\n // A consumer's `optionsOverride.xAxis` may legitimately be an array\n // (ECharts supports multiple x-axes on one grid). Merge the locked-range\n // crop into the primary (first) axis instead of discarding the rest via\n // an object fallback — `min`/`max` here bound a category axis by label\n // string, which is only ambiguous if `labelFormatter` produces duplicate\n // labels across bins (a structural limitation of label-string bounds,\n // not fixed here).\n //\n // `min`/`max` are ALWAYS written explicitly below (never omitted) —\n // ECharts' merge silently keeps whatever value it last received for an\n // omitted key, so omitting them while unlocked would leave a stale crop\n // in place from a previous locked render. But the fallback when there's\n // no active crop must be the CONSUMER's own `optionsOverride.xAxis.min/max`\n // (if they set one), not an unconditional `null` — `option.xAxis` here\n // is the post-structural-phase axis, which only ever carries the\n // consumer's static override (never our own prior crop — the structural\n // phase is rebuilt from scratch on every factory recreation, so it can't\n // have picked up a merge-phase write from a previous render).\n const currentAxis = (\n Array.isArray(option.xAxis) ? option.xAxis[0] : option.xAxis\n ) as { min?: unknown; max?: unknown } | undefined\n const lockedRangeAxis = {\n min: lockedRange?.min ?? currentAxis?.min ?? null,\n max: lockedRange?.max ?? currentAxis?.max ?? null,\n }\n const nextXAxis = Array.isArray(option.xAxis)\n ? [{ ...option.xAxis[0], ...lockedRangeAxis }, ...option.xAxis.slice(1)]\n : {\n ...(typeof option.xAxis === 'object' ? option.xAxis : {}),\n ...lockedRangeAxis,\n }\n\n return {\n ...option,\n xAxis: nextXAxis,\n dataset: seriesArr.map((bins) => ({\n source: binLabels.map((label, i) => {\n const bin = bins[i]\n return [label, bin == null ? 0 : getHistogramBinValue(bin)] as [\n string,\n number,\n ]\n }),\n })),\n series: seriesArr.map((bins, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n ...(typeof template === 'object' ? template : {}),\n type: 'bar' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n encode: { x: 0, y: 1 },\n barCategoryGap: '0%',\n emphasis: { focus: 'series' },\n itemStyle: makeDimItemStyle(bins, template),\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n legend: { ...baseLegend, show: hasLegend },\n grid: { ...baseGrid, bottom: gridBottom },\n ...(dataZoomLayout ? { dataZoom: dataZoomLayout } : {}),\n yAxis: {\n ...baseYAxis,\n min: (extent: { min: number }) => {\n niceMin = extent.min < 0 ? niceNum(extent.min) : 0\n return niceMin\n },\n max: (extent: { min: number; max: number }) => {\n niceMax = extent.max <= 0 ? 1 : niceNum(extent.max)\n return niceMax\n },\n axisLabel: {\n ...((baseYAxis as { axisLabel?: object }).axisLabel ?? {}),\n formatter: (value: number) => {\n if (value !== niceMax && value !== niceMin) return ''\n if (value === 0) return ''\n return liveFormatter ? liveFormatter(value) : String(value)\n },\n },\n } as EChartsOption['yAxis'],\n tooltip: {\n ...baseTooltip,\n formatter: buildHistogramTooltipFormatter(liveFormatter),\n },\n } as EChartsOption\n }\n}\n\n/**\n * Tooltip formatter for the histogram's positional `[binLabel, count]`\n * row shape. ECharts surfaces the x-axis category through `item.name`\n * (already pre-formatted by the bin-label generator), and `item.value`\n * comes in as the array tuple — distinct from bar's `{ name, value }`\n * object row.\n */\nfunction buildHistogramTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const row = item.value as [string, number] | undefined\n const raw = row?.[1]\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 return {\n name: String(item.name ?? ''),\n seriesName,\n marker,\n value: formattedValue,\n }\n })\n}\n\nfunction formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n)\n return Number(n.toFixed(2)).toString()\n}\n","import { Box, Skeleton, type SxProps, type Theme } from '@mui/material'\n\nconst styles = {\n container: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexDirection: 'column',\n gap: ({ spacing }) => spacing(1),\n height: ({ spacing }) => spacing(38),\n },\n grid: {\n display: 'flex',\n alignItems: 'flex-end',\n flex: '1 1 auto',\n gap: 0.5,\n width: '100%',\n },\n legend: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(2),\n height: ({ spacing }) => spacing(5),\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1.5),\n },\n} satisfies Record<string, SxProps<Theme>>\n\nconst barSx = (height: number): SxProps<Theme> => ({\n flex: 1,\n height: `${height}%`,\n minWidth: 8,\n})\n\nexport interface HistogramSkeletonProps {\n bins?: number\n}\n\n/**\n * Loading state for the Histogram widget. Mirrors Bar's skeleton structure\n * — a grid of bars (bin-shaped silhouette, anchored to the bottom) plus a\n * legend stub — so the placeholder reads consistently with Bar.\n */\nexport function HistogramSkeleton({ bins = 12 }: HistogramSkeletonProps) {\n // Sample heights mimicking a typical bell-shaped distribution.\n const heights = Array.from({ length: bins }, (_, i) => {\n const t = i / Math.max(1, bins - 1)\n return Math.round(20 + 80 * Math.exp(-((t - 0.5) ** 2) * 8))\n })\n return (\n <Box sx={styles.container}>\n <Box sx={styles.grid}>\n {heights.map((h, i) => (\n <Skeleton key={`bar-${i}`} variant='rectangular' sx={barSx(h)} />\n ))}\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 DownloadContext,\n type DownloadItem,\n} from '../actions/download'\nimport { getHistogramBinValue } from './bins'\nimport type { HistogramBin, HistogramWidgetData } from './types'\n\n/**\n * Download menu items for histograms. Always includes a CSV item with\n * `bin_low, bin_high, series_1_count, series_2_count, …` columns (one row\n * per bin). When `getCaptureEl` is supplied, prepends a PNG item that\n * rasterises the captured element via `html2canvas`.\n */\nexport function createHistogramDownloadConfig(args: {\n filename: string\n getData: (ctx: DownloadContext) => HistogramWidgetData<HistogramBin>\n getTicks: () => readonly number[]\n seriesNames?: readonly string[]\n getCaptureEl?: (ctx: DownloadContext) => 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: (ctx) => {\n const data = args.getData(ctx)\n const ticks = args.getTicks()\n const seriesCount = data.length\n const header: unknown[] = ['bin_low', 'bin_high']\n for (let i = 0; i < seriesCount; i++) {\n header.push(args.seriesNames?.[i] ?? `series_${i + 1}`)\n }\n const rows: unknown[][] = [header]\n for (let bin = 0; bin < Math.max(0, ticks.length - 1); bin++) {\n const row: unknown[] = [ticks[bin], ticks[bin + 1]]\n for (let s = 0; s < seriesCount; s++) {\n const value = data[s]?.[bin]\n row.push(value == null ? 0 : getHistogramBinValue(value))\n }\n rows.push(row)\n }\n return rows\n },\n }),\n )\n return items\n}\n","import {\n getHistogramBinValue,\n isHistogramBin,\n withHistogramBinValue,\n} from './bins'\nimport type { HistogramBin } from './types'\n\n/**\n * Histogram-specific `RelativeData` transform. Histogram data is\n * `HistogramBin[][]` — each series is a flat list of bin counts (plain\n * numbers or `{ value, color? }`, whose shape is kept). This\n * rewrites each count to its share of the series total (0–100), so\n * pairing with `createPercentFormatter` renders the y-axis as\n * percentages.\n *\n * Pass to `<Widget.RelativeData transform={toRelativeHistogramData} />`.\n *\n * The denominator is the sum of |value| across the series so mixed-sign\n * inputs produce sane signed shares-of-magnitude. A series whose total\n * magnitude is zero (all-zero or empty input) is returned unchanged so\n * a stalled or empty data set doesn't show misleading 0% values. Inputs\n * whose shape isn't `HistogramBin[][]` fall through untouched (same defensive\n * shape-check pattern as the default transform).\n */\nexport const toRelativeHistogramData = (input: unknown): unknown => {\n if (!Array.isArray(input)) return input\n return input.map((series: unknown): unknown => {\n if (!isBinArray(series)) return series\n const total = series.reduce<number>(\n (acc, b) => acc + Math.abs(getHistogramBinValue(b)),\n 0,\n )\n if (total <= 0) return series\n return series.map((b) =>\n withHistogramBinValue(b, (getHistogramBinValue(b) / total) * 100),\n )\n })\n}\n\nfunction isBinArray(v: unknown): v is HistogramBin[] {\n return Array.isArray(v) && v.every(isHistogramBin)\n}\n\n/**\n * `LockSelection` filter for Histogram. Data is `HistogramBin[][]` — a flat\n * list of bin counts per series, positionally paired with `ticks` (bin `i` covers\n * `[ticks[i], ticks[i+1])`). Unlike name-keyed widgets, locked-out bins can't\n * be REMOVED — that would shift every later bin's index and desync it from\n * its `ticks` range. Zeroing them out instead preserves array length/position,\n * so locked bins just render as empty (height 0) rather than disappearing.\n *\n * `lockedItems` holds bin indices (numbers, from Histogram's `selection`).\n */\nexport function filterHistogramByLockedBins(\n input: unknown,\n lockedItems: readonly (string | number)[],\n): unknown {\n if (lockedItems.length === 0) return input\n if (!Array.isArray(input)) return input\n const locked = new Set<number>(lockedItems.map(Number))\n return input.map((series: unknown): unknown => {\n if (!isBinArray(series)) return series\n return series.map((bin, i) =>\n locked.has(i) ? bin : withHistogramBinValue(bin, 0),\n )\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"histogram.js","names":["HistogramBin","getHistogramBinValue","bin","value","isHistogramBin","v","Number","isFinite","withHistogramBinValue","EChartsOption","echarts","CallbackDataParams","buildAxisLabelStyle","buildGridConfig","buildLegendConfig","createTooltipFormatter","createTooltipPositioner","niceNum","ZOOM_LAYOUT","OptionFactory","mergeOptions","resolveThemeColor","createItemColorResolver","getHistogramBinValue","positionDataZoomForLegend","HistogramEChartsOption","HistogramOptionFactoryInput","HistogramOptionsInput","HistogramBin","HistogramWidgetData","fixedAxisBounds","histogramOptions","theme","formatter","niceMin","niceMax","grid","left","parseInt","spacing","top","right","containLabel","tooltip","trigger","backgroundColor","palette","grey","borderWidth","padding","textStyle","color","common","white","fontSize","fontFamily","typography","caption","axisPointer","type","position","buildHistogramTooltipFormatter","legend","hasLegend","lineStyle","secondary","main","Object","values","qualitative","bold","Record","xAxis","axisLine","show","axisTick","axisLabel","margin","interval","hideOverlap","yAxis","min","extent","max","splitLine","black","divider","showMaxLabel","showMinLabel","verticalAlign","inside","value","String","createHistogramOptionFactory","options","ticks","series","labelFormatter","selection","optionsOverride","lockedItems","selectionSet","length","Set","binLabels","i","lo","hi","raw","formatNumber","push","lockedRange","indices","map","Number","Math","option","data","ctx","structural","Partial","seriesArr","Array","isArray","dataset","seriesTemplates","broadcastTemplate","baseYAxis","fixedY","baseGrid","baseTooltip","baseLegend","liveFormatter","dataZoomLayout","dataZoom","fallbackBottom","bottom","baseBottom","gridBottom","sliderHeight","sliderGap","makeDimItemStyle","datums","template","baseColor","fallback","params","base","has","dataIndex","modifyAlpha","currentAxis","lockedRangeAxis","nextXAxis","slice","bins","source","label","bin","overrideColor","const","datasetIndex","name","encode","x","y","barCategoryGap","emphasis","focus","itemStyle","item","row","formattedValue","marker","seriesName","n","isInteger","toFixed","toString","Box","Skeleton","SxProps","Theme","styles","container","display","alignItems","justifyContent","flexDirection","gap","spacing","height","grid","flex","width","legend","legendItem","Record","barSx","minWidth","HistogramSkeletonProps","bins","HistogramSkeleton","t0","$","_c","t1","undefined","T0","T1","t2","t3","t4","heights","Array","from","length","_","i","t","Math","max","round","exp","map","_temp","t5","t6","Symbol","for","_temp2","t7","i_1","h","i_0","buildCsvDownloadItem","buildPngDownloadItem","DownloadContext","DownloadItem","getHistogramBinValue","HistogramBin","HistogramWidgetData","createHistogramDownloadConfig","args","filename","getData","ctx","getTicks","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","ticks","seriesCount","length","header","i","rows","bin","Math","max","row","s","value","getHistogramBinValue","isHistogramBin","withHistogramBinValue","HistogramBin","toRelativeHistogramData","input","Array","isArray","map","series","isBinArray","total","reduce","acc","b","Math","abs","v","every","filterHistogramByLockedBins","lockedItems","length","locked","Set","Number","bin","i","has"],"sources":["../../src/widgets-v2/histogram/bins.ts","../../src/widgets-v2/histogram/options.ts","../../src/widgets-v2/histogram/skeleton.tsx","../../src/widgets-v2/histogram/download.ts","../../src/widgets-v2/histogram/transforms.ts"],"sourcesContent":["import type { HistogramBin } from './types'\n\n/** Count of a {@link HistogramBin}, whichever form it takes. */\nexport function getHistogramBinValue(bin: HistogramBin): number {\n return typeof bin === 'number' ? bin : bin.value\n}\n\n/** Whether `v` is a valid {@link HistogramBin} with a finite count. */\nexport function isHistogramBin(v: unknown): v is HistogramBin {\n if (typeof v === 'number') return Number.isFinite(v)\n if (v == null || typeof v !== 'object') return false\n const value = (v as { value?: unknown }).value\n return typeof value === 'number' && Number.isFinite(value)\n}\n\n/** Same bin with its count replaced; keeps the object form (and `color`). */\nexport function withHistogramBinValue(\n bin: HistogramBin,\n value: number,\n): HistogramBin {\n return typeof bin === 'number' ? value : { ...bin, value }\n}\n","import type { EChartsOption } from 'echarts'\nimport * as echarts from 'echarts'\nimport type { CallbackDataParams } from 'echarts/types/dist/shared'\nimport {\n buildAxisLabelStyle,\n buildGridConfig,\n buildLegendConfig,\n createTooltipFormatter,\n createTooltipPositioner,\n niceNum,\n} from '../../widgets/utils/chart-config'\nimport { ZOOM_LAYOUT } from '../actions/zoom-toggle'\nimport type { OptionFactory } from '../echart'\nimport { mergeOptions, resolveThemeColor } from '../utils'\nimport { createItemColorResolver } from '../utils/item-color'\nimport { getHistogramBinValue } from './bins'\nimport { positionDataZoomForLegend } from '../utils/data-zoom-layout'\nimport type {\n HistogramEChartsOption,\n HistogramOptionFactoryInput,\n HistogramOptionsInput,\n HistogramBin,\n HistogramWidgetData,\n} from './types'\nimport { fixedAxisBounds } from '../actions/relative-data/scale'\n\n/**\n * Builds the **structural** ECharts option for a histogram widget — axes,\n * grid, tooltip, value-axis label formatter, themed legend. Mirrors\n * {@link import('../bar/options').barOptions} so the two widgets share v1\n * look-and-feel: themed dark tooltip with positioner, CARTO color palette,\n * structural legend (`show` toggled by the merger based on series count),\n * y-axis labels rendered inside the plot via the `niceNum` closure pattern.\n *\n * Intentional deviations from bar (histogram-specific):\n * - **No `xAxis.axisLabel.formatter`.** Bin labels are pre-formatted in\n * the merger via `formatNumber(lo)–formatNumber(hi)` and optionally\n * the consumer's `labelFormatter`. The strings on the axis are\n * already display-ready, so there's nothing to post-format here.\n * - **Tooltip formatter reads the array-tuple row shape.** The dataset\n * uses positional `encode: { x: 0, y: 1 }`, so `item.value` comes in\n * as `[binLabel, count]` rather than bar's `{ name, value }` object.\n *\n * Intentionally data-agnostic: no series, no dataset, no x-axis category\n * data (those depend on data + ticks and are added by the option factory's\n * merge phase via {@link createHistogramOptionFactory}).\n */\nexport function histogramOptions({\n theme,\n formatter,\n}: HistogramOptionsInput): HistogramEChartsOption {\n // Closure shared between yAxis min/max callbacks and the label formatter,\n // so only the rounded extents are labelled (matches v1 + bar).\n let niceMin = 0\n let niceMax = 1\n\n return {\n grid: {\n left: parseInt(theme.spacing(1)),\n top: parseInt(theme.spacing(3)),\n right: parseInt(theme.spacing(1)),\n // Default: no legend. Merger bumps this when there are >1 series.\n ...buildGridConfig(false, theme),\n containLabel: true,\n },\n tooltip: {\n trigger: 'axis',\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 axisPointer: { type: 'line' },\n position: createTooltipPositioner(theme),\n formatter: buildHistogramTooltipFormatter(formatter),\n },\n // Legend styling baked here; `show` is toggled by the merger based on\n // series count. Histogram doesn't accept `labelFormatter` at the\n // options layer (bin labels are pre-formatted in the merger), so we\n // skip the legend `labelFormatter` argument too.\n legend: {\n ...buildLegendConfig({ hasLegend: false }),\n },\n axisPointer: { lineStyle: { color: theme.palette.grey[400] } },\n color: [\n theme.palette.secondary.main,\n ...Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n ],\n xAxis: {\n type: 'category',\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n ...buildAxisLabelStyle(theme),\n padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],\n margin: 0,\n // `interval: 0` makes every bin label a candidate so `hideOverlap`\n // can pack the maximum number that physically fit. The category-axis\n // default (`'auto'`) sub-samples first and leaves only one/two labels\n // even when there's room for more.\n interval: 0,\n hideOverlap: true,\n },\n },\n yAxis: {\n type: 'value',\n min: (extent: { min: number }) => {\n niceMin = extent.min < 0 ? niceNum(extent.min) : 0\n return niceMin\n },\n max: (extent: { min: number; max: number }) => {\n niceMax = extent.max <= 0 ? 1 : niceNum(extent.max)\n return niceMax\n },\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 axisLabel: {\n ...buildAxisLabelStyle(theme),\n margin: parseInt(theme.spacing(1)),\n show: true,\n showMaxLabel: true,\n showMinLabel: true,\n verticalAlign: 'bottom',\n inside: true,\n formatter: (value: number) => {\n if (value !== niceMax && value !== niceMin) return ''\n if (value === 0) return ''\n return formatter ? formatter(value) : String(value)\n },\n },\n },\n } as HistogramEChartsOption\n}\n\n/**\n * Returns the histogram widget's {@link OptionFactory} — one closure that\n * owns BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link histogramOptions}, optionally merging\n * the consumer-supplied `optionsOverride`. Called once by Provider to\n * seed `rawOptions` in the store.\n * - **Merge phase** (`option != null`) — fuses post-pipeline `state.data`\n * (`HistogramWidgetData` — `HistogramBin[][]`) into the option via the\n * dataset API. Each series gets its own dataset of `[binLabel, count]`\n * pairs derived from `ticks`; series reference their dataset by\n * `datasetIndex` and are encoded by column position. Reactive\n * `ctx.formatter` (driven by RelativeData → `%`) plus `niceMin`/`niceMax`\n * are re-derived here so the y-axis label formatter and the tooltip\n * pick up live store values, mirroring bar.\n */\nexport function createHistogramOptionFactory(\n options: HistogramOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, ticks, series, labelFormatter, selection } = options\n const optionsOverride = options.optionsOverride\n const lockedItems = options.lockedItems\n const selectionSet =\n selection && selection.length > 0 ? new Set<number>(selection) : null\n\n const binLabels: string[] = []\n for (let i = 0; i < ticks.length - 1; i++) {\n const lo = ticks[i]!\n const hi = ticks[i + 1]!\n const raw = `${formatNumber(lo)}–${formatNumber(hi)}`\n binLabels.push(labelFormatter ? labelFormatter(raw) : raw)\n }\n\n // Locked range → x-axis crop. `min`/`max` on a category axis accept a\n // category value (the bin label string), bounding the visible window\n // without touching `dataset`/`series` — the zeroed-out bins from\n // `filterHistogramByLockedBins` stay in the data, just scrolled out of\n // view. `null` (not omitted) on unlock, since ECharts' option merge skips\n // `undefined` keys and would otherwise leave a stale crop in place.\n const lockedRange =\n lockedItems && lockedItems.length > 0\n ? (() => {\n const indices = lockedItems.map(Number)\n const min = binLabels[Math.min(...indices)]\n const max = binLabels[Math.max(...indices)]\n return min != null && max != null ? { min, max } : null\n })()\n : null\n\n return (option, data, ctx) => {\n if (option == null) {\n const structural = histogramOptions({ theme, formatter })\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: HistogramWidgetData<HistogramBin> = Array.isArray(data)\n ? (data as HistogramWidgetData<HistogramBin>)\n : []\n if (seriesArr.length === 0 || binLabels.length === 0) {\n return { ...option, dataset: [], series: [] }\n }\n\n const hasLegend = seriesArr.length > 1\n const seriesTemplates = Array.isArray(option.series) ? option.series : []\n const broadcastTemplate = seriesTemplates[0] ?? {}\n const baseYAxis =\n typeof option.yAxis === 'object' && !Array.isArray(option.yAxis)\n ? option.yAxis\n : {}\n const fixedY = fixedAxisBounds(baseYAxis)\n const baseGrid =\n typeof option.grid === 'object' && !Array.isArray(option.grid)\n ? option.grid\n : {}\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 // Reactive (live store) formatter from ctx — distinct from the\n // closure-time `formatter` captured for the structural-build branch\n // above. RelativeData can install a percent formatter on the store\n // after the factory was constructed; the merge phase reads `ctx` to\n // pick that up.\n const liveFormatter = ctx?.formatter\n\n // Closure shared between the yAxis min/max callbacks and the label\n // formatter, so only the rounded extents are labelled (matches v1 +\n // bar). Delegating the extent to ECharts (rather than precomputing\n // scalars from the raw counts) keeps stacked bins inside the plot:\n // when StackToggle marks the series, ECharts feeds the *post-stack*\n // extent to these callbacks, so `niceNum` rounds the stacked total.\n let niceMin = 0\n let niceMax = 1\n\n // Zoom slider layout: when ZoomToggle has installed `dataZoom`, push\n // the slider above the legend (if any) and reserve room in the grid.\n const dataZoomLayout = positionDataZoomForLegend(option.dataZoom, hasLegend)\n const fallbackBottom =\n typeof baseGrid.bottom === 'number' ? baseGrid.bottom : 24\n const baseBottom = hasLegend ? 56 : fallbackBottom\n const gridBottom = dataZoomLayout\n ? baseBottom + ZOOM_LAYOUT.sliderHeight + ZOOM_LAYOUT.sliderGap\n : baseBottom\n\n // Dim non-selected bins via `series.itemStyle.color`. Per-row\n // `itemStyle` on dataset sources is silently ignored when\n // `series.encode` is in play.\n //\n // We *always* emit `itemStyle.color` (a passthrough when nothing is\n // selected), not conditionally — dropping the key between renders\n // would let ECharts' default merge keep the previous callback alive\n // and bins would stay dimmed forever after an external clear. Always\n // emitting lets normal merge swap the callback in place, no\n // `replaceMerge` and no entry-animation flash on selection on/off.\n //\n // The base colour is the bin's own `color` (object bins), else the\n // template's `itemStyle.color`, else the series colour / palette.\n const makeDimItemStyle = (\n datums: readonly unknown[],\n template: unknown,\n ) => {\n const baseColor = createItemColorResolver({\n theme,\n datums,\n template,\n fallback: (params) => params.color as string,\n })\n return {\n color: (params: CallbackDataParams) => {\n const base = baseColor(params)\n if (!selectionSet) return base\n return selectionSet.has(params.dataIndex)\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n },\n }\n }\n\n // A consumer's `optionsOverride.xAxis` may legitimately be an array\n // (ECharts supports multiple x-axes on one grid). Merge the locked-range\n // crop into the primary (first) axis instead of discarding the rest via\n // an object fallback — `min`/`max` here bound a category axis by label\n // string, which is only ambiguous if `labelFormatter` produces duplicate\n // labels across bins (a structural limitation of label-string bounds,\n // not fixed here).\n //\n // `min`/`max` are ALWAYS written explicitly below (never omitted) —\n // ECharts' merge silently keeps whatever value it last received for an\n // omitted key, so omitting them while unlocked would leave a stale crop\n // in place from a previous locked render. But the fallback when there's\n // no active crop must be the CONSUMER's own `optionsOverride.xAxis.min/max`\n // (if they set one), not an unconditional `null` — `option.xAxis` here\n // is the post-structural-phase axis, which only ever carries the\n // consumer's static override (never our own prior crop — the structural\n // phase is rebuilt from scratch on every factory recreation, so it can't\n // have picked up a merge-phase write from a previous render).\n const currentAxis = (\n Array.isArray(option.xAxis) ? option.xAxis[0] : option.xAxis\n ) as { min?: unknown; max?: unknown } | undefined\n const lockedRangeAxis = {\n min: lockedRange?.min ?? currentAxis?.min ?? null,\n max: lockedRange?.max ?? currentAxis?.max ?? null,\n }\n const nextXAxis = Array.isArray(option.xAxis)\n ? [{ ...option.xAxis[0], ...lockedRangeAxis }, ...option.xAxis.slice(1)]\n : {\n ...(typeof option.xAxis === 'object' ? option.xAxis : {}),\n ...lockedRangeAxis,\n }\n\n return {\n ...option,\n xAxis: nextXAxis,\n dataset: seriesArr.map((bins) => ({\n source: binLabels.map((label, i) => {\n const bin = bins[i]\n return [label, bin == null ? 0 : getHistogramBinValue(bin)] as [\n string,\n number,\n ]\n }),\n })),\n series: seriesArr.map((bins, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n ...(typeof template === 'object' ? template : {}),\n type: 'bar' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n encode: { x: 0, y: 1 },\n barCategoryGap: '0%',\n emphasis: { focus: 'series' },\n itemStyle: makeDimItemStyle(bins, template),\n ...(overrideColor ? { color: overrideColor } : {}),\n }\n }),\n legend: { ...baseLegend, show: hasLegend },\n grid: { ...baseGrid, bottom: gridBottom },\n ...(dataZoomLayout ? { dataZoom: dataZoomLayout } : {}),\n yAxis: {\n ...baseYAxis,\n // A config transform (RelativeData's `'total'` scale) may pin the\n // ends; each applies only on the side the data reaches.\n min: (extent: { min: number }) => {\n niceMin = extent.min < 0 ? (fixedY.min ?? niceNum(extent.min)) : 0\n return niceMin\n },\n max: (extent: { min: number; max: number }) => {\n niceMax = extent.max <= 0 ? 1 : (fixedY.max ?? niceNum(extent.max))\n return niceMax\n },\n axisLabel: {\n ...((baseYAxis as { axisLabel?: object }).axisLabel ?? {}),\n formatter: (value: number) => {\n if (value !== niceMax && value !== niceMin) return ''\n if (value === 0) return ''\n return liveFormatter ? liveFormatter(value) : String(value)\n },\n },\n } as EChartsOption['yAxis'],\n tooltip: {\n ...baseTooltip,\n formatter: buildHistogramTooltipFormatter(liveFormatter),\n },\n } as EChartsOption\n }\n}\n\n/**\n * Tooltip formatter for the histogram's positional `[binLabel, count]`\n * row shape. ECharts surfaces the x-axis category through `item.name`\n * (already pre-formatted by the bin-label generator), and `item.value`\n * comes in as the array tuple — distinct from bar's `{ name, value }`\n * object row.\n */\nfunction buildHistogramTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const row = item.value as [string, number] | undefined\n const raw = row?.[1]\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 return {\n name: String(item.name ?? ''),\n seriesName,\n marker,\n value: formattedValue,\n }\n })\n}\n\nfunction formatNumber(n: number): string {\n if (Number.isInteger(n)) return String(n)\n return Number(n.toFixed(2)).toString()\n}\n","import { Box, Skeleton, type SxProps, type Theme } from '@mui/material'\n\nconst styles = {\n container: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexDirection: 'column',\n gap: ({ spacing }) => spacing(1),\n height: ({ spacing }) => spacing(38),\n },\n grid: {\n display: 'flex',\n alignItems: 'flex-end',\n flex: '1 1 auto',\n gap: 0.5,\n width: '100%',\n },\n legend: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(2),\n height: ({ spacing }) => spacing(5),\n },\n legendItem: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1.5),\n },\n} satisfies Record<string, SxProps<Theme>>\n\nconst barSx = (height: number): SxProps<Theme> => ({\n flex: 1,\n height: `${height}%`,\n minWidth: 8,\n})\n\nexport interface HistogramSkeletonProps {\n bins?: number\n}\n\n/**\n * Loading state for the Histogram widget. Mirrors Bar's skeleton structure\n * — a grid of bars (bin-shaped silhouette, anchored to the bottom) plus a\n * legend stub — so the placeholder reads consistently with Bar.\n */\nexport function HistogramSkeleton({ bins = 12 }: HistogramSkeletonProps) {\n // Sample heights mimicking a typical bell-shaped distribution.\n const heights = Array.from({ length: bins }, (_, i) => {\n const t = i / Math.max(1, bins - 1)\n return Math.round(20 + 80 * Math.exp(-((t - 0.5) ** 2) * 8))\n })\n return (\n <Box sx={styles.container}>\n <Box sx={styles.grid}>\n {heights.map((h, i) => (\n <Skeleton key={`bar-${i}`} variant='rectangular' sx={barSx(h)} />\n ))}\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 DownloadContext,\n type DownloadItem,\n} from '../actions/download'\nimport { getHistogramBinValue } from './bins'\nimport type { HistogramBin, HistogramWidgetData } from './types'\n\n/**\n * Download menu items for histograms. Always includes a CSV item with\n * `bin_low, bin_high, series_1_count, series_2_count, …` columns (one row\n * per bin). When `getCaptureEl` is supplied, prepends a PNG item that\n * rasterises the captured element via `html2canvas`.\n */\nexport function createHistogramDownloadConfig(args: {\n filename: string\n getData: (ctx: DownloadContext) => HistogramWidgetData<HistogramBin>\n getTicks: () => readonly number[]\n seriesNames?: readonly string[]\n getCaptureEl?: (ctx: DownloadContext) => 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: (ctx) => {\n const data = args.getData(ctx)\n const ticks = args.getTicks()\n const seriesCount = data.length\n const header: unknown[] = ['bin_low', 'bin_high']\n for (let i = 0; i < seriesCount; i++) {\n header.push(args.seriesNames?.[i] ?? `series_${i + 1}`)\n }\n const rows: unknown[][] = [header]\n for (let bin = 0; bin < Math.max(0, ticks.length - 1); bin++) {\n const row: unknown[] = [ticks[bin], ticks[bin + 1]]\n for (let s = 0; s < seriesCount; s++) {\n const value = data[s]?.[bin]\n row.push(value == null ? 0 : getHistogramBinValue(value))\n }\n rows.push(row)\n }\n return rows\n },\n }),\n )\n return items\n}\n","import {\n getHistogramBinValue,\n isHistogramBin,\n withHistogramBinValue,\n} from './bins'\nimport type { HistogramBin } from './types'\n\n/**\n * Histogram-specific `RelativeData` transform. Histogram data is\n * `HistogramBin[][]` — each series is a flat list of bin counts (plain\n * numbers or `{ value, color? }`, whose shape is kept). This\n * rewrites each count to its share of the series total (0–100), so\n * pairing with `createPercentFormatter` renders the y-axis as\n * percentages.\n *\n * Pass to `<Widget.RelativeData transform={toRelativeHistogramData} />`.\n *\n * The denominator is the sum of |value| across the series so mixed-sign\n * inputs produce sane signed shares-of-magnitude. A series whose total\n * magnitude is zero (all-zero or empty input) is returned unchanged so\n * a stalled or empty data set doesn't show misleading 0% values. Inputs\n * whose shape isn't `HistogramBin[][]` fall through untouched (same defensive\n * shape-check pattern as the default transform).\n */\nexport const toRelativeHistogramData = (input: unknown): unknown => {\n if (!Array.isArray(input)) return input\n return input.map((series: unknown): unknown => {\n if (!isBinArray(series)) return series\n const total = series.reduce<number>(\n (acc, b) => acc + Math.abs(getHistogramBinValue(b)),\n 0,\n )\n if (total <= 0) return series\n return series.map((b) =>\n withHistogramBinValue(b, (getHistogramBinValue(b) / total) * 100),\n )\n })\n}\n\nfunction isBinArray(v: unknown): v is HistogramBin[] {\n return Array.isArray(v) && v.every(isHistogramBin)\n}\n\n/**\n * `LockSelection` filter for Histogram. Data is `HistogramBin[][]` — a flat\n * list of bin counts per series, positionally paired with `ticks` (bin `i` covers\n * `[ticks[i], ticks[i+1])`). Unlike name-keyed widgets, locked-out bins can't\n * be REMOVED — that would shift every later bin's index and desync it from\n * its `ticks` range. Zeroing them out instead preserves array length/position,\n * so locked bins just render as empty (height 0) rather than disappearing.\n *\n * `lockedItems` holds bin indices (numbers, from Histogram's `selection`).\n */\nexport function filterHistogramByLockedBins(\n input: unknown,\n lockedItems: readonly (string | number)[],\n): unknown {\n if (lockedItems.length === 0) return input\n if (!Array.isArray(input)) return input\n const locked = new Set<number>(lockedItems.map(Number))\n return input.map((series: unknown): unknown => {\n if (!isBinArray(series)) return series\n return series.map((bin, i) =>\n locked.has(i) ? bin : withHistogramBinValue(bin, 0),\n )\n })\n}\n"],"mappings":"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"}