@carto/ps-react-ui 4.25.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 (91) 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/item-color-C1cu6EJd.js +20 -0
  6. package/dist/item-color-C1cu6EJd.js.map +1 -0
  7. package/dist/scale-0elCv3tk.js +29 -0
  8. package/dist/scale-0elCv3tk.js.map +1 -0
  9. package/dist/types/widgets-v2/actions/index.d.ts +1 -1
  10. package/dist/types/widgets-v2/actions/relative-data/index.d.ts +1 -0
  11. package/dist/types/widgets-v2/actions/relative-data/labels.d.ts +3 -0
  12. package/dist/types/widgets-v2/actions/relative-data/relative-data.d.ts +16 -2
  13. package/dist/types/widgets-v2/actions/relative-data/scale.d.ts +26 -0
  14. package/dist/types/widgets-v2/actions/relative-data/style.d.ts +12 -0
  15. package/dist/types/widgets-v2/bar/types.d.ts +6 -0
  16. package/dist/types/widgets-v2/category/category.d.ts +2 -1
  17. package/dist/types/widgets-v2/histogram/bins.d.ts +7 -0
  18. package/dist/types/widgets-v2/histogram/download.d.ts +2 -2
  19. package/dist/types/widgets-v2/histogram/index.d.ts +2 -1
  20. package/dist/types/widgets-v2/histogram/options.d.ts +1 -1
  21. package/dist/types/widgets-v2/histogram/transforms.d.ts +5 -4
  22. package/dist/types/widgets-v2/histogram/types.d.ts +22 -5
  23. package/dist/types/widgets-v2/index.d.ts +2 -2
  24. package/dist/types/widgets-v2/pie/types.d.ts +6 -0
  25. package/dist/types/widgets-v2/scatterplot/download.d.ts +2 -2
  26. package/dist/types/widgets-v2/scatterplot/index.d.ts +2 -1
  27. package/dist/types/widgets-v2/scatterplot/points.d.ts +7 -0
  28. package/dist/types/widgets-v2/scatterplot/transforms.d.ts +4 -3
  29. package/dist/types/widgets-v2/scatterplot/types.d.ts +21 -2
  30. package/dist/types/widgets-v2/timeseries/types.d.ts +6 -0
  31. package/dist/types/widgets-v2/utils/item-color.d.ts +26 -0
  32. package/dist/widgets-v2/actions.js +1 -1
  33. package/dist/widgets-v2/bar.js +91 -81
  34. package/dist/widgets-v2/bar.js.map +1 -1
  35. package/dist/widgets-v2/category.js +1 -1
  36. package/dist/widgets-v2/histogram.js +133 -100
  37. package/dist/widgets-v2/histogram.js.map +1 -1
  38. package/dist/widgets-v2/pie.js +98 -78
  39. package/dist/widgets-v2/pie.js.map +1 -1
  40. package/dist/widgets-v2/scatterplot.js +151 -110
  41. package/dist/widgets-v2/scatterplot.js.map +1 -1
  42. package/dist/widgets-v2/timeseries.js +96 -86
  43. package/dist/widgets-v2/timeseries.js.map +1 -1
  44. package/dist/widgets-v2.js +2 -2
  45. package/dist/widgets-v2.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/widgets-v2/actions/fullscreen/fullscreen-store.test.tsx +77 -13
  48. package/src/widgets-v2/actions/fullscreen/fullscreen.tsx +48 -5
  49. package/src/widgets-v2/actions/index.ts +1 -0
  50. package/src/widgets-v2/actions/relative-data/index.ts +1 -0
  51. package/src/widgets-v2/actions/relative-data/labels.ts +6 -0
  52. package/src/widgets-v2/actions/relative-data/relative-data.test.tsx +78 -1
  53. package/src/widgets-v2/actions/relative-data/relative-data.tsx +137 -20
  54. package/src/widgets-v2/actions/relative-data/scale.ts +48 -0
  55. package/src/widgets-v2/actions/relative-data/style.ts +10 -0
  56. package/src/widgets-v2/bar/options.test.ts +122 -0
  57. package/src/widgets-v2/bar/options.ts +31 -16
  58. package/src/widgets-v2/bar/types.ts +6 -0
  59. package/src/widgets-v2/category/category.relative-data.test.tsx +51 -63
  60. package/src/widgets-v2/category/category.tsx +25 -11
  61. package/src/widgets-v2/histogram/bins.ts +22 -0
  62. package/src/widgets-v2/histogram/download.test.ts +10 -0
  63. package/src/widgets-v2/histogram/download.ts +7 -3
  64. package/src/widgets-v2/histogram/index.ts +3 -0
  65. package/src/widgets-v2/histogram/options.test.ts +62 -0
  66. package/src/widgets-v2/histogram/options.ts +44 -19
  67. package/src/widgets-v2/histogram/transforms.test.ts +21 -7
  68. package/src/widgets-v2/histogram/transforms.ts +26 -12
  69. package/src/widgets-v2/histogram/types.ts +25 -5
  70. package/src/widgets-v2/index.ts +7 -1
  71. package/src/widgets-v2/pie/options.test.ts +91 -0
  72. package/src/widgets-v2/pie/options.ts +50 -20
  73. package/src/widgets-v2/pie/types.ts +6 -0
  74. package/src/widgets-v2/scatterplot/download.test.ts +9 -0
  75. package/src/widgets-v2/scatterplot/download.ts +5 -3
  76. package/src/widgets-v2/scatterplot/index.ts +3 -0
  77. package/src/widgets-v2/scatterplot/options.test.ts +90 -0
  78. package/src/widgets-v2/scatterplot/options.ts +53 -15
  79. package/src/widgets-v2/scatterplot/points.ts +35 -0
  80. package/src/widgets-v2/scatterplot/transforms.test.ts +19 -0
  81. package/src/widgets-v2/scatterplot/transforms.ts +23 -18
  82. package/src/widgets-v2/scatterplot/types.ts +25 -2
  83. package/src/widgets-v2/timeseries/options.test.ts +65 -0
  84. package/src/widgets-v2/timeseries/options.ts +38 -19
  85. package/src/widgets-v2/timeseries/types.ts +6 -0
  86. package/src/widgets-v2/utils/item-color.test.ts +74 -0
  87. package/src/widgets-v2/utils/item-color.ts +55 -0
  88. package/dist/actions-B1ss030_.js +0 -1167
  89. package/dist/actions-B1ss030_.js.map +0 -1
  90. package/dist/category-DuKx_CJX.js +0 -933
  91. package/dist/category-DuKx_CJX.js.map +0 -1
@@ -1,20 +1,22 @@
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 { c as f } from "react/compiler-runtime";
6
- import { Box as p, Skeleton as m } from "@mui/material";
7
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
8
- import * as _ 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";
9
11
  //#region src/widgets-v2/timeseries/options.ts
10
- function v({ theme: e, formatter: t, labelFormatter: n }) {
12
+ function b({ theme: e, formatter: t, labelFormatter: n }) {
11
13
  let r = 0, i = 1;
12
14
  return {
13
15
  grid: {
14
16
  left: parseInt(e.spacing(1)),
15
17
  top: parseInt(e.spacing(3)),
16
18
  right: parseInt(e.spacing(1)),
17
- ...o(!1, e),
19
+ ...s(!1, e),
18
20
  containLabel: !0
19
21
  },
20
22
  tooltip: {
@@ -28,10 +30,10 @@ function v({ theme: e, formatter: t, labelFormatter: n }) {
28
30
  fontFamily: e.typography.caption.fontFamily
29
31
  },
30
32
  axisPointer: { type: "line" },
31
- position: s(e),
32
- formatter: b(t, n)
33
+ position: c(e),
34
+ formatter: S(t, n)
33
35
  },
34
- legend: { ...u({ hasLegend: !1 }) },
36
+ legend: { ...d({ hasLegend: !1 }) },
35
37
  axisPointer: { lineStyle: { color: e.palette.grey[400] } },
36
38
  color: [e.palette.secondary.main, ...Object.values(e.palette.qualitative?.bold ?? {})],
37
39
  xAxis: {
@@ -39,7 +41,7 @@ function v({ theme: e, formatter: t, labelFormatter: n }) {
39
41
  axisLine: { show: !1 },
40
42
  axisTick: { show: !1 },
41
43
  axisLabel: {
42
- ...l(e),
44
+ ...u(e),
43
45
  padding: [
44
46
  parseInt(e.spacing(.5)),
45
47
  0,
@@ -53,8 +55,8 @@ function v({ theme: e, formatter: t, labelFormatter: n }) {
53
55
  },
54
56
  yAxis: {
55
57
  type: "value",
56
- min: (e) => (r = e.min < 0 ? c(e.min) : 0, r),
57
- max: (e) => (i = e.max <= 0 ? 1 : c(e.max), i),
58
+ min: (e) => (r = e.min < 0 ? l(e.min) : 0, r),
59
+ max: (e) => (i = e.max <= 0 ? 1 : l(e.max), i),
58
60
  axisLine: { show: !1 },
59
61
  axisTick: { show: !1 },
60
62
  splitLine: {
@@ -62,7 +64,7 @@ function v({ theme: e, formatter: t, labelFormatter: n }) {
62
64
  lineStyle: { color: e.palette.black?.[4] ?? e.palette.divider }
63
65
  },
64
66
  axisLabel: {
65
- ...l(e),
67
+ ...u(e),
66
68
  margin: parseInt(e.spacing(1)),
67
69
  show: !0,
68
70
  showMaxLabel: !0,
@@ -74,46 +76,54 @@ function v({ theme: e, formatter: t, labelFormatter: n }) {
74
76
  }
75
77
  };
76
78
  }
77
- function y(t) {
78
- let { theme: n, formatter: o, labelFormatter: s, optionsOverride: l } = t, u = t.series, d = t.smooth ?? !0, f = t.area ?? !1, p = t.selection, m = p && p.length > 0 ? new Set(p) : null, h = (e) => e instanceof Date ? e.getTime() : e;
79
- return (t, p, g) => {
80
- if (t == null) {
81
- let e = v({
82
- theme: n,
83
- formatter: o,
84
- labelFormatter: s
79
+ function x(n) {
80
+ let { theme: r, formatter: s, labelFormatter: c, optionsOverride: u } = n, d = n.series, f = n.smooth ?? !0, m = n.area ?? !1, h = n.selection, g = h && h.length > 0 ? new Set(h) : null, _ = (e) => e instanceof Date ? e.getTime() : e;
81
+ return (n, h, v) => {
82
+ if (n == null) {
83
+ let e = b({
84
+ theme: r,
85
+ formatter: s,
86
+ labelFormatter: c
85
87
  });
86
- return l ? i(e, l) : e;
88
+ return u ? a(e, u) : e;
87
89
  }
88
- let y = Array.isArray(p) ? p : [];
89
- if (y.length === 0) return {
90
- ...t,
90
+ let x = Array.isArray(h) ? h : [];
91
+ if (x.length === 0) return {
92
+ ...n,
91
93
  dataset: [],
92
94
  series: []
93
95
  };
94
- let x = y.length > 1, S = Array.isArray(t.series) ? t.series : [], C = S[0] ?? {}, w = 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 = g?.formatter, k = 0, A = 1, j = r(t.dataZoom, x), M = typeof T.bottom == "number" ? T.bottom : 24, N = x ? 56 : M, P = j ? N + e.sliderHeight + e.sliderGap : N, F = { color: (e) => {
95
- let t = e.value?.name, n = e.color;
96
- return !m || t == null || m.has(h(t)) ? n : _.color.modifyAlpha(n, .15);
97
- } };
96
+ let C = x.length > 1, w = Array.isArray(n.series) ? n.series : [], T = w[0] ?? {}, E = typeof n.yAxis == "object" && !Array.isArray(n.yAxis) ? n.yAxis : {}, D = t(E), O = typeof n.grid == "object" && !Array.isArray(n.grid) ? n.grid : {}, k = typeof n.tooltip == "object" && !Array.isArray(n.tooltip) ? n.tooltip : {}, A = typeof n.legend == "object" && !Array.isArray(n.legend) ? n.legend : {}, j = v?.formatter, M = 0, N = 1, P = i(n.dataZoom, C), F = typeof O.bottom == "number" ? O.bottom : 24, I = C ? 56 : F, L = P ? I + e.sliderHeight + e.sliderGap : I, R = (e, t) => {
97
+ let n = p({
98
+ theme: r,
99
+ datums: e,
100
+ template: t,
101
+ fallback: (e) => e.color
102
+ });
103
+ return { color: (e) => {
104
+ let t = e.value?.name, r = n(e);
105
+ return !g || t == null || g.has(_(t)) ? r : y.color.modifyAlpha(r, .15);
106
+ } };
107
+ }, z = x.some((e) => e.some((e) => typeof e?.color == "string" && e.color !== ""));
98
108
  return {
99
- ...t,
100
- dataset: y.map((e) => ({ source: e })),
101
- series: y.map((e, t) => {
102
- let r = S[t] ?? C, i = a(n, u?.[t]?.color);
109
+ ...n,
110
+ dataset: x.map((e) => ({ source: e })),
111
+ series: x.map((e, t) => {
112
+ let n = w[t] ?? T, i = o(r, d?.[t]?.color);
103
113
  return {
104
- ...typeof r == "object" ? r : {},
114
+ ...typeof n == "object" ? n : {},
105
115
  type: "line",
106
116
  datasetIndex: t,
107
- name: u?.[t]?.name ?? `Series ${t + 1}`,
117
+ name: d?.[t]?.name ?? `Series ${t + 1}`,
108
118
  encode: {
109
119
  x: "name",
110
120
  y: "value"
111
121
  },
112
- smooth: d,
113
- showSymbol: m != null,
114
- ...f ? { areaStyle: {} } : {},
122
+ smooth: f,
123
+ showSymbol: g != null || z,
124
+ ...m ? { areaStyle: {} } : {},
115
125
  emphasis: { focus: "series" },
116
- itemStyle: F,
126
+ itemStyle: R(e, n),
117
127
  ...i ? {
118
128
  color: i,
119
129
  lineStyle: { color: i }
@@ -121,32 +131,32 @@ function y(t) {
121
131
  };
122
132
  }),
123
133
  legend: {
124
- ...D,
125
- show: x
134
+ ...A,
135
+ show: C
126
136
  },
127
137
  grid: {
128
- ...T,
129
- bottom: P
138
+ ...O,
139
+ bottom: L
130
140
  },
131
- ...j ? { dataZoom: j } : {},
141
+ ...P ? { dataZoom: P } : {},
132
142
  yAxis: {
133
- ...w,
134
- min: (e) => (k = e.min < 0 ? c(e.min) : 0, k),
135
- max: (e) => (A = e.max <= 0 ? 1 : c(e.max), A),
143
+ ...E,
144
+ min: (e) => (M = e.min < 0 ? D.min ?? l(e.min) : 0, M),
145
+ max: (e) => (N = e.max <= 0 ? 1 : D.max ?? l(e.max), N),
136
146
  axisLabel: {
137
- ...w.axisLabel ?? {},
138
- formatter: (e) => e !== A && e !== k || e === 0 ? "" : O ? O(e) : String(e)
147
+ ...E.axisLabel ?? {},
148
+ formatter: (e) => e !== N && e !== M || e === 0 ? "" : j ? j(e) : String(e)
139
149
  }
140
150
  },
141
151
  tooltip: {
142
- ...E,
143
- formatter: b(O, s)
152
+ ...k,
153
+ formatter: S(j, c)
144
154
  }
145
155
  };
146
156
  };
147
157
  }
148
- function b(e, t) {
149
- return d((n) => {
158
+ function S(e, t) {
159
+ return f((n) => {
150
160
  let r = n.value, i = r?.value, a = typeof i == "number" && e ? e(i) : i ?? "", o = typeof n.marker == "string" ? n.marker : "", s = n.seriesName ? `${n.seriesName}: ` : "", c = r?.name ?? n.name, l = t && c != null ? t(c instanceof Date ? c : new Date(c)) : c ?? "";
151
161
  return {
152
162
  name: String(l),
@@ -158,7 +168,7 @@ function b(e, t) {
158
168
  }
159
169
  //#endregion
160
170
  //#region src/widgets-v2/timeseries/skeleton.tsx
161
- var x = {
171
+ var C = {
162
172
  container: {
163
173
  display: "flex",
164
174
  flexDirection: "column",
@@ -204,42 +214,42 @@ var x = {
204
214
  gap: ({ spacing: e }) => e(1.5)
205
215
  }
206
216
  };
207
- function S() {
208
- let e = f(2), t;
209
- e[0] === Symbol.for("react.memo_cache_sentinel") ? (t = /* @__PURE__ */ g(p, {
210
- sx: x.graph,
217
+ function w() {
218
+ let e = m(2), t;
219
+ e[0] === Symbol.for("react.memo_cache_sentinel") ? (t = /* @__PURE__ */ v(h, {
220
+ sx: C.graph,
211
221
  children: [
212
- /* @__PURE__ */ h(m, {
222
+ /* @__PURE__ */ _(g, {
213
223
  variant: "rectangular",
214
- sx: x.segmentA
224
+ sx: C.segmentA
215
225
  }),
216
- /* @__PURE__ */ h(m, {
226
+ /* @__PURE__ */ _(g, {
217
227
  variant: "rectangular",
218
- sx: x.segmentB
228
+ sx: C.segmentB
219
229
  }),
220
- /* @__PURE__ */ h(m, {
230
+ /* @__PURE__ */ _(g, {
221
231
  variant: "rectangular",
222
- sx: x.segmentC
232
+ sx: C.segmentC
223
233
  })
224
234
  ]
225
235
  }), e[0] = t) : t = e[0];
226
236
  let n;
227
- return e[1] === Symbol.for("react.memo_cache_sentinel") ? (n = /* @__PURE__ */ g(p, {
228
- sx: x.container,
229
- children: [t, /* @__PURE__ */ h(p, {
230
- sx: x.legend,
231
- children: [0, 1].map(C)
237
+ return e[1] === Symbol.for("react.memo_cache_sentinel") ? (n = /* @__PURE__ */ v(h, {
238
+ sx: C.container,
239
+ children: [t, /* @__PURE__ */ _(h, {
240
+ sx: C.legend,
241
+ children: [0, 1].map(T)
232
242
  })]
233
243
  }), e[1] = n) : n = e[1], n;
234
244
  }
235
- function C(e) {
236
- return /* @__PURE__ */ g(p, {
237
- sx: x.legendItem,
238
- children: [/* @__PURE__ */ h(m, {
245
+ function T(e) {
246
+ return /* @__PURE__ */ v(h, {
247
+ sx: C.legendItem,
248
+ children: [/* @__PURE__ */ _(g, {
239
249
  variant: "circular",
240
250
  width: 8,
241
251
  height: 8
242
- }), /* @__PURE__ */ h(m, {
252
+ }), /* @__PURE__ */ _(g, {
243
253
  width: 48,
244
254
  height: 8
245
255
  })]
@@ -247,14 +257,14 @@ function C(e) {
247
257
  }
248
258
  //#endregion
249
259
  //#region src/widgets-v2/timeseries/download.ts
250
- function w(e) {
251
- let r = [];
252
- return e.getCaptureEl && r.push(t({
260
+ function E(e) {
261
+ let t = [];
262
+ return e.getCaptureEl && t.push(n({
253
263
  filename: e.filename,
254
264
  getCaptureEl: e.getCaptureEl,
255
265
  pixelRatio: e.pngPixelRatio,
256
266
  backgroundColor: e.pngBackgroundColor
257
- })), r.push(n({
267
+ })), t.push(r({
258
268
  filename: e.filename,
259
269
  getRows: (t) => {
260
270
  let n = e.getData(t), r = n.length, i = [], a = /* @__PURE__ */ new Set();
@@ -266,20 +276,20 @@ function w(e) {
266
276
  for (let t = 0; t < r; t++) s.push(e.seriesNames?.[t] ?? `series_${t + 1}`);
267
277
  let c = [s];
268
278
  for (let e of i) {
269
- let t = [T(e)], n = String(e);
279
+ let t = [D(e)], n = String(e);
270
280
  for (let e of o) t.push(e.get(n) ?? "");
271
281
  c.push(t);
272
282
  }
273
283
  return c;
274
284
  }
275
- })), r;
285
+ })), t;
276
286
  }
277
- function T(e) {
287
+ function D(e) {
278
288
  return e instanceof Date ? e.toISOString() : typeof e == "number" ? new Date(e).toISOString() : e;
279
289
  }
280
290
  //#endregion
281
291
  //#region src/widgets-v2/timeseries/transforms.ts
282
- function E(e, t) {
292
+ function O(e, t) {
283
293
  if (t.length === 0 || !Array.isArray(e)) return e;
284
294
  let n = new Set(t);
285
295
  return e.map((e) => Array.isArray(e) ? e.filter((e) => {
@@ -289,6 +299,6 @@ function E(e, t) {
289
299
  }) : e);
290
300
  }
291
301
  //#endregion
292
- export { S as TimeseriesSkeleton, w as createTimeseriesDownloadConfig, y as createTimeseriesOptionFactory, E as filterTimeseriesByLockedItems, v as timeseriesOptions };
302
+ export { w as TimeseriesSkeleton, E as createTimeseriesDownloadConfig, x as createTimeseriesOptionFactory, O as filterTimeseriesByLockedItems, b as timeseriesOptions };
293
303
 
294
304
  //# sourceMappingURL=timeseries.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeseries.js","names":["EChartsOption","echarts","CallbackDataParams","buildAxisLabelStyle","buildGridConfig","buildLegendConfig","createTooltipFormatter","createTooltipPositioner","niceNum","ZOOM_LAYOUT","OptionFactory","mergeOptions","resolveThemeColor","positionDataZoomForLegend","TimeseriesEChartsOption","TimeseriesOptionFactoryInput","TimeseriesOptionsInput","TimeseriesWidgetData","timeseriesOptions","theme","formatter","labelFormatter","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","buildTimeseriesTooltipFormatter","legend","hasLegend","lineStyle","secondary","main","Object","values","qualitative","bold","Record","xAxis","axisLine","show","axisTick","axisLabel","margin","hideOverlap","value","Date","yAxis","min","extent","max","splitLine","black","divider","showMaxLabel","showMinLabel","verticalAlign","inside","String","createTimeseriesOptionFactory","options","optionsOverride","series","smooth","area","selection","selectionSet","length","Set","normalizeName","n","getTime","option","data","ctx","structural","Partial","seriesArr","Array","isArray","dataset","seriesTemplates","broadcastTemplate","baseYAxis","baseGrid","baseTooltip","baseLegend","liveFormatter","dataZoomLayout","dataZoom","fallbackBottom","bottom","baseBottom","gridBottom","sliderHeight","sliderGap","dimItemStyle","params","datum","name","raw","base","has","modifyAlpha","map","s","source","_","i","template","overrideColor","const","datasetIndex","encode","x","y","showSymbol","areaStyle","emphasis","focus","itemStyle","item","row","formattedValue","marker","seriesName","rawName","Box","Skeleton","SxProps","Theme","styles","container","display","flexDirection","justifyContent","gap","spacing","height","graph","position","flex","width","segmentA","left","right","top","segmentB","segmentC","legend","alignItems","legendItem","Record","TimeseriesSkeleton","$","_c","t0","Symbol","for","t1","map","_temp","i","buildCsvDownloadItem","buildPngDownloadItem","DownloadContext","DownloadItem","TimeseriesWidgetData","createTimeseriesDownloadConfig","args","filename","getData","ctx","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","seriesCount","length","timeKeys","Date","seenKeys","Set","series","point","key","String","name","has","add","lookups","map","Map","p","value","header","i","rows","row","formatTime","lookupKey","lookup","get","v","toISOString","filterTimeseriesByLockedItems","input","lockedItems","length","Array","isArray","locked","Set","map","series","filter","item","raw","name","Date","getTime","has"],"sources":["../../src/widgets-v2/timeseries/options.ts","../../src/widgets-v2/timeseries/skeleton.tsx","../../src/widgets-v2/timeseries/download.ts","../../src/widgets-v2/timeseries/transforms.ts"],"sourcesContent":["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 { positionDataZoomForLegend } from '../utils/data-zoom-layout'\nimport type {\n TimeseriesEChartsOption,\n TimeseriesOptionFactoryInput,\n TimeseriesOptionsInput,\n TimeseriesWidgetData,\n} from './types'\n\n/**\n * Builds the **structural** ECharts option for a timeseries widget —\n * time x-axis, value y-axis, themed tooltip, themed legend, CARTO color\n * palette. Mirrors {@link import('../bar/options').barOptions} so all\n * four ECharts widgets share v1 look-and-feel.\n *\n * Intentional deviations from bar (timeseries-specific):\n * - **X-axis is `type: 'time'`** (not 'category'). ECharts handles\n * uneven sample spacing and zoom-level-aware label formatting.\n * `labelFormatter` is wrapped so the consumer sees a `Date`, not\n * a numeric timestamp.\n * - **Tooltip body reads `{ name, value }` rows**, same as bar, but\n * the `name` may arrive as `Date | number | string`. The\n * `labelFormatter` receives a `Date` regardless.\n *\n * Intentionally data-agnostic: no series, no dataset, no `legend.show`\n * (those depend on data and are added by the option factory's merge\n * phase via {@link createTimeseriesOptionFactory}).\n */\nexport function timeseriesOptions({\n theme,\n formatter,\n labelFormatter,\n}: TimeseriesOptionsInput): TimeseriesEChartsOption {\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: buildTimeseriesTooltipFormatter(formatter, labelFormatter),\n },\n // Legend styling baked here; `show` is toggled by the merger based on\n // series count.\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: 'time',\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 hideOverlap: true,\n ...(labelFormatter && {\n formatter: (value: number) => labelFormatter(new Date(value)),\n }),\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 TimeseriesEChartsOption\n}\n\n/**\n * Returns the timeseries widget's {@link OptionFactory} — one closure\n * that owns BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link timeseriesOptions}, 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 * (`TimeseriesWidgetData`) into the option via the dataset API: one\n * dataset per series, each series referencing its dataset by index,\n * encoded by `name` (x — time) and `value` (y). Mirrors {@link import('../bar/options').createBarOptionFactory}:\n * series-template merge for `addStack`, reactive formatters from\n * `ctx`, `niceNum`-rounded y-axis bounds at fusion time, and\n * `positionDataZoomForLegend` layout for ZoomToggle sliders.\n */\nexport function createTimeseriesOptionFactory(\n options: TimeseriesOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride } = options\n const series = options.series\n const smooth = options.smooth ?? true\n const area = options.area ?? false\n const selection = options.selection\n const selectionSet =\n selection && selection.length > 0\n ? new Set<string | number>(selection)\n : null\n // `name` may be Date | number | string. Normalize to the same type the\n // selection is keyed on (Date → ms) so Set lookups match.\n const normalizeName = (n: Date | number | string): string | number =>\n n instanceof Date ? n.getTime() : n\n return (option, data, ctx) => {\n if (option == null) {\n const structural = timeseriesOptions({ 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 TimeseriesWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\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\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. `labelFormatter` (Date → string) is structural-only —\n // not relativizable — so the merge branch reads the closure-time value.\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 data) keeps stacked lines inside the plot: when\n // StackToggle marks the series, ECharts feeds the *post-stack* extent\n // 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 the\n // slider above the legend (if any) and reserve room in the grid below.\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 points via `series.itemStyle.color`. Per-row\n // `itemStyle` on dataset object-rows 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 points would stay dimmed forever after an external clear.\n // Always emitting lets normal merge swap the callback in place, no\n // `replaceMerge` and no entry-animation flash on selection on/off.\n const dimItemStyle = {\n color: (params: CallbackDataParams) => {\n const datum = params.value as\n | { name?: Date | number | string }\n | undefined\n const raw = datum?.name\n const base = params.color as string\n if (!selectionSet || raw == null) return base\n return selectionSet.has(normalizeName(raw))\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n },\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 // For line series, set BOTH `series[i].color` (legend swatch +\n // markers) AND `series[i].lineStyle.color` (the line itself) so\n // the override paints everywhere a series has a colour slot.\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n ...(typeof template === 'object' ? template : {}),\n type: 'line' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n encode: { x: 'name', y: 'value' },\n smooth,\n // When a selection is active, surface markers so the per-point\n // color callback has something to dim — a continuous line would\n // hide the visual selection feedback.\n showSymbol: selectionSet != null,\n ...(area ? { areaStyle: {} } : {}),\n emphasis: { focus: 'series' },\n itemStyle: dimItemStyle,\n ...(overrideColor\n ? { color: overrideColor, lineStyle: { color: overrideColor } }\n : {}),\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: buildTimeseriesTooltipFormatter(\n liveFormatter,\n labelFormatter,\n ),\n },\n } as EChartsOption\n }\n}\n\n/**\n * Tooltip formatter for the timeseries `{ name, value }` row shape.\n * `name` arrives as `Date | number | string` (the time-axis stores the\n * raw value the consumer supplied). The consumer's `labelFormatter`\n * expects a `Date`, so we coerce non-Date values via `new Date(...)`\n * before invoking it.\n */\nfunction buildTimeseriesTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: Date) => string) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const row = item.value as\n | { name?: Date | number | string; value?: number }\n | undefined\n const raw = row?.value\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 rawName = row?.name ?? item.name\n const name =\n labelFormatter && rawName != null\n ? labelFormatter(rawName instanceof Date ? rawName : new Date(rawName))\n : (rawName ?? '')\n return { name: String(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 container: {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n gap: ({ spacing }) => spacing(1),\n height: ({ spacing }) => spacing(38),\n },\n graph: {\n position: 'relative',\n flex: '1 1 auto',\n width: '100%',\n },\n segmentA: {\n position: 'absolute',\n left: 0,\n right: '70%',\n top: '60%',\n height: 4,\n },\n segmentB: {\n position: 'absolute',\n left: '25%',\n right: '40%',\n top: '35%',\n height: 4,\n },\n segmentC: {\n position: 'absolute',\n left: '55%',\n right: 0,\n top: '50%',\n height: 4,\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\n/**\n * Loading state for the Timeseries widget. Mirrors a line chart's\n * silhouette — three thin horizontal segments at staggered offsets to\n * suggest a moving line, plus a 2-dot legend stub. Sibling-consistent\n * with Bar / Histogram / Scatter skeletons (column-flex container with\n * legend strip below).\n */\nexport function TimeseriesSkeleton() {\n return (\n <Box sx={styles.container}>\n <Box sx={styles.graph}>\n <Skeleton variant='rectangular' sx={styles.segmentA} />\n <Skeleton variant='rectangular' sx={styles.segmentB} />\n <Skeleton variant='rectangular' sx={styles.segmentC} />\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 type { TimeseriesWidgetData } from './types'\n\n/**\n * Download menu items for the Timeseries widget. Always includes a CSV\n * item with `time, series_1, series_2, …` columns (one row per unique time\n * across all series; ISO-8601 strings for `Date`/numeric times). When\n * `getCaptureEl` is supplied, prepends a PNG item that rasterises the\n * captured element via `html2canvas`.\n */\nexport function createTimeseriesDownloadConfig(args: {\n filename: string\n getData: (ctx: DownloadContext) => TimeseriesWidgetData\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 seriesCount = data.length\n\n // Collect every unique time, preserving insertion order.\n const timeKeys: (Date | number | string)[] = []\n const seenKeys = new Set<string>()\n for (const series of data) {\n for (const point of series) {\n const key = String(point.name)\n if (!seenKeys.has(key)) {\n seenKeys.add(key)\n timeKeys.push(point.name)\n }\n }\n }\n\n // Build a quick lookup per series for O(rows × series) emit.\n const lookups = data.map(\n (series) => new Map(series.map((p) => [String(p.name), p.value])),\n )\n\n const header: unknown[] = ['time']\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 (const key of timeKeys) {\n const row: unknown[] = [formatTime(key)]\n const lookupKey = String(key)\n for (const lookup of lookups) row.push(lookup.get(lookupKey) ?? '')\n rows.push(row)\n }\n\n return rows\n },\n }),\n )\n return items\n}\n\nfunction formatTime(v: Date | number | string): string {\n if (v instanceof Date) return v.toISOString()\n if (typeof v === 'number') return new Date(v).toISOString()\n return v\n}\n","/**\n * `LockSelection` filter for Timeseries. Data is `{name, value}[][]` like\n * Bar/Pie/Category, but `name` may arrive as `Date | number | string` (the\n * time axis stores a `Date`). `lockedItems` is snapshotted from `selection`,\n * whose keys are already normalized to `Date → ms` (see `options.ts`'s\n * `normalizeName`) — so a raw `Date` name must be normalized the same way\n * before the membership check, or every point would compare a `Date` object\n * against a `number` and silently fail to match, filtering everything out.\n */\nexport function filterTimeseriesByLockedItems(\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<string | number>(lockedItems)\n return input.map((series: unknown): unknown => {\n if (!Array.isArray(series)) return series\n return series.filter((item: unknown) => {\n if (item == null || typeof item !== 'object' || !('name' in item)) {\n return false\n }\n const raw = (item as { name: unknown }).name\n const name = raw instanceof Date ? raw.getTime() : raw\n return (\n (typeof name === 'string' || typeof name === 'number') &&\n locked.has(name)\n )\n })\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"timeseries.js","names":["EChartsOption","echarts","CallbackDataParams","buildAxisLabelStyle","buildGridConfig","buildLegendConfig","createTooltipFormatter","createTooltipPositioner","niceNum","ZOOM_LAYOUT","OptionFactory","mergeOptions","resolveThemeColor","createItemColorResolver","positionDataZoomForLegend","TimeseriesEChartsOption","TimeseriesOptionFactoryInput","TimeseriesOptionsInput","TimeseriesWidgetData","fixedAxisBounds","timeseriesOptions","theme","formatter","labelFormatter","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","buildTimeseriesTooltipFormatter","legend","hasLegend","lineStyle","secondary","main","Object","values","qualitative","bold","Record","xAxis","axisLine","show","axisTick","axisLabel","margin","hideOverlap","value","Date","yAxis","min","extent","max","splitLine","black","divider","showMaxLabel","showMinLabel","verticalAlign","inside","String","createTimeseriesOptionFactory","options","optionsOverride","series","smooth","area","selection","selectionSet","length","Set","normalizeName","n","getTime","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","datum","name","raw","base","has","modifyAlpha","hasDatumColor","some","s","d","map","source","i","overrideColor","const","datasetIndex","encode","x","y","showSymbol","areaStyle","emphasis","focus","itemStyle","item","row","formattedValue","marker","seriesName","rawName","Box","Skeleton","SxProps","Theme","styles","container","display","flexDirection","justifyContent","gap","spacing","height","graph","position","flex","width","segmentA","left","right","top","segmentB","segmentC","legend","alignItems","legendItem","Record","TimeseriesSkeleton","$","_c","t0","Symbol","for","t1","map","_temp","i","buildCsvDownloadItem","buildPngDownloadItem","DownloadContext","DownloadItem","TimeseriesWidgetData","createTimeseriesDownloadConfig","args","filename","getData","ctx","seriesNames","getCaptureEl","HTMLElement","pngPixelRatio","pngBackgroundColor","items","push","pixelRatio","backgroundColor","getRows","data","seriesCount","length","timeKeys","Date","seenKeys","Set","series","point","key","String","name","has","add","lookups","map","Map","p","value","header","i","rows","row","formatTime","lookupKey","lookup","get","v","toISOString","filterTimeseriesByLockedItems","input","lockedItems","length","Array","isArray","locked","Set","map","series","filter","item","raw","name","Date","getTime","has"],"sources":["../../src/widgets-v2/timeseries/options.ts","../../src/widgets-v2/timeseries/skeleton.tsx","../../src/widgets-v2/timeseries/download.ts","../../src/widgets-v2/timeseries/transforms.ts"],"sourcesContent":["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 { positionDataZoomForLegend } from '../utils/data-zoom-layout'\nimport type {\n TimeseriesEChartsOption,\n TimeseriesOptionFactoryInput,\n TimeseriesOptionsInput,\n TimeseriesWidgetData,\n} from './types'\nimport { fixedAxisBounds } from '../actions/relative-data/scale'\n\n/**\n * Builds the **structural** ECharts option for a timeseries widget —\n * time x-axis, value y-axis, themed tooltip, themed legend, CARTO color\n * palette. Mirrors {@link import('../bar/options').barOptions} so all\n * four ECharts widgets share v1 look-and-feel.\n *\n * Intentional deviations from bar (timeseries-specific):\n * - **X-axis is `type: 'time'`** (not 'category'). ECharts handles\n * uneven sample spacing and zoom-level-aware label formatting.\n * `labelFormatter` is wrapped so the consumer sees a `Date`, not\n * a numeric timestamp.\n * - **Tooltip body reads `{ name, value }` rows**, same as bar, but\n * the `name` may arrive as `Date | number | string`. The\n * `labelFormatter` receives a `Date` regardless.\n *\n * Intentionally data-agnostic: no series, no dataset, no `legend.show`\n * (those depend on data and are added by the option factory's merge\n * phase via {@link createTimeseriesOptionFactory}).\n */\nexport function timeseriesOptions({\n theme,\n formatter,\n labelFormatter,\n}: TimeseriesOptionsInput): TimeseriesEChartsOption {\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: buildTimeseriesTooltipFormatter(formatter, labelFormatter),\n },\n // Legend styling baked here; `show` is toggled by the merger based on\n // series count.\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: 'time',\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 hideOverlap: true,\n ...(labelFormatter && {\n formatter: (value: number) => labelFormatter(new Date(value)),\n }),\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 TimeseriesEChartsOption\n}\n\n/**\n * Returns the timeseries widget's {@link OptionFactory} — one closure\n * that owns BOTH phases of option construction:\n *\n * - **Structural phase** (`option == null`) — builds the theme-aware\n * structural option via {@link timeseriesOptions}, 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 * (`TimeseriesWidgetData`) into the option via the dataset API: one\n * dataset per series, each series referencing its dataset by index,\n * encoded by `name` (x — time) and `value` (y). Mirrors {@link import('../bar/options').createBarOptionFactory}:\n * series-template merge for `addStack`, reactive formatters from\n * `ctx`, `niceNum`-rounded y-axis bounds at fusion time, and\n * `positionDataZoomForLegend` layout for ZoomToggle sliders.\n */\nexport function createTimeseriesOptionFactory(\n options: TimeseriesOptionFactoryInput,\n): OptionFactory {\n const { theme, formatter, labelFormatter, optionsOverride } = options\n const series = options.series\n const smooth = options.smooth ?? true\n const area = options.area ?? false\n const selection = options.selection\n const selectionSet =\n selection && selection.length > 0\n ? new Set<string | number>(selection)\n : null\n // `name` may be Date | number | string. Normalize to the same type the\n // selection is keyed on (Date → ms) so Set lookups match.\n const normalizeName = (n: Date | number | string): string | number =>\n n instanceof Date ? n.getTime() : n\n return (option, data, ctx) => {\n if (option == null) {\n const structural = timeseriesOptions({ 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 TimeseriesWidgetData) : []\n if (seriesArr.length === 0) {\n return { ...option, dataset: [], series: [] }\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\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. `labelFormatter` (Date → string) is structural-only —\n // not relativizable — so the merge branch reads the closure-time value.\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 data) keeps stacked lines inside the plot: when\n // StackToggle marks the series, ECharts feeds the *post-stack* extent\n // 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 the\n // slider above the legend (if any) and reserve room in the grid below.\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 points via `series.itemStyle.color`. Per-row\n // `itemStyle` on dataset object-rows 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 points would stay dimmed forever after an external clear.\n // Always 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 point's own `color`, else the template's\n // `itemStyle.color`, else the series colour / palette (`params.color`).\n const makeDimItemStyle = (datums: readonly object[], template: unknown) => {\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 datum = params.value as\n { name?: Date | number | string } | undefined\n const raw = datum?.name\n const base = baseColor(params)\n if (!selectionSet || raw == null) return base\n return selectionSet.has(normalizeName(raw))\n ? base\n : echarts.color.modifyAlpha(base, 0.15)\n },\n }\n }\n // Per-point colours only show on markers, so surface them whenever a\n // point carries its own `color` (same reason as the selection case).\n const hasDatumColor = seriesArr.some((s) =>\n s.some((d) => typeof d?.color === 'string' && d.color !== ''),\n )\n\n return {\n ...option,\n dataset: seriesArr.map((s) => ({ source: s as readonly object[] })),\n series: seriesArr.map((s, i) => {\n const template =\n (seriesTemplates[i] as object | undefined) ??\n (broadcastTemplate as object)\n // For line series, set BOTH `series[i].color` (legend swatch +\n // markers) AND `series[i].lineStyle.color` (the line itself) so\n // the override paints everywhere a series has a colour slot.\n const overrideColor = resolveThemeColor(theme, series?.[i]?.color)\n return {\n ...(typeof template === 'object' ? template : {}),\n type: 'line' as const,\n datasetIndex: i,\n name: series?.[i]?.name ?? `Series ${i + 1}`,\n encode: { x: 'name', y: 'value' },\n smooth,\n // When a selection is active, surface markers so the per-point\n // color callback has something to dim — a continuous line would\n // hide the visual selection feedback.\n showSymbol: selectionSet != null || hasDatumColor,\n ...(area ? { areaStyle: {} } : {}),\n emphasis: { focus: 'series' },\n itemStyle: makeDimItemStyle(s, template),\n ...(overrideColor\n ? { color: overrideColor, lineStyle: { color: overrideColor } }\n : {}),\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: buildTimeseriesTooltipFormatter(\n liveFormatter,\n labelFormatter,\n ),\n },\n } as EChartsOption\n }\n}\n\n/**\n * Tooltip formatter for the timeseries `{ name, value }` row shape.\n * `name` arrives as `Date | number | string` (the time-axis stores the\n * raw value the consumer supplied). The consumer's `labelFormatter`\n * expects a `Date`, so we coerce non-Date values via `new Date(...)`\n * before invoking it.\n */\nfunction buildTimeseriesTooltipFormatter(\n formatter: ((value: number) => string) | undefined,\n labelFormatter: ((value: Date) => string) | undefined,\n) {\n return createTooltipFormatter((item) => {\n const row = item.value as\n { name?: Date | number | string; value?: number } | undefined\n const raw = row?.value\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 rawName = row?.name ?? item.name\n const name =\n labelFormatter && rawName != null\n ? labelFormatter(rawName instanceof Date ? rawName : new Date(rawName))\n : (rawName ?? '')\n return { name: String(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 container: {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n gap: ({ spacing }) => spacing(1),\n height: ({ spacing }) => spacing(38),\n },\n graph: {\n position: 'relative',\n flex: '1 1 auto',\n width: '100%',\n },\n segmentA: {\n position: 'absolute',\n left: 0,\n right: '70%',\n top: '60%',\n height: 4,\n },\n segmentB: {\n position: 'absolute',\n left: '25%',\n right: '40%',\n top: '35%',\n height: 4,\n },\n segmentC: {\n position: 'absolute',\n left: '55%',\n right: 0,\n top: '50%',\n height: 4,\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\n/**\n * Loading state for the Timeseries widget. Mirrors a line chart's\n * silhouette — three thin horizontal segments at staggered offsets to\n * suggest a moving line, plus a 2-dot legend stub. Sibling-consistent\n * with Bar / Histogram / Scatter skeletons (column-flex container with\n * legend strip below).\n */\nexport function TimeseriesSkeleton() {\n return (\n <Box sx={styles.container}>\n <Box sx={styles.graph}>\n <Skeleton variant='rectangular' sx={styles.segmentA} />\n <Skeleton variant='rectangular' sx={styles.segmentB} />\n <Skeleton variant='rectangular' sx={styles.segmentC} />\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 type { TimeseriesWidgetData } from './types'\n\n/**\n * Download menu items for the Timeseries widget. Always includes a CSV\n * item with `time, series_1, series_2, …` columns (one row per unique time\n * across all series; ISO-8601 strings for `Date`/numeric times). When\n * `getCaptureEl` is supplied, prepends a PNG item that rasterises the\n * captured element via `html2canvas`.\n */\nexport function createTimeseriesDownloadConfig(args: {\n filename: string\n getData: (ctx: DownloadContext) => TimeseriesWidgetData\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 seriesCount = data.length\n\n // Collect every unique time, preserving insertion order.\n const timeKeys: (Date | number | string)[] = []\n const seenKeys = new Set<string>()\n for (const series of data) {\n for (const point of series) {\n const key = String(point.name)\n if (!seenKeys.has(key)) {\n seenKeys.add(key)\n timeKeys.push(point.name)\n }\n }\n }\n\n // Build a quick lookup per series for O(rows × series) emit.\n const lookups = data.map(\n (series) => new Map(series.map((p) => [String(p.name), p.value])),\n )\n\n const header: unknown[] = ['time']\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 (const key of timeKeys) {\n const row: unknown[] = [formatTime(key)]\n const lookupKey = String(key)\n for (const lookup of lookups) row.push(lookup.get(lookupKey) ?? '')\n rows.push(row)\n }\n\n return rows\n },\n }),\n )\n return items\n}\n\nfunction formatTime(v: Date | number | string): string {\n if (v instanceof Date) return v.toISOString()\n if (typeof v === 'number') return new Date(v).toISOString()\n return v\n}\n","/**\n * `LockSelection` filter for Timeseries. Data is `{name, value}[][]` like\n * Bar/Pie/Category, but `name` may arrive as `Date | number | string` (the\n * time axis stores a `Date`). `lockedItems` is snapshotted from `selection`,\n * whose keys are already normalized to `Date → ms` (see `options.ts`'s\n * `normalizeName`) — so a raw `Date` name must be normalized the same way\n * before the membership check, or every point would compare a `Date` object\n * against a `number` and silently fail to match, filtering everything out.\n */\nexport function filterTimeseriesByLockedItems(\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<string | number>(lockedItems)\n return input.map((series: unknown): unknown => {\n if (!Array.isArray(series)) return series\n return series.filter((item: unknown) => {\n if (item == null || typeof item !== 'object' || !('name' in item)) {\n return false\n }\n const raw = (item as { name: unknown }).name\n const name = raw instanceof Date ? raw.getTime() : raw\n return (\n (typeof name === 'string' || typeof name === 'number') &&\n locked.has(name)\n )\n })\n })\n}\n"],"mappings":";;;;;;;;;;;AA2CA,SAAgBoB,EAAkB,EAChCC,UACAC,cACAC,qBACkD;CAGlD,IAAIC,IAAU,GACVC,IAAU;CAEd,OAAO;EACLC,MAAM;GACJC,MAAMC,SAASP,EAAMQ,QAAQ,CAAC,CAAC;GAC/BC,KAAKF,SAASP,EAAMQ,QAAQ,CAAC,CAAC;GAC9BE,OAAOH,SAASP,EAAMQ,QAAQ,CAAC,CAAC;GAEhC,GAAGzB,EAAgB,IAAOiB,CAAK;GAC/BW,cAAc;EAChB;EACAC,SAAS;GACPC,SAAS;GACTC,iBAAiBd,EAAMe,QAAQC,KAAK;GACpCC,aAAa;GACbC,SAAS,CAACX,SAASP,EAAMQ,QAAQ,CAAC,CAAC,GAAGD,SAASP,EAAMQ,QAAQ,CAAC,CAAC,CAAC;GAChEW,WAAW;IACTC,OAAOpB,EAAMe,QAAQM,OAAOC;IAC5BC,UAAU;IACVC,YAAYxB,EAAMyB,WAAWC,QAAQF;GACvC;GACAG,aAAa,EAAEC,MAAM,OAAO;GAC5BC,UAAU3C,EAAwBc,CAAK;GACvCC,WAAW6B,EAAgC7B,GAAWC,CAAc;EACtE;EAGA6B,QAAQ,EACN,GAAG/C,EAAkB,EAAEgD,WAAW,GAAM,CAAC,EAC3C;EACAL,aAAa,EAAEM,WAAW,EAAEb,OAAOpB,EAAMe,QAAQC,KAAK,KAAK,EAAE;EAC7DI,OAAO,CACLpB,EAAMe,QAAQmB,UAAUC,MACxB,GAAGC,OAAOC,OACPrC,EAAMe,QACJuB,aAAaC,QAAQ,CAAC,CAC3B,CAAC;EAEHE,OAAO;GACLb,MAAM;GACNc,UAAU,EAAEC,MAAM,GAAM;GACxBC,UAAU,EAAED,MAAM,GAAM;GACxBE,WAAW;IACT,GAAG/D,EAAoBkB,CAAK;IAC5BkB,SAAS;KAACX,SAASP,EAAMQ,QAAQ,EAAG,CAAC;KAAG;KAAG;KAAG;IAAC;IAC/CsC,QAAQ;IACRC,aAAa;IACb,GAAI7C,KAAkB,EACpBD,YAAY+C,MAAkB9C,EAAe,IAAI+C,KAAKD,CAAK,CAAC,EAC9D;GACF;EACF;EACAE,OAAO;GACLtB,MAAM;GACNuB,MAAMC,OACJjD,IAAUiD,EAAOD,MAAM,IAAIhE,EAAQiE,EAAOD,GAAG,IAAI,GAC1ChD;GAETkD,MAAMD,OACJhD,IAAUgD,EAAOC,OAAO,IAAI,IAAIlE,EAAQiE,EAAOC,GAAG,GAC3CjD;GAETsC,UAAU,EAAEC,MAAM,GAAM;GACxBC,UAAU,EAAED,MAAM,GAAM;GACxBW,WAAW;IACTX,MAAM;IACNV,WAAW,EAAEb,OAAOpB,EAAMe,QAAQwC,QAAQ,MAAMvD,EAAMe,QAAQyC,QAAQ;GACxE;GACAX,WAAW;IACT,GAAG/D,EAAoBkB,CAAK;IAC5B8C,QAAQvC,SAASP,EAAMQ,QAAQ,CAAC,CAAC;IACjCmC,MAAM;IACNc,cAAc;IACdC,cAAc;IACdC,eAAe;IACfC,QAAQ;IACR3D,YAAY+C,MACNA,MAAU5C,KAAW4C,MAAU7C,KAC/B6C,MAAU,IAAU,KACjB/C,IAAYA,EAAU+C,CAAK,IAAIa,OAAOb,CAAK;GAEtD;EACF;CACF;AACF;AAkBA,SAAgBc,EACdC,GACe;CACf,IAAM,EAAE/D,UAAOC,cAAWC,mBAAgB8D,uBAAoBD,GACxDE,IAASF,EAAQE,QACjBC,IAASH,EAAQG,UAAU,IAC3BC,IAAOJ,EAAQI,QAAQ,IACvBC,IAAYL,EAAQK,WACpBC,IACJD,KAAaA,EAAUE,SAAS,IAC5B,IAAIC,IAAqBH,CAAS,IAClC,MAGAI,KAAiBC,MACrBA,aAAaxB,OAAOwB,EAAEC,QAAQ,IAAID;CACpC,QAAQE,GAAQC,GAAMC,MAAQ;EAC5B,IAAIF,KAAU,MAAM;GAClB,IAAMG,IAAa/E,EAAkB;IAAEC;IAAOC;IAAWC;GAAe,CAAC;GACzE,OAAO8D,IACF1E,EACCwF,GACAd,CACF,IACAc;EACN;EAEA,IAAME,IAAYC,MAAMC,QAAQN,CAAI,IAAKA,IAAgC,CAAA;EACzE,IAAII,EAAUV,WAAW,GACvB,OAAO;GAAE,GAAGK;GAAQQ,SAAS,CAAA;GAAIlB,QAAQ,CAAA;EAAG;EAE9C,IAAMjC,IAAYgD,EAAUV,SAAS,GAC/Bc,IAAkBH,MAAMC,QAAQP,EAAOV,MAAM,IAAIU,EAAOV,SAAS,CAAA,GACjEoB,IAAoBD,EAAgB,MAAM,CAAC,GAC3CE,IACJ,OAAOX,EAAOzB,SAAU,YAAY,CAAC+B,MAAMC,QAAQP,EAAOzB,KAAK,IAC3DyB,EAAOzB,QACP,CAAC,GACDqC,IAASzF,EAAgBwF,CAAS,GAClCE,IACJ,OAAOb,EAAOtE,QAAS,YAAY,CAAC4E,MAAMC,QAAQP,EAAOtE,IAAI,IACzDsE,EAAOtE,OACP,CAAC,GACDoF,IACJ,OAAOd,EAAO/D,WAAY,YAAY,CAACqE,MAAMC,QAAQP,EAAO/D,OAAO,IAC/D+D,EAAO/D,UACP,CAAC,GACD8E,IACJ,OAAOf,EAAO5C,UAAW,YAAY,CAACkD,MAAMC,QAAQP,EAAO5C,MAAM,IAC7D4C,EAAO5C,SACP,CAAC,GAQD4D,IAAgBd,GAAK5E,WAQvBE,IAAU,GACVC,IAAU,GAIRwF,IAAiBnG,EAA0BkF,EAAOkB,UAAU7D,CAAS,GACrE8D,IACJ,OAAON,EAASO,UAAW,WAAWP,EAASO,SAAS,IACpDC,IAAahE,IAAY,KAAK8D,GAC9BG,IAAaL,IACfI,IAAa5G,EAAY8G,eAAe9G,EAAY+G,YACpDH,GAeEI,KAAoBC,GAA2BC,MAAsB;GACzE,IAAMC,IAAY/G,EAAwB;IACxCQ;IACAqG;IACAC;IACAE,WAAWC,MAAWA,EAAOrF;GAC/B,CAAC;GACD,OAAO,EACLA,QAAQqF,MAA+B;IAGrC,IAAMG,IAFQH,EAAOzD,OAEF2D,MACbE,IAAON,EAAUE,CAAM;IAE7B,OADI,CAACpC,KAAgBuC,KAAO,QACrBvC,EAAayC,IAAItC,EAAcoC,CAAG,CAAC,IADDC,IAGrCjI,EAAQwC,MAAM2F,YAAYF,GAAM,GAAI;GAC1C,EACF;EACF,GAGMG,IAAgBhC,EAAUiC,MAAMC,MACpCA,EAAED,MAAME,MAAM,OAAOA,GAAG/F,SAAU,YAAY+F,EAAE/F,UAAU,EAAE,CAC9D;EAEA,OAAO;GACL,GAAGuD;GACHQ,SAASH,EAAUoC,KAAKF,OAAO,EAAEG,QAAQH,EAAuB,EAAE;GAClEjD,QAAQe,EAAUoC,KAAKF,GAAGI,MAAM;IAC9B,IAAMhB,IACHlB,EAAgBkC,MAChBjC,GAIGkC,IAAgBhI,EAAkBS,GAAOiE,IAASqD,EAAE,EAAElG,KAAK;IACjE,OAAO;KACL,GAAI,OAAOkF,KAAa,WAAWA,IAAW,CAAC;KAC/C1E,MAAM;KACN6F,cAAcH;KACdX,MAAM1C,IAASqD,EAAE,EAAEX,QAAQ,UAAUW,IAAI;KACzCI,QAAQ;MAAEC,GAAG;MAAQC,GAAG;KAAQ;KAChC1D;KAIA2D,YAAYxD,KAAgB,QAAQ2C;KACpC,GAAI7C,IAAO,EAAE2D,WAAW,CAAC,EAAE,IAAI,CAAC;KAChCC,UAAU,EAAEC,OAAO,SAAS;KAC5BC,WAAW7B,EAAiBc,GAAGZ,CAAQ;KACvC,GAAIiB,IACA;MAAEnG,OAAOmG;MAAetF,WAAW,EAAEb,OAAOmG,EAAc;KAAE,IAC5D,CAAC;IACP;GACF,CAAC;GACDxF,QAAQ;IAAE,GAAG2D;IAAY/C,MAAMX;GAAU;GACzC3B,MAAM;IAAE,GAAGmF;IAAUO,QAAQE;GAAW;GACxC,GAAIL,IAAiB,EAAEC,UAAUD,EAAe,IAAI,CAAC;GACrD1C,OAAO;IACL,GAAGoC;IAGHnC,MAAMC,OACJjD,IAAUiD,EAAOD,MAAM,IAAKoC,EAAOpC,OAAOhE,EAAQiE,EAAOD,GAAG,IAAK,GAC1DhD;IAETkD,MAAMD,OACJhD,IAAUgD,EAAOC,OAAO,IAAI,IAAKkC,EAAOlC,OAAOlE,EAAQiE,EAAOC,GAAG,GAC1DjD;IAETyC,WAAW;KACT,GAAKyC,EAAqCzC,aAAa,CAAC;KACxD5C,YAAY+C,MACNA,MAAU5C,KAAW4C,MAAU7C,KAC/B6C,MAAU,IAAU,KACjB2C,IAAgBA,EAAc3C,CAAK,IAAIa,OAAOb,CAAK;IAE9D;GACF;GACApC,SAAS;IACP,GAAG6E;IACHxF,WAAW6B,EACT6D,GACAzF,CACF;GACF;EACF;CACF;AACF;AASA,SAAS4B,EACP7B,GACAC,GACA;CACA,OAAOjB,GAAwBiJ,MAAS;EACtC,IAAMC,IAAMD,EAAKlF,OAEX4D,IAAMuB,GAAKnF,OACXoF,IACJ,OAAOxB,KAAQ,YAAY3G,IAAYA,EAAU2G,CAAG,IAAKA,KAAO,IAC5DyB,IAAS,OAAOH,EAAKG,UAAW,WAAWH,EAAKG,SAAS,IACzDC,IAAaJ,EAAKI,aAAa,GAAGJ,EAAKI,WAAU,MAAO,IACxDC,IAAUJ,GAAKxB,QAAQuB,EAAKvB,MAC5BA,IACJzG,KAAkBqI,KAAW,OACzBrI,EAAeqI,aAAmBtF,OAAOsF,IAAU,IAAItF,KAAKsF,CAAO,CAAC,IACnEA,KAAW;EAClB,OAAO;GAAE5B,MAAM9C,OAAO8C,CAAI;GAAG2B;GAAYD;GAAQrF,OAAOoF;EAAe;CACzE,CAAC;AACH;;;ACvWA,IAAMQ,IAAS;CACbC,WAAW;EACTC,SAAS;EACTC,eAAe;EACfC,gBAAgB;EAChBC,MAAM,EAAEC,iBAAcA,EAAQ,CAAC;EAC/BC,SAAS,EAAED,iBAAcA,EAAQ,EAAE;CACrC;CACAE,OAAO;EACLC,UAAU;EACVC,MAAM;EACNC,OAAO;CACT;CACAC,UAAU;EACRH,UAAU;EACVI,MAAM;EACNC,OAAO;EACPC,KAAK;EACLR,QAAQ;CACV;CACAS,UAAU;EACRP,UAAU;EACVI,MAAM;EACNC,OAAO;EACPC,KAAK;EACLR,QAAQ;CACV;CACAU,UAAU;EACRR,UAAU;EACVI,MAAM;EACNC,OAAO;EACPC,KAAK;EACLR,QAAQ;CACV;CACAW,QAAQ;EACNhB,SAAS;EACTiB,YAAY;EACZd,MAAM,EAAEC,iBAAcA,EAAQ,CAAC;EAC/BC,SAAS,EAAED,iBAAcA,EAAQ,CAAC;CACpC;CACAc,YAAY;EACVlB,SAAS;EACTiB,YAAY;EACZd,MAAM,EAAEC,iBAAcA,EAAQ,GAAG;CACnC;AACF;AASA,SAAOgB,IAAA;CAAA,IAAAC,IAAAC,EAAA,CAAA,GAAAC;CAAA,AAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KAGDF,IAAA,kBAAC,GAAD;EAAS,IAAAzB,EAAMQ;EAAf,UAAA;GACE,kBAAC,GAAD;IAAkB,SAAA;IAAkB,IAAAR,EAAMY;GAAS,CAAA;GACnD,kBAAC,GAAD;IAAkB,SAAA;IAAkB,IAAAZ,EAAMgB;GAAS,CAAA;GACnD,kBAAC,GAAD;IAAkB,SAAA;IAAkB,IAAAhB,EAAMiB;GAAS,CAAA;EAHjD;KAIEM,EAAA,KAAAE,KAAAA,IAAAF,EAAA;CAAA,IAAAK;CASF,OATEL,EAAA,OAAAG,OAAAC,IAAA,2BAAA,KALRC,IAAA,kBAAC,GAAD;EAAS,IAAA5B,EAAMC;EAAf,UAAA,CACEwB,GAKA,kBAAC,GAAD;GAAS,IAAAzB,EAAMkB;GACZ,UAAA,CAAC,GAAG,CAAC,CAAC,CAAAW,IAAKC,CAKX;EANC,CAAA,CANF;KAcEP,EAAA,KAAAK,KAAAA,IAAAL,EAAA,IAdNK;AAcM;AAhBH,SAAAE,EAAAC,GAAA;CAAA,OAUG,kBAAC,GAAD;EAA6B,IAAA/B,EAAMoB;EAAnC,UAAA,CACE,kBAAC,GAAD;GAAkB,SAAA;GAAkB,OAAA;GAAW,QAAA;EAAC,CAAA,GAChD,kBAAC,GAAD;GAAiB,OAAA;GAAY,QAAA;EAAC,CAAA,CAF5B;CAAM,GAAA,UAAUW,GAAhB;AAGE;;;ACvDhB,SAAgBM,EAA+BC,GAO5B;CACjB,IAAMS,IAAwB,CAAA;CAoD9B,OAnDIT,EAAKK,gBACPI,EAAMC,KACJf,EAAqB;EACnBM,UAAUD,EAAKC;EACfI,cAAcL,EAAKK;EACnBM,YAAYX,EAAKO;EACjBK,iBAAiBZ,EAAKQ;CACxB,CAAC,CACH,GAEFC,EAAMC,KACJhB,EAAqB;EACnBO,UAAUD,EAAKC;EACfY,UAAUV,MAAQ;GAChB,IAAMW,IAAOd,EAAKE,QAAQC,CAAG,GACvBY,IAAcD,EAAKE,QAGnBC,IAAuC,CAAA,GACvCE,oBAAW,IAAIC,IAAY;GACjC,KAAK,IAAMC,KAAUP,GACnB,KAAK,IAAMQ,KAASD,GAAQ;IAC1B,IAAME,IAAMC,OAAOF,EAAMG,IAAI;IAC7B,AAAKN,EAASO,IAAIH,CAAG,MACnBJ,EAASQ,IAAIJ,CAAG,GAChBN,EAASP,KAAKY,EAAMG,IAAI;GAE5B;GAIF,IAAMG,IAAUd,EAAKe,KAClBR,MAAW,IAAIS,IAAIT,EAAOQ,KAAKE,MAAM,CAACP,OAAOO,EAAEN,IAAI,GAAGM,EAAEC,KAAK,CAAC,CAAC,CAClE,GAEMC,IAAoB,CAAC,MAAM;GACjC,KAAK,IAAIC,IAAI,GAAGA,IAAInB,GAAamB,KAC/BD,EAAOvB,KAAKV,EAAKI,cAAc8B,MAAM,UAAUA,IAAI,GAAG;GAExD,IAAMC,IAAoB,CAACF,CAAM;GACjC,KAAK,IAAMV,KAAON,GAAU;IAC1B,IAAMmB,IAAiB,CAACC,EAAWd,CAAG,CAAC,GACjCe,IAAYd,OAAOD,CAAG;IAC5B,KAAK,IAAMgB,KAAUX,GAASQ,EAAI1B,KAAK6B,EAAOC,IAAIF,CAAS,KAAK,EAAE;IAClEH,EAAKzB,KAAK0B,CAAG;GACf;GAEA,OAAOD;EACT;CACF,CAAC,CACH,GACO1B;AACT;AAEA,SAAS4B,EAAWI,GAAmC;CAGrD,OAFIA,aAAavB,OAAauB,EAAEC,YAAY,IACxC,OAAOD,KAAM,WAAiB,IAAIvB,KAAKuB,CAAC,CAAC,CAACC,YAAY,IACnDD;AACT;;;ACzEA,SAAgBE,EACdC,GACAC,GACS;CAET,IADIA,EAAYC,WAAW,KACvB,CAACC,MAAMC,QAAQJ,CAAK,GAAG,OAAOA;CAClC,IAAMK,IAAS,IAAIC,IAAqBL,CAAW;CACnD,OAAOD,EAAMO,KAAKC,MACXL,MAAMC,QAAQI,CAAM,IAClBA,EAAOC,QAAQC,MAAkB;EACtC,IAAoB,OAAOA,KAAS,aAAhCA,KAA4C,EAAE,UAAUA,IAC1D,OAAO;EAET,IAAMC,IAAOD,EAA2BE,MAClCA,IAAOD,aAAeE,OAAOF,EAAIG,QAAQ,IAAIH;EACnD,QACG,OAAOC,KAAS,YAAY,OAAOA,KAAS,aAC7CP,EAAOU,IAAIH,CAAI;CAEnB,CAAC,IAXkCJ,CAYpC;AACH"}
@@ -2,7 +2,7 @@ import { t as e } from "./tooltip-DJUGNZxY.js";
2
2
  import "./components-DKjBezcJ.js";
3
3
  import { t } from "./smart-tooltip-CwGHCqab.js";
4
4
  import { C as n, S as r, T as i, _ as a } from "./stores-BVFMfgyo.js";
5
- import { C as o, D as s, S as c, c as l, f as u, g as d, o as f, r as p, t as m, y as h } from "./actions-B1ss030_.js";
5
+ import { C as o, D as s, S as c, c as l, f as u, g as d, o as f, r as p, t as m, y as h } from "./actions-DON6fSCh.js";
6
6
  import { i as g, n as _, o as v, r as y } from "./echart-CgOQw9XB.js";
7
7
  import { t as b } from "./markdown-content-BzKoX3eu.js";
8
8
  import { t as x } from "./zoom-toggle-KA63b6-J.js";
@@ -11,7 +11,7 @@ import { i as ee, r as C } from "./formula-DRuMIVo8.js";
11
11
  import { i as w, r as T } from "./markdown-C3OX9jyy.js";
12
12
  import { a as E, i as D } from "./spread-BT07rCJw.js";
13
13
  import { n as O, r as k } from "./range-BPWVrAsY.js";
14
- import { i as A, r as te } from "./category-DuKx_CJX.js";
14
+ import { i as A, r as te } from "./category-BoT5FHHp.js";
15
15
  import { d as j, i as M } from "./table-CRG9eOs9.js";
16
16
  import { c as N } from "react/compiler-runtime";
17
17
  import { Children as ne, Component as P, isValidElement as F, useEffect as I, useLayoutEffect as re, useRef as L, useState as R } from "react";