drizzle-cube 0.4.13 → 0.4.14

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 (116) hide show
  1. package/README.md +1 -0
  2. package/dist/adapters/express/index.cjs +6 -6
  3. package/dist/adapters/express/index.js +73 -72
  4. package/dist/adapters/fastify/index.cjs +5 -5
  5. package/dist/adapters/fastify/index.js +110 -109
  6. package/dist/adapters/{handler-CQkIwtxp.js → handler-DZnCbydH.js} +719 -272
  7. package/dist/adapters/handler-ZDYlokiM.cjs +25 -0
  8. package/dist/adapters/hono/index.cjs +6 -6
  9. package/dist/adapters/hono/index.js +121 -120
  10. package/dist/adapters/nextjs/index.cjs +5 -5
  11. package/dist/adapters/nextjs/index.js +92 -91
  12. package/dist/client/charts.js +67 -59
  13. package/dist/client/charts.js.map +1 -1
  14. package/dist/client/chunks/{RetentionCombinedChart-CEI8KQ3t.js → RetentionCombinedChart-CLq89aOJ.js} +2 -2
  15. package/dist/client/chunks/{RetentionCombinedChart-CEI8KQ3t.js.map → RetentionCombinedChart-CLq89aOJ.js.map} +1 -1
  16. package/dist/client/chunks/{analysis-builder-BMmWeFPr.js → analysis-builder-C5e52Z3p.js} +419 -411
  17. package/dist/client/chunks/analysis-builder-C5e52Z3p.js.map +1 -0
  18. package/dist/client/chunks/{analysis-builder-shared-D56zYeV0.js → analysis-builder-shared-EnM-8plh.js} +2 -2
  19. package/dist/client/chunks/{analysis-builder-shared-D56zYeV0.js.map → analysis-builder-shared-EnM-8plh.js.map} +1 -1
  20. package/dist/client/chunks/{chart-activity-grid-CE7xGFQo.js → chart-activity-grid-CPGcTSuh.js} +2 -2
  21. package/dist/client/chunks/{chart-activity-grid-CE7xGFQo.js.map → chart-activity-grid-CPGcTSuh.js.map} +1 -1
  22. package/dist/client/chunks/{chart-area-BJAgusst.js → chart-area-ByJQ7NZd.js} +3 -3
  23. package/dist/client/chunks/{chart-area-BJAgusst.js.map → chart-area-ByJQ7NZd.js.map} +1 -1
  24. package/dist/client/chunks/{chart-bar-Blypx8O4.js → chart-bar-dj14frMt.js} +2 -2
  25. package/dist/client/chunks/{chart-bar-Blypx8O4.js.map → chart-bar-dj14frMt.js.map} +1 -1
  26. package/dist/client/chunks/chart-box-plot-ZatBpatq.js +322 -0
  27. package/dist/client/chunks/chart-box-plot-ZatBpatq.js.map +1 -0
  28. package/dist/client/chunks/{chart-bubble-Bf42A1-B.js → chart-bubble-CemotLx-.js} +2 -2
  29. package/dist/client/chunks/{chart-bubble-Bf42A1-B.js.map → chart-bubble-CemotLx-.js.map} +1 -1
  30. package/dist/client/chunks/chart-candlestick-BIR4uGGt.js +269 -0
  31. package/dist/client/chunks/chart-candlestick-BIR4uGGt.js.map +1 -0
  32. package/dist/client/chunks/chart-config-box-plot-D_E_SSc2.js +38 -0
  33. package/dist/client/chunks/chart-config-box-plot-D_E_SSc2.js.map +1 -0
  34. package/dist/client/chunks/chart-config-candlestick-CRCpD43-.js +70 -0
  35. package/dist/client/chunks/chart-config-candlestick-CRCpD43-.js.map +1 -0
  36. package/dist/client/chunks/chart-config-gauge-CQx9w3d4.js +64 -0
  37. package/dist/client/chunks/chart-config-gauge-CQx9w3d4.js.map +1 -0
  38. package/dist/client/chunks/chart-config-measure-profile-ZYaMrtws.js +70 -0
  39. package/dist/client/chunks/chart-config-measure-profile-ZYaMrtws.js.map +1 -0
  40. package/dist/client/chunks/chart-config-waterfall-DTyXV_fo.js +60 -0
  41. package/dist/client/chunks/chart-config-waterfall-DTyXV_fo.js.map +1 -0
  42. package/dist/client/chunks/{chart-data-table-Ba_6tuJw.js → chart-data-table-D5G8nMnb.js} +2 -2
  43. package/dist/client/chunks/{chart-data-table-Ba_6tuJw.js.map → chart-data-table-D5G8nMnb.js.map} +1 -1
  44. package/dist/client/chunks/{chart-funnel-C9kenCpp.js → chart-funnel-dofnhD24.js} +2 -2
  45. package/dist/client/chunks/{chart-funnel-C9kenCpp.js.map → chart-funnel-dofnhD24.js.map} +1 -1
  46. package/dist/client/chunks/chart-gauge-CKJJ8m3b.js +374 -0
  47. package/dist/client/chunks/chart-gauge-CKJJ8m3b.js.map +1 -0
  48. package/dist/client/chunks/{chart-heat-map-CYGemyPB.js → chart-heat-map-BVuPUKHT.js} +2 -2
  49. package/dist/client/chunks/{chart-heat-map-CYGemyPB.js.map → chart-heat-map-BVuPUKHT.js.map} +1 -1
  50. package/dist/client/chunks/{chart-kpi-delta-D9XJoKuA.js → chart-kpi-delta-Dgg2eYRl.js} +3 -3
  51. package/dist/client/chunks/{chart-kpi-delta-D9XJoKuA.js.map → chart-kpi-delta-Dgg2eYRl.js.map} +1 -1
  52. package/dist/client/chunks/{chart-kpi-number-C29Vj2g8.js → chart-kpi-number-DkoO99c1.js} +2 -2
  53. package/dist/client/chunks/{chart-kpi-number-C29Vj2g8.js.map → chart-kpi-number-DkoO99c1.js.map} +1 -1
  54. package/dist/client/chunks/{chart-kpi-text-CgjjrurK.js → chart-kpi-text-1O6_lmz7.js} +3 -3
  55. package/dist/client/chunks/{chart-kpi-text-CgjjrurK.js.map → chart-kpi-text-1O6_lmz7.js.map} +1 -1
  56. package/dist/client/chunks/{chart-line-zi6olZet.js → chart-line-DzyZkugh.js} +3 -3
  57. package/dist/client/chunks/{chart-line-zi6olZet.js.map → chart-line-DzyZkugh.js.map} +1 -1
  58. package/dist/client/chunks/chart-measure-profile-C2IkBG3V.js +114 -0
  59. package/dist/client/chunks/chart-measure-profile-C2IkBG3V.js.map +1 -0
  60. package/dist/client/chunks/{chart-pie-C4SuxKSN.js → chart-pie-akbfRfb9.js} +2 -2
  61. package/dist/client/chunks/{chart-pie-C4SuxKSN.js.map → chart-pie-akbfRfb9.js.map} +1 -1
  62. package/dist/client/chunks/{chart-radar-BW3Z_-Ly.js → chart-radar-BaN-Kjww.js} +2 -2
  63. package/dist/client/chunks/{chart-radar-BW3Z_-Ly.js.map → chart-radar-BaN-Kjww.js.map} +1 -1
  64. package/dist/client/chunks/{chart-radial-bar-0Fa3aeP5.js → chart-radial-bar-DpptEL3s.js} +2 -2
  65. package/dist/client/chunks/{chart-radial-bar-0Fa3aeP5.js.map → chart-radial-bar-DpptEL3s.js.map} +1 -1
  66. package/dist/client/chunks/{chart-sankey-DBghfbg1.js → chart-sankey-CG-3hHmX.js} +2 -2
  67. package/dist/client/chunks/{chart-sankey-DBghfbg1.js.map → chart-sankey-CG-3hHmX.js.map} +1 -1
  68. package/dist/client/chunks/{chart-scatter-DOVu1TNq.js → chart-scatter-l_yTVxF3.js} +2 -2
  69. package/dist/client/chunks/{chart-scatter-DOVu1TNq.js.map → chart-scatter-l_yTVxF3.js.map} +1 -1
  70. package/dist/client/chunks/{chart-sunburst-LfNthFlZ.js → chart-sunburst-KhDcKhmZ.js} +2 -2
  71. package/dist/client/chunks/{chart-sunburst-LfNthFlZ.js.map → chart-sunburst-KhDcKhmZ.js.map} +1 -1
  72. package/dist/client/chunks/{chart-tree-map-DZtQPyWX.js → chart-tree-map-CBbiaBXV.js} +2 -2
  73. package/dist/client/chunks/{chart-tree-map-DZtQPyWX.js.map → chart-tree-map-CBbiaBXV.js.map} +1 -1
  74. package/dist/client/chunks/chart-waterfall-CX3vx_lI.js +191 -0
  75. package/dist/client/chunks/chart-waterfall-CX3vx_lI.js.map +1 -0
  76. package/dist/client/chunks/{charts-core-DmGfleFz.js → charts-core-CU9u_HtL.js} +2 -1
  77. package/dist/client/chunks/charts-core-CU9u_HtL.js.map +1 -0
  78. package/dist/client/chunks/{charts-loader-CH0_S06T.js → charts-loader-AW3T1nv5.js} +58 -42
  79. package/dist/client/chunks/charts-loader-AW3T1nv5.js.map +1 -0
  80. package/dist/client/chunks/{components-ClQziOcT.js → components-BkeSy9xv.js} +4 -4
  81. package/dist/client/chunks/components-BkeSy9xv.js.map +1 -0
  82. package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +10 -0
  83. package/dist/client/components/AgenticNotebook/ChatMessage.d.ts +2 -0
  84. package/dist/client/components/AgenticNotebook/index.d.ts +11 -1
  85. package/dist/client/components/LoadingIndicator.d.ts +2 -2
  86. package/dist/client/components/charts/BoxPlotChart.config.d.ts +1 -7
  87. package/dist/client/components/charts/CandlestickChart.config.d.ts +5 -0
  88. package/dist/client/components/charts/CandlestickChart.d.ts +4 -0
  89. package/dist/client/components/charts/GaugeChart.config.d.ts +5 -0
  90. package/dist/client/components/charts/GaugeChart.d.ts +4 -0
  91. package/dist/client/components/charts/MeasureProfileChart.config.d.ts +5 -0
  92. package/dist/client/components/charts/MeasureProfileChart.d.ts +4 -0
  93. package/dist/client/components/charts/WaterfallChart.config.d.ts +5 -0
  94. package/dist/client/components/charts/WaterfallChart.d.ts +4 -0
  95. package/dist/client/components/charts/index.d.ts +4 -0
  96. package/dist/client/components.js +1 -1
  97. package/dist/client/hooks/useAgentChat.d.ts +20 -2
  98. package/dist/client/index.js +583 -522
  99. package/dist/client/index.js.map +1 -1
  100. package/dist/client/styles.css +1 -1
  101. package/dist/client/types.d.ts +19 -1
  102. package/dist/client/utils.js +4 -4
  103. package/dist/client-bundle-stats.html +1 -1
  104. package/dist/server/index.cjs +47 -45
  105. package/dist/server/index.d.ts +37 -0
  106. package/dist/server/index.js +1745 -1298
  107. package/package.json +4 -1
  108. package/dist/adapters/handler-dnkqpznh.cjs +0 -23
  109. package/dist/client/chunks/analysis-builder-BMmWeFPr.js.map +0 -1
  110. package/dist/client/chunks/chart-box-plot-Dja4LS3O.js +0 -313
  111. package/dist/client/chunks/chart-box-plot-Dja4LS3O.js.map +0 -1
  112. package/dist/client/chunks/chart-config-box-plot-D3DA7_pr.js +0 -85
  113. package/dist/client/chunks/chart-config-box-plot-D3DA7_pr.js.map +0 -1
  114. package/dist/client/chunks/charts-core-DmGfleFz.js.map +0 -1
  115. package/dist/client/chunks/charts-loader-CH0_S06T.js.map +0 -1
  116. package/dist/client/chunks/components-ClQziOcT.js.map +0 -1
@@ -1,313 +0,0 @@
1
- import { jsx as s, jsxs as v } from "react/jsx-runtime";
2
- import G, { useRef as I, useState as J, useLayoutEffect as K, useMemo as j } from "react";
3
- import { f as Q, c as U } from "./charts-core-DmGfleFz.js";
4
- const X = 50;
5
- function p(i) {
6
- if (i == null) return null;
7
- const n = typeof i == "number" ? i : parseFloat(String(i));
8
- return isNaN(n) ? null : n;
9
- }
10
- function Z(i, n, r, h, c, f, d, l) {
11
- const a = p(i[n]), m = p(i[r]), o = p(i[h]), g = p(i[c]), A = p(i[f]);
12
- return a === null || m === null || o === null || g === null || A === null ? null : { label: d, min: a, q1: m, median: o, q3: g, max: A, color: l };
13
- }
14
- function ee(i, n, r, h, c, f) {
15
- const d = p(i[n]), l = p(i[r]), a = p(i[h]);
16
- if (d === null || l === null || a === null) return null;
17
- const m = Math.abs(l);
18
- return {
19
- label: c,
20
- min: d - 2 * m,
21
- q1: d - m,
22
- median: a,
23
- q3: d + m,
24
- max: d + 2 * m,
25
- color: f
26
- };
27
- }
28
- function te({
29
- x: i,
30
- boxWidth: n,
31
- minY: r,
32
- q1Y: h,
33
- medianY: c,
34
- q3Y: f,
35
- maxY: d,
36
- color: l,
37
- label: a
38
- }) {
39
- const m = n / 2, o = i, g = n * 0.4;
40
- return /* @__PURE__ */ v("g", { "data-testid": `box-${a}`, children: [
41
- /* @__PURE__ */ s("line", { x1: o, y1: r, x2: o, y2: d, stroke: l, strokeWidth: 1.5 }),
42
- /* @__PURE__ */ s(
43
- "line",
44
- {
45
- x1: o - g / 2,
46
- y1: r,
47
- x2: o + g / 2,
48
- y2: r,
49
- stroke: l,
50
- strokeWidth: 1.5
51
- }
52
- ),
53
- /* @__PURE__ */ s(
54
- "line",
55
- {
56
- x1: o - g / 2,
57
- y1: d,
58
- x2: o + g / 2,
59
- y2: d,
60
- stroke: l,
61
- strokeWidth: 1.5
62
- }
63
- ),
64
- /* @__PURE__ */ s(
65
- "rect",
66
- {
67
- x: o - m,
68
- y: Math.min(h, f),
69
- width: n,
70
- height: Math.abs(f - h) || 2,
71
- fill: l,
72
- fillOpacity: 0.3,
73
- stroke: l,
74
- strokeWidth: 1.5
75
- }
76
- ),
77
- /* @__PURE__ */ s(
78
- "line",
79
- {
80
- x1: o - m,
81
- y1: c,
82
- x2: o + m,
83
- y2: c,
84
- stroke: l,
85
- strokeWidth: 2.5,
86
- "data-testid": `median-${a}`
87
- }
88
- )
89
- ] });
90
- }
91
- function ne({
92
- scale: i,
93
- domainMin: n,
94
- domainMax: r,
95
- width: h,
96
- tickCount: c = 5,
97
- format: f
98
- }) {
99
- const d = j(() => {
100
- const l = r - n;
101
- if (l === 0) return [n];
102
- const a = l / (c - 1);
103
- return Array.from({ length: c }, (m, o) => n + o * a);
104
- }, [n, r, c]);
105
- return /* @__PURE__ */ v("g", { "data-testid": "y-axis", children: [
106
- d.map((l, a) => /* @__PURE__ */ v("g", { transform: `translate(0, ${i(l)})`, children: [
107
- /* @__PURE__ */ s("line", { x1: 0, x2: -6, stroke: "currentColor", strokeWidth: 1 }),
108
- /* @__PURE__ */ s(
109
- "text",
110
- {
111
- x: -10,
112
- textAnchor: "end",
113
- dominantBaseline: "middle",
114
- fontSize: 11,
115
- fill: "currentColor",
116
- className: "text-dc-text-secondary",
117
- children: f ? f(l) : l.toLocaleString()
118
- }
119
- ),
120
- /* @__PURE__ */ s("line", { x1: 0, x2: h, stroke: "currentColor", strokeOpacity: 0.1, strokeWidth: 1 })
121
- ] }, a)),
122
- /* @__PURE__ */ s("line", { y1: i(d[0]), y2: i(d[d.length - 1]), stroke: "currentColor", strokeWidth: 1 })
123
- ] });
124
- }
125
- const re = G.memo(function({
126
- data: n,
127
- chartConfig: r,
128
- displayConfig: h = {},
129
- height: c = "100%",
130
- colorPalette: f,
131
- onDataPointClick: d,
132
- drillEnabled: l
133
- }) {
134
- const a = I(null), [m, o] = J({ width: 0, height: 0 });
135
- K(() => {
136
- const e = a.current;
137
- if (!e) return;
138
- const t = new ResizeObserver((u) => {
139
- for (const y of u) {
140
- const { width: S, height: q } = y.contentRect;
141
- S > 0 && q > 0 && o({ width: S, height: q });
142
- }
143
- });
144
- t.observe(e);
145
- const x = e.getBoundingClientRect();
146
- return x.width > 0 && x.height > 0 && o({ width: x.width, height: x.height }), () => t.disconnect();
147
- }, []);
148
- const g = h?.leftYAxisFormat, { xField: A, mode: M, fields: F, configError: R } = j(() => {
149
- const e = Array.isArray(r?.xAxis) ? r.xAxis[0] : r?.xAxis ?? r?.x, t = h, x = t?.minField && t?.q1Field && t?.medianField && t?.q3Field && t?.maxField, u = t?.avgField && t?.stddevField && t?.medianField, y = Array.isArray(r?.yAxis) ? r.yAxis : r?.yAxis ? [r.yAxis] : [];
150
- return !e && !y.length && !x && !u ? {
151
- xField: e,
152
- mode: "none",
153
- fields: {},
154
- configError: "BoxPlot requires an X-Axis dimension and at least one measure"
155
- } : x ? {
156
- xField: e,
157
- mode: "5measure",
158
- fields: {
159
- minField: String(t.minField),
160
- q1Field: String(t.q1Field),
161
- medianField: String(t.medianField),
162
- q3Field: String(t.q3Field),
163
- maxField: String(t.maxField)
164
- },
165
- configError: null
166
- } : u ? {
167
- xField: e,
168
- mode: "3measure",
169
- fields: {
170
- avgField: String(t.avgField),
171
- stddevField: String(t.stddevField),
172
- medianField: String(t.medianField)
173
- },
174
- configError: null
175
- } : !e || y.length === 0 ? {
176
- xField: e,
177
- mode: "none",
178
- fields: {},
179
- configError: "BoxPlot requires an X-Axis dimension and at least one measure in Y-Axis"
180
- } : {
181
- xField: e,
182
- mode: "auto",
183
- fields: { valueField: y[0] },
184
- configError: null
185
- };
186
- }, [r, h]), $ = j(() => {
187
- if (R || !n || n.length === 0 || M === "none") return [];
188
- const e = n.slice(0, X), t = f?.colors ?? U, x = [];
189
- for (let u = 0; u < e.length; u++) {
190
- const y = e[u], S = A ? String(y[A] ?? `Row ${u + 1}`) : `Row ${u + 1}`, q = t[u % t.length];
191
- let w = null;
192
- if (M === "5measure")
193
- w = Z(
194
- y,
195
- F.minField,
196
- F.q1Field,
197
- F.medianField,
198
- F.q3Field,
199
- F.maxField,
200
- S,
201
- q
202
- );
203
- else if (M === "3measure")
204
- w = ee(y, F.avgField, F.stddevField, F.medianField, S, q);
205
- else {
206
- const k = p(y[F.valueField]);
207
- k !== null && (w = { label: S, min: k, q1: k, median: k, q3: k, max: k, color: q });
208
- }
209
- w && x.push(w);
210
- }
211
- return x;
212
- }, [n, A, M, F, f, R]);
213
- if (!n || n.length === 0)
214
- return /* @__PURE__ */ s("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height: c }, children: /* @__PURE__ */ v("div", { className: "dc:text-center", children: [
215
- /* @__PURE__ */ s("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "No data available" }),
216
- /* @__PURE__ */ s("div", { className: "dc:text-xs text-dc-text-secondary", children: "No data points to display in box plot chart" })
217
- ] }) });
218
- if (R)
219
- return /* @__PURE__ */ s("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning", style: { height: c }, children: /* @__PURE__ */ v("div", { className: "dc:text-center", children: [
220
- /* @__PURE__ */ s("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "Configuration Error" }),
221
- /* @__PURE__ */ s("div", { className: "dc:text-xs", children: R })
222
- ] }) });
223
- if ($.length === 0)
224
- return /* @__PURE__ */ s("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted", style: { height: c }, children: /* @__PURE__ */ v("div", { className: "dc:text-center", children: [
225
- /* @__PURE__ */ s("div", { className: "dc:text-sm dc:font-semibold dc:mb-1", children: "No valid data" }),
226
- /* @__PURE__ */ s("div", { className: "dc:text-xs text-dc-text-secondary", children: "Could not compute box plot statistics from the provided data" })
227
- ] }) });
228
- const N = { top: 20, right: 20, bottom: 60, left: 60 }, _ = m.width || 600, E = typeof c == "number" ? c : m.height || 400, z = Math.max(_ - N.left - N.right, 50), W = Math.max(E - N.top - N.bottom, 50), H = $.flatMap((e) => [e.min, e.max]), L = Math.min(...H), P = Math.max(...H), V = (P - L) * 0.1 || 1, B = L - V, T = P + V, Y = T - B, b = (e) => Y === 0 ? W / 2 : W - (e - B) / Y * W, O = z / $.length, D = Math.min(O * 0.6, 40), C = n.length > X;
229
- return /* @__PURE__ */ v("div", { ref: a, className: "dc:relative dc:w-full", style: { height: c }, children: [
230
- /* @__PURE__ */ s(
231
- "svg",
232
- {
233
- width: "100%",
234
- height: C ? "calc(100% - 20px)" : "100%",
235
- viewBox: `0 0 ${_} ${typeof E == "number" ? E : 400}`,
236
- preserveAspectRatio: "none",
237
- "data-testid": "boxplot-svg",
238
- children: /* @__PURE__ */ v("g", { transform: `translate(${N.left}, ${N.top})`, children: [
239
- /* @__PURE__ */ s(
240
- ne,
241
- {
242
- scale: b,
243
- domainMin: B,
244
- domainMax: T,
245
- width: z,
246
- tickCount: 5,
247
- format: g ? (e) => Q(e, g) : void 0
248
- }
249
- ),
250
- $.map((e, t) => {
251
- const x = O * t + O / 2;
252
- return /* @__PURE__ */ v(
253
- "g",
254
- {
255
- onClick: (u) => {
256
- d && l && d({
257
- dataPoint: { ...e },
258
- clickedField: A ?? "",
259
- xValue: e.label,
260
- position: { x: u.clientX, y: u.clientY },
261
- nativeEvent: u
262
- });
263
- },
264
- cursor: l ? "pointer" : void 0,
265
- children: [
266
- /* @__PURE__ */ s(
267
- te,
268
- {
269
- x,
270
- boxWidth: D,
271
- minY: b(e.min),
272
- q1Y: b(e.q1),
273
- medianY: b(e.median),
274
- q3Y: b(e.q3),
275
- maxY: b(e.max),
276
- color: e.color,
277
- label: e.label
278
- }
279
- ),
280
- /* @__PURE__ */ s(
281
- "text",
282
- {
283
- x,
284
- y: W + 20,
285
- textAnchor: "middle",
286
- fontSize: 11,
287
- fill: "currentColor",
288
- className: "text-dc-text-secondary",
289
- "data-testid": `x-label-${e.label}`,
290
- children: e.label
291
- }
292
- )
293
- ]
294
- },
295
- `${e.label}-${t}`
296
- );
297
- })
298
- ] })
299
- }
300
- ),
301
- C && /* @__PURE__ */ v("div", { className: "dc:text-xs text-dc-text-muted dc:text-center dc:mt-1", children: [
302
- "Data truncated to ",
303
- X,
304
- " groups (original: ",
305
- n.length,
306
- ")"
307
- ] })
308
- ] });
309
- });
310
- export {
311
- re as default
312
- };
313
- //# sourceMappingURL=chart-box-plot-Dja4LS3O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-box-plot-Dja4LS3O.js","sources":["../../../src/client/components/charts/BoxPlotChart.tsx"],"sourcesContent":["import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { CHART_COLORS } from '../../utils/chartConstants'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport type { ChartProps } from '../../types'\n\nconst MAX_BOXES = 50\n\ninterface BoxStats {\n label: string\n min: number\n q1: number\n median: number\n q3: number\n max: number\n color: string\n}\n\nfunction parseNumeric(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\n/** Build box stats from 5-measure mode fields */\nfunction buildFrom5Measures(\n row: Record<string, unknown>,\n minField: string,\n q1Field: string,\n medianField: string,\n q3Field: string,\n maxField: string,\n label: string,\n color: string\n): BoxStats | null {\n const min = parseNumeric(row[minField])\n const q1 = parseNumeric(row[q1Field])\n const median = parseNumeric(row[medianField])\n const q3 = parseNumeric(row[q3Field])\n const max = parseNumeric(row[maxField])\n if (min === null || q1 === null || median === null || q3 === null || max === null) return null\n return { label, min, q1, median, q3, max, color }\n}\n\n/** Build approximate box stats from 3-measure mode (avg ± stddev, median) */\nfunction buildFrom3Measures(\n row: Record<string, unknown>,\n avgField: string,\n stddevField: string,\n medianField: string,\n label: string,\n color: string\n): BoxStats | null {\n const avg = parseNumeric(row[avgField])\n const sd = parseNumeric(row[stddevField])\n const median = parseNumeric(row[medianField])\n if (avg === null || sd === null || median === null) return null\n const absSd = Math.abs(sd)\n return {\n label,\n min: avg - 2 * absSd,\n q1: avg - absSd,\n median,\n q3: avg + absSd,\n max: avg + 2 * absSd,\n color,\n }\n}\n\n// Render a single box plot element\nfunction BoxElement({\n x,\n boxWidth,\n minY,\n q1Y,\n medianY,\n q3Y,\n maxY,\n color,\n label,\n}: {\n x: number\n boxWidth: number\n minY: number\n q1Y: number\n medianY: number\n q3Y: number\n maxY: number\n color: string\n label: string\n}) {\n const halfWidth = boxWidth / 2\n const whiskerX = x\n const capWidth = boxWidth * 0.4\n\n return (\n <g data-testid={`box-${label}`}>\n {/* Whisker line (min to max) */}\n <line x1={whiskerX} y1={minY} x2={whiskerX} y2={maxY} stroke={color} strokeWidth={1.5} />\n {/* Min cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={minY}\n x2={whiskerX + capWidth / 2}\n y2={minY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Max cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={maxY}\n x2={whiskerX + capWidth / 2}\n y2={maxY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* IQR Box (Q1 to Q3) */}\n <rect\n x={whiskerX - halfWidth}\n y={Math.min(q1Y, q3Y)}\n width={boxWidth}\n height={Math.abs(q3Y - q1Y) || 2}\n fill={color}\n fillOpacity={0.3}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Median line */}\n <line\n x1={whiskerX - halfWidth}\n y1={medianY}\n x2={whiskerX + halfWidth}\n y2={medianY}\n stroke={color}\n strokeWidth={2.5}\n data-testid={`median-${label}`}\n />\n </g>\n )\n}\n\n// Y-axis tick renderer\nfunction YAxis({\n scale,\n domainMin,\n domainMax,\n width,\n tickCount = 5,\n format,\n}: {\n scale: (v: number) => number\n domainMin: number\n domainMax: number\n width: number\n tickCount?: number\n format?: (v: number) => string\n}) {\n const ticks = useMemo(() => {\n const range = domainMax - domainMin\n if (range === 0) return [domainMin]\n const step = range / (tickCount - 1)\n return Array.from({ length: tickCount }, (_, i) => domainMin + i * step)\n }, [domainMin, domainMax, tickCount])\n\n return (\n <g data-testid=\"y-axis\">\n {ticks.map((tick, i) => (\n <g key={i} transform={`translate(0, ${scale(tick)})`}>\n <line x1={0} x2={-6} stroke=\"currentColor\" strokeWidth={1} />\n <text\n x={-10}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n >\n {format ? format(tick) : tick.toLocaleString()}\n </text>\n <line x1={0} x2={width} stroke=\"currentColor\" strokeOpacity={0.1} strokeWidth={1} />\n </g>\n ))}\n <line y1={scale(ticks[0])} y2={scale(ticks[ticks.length - 1])} stroke=\"currentColor\" strokeWidth={1} />\n </g>\n )\n}\n\nconst BoxPlotChart = React.memo(function BoxPlotChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n colorPalette,\n onDataPointClick,\n drillEnabled,\n}: ChartProps) {\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n // Determine config mode and extract fields\n const { xField, mode, fields, configError } = useMemo(() => {\n const xField = Array.isArray(chartConfig?.xAxis)\n ? chartConfig.xAxis[0]\n : chartConfig?.xAxis ?? chartConfig?.x\n\n // 5-measure mode: explicit q1/median/q3/min/max in displayConfig\n const dc = displayConfig as Record<string, unknown>\n const has5 = dc?.minField && dc?.q1Field && dc?.medianField && dc?.q3Field && dc?.maxField\n // 3-measure mode: avgField + stddevField + medianField in displayConfig\n const has3 = dc?.avgField && dc?.stddevField && dc?.medianField\n // Auto mode: single yAxis measure used as median, stddev from value if available\n const yAxisFields: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : chartConfig?.yAxis\n ? [chartConfig.yAxis as string]\n : []\n\n if (!xField && !yAxisFields.length && !has5 && !has3) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires an X-Axis dimension and at least one measure',\n }\n }\n\n if (has5) {\n return {\n xField,\n mode: '5measure' as const,\n fields: {\n minField: String(dc.minField),\n q1Field: String(dc.q1Field),\n medianField: String(dc.medianField),\n q3Field: String(dc.q3Field),\n maxField: String(dc.maxField),\n },\n configError: null,\n }\n }\n\n if (has3) {\n return {\n xField,\n mode: '3measure' as const,\n fields: {\n avgField: String(dc.avgField),\n stddevField: String(dc.stddevField),\n medianField: String(dc.medianField),\n },\n configError: null,\n }\n }\n\n // Fallback: need at least xAxis + 1 measure in yAxis\n if (!xField || yAxisFields.length === 0) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires an X-Axis dimension and at least one measure in Y-Axis',\n }\n }\n\n // Auto mode: use yAxis[0] as the value field (treated as median/value)\n return {\n xField,\n mode: 'auto' as const,\n fields: { valueField: yAxisFields[0] },\n configError: null,\n }\n }, [chartConfig, displayConfig])\n\n const boxes: BoxStats[] = useMemo(() => {\n if (configError || !data || data.length === 0 || mode === 'none') return []\n const rows = (data as Record<string, unknown>[]).slice(0, MAX_BOXES)\n const palette = colorPalette?.colors ?? CHART_COLORS\n\n const results: BoxStats[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const label = xField ? String(row[xField] ?? `Row ${i + 1}`) : `Row ${i + 1}`\n const color = palette[i % palette.length]\n\n let box: BoxStats | null = null\n if (mode === '5measure') {\n box = buildFrom5Measures(\n row,\n fields.minField!,\n fields.q1Field!,\n fields.medianField!,\n fields.q3Field!,\n fields.maxField!,\n label,\n color\n )\n } else if (mode === '3measure') {\n box = buildFrom3Measures(row, fields.avgField!, fields.stddevField!, fields.medianField!, label, color)\n } else {\n // Auto: use value as median, build minimal box (value ± 0)\n const v = parseNumeric(row[fields.valueField!])\n if (v !== null) {\n box = { label, min: v, q1: v, median: v, q3: v, max: v, color }\n }\n }\n if (box) results.push(box)\n }\n return results\n }, [data, xField, mode, fields, colorPalette, configError])\n\n if (!data || data.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data available</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in box plot chart</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Error</div>\n <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n if (boxes.length === 0) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No valid data</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n Could not compute box plot statistics from the provided data\n </div>\n </div>\n </div>\n )\n }\n\n // Compute layout\n const margin = { top: 20, right: 20, bottom: 60, left: 60 }\n const containerWidth = dimensions.width || 600\n const containerHeight = typeof height === 'number' ? height : (dimensions.height || 400)\n const innerWidth = Math.max(containerWidth - margin.left - margin.right, 50)\n const innerHeight = Math.max(containerHeight - margin.top - margin.bottom, 50)\n\n // Y scale: linear from min-of-all to max-of-all\n const allValues = boxes.flatMap((b) => [b.min, b.max])\n const rawMin = Math.min(...allValues)\n const rawMax = Math.max(...allValues)\n const padding = (rawMax - rawMin) * 0.1 || 1\n const domainMin = rawMin - padding\n const domainMax = rawMax + padding\n\n const domainRange = domainMax - domainMin\n const yScale = (v: number) =>\n domainRange === 0 ? innerHeight / 2 : innerHeight - ((v - domainMin) / domainRange) * innerHeight\n\n const boxSpacing = innerWidth / boxes.length\n const boxWidth = Math.min(boxSpacing * 0.6, 40)\n\n const isTruncated = (data as unknown[]).length > MAX_BOXES\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height={isTruncated ? `calc(100% - 20px)` : '100%'}\n viewBox={`0 0 ${containerWidth} ${typeof containerHeight === 'number' ? containerHeight : 400}`}\n preserveAspectRatio=\"none\"\n data-testid=\"boxplot-svg\"\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n {/* Y Axis */}\n <YAxis\n scale={yScale}\n domainMin={domainMin}\n domainMax={domainMax}\n width={innerWidth}\n tickCount={5}\n format={yAxisFormat ? (v) => formatAxisValue(v, yAxisFormat) : undefined}\n />\n\n {/* Box plot elements */}\n {boxes.map((box, i) => {\n const cx = boxSpacing * i + boxSpacing / 2\n return (\n <g\n key={`${box.label}-${i}`}\n onClick={(event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled) {\n onDataPointClick({\n dataPoint: { ...box },\n clickedField: xField ?? '',\n xValue: box.label,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event,\n })\n }\n }}\n cursor={drillEnabled ? 'pointer' : undefined}\n >\n <BoxElement\n x={cx}\n boxWidth={boxWidth}\n minY={yScale(box.min)}\n q1Y={yScale(box.q1)}\n medianY={yScale(box.median)}\n q3Y={yScale(box.q3)}\n maxY={yScale(box.max)}\n color={box.color}\n label={box.label}\n />\n {/* X axis label */}\n <text\n x={cx}\n y={innerHeight + 20}\n textAnchor=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid={`x-label-${box.label}`}\n >\n {box.label}\n </text>\n </g>\n )\n })}\n </g>\n </svg>\n {isTruncated && (\n <div className=\"dc:text-xs text-dc-text-muted dc:text-center dc:mt-1\">\n Data truncated to {MAX_BOXES} groups (original: {(data as unknown[]).length})\n </div>\n )}\n </div>\n )\n})\n\nexport default BoxPlotChart\n"],"names":["MAX_BOXES","parseNumeric","v","buildFrom5Measures","row","minField","q1Field","medianField","q3Field","maxField","label","color","min","q1","median","q3","max","buildFrom3Measures","avgField","stddevField","avg","sd","absSd","BoxElement","x","boxWidth","minY","q1Y","medianY","q3Y","maxY","halfWidth","whiskerX","capWidth","jsxs","jsx","YAxis","scale","domainMin","domainMax","width","tickCount","format","ticks","useMemo","range","step","_","i","tick","BoxPlotChart","React","data","chartConfig","displayConfig","height","colorPalette","onDataPointClick","drillEnabled","containerRef","useRef","dimensions","setDimensions","useState","useLayoutEffect","el","observer","entries","entry","h","rect","yAxisFormat","xField","mode","fields","configError","dc","has5","has3","yAxisFields","boxes","rows","palette","CHART_COLORS","results","box","margin","containerWidth","containerHeight","innerWidth","innerHeight","allValues","b","rawMin","rawMax","padding","domainRange","yScale","boxSpacing","isTruncated","formatAxisValue","cx","event"],"mappings":"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"}
@@ -1,85 +0,0 @@
1
- const e = {
2
- label: "Box Plot",
3
- description: "Show statistical distribution (median, IQR, whiskers) across categories",
4
- useCase: "Best for P&L spread per symbol, trade size distribution, latency distribution across platforms",
5
- dropZones: [
6
- {
7
- key: "xAxis",
8
- label: "X-Axis (Groups)",
9
- description: "Dimension to group boxes by (e.g. symbol, platform)",
10
- mandatory: !0,
11
- maxItems: 1,
12
- acceptTypes: ["dimension", "timeDimension"],
13
- emptyText: "Drop a dimension here"
14
- },
15
- {
16
- key: "yAxis",
17
- label: "Y-Axis (Measures)",
18
- description: "For auto mode: drop 1 measure here. For 3-measure mode set avg/stddev/median fields in Display Options.",
19
- mandatory: !1,
20
- acceptTypes: ["measure"],
21
- emptyText: "Drop a measure here (or configure 3/5-measure mode below)"
22
- }
23
- ],
24
- displayOptionsConfig: [
25
- {
26
- key: "avgField",
27
- label: "Avg Field (3-measure mode)",
28
- type: "string",
29
- placeholder: "e.g. Trades.avgPnl",
30
- description: "Average measure for 3-measure mode (mean ± σ whiskers)"
31
- },
32
- {
33
- key: "stddevField",
34
- label: "Stddev Field (3-measure mode)",
35
- type: "string",
36
- placeholder: "e.g. Trades.stddevPnl",
37
- description: "Standard deviation measure for 3-measure mode"
38
- },
39
- {
40
- key: "medianField",
41
- label: "Median Field (3/5-measure mode)",
42
- type: "string",
43
- placeholder: "e.g. Trades.medianPnl",
44
- description: "Median measure for 3-measure or 5-measure mode"
45
- },
46
- {
47
- key: "minField",
48
- label: "Min Field (5-measure mode)",
49
- type: "string",
50
- placeholder: "e.g. Trades.minPnl",
51
- description: "Minimum measure for 5-measure full box plot"
52
- },
53
- {
54
- key: "q1Field",
55
- label: "Q1 Field (5-measure mode)",
56
- type: "string",
57
- placeholder: "e.g. Trades.q1Pnl",
58
- description: "First quartile measure for 5-measure full box plot"
59
- },
60
- {
61
- key: "q3Field",
62
- label: "Q3 Field (5-measure mode)",
63
- type: "string",
64
- placeholder: "e.g. Trades.q3Pnl",
65
- description: "Third quartile measure for 5-measure full box plot"
66
- },
67
- {
68
- key: "maxField",
69
- label: "Max Field (5-measure mode)",
70
- type: "string",
71
- placeholder: "e.g. Trades.maxPnl",
72
- description: "Maximum measure for 5-measure full box plot"
73
- },
74
- {
75
- key: "leftYAxisFormat",
76
- label: "Y-Axis Format",
77
- type: "axisFormat",
78
- description: "Number formatting for the value axis"
79
- }
80
- ]
81
- };
82
- export {
83
- e as boxPlotChartConfig
84
- };
85
- //# sourceMappingURL=chart-config-box-plot-D3DA7_pr.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-config-box-plot-D3DA7_pr.js","sources":["../../../src/client/components/charts/BoxPlotChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the box plot chart type.\n * Visualises the statistical distribution of a measure across groupings.\n *\n * Two modes:\n * - 5-measure: explicit min/q1/median/q3/max fields (displayConfig)\n * - 3-measure: avg + stddev + median fields (displayConfig), draws mean ± σ whiskers\n * - Auto: single yAxis measure shown as a point (degenerate box)\n */\nexport const boxPlotChartConfig: ChartTypeConfig = {\n label: 'Box Plot',\n description: 'Show statistical distribution (median, IQR, whiskers) across categories',\n useCase:\n 'Best for P&L spread per symbol, trade size distribution, latency distribution across platforms',\n dropZones: [\n {\n key: 'xAxis',\n label: 'X-Axis (Groups)',\n description: 'Dimension to group boxes by (e.g. symbol, platform)',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop a dimension here',\n },\n {\n key: 'yAxis',\n label: 'Y-Axis (Measures)',\n description:\n 'For auto mode: drop 1 measure here. For 3-measure mode set avg/stddev/median fields in Display Options.',\n mandatory: false,\n acceptTypes: ['measure'],\n emptyText: 'Drop a measure here (or configure 3/5-measure mode below)',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'avgField',\n label: 'Avg Field (3-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.avgPnl',\n description: 'Average measure for 3-measure mode (mean ± σ whiskers)',\n },\n {\n key: 'stddevField',\n label: 'Stddev Field (3-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.stddevPnl',\n description: 'Standard deviation measure for 3-measure mode',\n },\n {\n key: 'medianField',\n label: 'Median Field (3/5-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.medianPnl',\n description: 'Median measure for 3-measure or 5-measure mode',\n },\n {\n key: 'minField',\n label: 'Min Field (5-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.minPnl',\n description: 'Minimum measure for 5-measure full box plot',\n },\n {\n key: 'q1Field',\n label: 'Q1 Field (5-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.q1Pnl',\n description: 'First quartile measure for 5-measure full box plot',\n },\n {\n key: 'q3Field',\n label: 'Q3 Field (5-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.q3Pnl',\n description: 'Third quartile measure for 5-measure full box plot',\n },\n {\n key: 'maxField',\n label: 'Max Field (5-measure mode)',\n type: 'string',\n placeholder: 'e.g. Trades.maxPnl',\n description: 'Maximum measure for 5-measure full box plot',\n },\n {\n key: 'leftYAxisFormat',\n label: 'Y-Axis Format',\n type: 'axisFormat',\n description: 'Number formatting for the value axis',\n },\n ],\n}\n"],"names":["boxPlotChartConfig"],"mappings":"AAWO,MAAMA,IAAsC;AAAA,EACjD,OAAO;AAAA,EACP,aAAa;AAAA,EACb,SACE;AAAA,EACF,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa,CAAC,aAAa,eAAe;AAAA,MAC1C,WAAW;AAAA,IAAA;AAAA,IAEb;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aACE;AAAA,MACF,WAAW;AAAA,MACX,aAAa,CAAC,SAAS;AAAA,MACvB,WAAW;AAAA,IAAA;AAAA,EACb;AAAA,EAEF,sBAAsB;AAAA,IACpB;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"charts-core-DmGfleFz.js","sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/components/AnalysisBuilder/SectionHeading.tsx","../../../src/client/utils/chartUtils.ts","../../../src/client/components/charts/AxisFormatControls.tsx","../../../src/client/hooks/useCubeFieldLabel.ts","../../../src/client/utils/chartConstants.ts","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/utils/targetUtils.ts"],"sourcesContent":["/**\n * LoadingIndicator Component\n *\n * A centralized, theme-aware loading spinner that uses CSS variables\n * for consistent styling across all drizzle-cube components.\n *\n * Can be overridden at the Dashboard or Portlet level by passing a\n * custom loadingComponent prop.\n */\n\nexport interface LoadingIndicatorProps {\n /** Size variant: 'sm' (24px), 'md' (32px), 'lg' (48px) */\n size?: 'sm' | 'md' | 'lg'\n /** Additional CSS classes */\n className?: string\n}\n\nconst sizeClasses = {\n sm: 'dc:h-6 dc:w-6',\n md: 'dc:h-8 dc:w-8',\n lg: 'dc:h-12 dc:w-12'\n}\n\nexport default function LoadingIndicator({\n size = 'md',\n className = ''\n}: LoadingIndicatorProps) {\n return (\n <div\n className={`dc:animate-spin dc:rounded-full dc:border-b-2 ${sizeClasses[size]} ${className}`}\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n role=\"status\"\n aria-label=\"Loading\"\n />\n )\n}\n","/**\n * SectionHeading Component\n *\n * A reusable section heading for the Analysis Builder panels.\n * Provides consistent styling that can be easily adjusted in one place.\n */\n\nimport type { ReactNode } from 'react'\n\ninterface SectionHeadingProps {\n children: ReactNode\n /** Optional className to add additional styles */\n className?: string\n}\n\n/**\n * Consistent section heading style for Analysis Builder panels.\n * Change the styles here to update all section headings at once.\n */\nexport default function SectionHeading({ children, className = '' }: SectionHeadingProps) {\n return (\n <h3 className={`dc:text-sm dc:font-semibold text-dc-primary dc:uppercase dc:tracking-wide ${className}`}>\n {children}\n </h3>\n )\n}\n","import type { FieldLabelMap, AxisFormatConfig } from '../types'\n\n// Utility function to check if a value is a valid numeric value (not null, undefined, or NaN)\n// This is used to preserve null values instead of converting them to 0\nexport function isValidNumericValue(value: any): boolean {\n return value !== null && value !== undefined && !isNaN(Number(value))\n}\n\n// Utility function to parse numeric value from data, preserving nulls\n// Returns null for null/undefined/NaN values, otherwise returns the numeric value\nexport function parseNumericValue(value: any): number | null {\n if (value === null || value === undefined) return null\n const num = typeof value === 'string' ? parseFloat(value) : Number(value)\n return isNaN(num) ? null : num\n}\n\n// Utility function to format numeric values for display in charts\n// Rounds to at most 2 decimal places, preserves integers\nexport function formatNumericValue(value: any): string {\n if (value === null || value === undefined) return 'No data'\n const num = typeof value === 'number' ? value : parseFloat(value)\n if (isNaN(num)) return String(value)\n if (Number.isInteger(num)) return num.toLocaleString()\n // Round to at most 2 decimal places, remove trailing zeros\n return parseFloat(num.toFixed(2)).toLocaleString()\n}\n\n/**\n * Format a numeric value for axis/tooltip display with configurable formatting\n *\n * @param value - The numeric value to format\n * @param config - Optional formatting configuration\n * @param locale - Optional locale string (defaults to browser locale)\n * @returns Formatted string representation of the value\n *\n * @example\n * formatAxisValue(1250000, { unit: 'currency', abbreviate: true }) // \"$1.25M\"\n * formatAxisValue(0.75, { unit: 'percent', decimals: 1 }) // \"75.0%\"\n * formatAxisValue(1234567, { abbreviate: true, decimals: 2 }) // \"1.23M\"\n */\nexport function formatAxisValue(\n value: number | null | undefined,\n config?: AxisFormatConfig,\n locale?: string\n): string {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return 'No data'\n }\n\n // Handle non-numeric values\n const num = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(num)) {\n return String(value)\n }\n\n // Handle special cases\n if (!isFinite(num)) {\n return num > 0 ? '∞' : '-∞'\n }\n\n // Get locale (default to browser locale)\n const effectiveLocale = locale || (typeof navigator !== 'undefined' ? navigator.language : 'en-US')\n\n // If no config provided, use default formatting\n if (!config) {\n return formatNumericValue(value)\n }\n\n const { unit, abbreviate = true, decimals, customPrefix, customSuffix } = config\n\n // Calculate the display value and suffix for abbreviation\n // Default to true for abbreviation when config is provided\n let displayValue = num\n let abbreviationSuffix = ''\n\n if (abbreviate) {\n const absNum = Math.abs(num)\n if (absNum >= 1_000_000_000) {\n displayValue = num / 1_000_000_000\n abbreviationSuffix = 'B'\n } else if (absNum >= 1_000_000) {\n displayValue = num / 1_000_000\n abbreviationSuffix = 'M'\n } else if (absNum >= 1_000) {\n displayValue = num / 1_000\n abbreviationSuffix = 'K'\n }\n }\n\n // Determine decimal places\n // If decimals is undefined, use auto (2 for non-integers, 0 for integers after abbreviation)\n const effectiveDecimals = decimals !== undefined\n ? decimals\n : (Number.isInteger(displayValue) ? 0 : 2)\n\n // Format based on unit type\n switch (unit) {\n case 'currency': {\n // Use Intl.NumberFormat for currency\n // Currency code is determined by locale (USD for en-US, EUR for de-DE, etc.)\n const currencyCode = getCurrencyCodeForLocale(effectiveLocale)\n\n if (abbreviate && abbreviationSuffix) {\n // For abbreviated currency, format the number part and add suffix\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n // Insert abbreviation suffix before any trailing currency symbol or at end\n // Handle both \"$1.25\" -> \"$1.25M\" and \"1.25 €\" -> \"1.25M €\"\n const parts = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n }).formatToParts(displayValue)\n const hasTrailingCurrency = parts[parts.length - 1]?.type === 'currency'\n if (hasTrailingCurrency) {\n // Currency symbol is at the end (e.g., \"1.25 €\")\n return formatted.replace(/(\\s*[^\\d\\s]+)$/, abbreviationSuffix + '$1')\n }\n return formatted + abbreviationSuffix\n }\n\n return new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n }\n\n case 'percent': {\n // Format as percentage (multiply by 100 if value is 0-1 range, otherwise use as-is)\n // Assume values > 1 are already percentages, values <= 1 need multiplication\n const percentValue = Math.abs(displayValue) <= 1 && !abbreviate ? displayValue * 100 : displayValue\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(percentValue)\n return formatted + abbreviationSuffix + '%'\n }\n\n case 'custom': {\n // Apply custom prefix/suffix\n const prefix = customPrefix || ''\n const suffix = customSuffix || ''\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return prefix + formatted + abbreviationSuffix + suffix\n }\n\n case 'number':\n default: {\n // Standard number formatting with locale-aware grouping\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return formatted + abbreviationSuffix\n }\n }\n}\n\n/**\n * Get the currency code for a given locale\n * Maps common locales to their default currency\n */\nfunction getCurrencyCodeForLocale(locale: string): string {\n // Extract language and region from locale (e.g., \"en-US\" -> [\"en\", \"US\"])\n const parts = locale.split('-')\n const region = parts[1]?.toUpperCase()\n\n // Map regions to currencies\n const currencyMap: Record<string, string> = {\n 'US': 'USD',\n 'CA': 'CAD',\n 'GB': 'GBP',\n 'UK': 'GBP',\n 'AU': 'AUD',\n 'NZ': 'NZD',\n 'EU': 'EUR',\n 'DE': 'EUR',\n 'FR': 'EUR',\n 'IT': 'EUR',\n 'ES': 'EUR',\n 'NL': 'EUR',\n 'BE': 'EUR',\n 'AT': 'EUR',\n 'IE': 'EUR',\n 'PT': 'EUR',\n 'FI': 'EUR',\n 'JP': 'JPY',\n 'CN': 'CNY',\n 'KR': 'KRW',\n 'IN': 'INR',\n 'BR': 'BRL',\n 'MX': 'MXN',\n 'CH': 'CHF',\n 'SE': 'SEK',\n 'NO': 'NOK',\n 'DK': 'DKK',\n 'PL': 'PLN',\n 'RU': 'RUB',\n 'ZA': 'ZAR',\n 'SG': 'SGD',\n 'HK': 'HKD',\n 'TW': 'TWD',\n 'TH': 'THB',\n 'MY': 'MYR',\n 'PH': 'PHP',\n 'ID': 'IDR',\n 'VN': 'VND',\n 'AE': 'AED',\n 'SA': 'SAR',\n 'IL': 'ILS',\n 'TR': 'TRY',\n }\n\n return currencyMap[region] || 'USD'\n}\n\n/**\n * Create a tick formatter function for Recharts axes\n * Returns a function that can be used as tickFormatter prop\n */\nexport function createAxisTickFormatter(config?: AxisFormatConfig): (value: any) => string {\n return (value: any) => formatAxisValue(value, config)\n}\n\n// Utility function to get field label from field name\nexport function getFieldLabel(fieldName: string, labelMap: FieldLabelMap): string {\n return labelMap[fieldName] || fieldName\n}\n\n// Utility function to transform series keys to use labels\nexport function transformSeriesKeysWithLabels(seriesKeys: string[], labelMap: FieldLabelMap): string[] {\n return seriesKeys.map(key => getFieldLabel(key, labelMap))\n}\n\n// Utility function to format time values for better display using known granularity\nexport function formatTimeValue(value: any, granularity?: string): string {\n if (!value) return String(value || 'Unknown')\n \n const str = String(value)\n \n // Check if it's a timestamp (ISO format or PostgreSQL format)\n // Handles formats like: \"2025-04-01T00:00:00.000\" or \"2023-02-01 00:00:00+00\"\n if (str.match(/^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}/)) {\n // Convert PostgreSQL format to ISO format if needed\n let isoStr = str\n if (str.includes(' ')) {\n // Convert \"2023-02-01 00:00:00+00\" to \"2023-02-01T00:00:00Z\"\n isoStr = str.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n // Ensure the timestamp ends with 'Z' if not present\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n const date = new Date(isoStr)\n \n // Ensure we're working with valid date\n if (isNaN(date.getTime())) {\n return str\n }\n \n // Use UTC methods on the properly UTC-parsed date\n const year = date.getUTCFullYear()\n const month = String(date.getUTCMonth() + 1).padStart(2, '0')\n const day = String(date.getUTCDate()).padStart(2, '0')\n const hours = date.getUTCHours()\n const minutes = date.getUTCMinutes()\n \n // Format based on known granularity if provided\n if (granularity) {\n switch (granularity.toLowerCase()) {\n case 'year':\n return `${year}`\n case 'quarter': {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n case 'month':\n return `${year}-${month}`\n case 'week':\n // For week, we could calculate week number, but let's use date for simplicity\n return `${year}-${month}-${day}`\n case 'day':\n return `${year}-${month}-${day}`\n case 'hour':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n case 'minute':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n default:\n // Unknown granularity, fall back to heuristic\n break\n }\n }\n \n // Fallback heuristic if granularity not provided or unknown\n const seconds = date.getUTCSeconds()\n const milliseconds = date.getUTCMilliseconds()\n \n // If it's the first day of the month at exactly midnight UTC, it's likely a month granularity\n if (day === '01' && hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Check if it's also first month of a quarter (quarter granularity)\n if (month === '01' || month === '04' || month === '07' || month === '10') {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n // Month granularity\n return `${year}-${month}`\n }\n \n // If it's exactly midnight UTC, it's likely a day granularity\n if (hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n return `${year}-${month}-${day}`\n }\n \n // If it has time components, include them (hour/minute granularity)\n if (minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Hour granularity\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n }\n \n // Full timestamp\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n }\n \n // Return as-is if not a timestamp\n return str\n}\n\n// Helper function to get granularity for a field from the query timeDimensions\nexport function getFieldGranularity(queryObject: any, fieldName: string): string | undefined {\n try {\n if (queryObject?.timeDimensions) {\n // Find the timeDimension that matches this field\n const timeDim = queryObject.timeDimensions.find((td: any) => {\n // Check if field name matches the dimension or dimension with granularity suffix\n return fieldName === td.dimension || \n fieldName.startsWith(td.dimension.replace('.', '_')) ||\n fieldName === `${td.dimension}_${td.granularity}`\n })\n \n if (timeDim?.granularity) {\n return timeDim.granularity\n }\n }\n \n // Fallback: extract granularity from field name suffix if present\n const granularityMatch = fieldName.match(/_([a-z]+)$/)\n if (granularityMatch) {\n const suffix = granularityMatch[1]\n // Only return if it's a valid granularity\n if (['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second'].includes(suffix)) {\n return suffix\n }\n }\n \n return undefined\n } catch {\n return undefined\n }\n}\n\n// Transform data for charts with proper type handling\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartData(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName\n) {\n if (!data || data.length === 0) return []\n\n const granularity = getFieldGranularity(queryObject, xAxisField)\n\n return data.map((row: any) => {\n const transformed: any = {\n name: formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown',\n }\n\n yAxisFields.forEach(field => {\n const displayName = getFieldLabelFn(field)\n // Preserve null values instead of converting to 0\n transformed[displayName] = parseNumericValue(row[field])\n })\n\n return transformed\n })\n}\n\nexport interface ChartSeriesResult {\n data: any[]\n seriesKeys: string[]\n hasDimensions: boolean\n}\n\n// Advanced data transformation that handles both measures and dimensions on Y-axis\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartDataWithSeries(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n seriesFields?: string[], // New optional parameter for explicit series fields\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName // Function to get field labels\n): ChartSeriesResult {\n if (!data || data.length === 0) {\n return { data: [], seriesKeys: [], hasDimensions: false }\n }\n\n const originalQuery = queryObject || {}\n const queryDimensions = [\n ...(originalQuery.dimensions || []),\n ...(originalQuery.timeDimensions?.map((td: any) => td.dimension) || [])\n ]\n const queryMeasures = originalQuery.measures || []\n\n // Use explicit series fields if provided, otherwise no dimension-based series\n const yAxisMeasures = yAxisFields.filter(field => queryMeasures.includes(field))\n const yAxisDimensions = (seriesFields || []).filter(field => queryDimensions.includes(field))\n\n // Handle complex case with dimensions on Y-axis\n if (yAxisDimensions.length > 0) {\n // Group data by X-axis field and create separate series for dimension values\n const groupedData: { [key: string]: any } = {}\n\n data.forEach((row: any) => {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n const xValue = formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown'\n if (!groupedData[xValue]) {\n groupedData[xValue] = { name: String(xValue) }\n }\n\n // Add measures - preserve nulls for individual measures\n yAxisMeasures.forEach(measure => {\n const displayName = getFieldLabelFn(measure)\n const measureValue = parseNumericValue(row[measure])\n\n // For aggregation: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][displayName]\n groupedData[xValue][displayName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(displayName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][displayName] = null\n }\n })\n\n // Add dimensions as separate series (aggregate measure values by dimension)\n yAxisDimensions.forEach(dimension => {\n const dimValue = row[dimension]\n if (dimValue !== undefined && dimValue !== null) {\n const seriesName = String(dimValue)\n // Aggregate the first measure for this dimension value, or use totalCost if available\n const measureToAggregate = yAxisMeasures[0] || queryMeasures.find((m: string) =>\n m.includes('totalCost') || m.includes('count') || m.includes('sum')\n ) || queryMeasures[0]\n\n if (measureToAggregate) {\n const measureValue = parseNumericValue(row[measureToAggregate])\n\n // For dimension series: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][seriesName]\n groupedData[xValue][seriesName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(seriesName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][seriesName] = null\n }\n }\n }\n })\n })\n \n const chartData = Object.values(groupedData)\n \n // Get all series keys for rendering\n // When dimensions are on Y-axis, only show dimension series, not measures\n // The measures are the values being aggregated for each dimension series\n const dimensionSeries = Array.from(new Set(\n data.flatMap((row: any) => \n yAxisDimensions.map(dimension => {\n const value = row[dimension]\n return value !== undefined && value !== null \n ? String(value)\n : null\n }).filter((value): value is string => value !== null)\n )\n ))\n \n return {\n data: chartData,\n seriesKeys: dimensionSeries,\n hasDimensions: true\n }\n }\n \n // Standard measures-only path\n const chartData = transformChartData(data, xAxisField, yAxisFields, queryObject, getFieldLabelFn)\n const seriesKeys = yAxisFields.map(field => getFieldLabelFn(field))\n \n return {\n data: chartData,\n seriesKeys,\n hasDimensions: false\n }\n}","/**\n * AxisFormatControls Component\n *\n * A reusable component for configuring axis number formatting.\n * Provides controls for unit type, abbreviation, decimal places, and custom labels.\n */\n\nimport { useMemo } from 'react'\nimport SectionHeading from '../AnalysisBuilder/SectionHeading'\nimport type { AxisFormatConfig } from '../../types'\nimport { formatAxisValue } from '../../utils/chartUtils'\n\ninterface AxisFormatControlsProps {\n value: AxisFormatConfig\n onChange: (config: AxisFormatConfig) => void\n axisLabel: string // \"X-Axis\", \"Left Y-Axis\", \"Right Y-Axis\"\n /** Sample value for preview (default: 1250000) */\n previewValue?: number\n}\n\n/**\n * Get the currency symbol for the user's locale\n */\nfunction getLocaleCurrencySymbol(): string {\n const locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US'\n // Format a number as currency and extract just the symbol\n const formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: getCurrencyCodeForLocale(locale),\n currencyDisplay: 'narrowSymbol'\n }).format(0)\n // Extract the currency symbol (remove digits, spaces, and common separators)\n return formatted.replace(/[\\d.,\\s]/g, '').trim() || '$'\n}\n\n/**\n * Get the currency code for a given locale (duplicated from chartUtils for component isolation)\n */\nfunction getCurrencyCodeForLocale(locale: string): string {\n const parts = locale.split('-')\n const region = parts[1]?.toUpperCase()\n const currencyMap: Record<string, string> = {\n 'US': 'USD', 'CA': 'CAD', 'GB': 'GBP', 'UK': 'GBP', 'AU': 'AUD', 'NZ': 'NZD',\n 'EU': 'EUR', 'DE': 'EUR', 'FR': 'EUR', 'IT': 'EUR', 'ES': 'EUR', 'NL': 'EUR',\n 'BE': 'EUR', 'AT': 'EUR', 'IE': 'EUR', 'PT': 'EUR', 'FI': 'EUR',\n 'JP': 'JPY', 'CN': 'CNY', 'KR': 'KRW', 'IN': 'INR', 'BR': 'BRL', 'MX': 'MXN',\n 'CH': 'CHF', 'SE': 'SEK', 'NO': 'NOK', 'DK': 'DKK', 'PL': 'PLN', 'RU': 'RUB',\n 'ZA': 'ZAR', 'SG': 'SGD', 'HK': 'HKD', 'TW': 'TWD', 'TH': 'THB', 'MY': 'MYR',\n 'PH': 'PHP', 'ID': 'IDR', 'VN': 'VND', 'AE': 'AED', 'SA': 'SAR', 'IL': 'ILS', 'TR': 'TRY',\n }\n return currencyMap[region] || 'USD'\n}\n\n/**\n * Single axis format control section\n */\nexport function AxisFormatControls({\n value,\n onChange,\n axisLabel,\n previewValue = 1250000\n}: AxisFormatControlsProps) {\n const config = useMemo(() => value || {}, [value])\n\n // Get locale-aware currency symbol for the button\n const currencySymbol = useMemo(() => getLocaleCurrencySymbol(), [])\n\n // Generate preview of formatted value\n const preview = useMemo(() => {\n return formatAxisValue(previewValue, config)\n }, [previewValue, config])\n\n const handleChange = (updates: Partial<AxisFormatConfig>) => {\n onChange({ ...config, ...updates })\n }\n\n const unitButtons: Array<{ value: AxisFormatConfig['unit']; label: string }> = [\n { value: 'currency', label: currencySymbol },\n { value: 'percent', label: '%' },\n { value: 'number', label: '#' },\n { value: 'custom', label: 'Custom' }\n ]\n\n return (\n <div className=\"dc:space-y-3 dc:pb-4\">\n {/* Axis Header */}\n <SectionHeading>{axisLabel}</SectionHeading>\n\n {/* Label Input */}\n <div className=\"dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Label</label>\n <input\n type=\"text\"\n value={config.label || ''}\n onChange={(e) => handleChange({ label: e.target.value || undefined })}\n placeholder=\"Auto-generated label\"\n className=\"dc:w-full dc:px-2 dc:py-1 dc:text-sm dc:border border-dc-border dc:rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n </div>\n\n {/* Unit Type */}\n <div className=\"dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Unit</label>\n <div className=\"dc:flex dc:border border-dc-border dc:rounded-sm dc:overflow-hidden\">\n {unitButtons.map((btn) => (\n <button\n key={btn.value}\n type=\"button\"\n onClick={() => handleChange({ unit: btn.value })}\n className={`dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${\n config.unit === btn.value\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n {btn.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Custom Prefix/Suffix (only when Custom is selected) */}\n {config.unit === 'custom' && (\n <div className=\"dc:flex dc:gap-2\">\n <div className=\"dc:flex-1 dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Prefix</label>\n <input\n type=\"text\"\n value={config.customPrefix || ''}\n onChange={(e) => handleChange({ customPrefix: e.target.value || undefined })}\n placeholder=\"e.g., $\"\n className=\"dc:w-full dc:px-2 dc:py-1 dc:text-sm dc:border border-dc-border dc:rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n </div>\n <div className=\"dc:flex-1 dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Suffix</label>\n <input\n type=\"text\"\n value={config.customSuffix || ''}\n onChange={(e) => handleChange({ customSuffix: e.target.value || undefined })}\n placeholder=\"e.g., units\"\n className=\"dc:w-full dc:px-2 dc:py-1 dc:text-sm dc:border border-dc-border dc:rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n </div>\n </div>\n )}\n\n {/* Abbreviation Toggle */}\n <div className=\"dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Abbreviation</label>\n <div className=\"dc:flex dc:border border-dc-border dc:rounded-sm dc:overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => handleChange({ abbreviate: true })}\n className={`dc:flex-1 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${\n config.abbreviate !== false\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n Yes\n </button>\n <button\n type=\"button\"\n onClick={() => handleChange({ abbreviate: false })}\n className={`dc:flex-1 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${\n config.abbreviate === false\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n No\n </button>\n </div>\n </div>\n\n {/* Decimals */}\n <div className=\"dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Decimals</label>\n <div className=\"dc:flex dc:gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n const current = config.decimals ?? 2\n if (current > 0) handleChange({ decimals: current - 1 })\n }}\n disabled={(config.decimals ?? 2) <= 0}\n className=\"dc:flex-1 dc:px-3 dc:py-2 dc:text-sm dc:border border-dc-border dc:rounded-sm bg-dc-surface text-dc-text hover:bg-dc-border dc:disabled:opacity-40 dc:disabled:cursor-not-allowed dc:transition-colors\"\n >\n ← .0\n </button>\n <button\n type=\"button\"\n onClick={() => {\n const current = config.decimals ?? 2\n if (current < 4) handleChange({ decimals: current + 1 })\n }}\n disabled={(config.decimals ?? 2) >= 4}\n className=\"dc:flex-1 dc:px-3 dc:py-2 dc:text-sm dc:border border-dc-border dc:rounded-sm bg-dc-surface text-dc-text hover:bg-dc-border dc:disabled:opacity-40 dc:disabled:cursor-not-allowed dc:transition-colors\"\n >\n .00 →\n </button>\n </div>\n </div>\n\n {/* Preview */}\n <div className=\"dc:space-y-1\">\n <label className=\"dc:text-xs text-dc-text-secondary\">Preview</label>\n <div className=\"dc:text-sm dc:font-mono text-dc-text\">\n {preview}\n </div>\n </div>\n </div>\n )\n}\n\ninterface MultiAxisFormatControlsProps {\n displayConfig: {\n xAxisFormat?: AxisFormatConfig\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n }\n onChange: (updates: {\n xAxisFormat?: AxisFormatConfig\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n }) => void\n /** Which axes to show controls for */\n showAxes?: {\n xAxis?: boolean\n leftYAxis?: boolean\n rightYAxis?: boolean\n }\n}\n\n/**\n * Container component for multiple axis format controls\n */\nexport function MultiAxisFormatControls({\n displayConfig,\n onChange,\n showAxes = { leftYAxis: true, rightYAxis: true }\n}: MultiAxisFormatControlsProps) {\n return (\n <div className=\"dc:space-y-4\">\n {showAxes.leftYAxis && (\n <AxisFormatControls\n axisLabel=\"Left Y-Axis\"\n value={displayConfig.leftYAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n leftYAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {showAxes.rightYAxis && (\n <AxisFormatControls\n axisLabel=\"Right Y-Axis\"\n value={displayConfig.rightYAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n rightYAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {showAxes.xAxis && (\n <AxisFormatControls\n axisLabel=\"X-Axis\"\n value={displayConfig.xAxisFormat || {}}\n onChange={(config) =>\n onChange({\n ...displayConfig,\n xAxisFormat: Object.keys(config).length > 0 ? config : undefined\n })\n }\n previewValue={2024} // Use a year-like number for X-axis preview\n />\n )}\n </div>\n )\n}\n\nexport default AxisFormatControls\n","/**\n * Optimized hook that only subscribes to field label functionality\n * from CubeMeta context. This prevents re-renders when unrelated\n * contexts (CubeApi, Features) change.\n *\n * Use this instead of useCubeContext() when you only need getFieldLabel.\n */\n\nimport { useContext, useMemo } from 'react'\nimport { CubeMetaContext, type CubeMetaContextValue } from '../providers/CubeMetaContext'\n\n/**\n * Returns a stable reference to the getFieldLabel function.\n * Components using this hook will only re-render when the field label\n * mapping actually changes, not when unrelated API or feature contexts update.\n *\n * @returns Function to get human-readable label for a field name\n * @throws Error if used outside CubeProvider\n */\nexport function useCubeFieldLabel(): (fieldName: string) => string {\n const context = useContext(CubeMetaContext) as CubeMetaContextValue | null\n\n if (!context) {\n throw new Error('useCubeFieldLabel must be used within CubeProvider')\n }\n\n // Return stable reference - only changes when getFieldLabel itself changes\n return useMemo(() => context.getFieldLabel, [context.getFieldLabel])\n}\n","// Default color palette for charts - used as fallback when no dashboard palette is specified\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS = [\n '#3b82f6', // blue\n '#10b981', // green\n '#f59e0b', // yellow\n '#ef4444', // red\n '#8b5cf6', // purple\n '#f97316', // orange\n '#06b6d4', // cyan\n '#84cc16', // lime\n]\n\n// Default gradient colors for continuous numeric scales - used as fallback\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS_GRADIENT = [\n '#440154', // dark purple\n '#414487', // purple-blue\n '#2a788e', // teal\n '#22a884', // green-teal \n '#7ad151', // green\n '#fde725', // yellow\n]\n\n// Colors for positive/negative values\nexport const POSITIVE_COLOR = '#10b981' // green\nexport const NEGATIVE_COLOR = '#ef4444' // red\n\nexport const CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 5\n}\n\nexport const RESPONSIVE_CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 60 // Extra space for rotated labels\n}","import { ReactElement, useState, useRef, useLayoutEffect, startTransition } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport LoadingIndicator from '../LoadingIndicator'\n\ninterface ChartContainerProps {\n children: ReactElement\n height?: string | number\n}\n\nexport default function ChartContainer({ children, height = \"100%\" }: ChartContainerProps) {\n // Track if container is ready to render ResponsiveContainer\n // We need to wait for the container to be in the DOM with valid dimensions\n const containerRef = useRef<HTMLDivElement>(null)\n const [isReady, setIsReady] = useState(false)\n const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })\n const sizeRef = useRef({ width: 0, height: 0 })\n const readyRef = useRef(false)\n const pendingSizeRef = useRef<{ width: number; height: number } | null>(null)\n const frameRef = useRef<number | null>(null)\n\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\n\n const flushPendingSize = () => {\n frameRef.current = null\n if (!mounted) return\n const pending = pendingSizeRef.current\n pendingSizeRef.current = null\n if (!pending) return\n\n const nextWidth = Math.round(pending.width)\n const nextHeight = Math.round(pending.height)\n if (nextWidth <= 0 || nextHeight <= 0) return\n\n const sizeChanged =\n sizeRef.current.width !== nextWidth || sizeRef.current.height !== nextHeight\n const shouldBecomeReady = !readyRef.current\n\n if (!sizeChanged && !shouldBecomeReady) return\n\n sizeRef.current = { width: nextWidth, height: nextHeight }\n readyRef.current = true\n\n // Resize-driven chart updates can come in bursts (one per portlet).\n // Transitioning these avoids blocking urgent input and coalesces visual work.\n startTransition(() => {\n if (sizeChanged) {\n setContainerSize({ width: nextWidth, height: nextHeight })\n }\n if (shouldBecomeReady) {\n setIsReady(true)\n }\n })\n }\n\n const scheduleSizeUpdate = (width: number, height: number) => {\n pendingSizeRef.current = { width, height }\n if (frameRef.current === null) {\n frameRef.current = requestAnimationFrame(flushPendingSize)\n }\n }\n\n const measureAndSetReady = () => {\n if (!mounted || !containerRef.current) return\n\n const rect = containerRef.current.getBoundingClientRect()\n // Check both clientWidth/Height AND getBoundingClientRect for robustness\n const width = Math.max(containerRef.current.clientWidth, rect.width)\n const measuredHeight = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && measuredHeight > 0) {\n scheduleSizeUpdate(width, measuredHeight)\n }\n }\n\n // Set up ResizeObserver to detect when container gets valid dimensions\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: entryHeight } = entry.contentRect\n if (width > 0 && entryHeight > 0) {\n scheduleSizeUpdate(width, entryHeight)\n }\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n // Also try immediate measurement\n measureAndSetReady()\n }\n\n return () => {\n mounted = false\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n resizeObserver?.disconnect()\n }\n }, [])\n\n try {\n if (height === \"100%\") {\n // For 100% height, make the container fill the available flex space with proper sizing\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative\"\n style={{ minHeight: '250px', minWidth: '100px', overflow: 'hidden', userSelect: 'none' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n }\n\n // For specific heights, use them directly\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n const containerStyle = {\n height: typeof height === 'number' ? `${height}px` : height,\n width: '100%',\n minHeight: '200px',\n minWidth: '100px',\n userSelect: 'none' as const\n }\n\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:flex dc:flex-col dc:relative\"\n style={{ ...containerStyle, overflow: 'hidden' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n } catch (error) {\n // ChartContainer ResponsiveContainer error\n\n return (\n <div\n className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-4 dc:text-center dc:border dc:border-dashed dc:rounded-lg\"\n style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}\n >\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted\">Unable to display chart</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {error instanceof Error ? error.message : 'Failed to create responsive container'}\n </div>\n </div>\n )\n }\n}\n","import React from 'react'\nimport { Tooltip } from 'recharts'\nimport { formatNumericValue } from '../../utils/chartUtils'\n\ninterface ChartTooltipProps {\n formatter?: (value: any, name: any, props: any) => [React.ReactText, React.ReactText]\n labelFormatter?: (label: any, payload?: readonly any[]) => React.ReactText\n}\n\n// Default formatter that rounds numeric values to at most 2 decimal places\nconst defaultFormatter = (value: any, name: any): [React.ReactText, React.ReactText] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatNumericValue(value), name]\n}\n\nexport default function ChartTooltip({ formatter, labelFormatter }: ChartTooltipProps) {\n return (\n <Tooltip\n formatter={formatter || defaultFormatter}\n labelFormatter={labelFormatter}\n contentStyle={{\n backgroundColor: 'white',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n fontSize: '0.875rem',\n color: '#1f2937',\n boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n padding: '8px 12px'\n }}\n />\n )\n}","/**\n * Utility functions for handling target values in charts\n */\n\n/**\n * Parse target values from string format\n * @param targetString - String containing target values (e.g., \"100\" or \"50,75,100\")\n * @returns Array of numeric target values\n */\nexport function parseTargetValues(targetString: string): number[] {\n if (!targetString || typeof targetString !== 'string') {\n return []\n }\n\n const trimmed = targetString.trim()\n if (!trimmed) {\n return []\n }\n\n try {\n // Split by comma and parse each value\n const values = trimmed\n .split(',')\n .map(val => val.trim())\n .filter(val => val !== '')\n .map(val => {\n const num = parseFloat(val)\n if (isNaN(num)) {\n throw new Error(`Invalid numeric value: ${val}`)\n }\n return num\n })\n\n return values.length > 0 ? values : []\n } catch (error) {\n console.warn('Failed to parse target values:', error)\n return []\n }\n}\n\n/**\n * Spread target values across data points\n * @param targets - Array of target values\n * @param dataLength - Number of data points to spread across\n * @returns Array of target values for each data point\n */\nexport function spreadTargetValues(targets: number[], dataLength: number): number[] {\n if (targets.length === 0 || dataLength <= 0) {\n return []\n }\n\n // If only one target value, repeat for all data points\n if (targets.length === 1) {\n return new Array(dataLength).fill(targets[0])\n }\n\n // If we have multiple targets, spread them evenly across data points\n const result: number[] = []\n const baseGroupSize = Math.floor(dataLength / targets.length)\n const remainder = dataLength % targets.length\n\n let currentIndex = 0\n \n for (let i = 0; i < targets.length; i++) {\n // Calculate group size for this target\n // First 'remainder' groups get an extra item\n const groupSize = baseGroupSize + (i < remainder ? 1 : 0)\n \n // Fill this group with the current target value\n for (let j = 0; j < groupSize; j++) {\n result[currentIndex++] = targets[i]\n }\n }\n\n return result\n}\n\n/**\n * Calculate variance between actual and target values\n * @param actual - Actual value\n * @param target - Target value\n * @returns Variance as percentage\n */\nexport function calculateVariance(actual: number, target: number): number {\n if (target === 0) {\n return actual === 0 ? 0 : (actual > 0 ? 100 : -100)\n }\n return ((actual - target) / target) * 100\n}\n\n/**\n * Format variance as percentage string with appropriate sign and color indication\n * @param variance - Variance percentage\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted variance string (e.g., \"+12.5%\" or \"-8.3%\")\n */\nexport function formatVariance(variance: number, decimals: number = 1): string {\n const sign = variance >= 0 ? '+' : ''\n return `${sign}${variance.toFixed(decimals)}%`\n}\n\n/**\n * Get unique target values for reference lines\n * @param targets - Array of target values (may contain duplicates)\n * @returns Array of unique target values\n */\nexport function getUniqueTargets(targets: number[]): number[] {\n return [...new Set(targets)].sort((a, b) => a - b)\n}"],"names":["sizeClasses","LoadingIndicator","size","className","jsx","SectionHeading","children","isValidNumericValue","value","parseNumericValue","num","formatNumericValue","formatAxisValue","config","locale","effectiveLocale","unit","abbreviate","decimals","customPrefix","customSuffix","displayValue","abbreviationSuffix","absNum","effectiveDecimals","currencyCode","getCurrencyCodeForLocale","formatted","parts","percentValue","prefix","suffix","region","createAxisTickFormatter","getFieldLabel","fieldName","labelMap","transformSeriesKeysWithLabels","seriesKeys","key","formatTimeValue","granularity","str","isoStr","date","year","month","day","hours","minutes","quarter","seconds","milliseconds","getFieldGranularity","queryObject","timeDim","td","granularityMatch","transformChartData","data","xAxisField","yAxisFields","getFieldLabelFn","row","transformed","field","displayName","transformChartDataWithSeries","seriesFields","originalQuery","queryDimensions","queryMeasures","yAxisMeasures","yAxisDimensions","groupedData","xValue","measure","measureValue","currentValue","dimension","dimValue","seriesName","measureToAggregate","m","chartData","dimensionSeries","getLocaleCurrencySymbol","AxisFormatControls","onChange","axisLabel","previewValue","useMemo","currencySymbol","preview","handleChange","updates","unitButtons","jsxs","e","btn","current","useCubeFieldLabel","context","useContext","CubeMetaContext","CHART_COLORS","CHART_COLORS_GRADIENT","POSITIVE_COLOR","NEGATIVE_COLOR","CHART_MARGINS","RESPONSIVE_CHART_MARGINS","ChartContainer","height","containerRef","useRef","isReady","setIsReady","useState","containerSize","setContainerSize","sizeRef","readyRef","pendingSizeRef","frameRef","useLayoutEffect","mounted","resizeObserver","flushPendingSize","pending","nextWidth","nextHeight","sizeChanged","shouldBecomeReady","startTransition","scheduleSizeUpdate","width","measureAndSetReady","rect","measuredHeight","entries","entry","entryHeight","ResponsiveContainer","containerStyle","error","defaultFormatter","name","ChartTooltip","formatter","labelFormatter","Tooltip","parseTargetValues","targetString","trimmed","values","val","spreadTargetValues","targets","dataLength","result","baseGroupSize","remainder","currentIndex","i","groupSize","j","calculateVariance","actual","target","formatVariance","variance"],"mappings":"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"}