drizzle-cube 0.3.21 → 0.3.23

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 (122) hide show
  1. package/dist/adapters/express/index.cjs +1 -1
  2. package/dist/adapters/express/index.js +1 -1
  3. package/dist/adapters/fastify/index.cjs +1 -1
  4. package/dist/adapters/fastify/index.js +1 -1
  5. package/dist/adapters/hono/index.cjs +1 -1
  6. package/dist/adapters/hono/index.js +1 -1
  7. package/dist/adapters/{mcp-transport-DHBUNdYg.js → mcp-transport-lkEjNwDH.js} +3242 -3201
  8. package/dist/adapters/mcp-transport-oPf8JYHv.cjs +275 -0
  9. package/dist/adapters/nextjs/index.cjs +1 -1
  10. package/dist/adapters/nextjs/index.js +1 -1
  11. package/dist/client/charts/chartConfigs.d.ts +21 -0
  12. package/dist/client/charts.js +14 -14
  13. package/dist/client/chunks/{RetentionCombinedChart-DsWhPI0q.js → RetentionCombinedChart-DpEKFYsd.js} +3 -3
  14. package/dist/client/chunks/RetentionCombinedChart-DpEKFYsd.js.map +1 -0
  15. package/dist/client/chunks/{analysis-builder-DcZgXtPK.js → analysis-builder-DiaxkEY-.js} +9 -9
  16. package/dist/client/chunks/{analysis-builder-DcZgXtPK.js.map → analysis-builder-DiaxkEY-.js.map} +1 -1
  17. package/dist/client/chunks/{analysis-builder-shared-ZnrPzt_d.js → analysis-builder-shared-BzM5Vwpr.js} +5 -5
  18. package/dist/client/chunks/{analysis-builder-shared-ZnrPzt_d.js.map → analysis-builder-shared-BzM5Vwpr.js.map} +1 -1
  19. package/dist/client/chunks/{chart-activity-grid-BUc21L0U.js → chart-activity-grid-CCGyWo1c.js} +116 -106
  20. package/dist/client/chunks/chart-activity-grid-CCGyWo1c.js.map +1 -0
  21. package/dist/client/chunks/chart-area-ZZp1libT.js +234 -0
  22. package/dist/client/chunks/chart-area-ZZp1libT.js.map +1 -0
  23. package/dist/client/chunks/chart-bar-B4grbo6Q.js +254 -0
  24. package/dist/client/chunks/chart-bar-B4grbo6Q.js.map +1 -0
  25. package/dist/client/chunks/{chart-bubble-CO7qvWR9.js → chart-bubble-BGGAQQUQ.js} +2 -2
  26. package/dist/client/chunks/{chart-bubble-CO7qvWR9.js.map → chart-bubble-BGGAQQUQ.js.map} +1 -1
  27. package/dist/client/chunks/{chart-config-activity-grid-BBSNCbkb.js → chart-config-activity-grid-CAlo1cHA.js} +3 -2
  28. package/dist/client/chunks/{chart-config-activity-grid-BBSNCbkb.js.map → chart-config-activity-grid-CAlo1cHA.js.map} +1 -1
  29. package/dist/client/chunks/{chart-config-bar-BJKGnfLt.js → chart-config-bar-soxw6m2o.js} +2 -1
  30. package/dist/client/chunks/chart-config-bar-soxw6m2o.js.map +1 -0
  31. package/dist/client/chunks/{chart-config-line-DR0ThxZy.js → chart-config-line-D5ME6w0v.js} +2 -1
  32. package/dist/client/chunks/chart-config-line-D5ME6w0v.js.map +1 -0
  33. package/dist/client/chunks/{chart-config-pie-BM5lgH-w.js → chart-config-pie-DlHa2jTy.js} +2 -1
  34. package/dist/client/chunks/chart-config-pie-DlHa2jTy.js.map +1 -0
  35. package/dist/client/chunks/{chart-config-tree-map-CLmRvvMR.js → chart-config-tree-map-IRAYf9YM.js} +3 -2
  36. package/dist/client/chunks/{chart-config-tree-map-CLmRvvMR.js.map → chart-config-tree-map-IRAYf9YM.js.map} +1 -1
  37. package/dist/client/chunks/{chart-data-table-bclSKgkZ.js → chart-data-table-BcH_h6kZ.js} +3 -3
  38. package/dist/client/chunks/{chart-data-table-bclSKgkZ.js.map → chart-data-table-BcH_h6kZ.js.map} +1 -1
  39. package/dist/client/chunks/{chart-funnel-FvDvq015.js → chart-funnel-DI8RMacf.js} +3 -3
  40. package/dist/client/chunks/chart-funnel-DI8RMacf.js.map +1 -0
  41. package/dist/client/chunks/{chart-heat-map-GpFE-PFB.js → chart-heat-map-D3xNV9ep.js} +2 -2
  42. package/dist/client/chunks/{chart-heat-map-GpFE-PFB.js.map → chart-heat-map-D3xNV9ep.js.map} +1 -1
  43. package/dist/client/chunks/{chart-kpi-delta-jmz-CK8X.js → chart-kpi-delta-BJMQKPor.js} +3 -3
  44. package/dist/client/chunks/{chart-kpi-delta-jmz-CK8X.js.map → chart-kpi-delta-BJMQKPor.js.map} +1 -1
  45. package/dist/client/chunks/{chart-kpi-number-DbSmomE8.js → chart-kpi-number-B8u4tWmu.js} +2 -2
  46. package/dist/client/chunks/{chart-kpi-number-DbSmomE8.js.map → chart-kpi-number-B8u4tWmu.js.map} +1 -1
  47. package/dist/client/chunks/{chart-kpi-text-erI9U7PZ.js → chart-kpi-text--r1d4zAz.js} +3 -3
  48. package/dist/client/chunks/{chart-kpi-text-erI9U7PZ.js.map → chart-kpi-text--r1d4zAz.js.map} +1 -1
  49. package/dist/client/chunks/chart-line-K0ACw4cV.js +413 -0
  50. package/dist/client/chunks/chart-line-K0ACw4cV.js.map +1 -0
  51. package/dist/client/chunks/chart-pie-DC7axSwd.js +137 -0
  52. package/dist/client/chunks/chart-pie-DC7axSwd.js.map +1 -0
  53. package/dist/client/chunks/{chart-radar-BE6xsFiF.js → chart-radar-BDKgpLw5.js} +33 -33
  54. package/dist/client/chunks/chart-radar-BDKgpLw5.js.map +1 -0
  55. package/dist/client/chunks/{chart-radial-bar-BEEwtFDc.js → chart-radial-bar-BYNng7Nz.js} +7 -6
  56. package/dist/client/chunks/chart-radial-bar-BYNng7Nz.js.map +1 -0
  57. package/dist/client/chunks/{chart-sankey-Dt3KaYrH.js → chart-sankey-CpsKerey.js} +2 -2
  58. package/dist/client/chunks/{chart-sankey-Dt3KaYrH.js.map → chart-sankey-CpsKerey.js.map} +1 -1
  59. package/dist/client/chunks/{chart-scatter-gAlYkQcW.js → chart-scatter-CXqFltJg.js} +11 -11
  60. package/dist/client/chunks/chart-scatter-CXqFltJg.js.map +1 -0
  61. package/dist/client/chunks/{chart-sunburst-D0Lvdjwu.js → chart-sunburst-DSsO2CzY.js} +2 -2
  62. package/dist/client/chunks/{chart-sunburst-D0Lvdjwu.js.map → chart-sunburst-DSsO2CzY.js.map} +1 -1
  63. package/dist/client/chunks/{chart-tree-map-Bv_PYe0c.js → chart-tree-map-D_SeBBD-.js} +77 -57
  64. package/dist/client/chunks/chart-tree-map-D_SeBBD-.js.map +1 -0
  65. package/dist/client/chunks/{chartConfigRegistry-BumUIPw4.js → chartConfigRegistry-DNEbwgTc.js} +6 -6
  66. package/dist/client/chunks/{chartConfigRegistry-BumUIPw4.js.map → chartConfigRegistry-DNEbwgTc.js.map} +1 -1
  67. package/dist/client/chunks/{charts-DqWRT0TE.js → charts-T6qNi6FO.js} +17 -17
  68. package/dist/client/chunks/charts-T6qNi6FO.js.map +1 -0
  69. package/dist/client/chunks/{charts-core-BfxnhMfd.js → charts-core-8jDh3mKC.js} +64 -63
  70. package/dist/client/chunks/charts-core-8jDh3mKC.js.map +1 -0
  71. package/dist/client/chunks/{charts-loader-DCGbL50r.js → charts-loader-DpJr9z2e.js} +20 -20
  72. package/dist/client/chunks/{charts-loader-DCGbL50r.js.map → charts-loader-DpJr9z2e.js.map} +1 -1
  73. package/dist/client/chunks/{components-NmBmOEqV.js → components-vl_fdWud.js} +3579 -2880
  74. package/dist/client/chunks/components-vl_fdWud.js.map +1 -0
  75. package/dist/client/chunks/{hooks-D7APQ8uS.js → hooks-CKYzVf_7.js} +3 -3
  76. package/dist/client/chunks/{hooks-D7APQ8uS.js.map → hooks-CKYzVf_7.js.map} +1 -1
  77. package/dist/client/chunks/{index-CBvXpG92.js → index-_2PSgbkC.js} +270 -261
  78. package/dist/client/chunks/index-_2PSgbkC.js.map +1 -0
  79. package/dist/client/chunks/{providers-Cj7PQfXn.js → providers-BBrUJB2U.js} +2 -2
  80. package/dist/client/chunks/{providers-Cj7PQfXn.js.map → providers-BBrUJB2U.js.map} +1 -1
  81. package/dist/client/chunks/{useDirtyStateTracking-ZSi3voVl.js → useDirtyStateTracking-DDQ_Lbki.js} +2 -2
  82. package/dist/client/chunks/{useDirtyStateTracking-ZSi3voVl.js.map → useDirtyStateTracking-DDQ_Lbki.js.map} +1 -1
  83. package/dist/client/components/DrillBreadcrumb.d.ts +6 -0
  84. package/dist/client/components/DrillMenu.d.ts +8 -0
  85. package/dist/client/components/charts/AngledXAxisTick.d.ts +19 -0
  86. package/dist/client/components.js +2 -2
  87. package/dist/client/hooks/useDrillInteraction.d.ts +9 -0
  88. package/dist/client/hooks.js +3 -3
  89. package/dist/client/index.js +9 -9
  90. package/dist/client/providers.js +1 -1
  91. package/dist/client/styles.css +1 -1
  92. package/dist/client/types/drill.d.ts +240 -0
  93. package/dist/client/types.d.ts +53 -2
  94. package/dist/client/utils/drillQueryBuilder.d.ts +41 -0
  95. package/dist/client-bundle-stats.html +1 -1
  96. package/dist/server/index.cjs +31 -31
  97. package/dist/server/index.d.ts +78 -0
  98. package/dist/server/index.js +2730 -2689
  99. package/package.json +6 -3
  100. package/dist/adapters/mcp-transport-B37JTeww.cjs +0 -275
  101. package/dist/client/chunks/RetentionCombinedChart-DsWhPI0q.js.map +0 -1
  102. package/dist/client/chunks/chart-activity-grid-BUc21L0U.js.map +0 -1
  103. package/dist/client/chunks/chart-area-B_64FScj.js +0 -190
  104. package/dist/client/chunks/chart-area-B_64FScj.js.map +0 -1
  105. package/dist/client/chunks/chart-bar-Ctiy2tpQ.js +0 -216
  106. package/dist/client/chunks/chart-bar-Ctiy2tpQ.js.map +0 -1
  107. package/dist/client/chunks/chart-config-bar-BJKGnfLt.js.map +0 -1
  108. package/dist/client/chunks/chart-config-line-DR0ThxZy.js.map +0 -1
  109. package/dist/client/chunks/chart-config-pie-BM5lgH-w.js.map +0 -1
  110. package/dist/client/chunks/chart-funnel-FvDvq015.js.map +0 -1
  111. package/dist/client/chunks/chart-line-B0YOZ88n.js +0 -364
  112. package/dist/client/chunks/chart-line-B0YOZ88n.js.map +0 -1
  113. package/dist/client/chunks/chart-pie-CImB6r4F.js +0 -125
  114. package/dist/client/chunks/chart-pie-CImB6r4F.js.map +0 -1
  115. package/dist/client/chunks/chart-radar-BE6xsFiF.js.map +0 -1
  116. package/dist/client/chunks/chart-radial-bar-BEEwtFDc.js.map +0 -1
  117. package/dist/client/chunks/chart-scatter-gAlYkQcW.js.map +0 -1
  118. package/dist/client/chunks/chart-tree-map-Bv_PYe0c.js.map +0 -1
  119. package/dist/client/chunks/charts-DqWRT0TE.js.map +0 -1
  120. package/dist/client/chunks/charts-core-BfxnhMfd.js.map +0 -1
  121. package/dist/client/chunks/components-NmBmOEqV.js.map +0 -1
  122. package/dist/client/chunks/index-CBvXpG92.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { useContext as P, useMemo as U, useRef as L, useState as E, useLayoutEffect as H } from "react";
2
- import { C as K } from "./providers-Cj7PQfXn.js";
2
+ import { C as K } from "./providers-BBrUJB2U.js";
3
3
  import { jsx as l, jsxs as p } from "react/jsx-runtime";
4
4
  import { ResponsiveContainer as T, Tooltip as V } from "recharts";
5
5
  const B = {
@@ -51,48 +51,48 @@ function G(e, t, c) {
51
51
  const r = typeof navigator < "u" ? navigator.language : "en-US";
52
52
  if (!t)
53
53
  return A(e);
54
- const { unit: i, abbreviate: s = !0, decimals: a, customPrefix: m, customSuffix: d } = t;
54
+ const { unit: i, abbreviate: s = !0, decimals: o, customPrefix: m, customSuffix: d } = t;
55
55
  let u = n, h = "";
56
56
  if (s) {
57
- const o = Math.abs(n);
58
- o >= 1e9 ? (u = n / 1e9, h = "B") : o >= 1e6 ? (u = n / 1e6, h = "M") : o >= 1e3 && (u = n / 1e3, h = "K");
57
+ const a = Math.abs(n);
58
+ a >= 1e9 ? (u = n / 1e9, h = "B") : a >= 1e6 ? (u = n / 1e6, h = "M") : a >= 1e3 && (u = n / 1e3, h = "K");
59
59
  }
60
- const f = a !== void 0 ? a : Number.isInteger(u) ? 0 : 2;
60
+ const f = o !== void 0 ? o : Number.isInteger(u) ? 0 : 2;
61
61
  switch (i) {
62
62
  case "currency": {
63
- const o = k(r);
63
+ const a = k(r);
64
64
  if (s && h) {
65
65
  const N = new Intl.NumberFormat(r, {
66
66
  style: "currency",
67
- currency: o,
67
+ currency: a,
68
68
  minimumFractionDigits: f,
69
69
  maximumFractionDigits: f
70
70
  }).format(u), C = new Intl.NumberFormat(r, {
71
71
  style: "currency",
72
- currency: o
72
+ currency: a
73
73
  }).formatToParts(u);
74
74
  return C[C.length - 1]?.type === "currency" ? N.replace(/(\s*[^\d\s]+)$/, h + "$1") : N + h;
75
75
  }
76
76
  return new Intl.NumberFormat(r, {
77
77
  style: "currency",
78
- currency: o,
78
+ currency: a,
79
79
  minimumFractionDigits: f,
80
80
  maximumFractionDigits: f
81
81
  }).format(u);
82
82
  }
83
83
  case "percent": {
84
- const o = Math.abs(u) <= 1 && !s ? u * 100 : u;
84
+ const a = Math.abs(u) <= 1 && !s ? u * 100 : u;
85
85
  return new Intl.NumberFormat(r, {
86
86
  minimumFractionDigits: f,
87
87
  maximumFractionDigits: f
88
- }).format(o) + h + "%";
88
+ }).format(a) + h + "%";
89
89
  }
90
90
  case "custom": {
91
- const o = m || "", N = d || "", C = new Intl.NumberFormat(r, {
91
+ const a = m || "", N = d || "", C = new Intl.NumberFormat(r, {
92
92
  minimumFractionDigits: f,
93
93
  maximumFractionDigits: f
94
94
  }).format(u);
95
- return o + C + h + N;
95
+ return a + C + h + N;
96
96
  }
97
97
  default:
98
98
  return new Intl.NumberFormat(r, {
@@ -157,7 +157,7 @@ function F(e, t) {
157
157
  const r = new Date(n);
158
158
  if (isNaN(r.getTime()))
159
159
  return c;
160
- const i = r.getUTCFullYear(), s = String(r.getUTCMonth() + 1).padStart(2, "0"), a = String(r.getUTCDate()).padStart(2, "0"), m = r.getUTCHours(), d = r.getUTCMinutes();
160
+ const i = r.getUTCFullYear(), s = String(r.getUTCMonth() + 1).padStart(2, "0"), o = String(r.getUTCDate()).padStart(2, "0"), m = r.getUTCHours(), d = r.getUTCMinutes();
161
161
  if (t)
162
162
  switch (t.toLowerCase()) {
163
163
  case "year":
@@ -169,23 +169,23 @@ function F(e, t) {
169
169
  case "month":
170
170
  return `${i}-${s}`;
171
171
  case "week":
172
- return `${i}-${s}-${a}`;
172
+ return `${i}-${s}-${o}`;
173
173
  case "day":
174
- return `${i}-${s}-${a}`;
174
+ return `${i}-${s}-${o}`;
175
175
  case "hour":
176
- return `${i}-${s}-${a} ${String(m).padStart(2, "0")}:00`;
176
+ return `${i}-${s}-${o} ${String(m).padStart(2, "0")}:00`;
177
177
  case "minute":
178
- return `${i}-${s}-${a} ${String(m).padStart(2, "0")}:${String(d).padStart(2, "0")}`;
178
+ return `${i}-${s}-${o} ${String(m).padStart(2, "0")}:${String(d).padStart(2, "0")}`;
179
179
  }
180
180
  const u = r.getUTCSeconds(), h = r.getUTCMilliseconds();
181
- if (a === "01" && m === 0 && d === 0 && u === 0 && h === 0) {
181
+ if (o === "01" && m === 0 && d === 0 && u === 0 && h === 0) {
182
182
  if (s === "01" || s === "04" || s === "07" || s === "10") {
183
183
  const f = Math.floor(r.getUTCMonth() / 3) + 1;
184
184
  return `${i}-Q${f}`;
185
185
  }
186
186
  return `${i}-${s}`;
187
187
  }
188
- return m === 0 && d === 0 && u === 0 && h === 0 ? `${i}-${s}-${a}` : d === 0 && u === 0 && h === 0 ? `${i}-${s}-${a} ${String(m).padStart(2, "0")}:00` : `${i}-${s}-${a} ${String(m).padStart(2, "0")}:${String(d).padStart(2, "0")}`;
188
+ return m === 0 && d === 0 && u === 0 && h === 0 ? `${i}-${s}-${o}` : d === 0 && u === 0 && h === 0 ? `${i}-${s}-${o} ${String(m).padStart(2, "0")}:00` : `${i}-${s}-${o} ${String(m).padStart(2, "0")}:${String(d).padStart(2, "0")}`;
189
189
  }
190
190
  return c;
191
191
  }
@@ -211,32 +211,32 @@ function O(e, t, c, n, r = (i) => i) {
211
211
  if (!e || e.length === 0) return [];
212
212
  const i = M(n, t);
213
213
  return e.map((s) => {
214
- const a = {
214
+ const o = {
215
215
  name: F(s[t], i) || s[t] || "Unknown"
216
216
  };
217
217
  return c.forEach((m) => {
218
218
  const d = r(m);
219
- a[d] = $(s[m]);
220
- }), a;
219
+ o[d] = $(s[m]);
220
+ }), o;
221
221
  });
222
222
  }
223
223
  function ee(e, t, c, n, r, i = (s) => s) {
224
224
  if (!e || e.length === 0)
225
225
  return { data: [], seriesKeys: [], hasDimensions: !1 };
226
- const s = n || {}, a = [
226
+ const s = n || {}, o = [
227
227
  ...s.dimensions || [],
228
- ...s.timeDimensions?.map((o) => o.dimension) || []
229
- ], m = s.measures || [], d = c.filter((o) => m.includes(o)), u = (r || []).filter((o) => a.includes(o));
228
+ ...s.timeDimensions?.map((a) => a.dimension) || []
229
+ ], m = s.measures || [], d = c.filter((a) => m.includes(a)), u = (r || []).filter((a) => o.includes(a));
230
230
  if (u.length > 0) {
231
- const o = {};
231
+ const a = {};
232
232
  e.forEach((x) => {
233
233
  const v = M(n, t), b = F(x[t], v) || x[t] || "Unknown";
234
- o[b] || (o[b] = { name: String(b) }), d.forEach((D) => {
234
+ a[b] || (a[b] = { name: String(b) }), d.forEach((D) => {
235
235
  const g = i(D), y = $(x[D]);
236
236
  if (y !== null) {
237
- const R = o[b][g];
238
- o[b][g] = R == null ? y : R + y;
239
- } else g in o[b] || (o[b][g] = null);
237
+ const R = a[b][g];
238
+ a[b][g] = R == null ? y : R + y;
239
+ } else g in a[b] || (a[b][g] = null);
240
240
  }), u.forEach((D) => {
241
241
  const g = x[D];
242
242
  if (g != null) {
@@ -246,14 +246,14 @@ function ee(e, t, c, n, r, i = (s) => s) {
246
246
  if (R) {
247
247
  const S = $(x[R]);
248
248
  if (S !== null) {
249
- const w = o[b][y];
250
- o[b][y] = w == null ? S : w + S;
251
- } else y in o[b] || (o[b][y] = null);
249
+ const w = a[b][y];
250
+ a[b][y] = w == null ? S : w + S;
251
+ } else y in a[b] || (a[b][y] = null);
252
252
  }
253
253
  }
254
254
  });
255
255
  });
256
- const N = Object.values(o), C = Array.from(new Set(
256
+ const N = Object.values(a), C = Array.from(new Set(
257
257
  e.flatMap(
258
258
  (x) => u.map((v) => {
259
259
  const b = x[v];
@@ -267,7 +267,7 @@ function ee(e, t, c, n, r, i = (s) => s) {
267
267
  hasDimensions: !0
268
268
  };
269
269
  }
270
- const h = O(e, t, c, n, i), f = c.map((o) => i(o));
270
+ const h = O(e, t, c, n, i), f = c.map((a) => i(a));
271
271
  return {
272
272
  data: h,
273
273
  seriesKeys: f,
@@ -313,19 +313,19 @@ const te = [
313
313
  function ie({ children: e, height: t = "100%" }) {
314
314
  const c = L(null), [n, r] = E(!1), [i, s] = E({ width: 0, height: 0 });
315
315
  H(() => {
316
- let a = !0, m = null;
316
+ let o = !0, m = null;
317
317
  const d = () => {
318
- if (!a || !c.current) return;
318
+ if (!o || !c.current) return;
319
319
  const u = c.current.getBoundingClientRect(), h = Math.max(c.current.clientWidth, u.width), f = Math.max(c.current.clientHeight, u.height);
320
320
  h > 0 && f > 0 && (s({ width: h, height: f }), r(!0));
321
321
  };
322
322
  return m = new ResizeObserver((u) => {
323
323
  for (const h of u) {
324
- const { width: f, height: o } = h.contentRect;
325
- f > 0 && o > 0 && (s({ width: f, height: o }), n || r(!0));
324
+ const { width: f, height: a } = h.contentRect;
325
+ f > 0 && a > 0 && (s({ width: f, height: a }), n || r(!0));
326
326
  }
327
327
  }), c.current && (m.observe(c.current), d()), () => {
328
- a = !1, m?.disconnect();
328
+ o = !1, m?.disconnect();
329
329
  };
330
330
  }, [n]);
331
331
  try {
@@ -335,7 +335,7 @@ function ie({ children: e, height: t = "100%" }) {
335
335
  {
336
336
  ref: c,
337
337
  className: "dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative",
338
- style: { minHeight: "250px", minWidth: "100px", overflow: "hidden" },
338
+ style: { minHeight: "250px", minWidth: "100px", overflow: "hidden", userSelect: "none" },
339
339
  children: n && i.width > 0 && i.height > 0 ? /* @__PURE__ */ l(
340
340
  T,
341
341
  {
@@ -348,18 +348,19 @@ function ie({ children: e, height: t = "100%" }) {
348
348
  ) : /* @__PURE__ */ l("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full", children: /* @__PURE__ */ l(I, { size: "sm" }) })
349
349
  }
350
350
  );
351
- const a = {
351
+ const o = {
352
352
  height: typeof t == "number" ? `${t}px` : t,
353
353
  width: "100%",
354
354
  minHeight: "200px",
355
- minWidth: "100px"
355
+ minWidth: "100px",
356
+ userSelect: "none"
356
357
  };
357
358
  return /* @__PURE__ */ l(
358
359
  "div",
359
360
  {
360
361
  ref: c,
361
362
  className: "dc:w-full dc:flex dc:flex-col dc:relative",
362
- style: { ...a, overflow: "hidden" },
363
+ style: { ...o, overflow: "hidden" },
363
364
  children: n && i.width > 0 && i.height > 0 ? /* @__PURE__ */ l(
364
365
  T,
365
366
  {
@@ -372,7 +373,7 @@ function ie({ children: e, height: t = "100%" }) {
372
373
  ) : /* @__PURE__ */ l("div", { className: "dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full", children: /* @__PURE__ */ l(I, { size: "sm" }) })
373
374
  }
374
375
  );
375
- } catch (a) {
376
+ } catch (o) {
376
377
  return /* @__PURE__ */ p(
377
378
  "div",
378
379
  {
@@ -380,14 +381,14 @@ function ie({ children: e, height: t = "100%" }) {
380
381
  style: { height: t, borderColor: "var(--dc-border)", backgroundColor: "var(--dc-surface)" },
381
382
  children: [
382
383
  /* @__PURE__ */ l("div", { className: "dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted", children: "Unable to display chart" }),
383
- /* @__PURE__ */ l("div", { className: "dc:text-xs text-dc-text-secondary", children: a instanceof Error ? a.message : "Failed to create responsive container" })
384
+ /* @__PURE__ */ l("div", { className: "dc:text-xs text-dc-text-secondary", children: o instanceof Error ? o.message : "Failed to create responsive container" })
384
385
  ]
385
386
  }
386
387
  );
387
388
  }
388
389
  }
389
390
  const W = (e, t) => e == null ? ["No data", t] : [A(e), t];
390
- function ae({ formatter: e, labelFormatter: t }) {
391
+ function oe({ formatter: e, labelFormatter: t }) {
391
392
  return /* @__PURE__ */ l(
392
393
  V,
393
394
  {
@@ -405,7 +406,7 @@ function ae({ formatter: e, labelFormatter: t }) {
405
406
  }
406
407
  );
407
408
  }
408
- function oe(e) {
409
+ function ae(e) {
409
410
  if (!e || typeof e != "string")
410
411
  return [];
411
412
  const t = e.trim();
@@ -431,8 +432,8 @@ function de(e, t) {
431
432
  const c = [], n = Math.floor(t / e.length), r = t % e.length;
432
433
  let i = 0;
433
434
  for (let s = 0; s < e.length; s++) {
434
- const a = n + (s < r ? 1 : 0);
435
- for (let m = 0; m < a; m++)
435
+ const o = n + (s < r ? 1 : 0);
436
+ for (let m = 0; m < o; m++)
436
437
  c[i++] = e[s];
437
438
  }
438
439
  return c;
@@ -507,7 +508,7 @@ function me({
507
508
  axisLabel: c,
508
509
  previewValue: n = 125e4
509
510
  }) {
510
- const r = U(() => e || {}, [e]), i = U(() => Z(), []), s = U(() => G(n, r), [n, r]), a = (d) => {
511
+ const r = U(() => e || {}, [e]), i = U(() => Z(), []), s = U(() => G(n, r), [n, r]), o = (d) => {
511
512
  t({ ...r, ...d });
512
513
  }, m = [
513
514
  { value: "currency", label: i },
@@ -524,7 +525,7 @@ function me({
524
525
  {
525
526
  type: "text",
526
527
  value: r.label || "",
527
- onChange: (d) => a({ label: d.target.value || void 0 }),
528
+ onChange: (d) => o({ label: d.target.value || void 0 }),
528
529
  placeholder: "Auto-generated label",
529
530
  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"
530
531
  }
@@ -536,7 +537,7 @@ function me({
536
537
  "button",
537
538
  {
538
539
  type: "button",
539
- onClick: () => a({ unit: d.value }),
540
+ onClick: () => o({ unit: d.value }),
540
541
  className: `dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${r.unit === d.value ? "bg-dc-primary text-white" : "bg-dc-surface text-dc-text hover:bg-dc-border"}`,
541
542
  children: d.label
542
543
  },
@@ -551,7 +552,7 @@ function me({
551
552
  {
552
553
  type: "text",
553
554
  value: r.customPrefix || "",
554
- onChange: (d) => a({ customPrefix: d.target.value || void 0 }),
555
+ onChange: (d) => o({ customPrefix: d.target.value || void 0 }),
555
556
  placeholder: "e.g., $",
556
557
  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"
557
558
  }
@@ -564,7 +565,7 @@ function me({
564
565
  {
565
566
  type: "text",
566
567
  value: r.customSuffix || "",
567
- onChange: (d) => a({ customSuffix: d.target.value || void 0 }),
568
+ onChange: (d) => o({ customSuffix: d.target.value || void 0 }),
568
569
  placeholder: "e.g., units",
569
570
  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"
570
571
  }
@@ -578,7 +579,7 @@ function me({
578
579
  "button",
579
580
  {
580
581
  type: "button",
581
- onClick: () => a({ abbreviate: !0 }),
582
+ onClick: () => o({ abbreviate: !0 }),
582
583
  className: `dc:flex-1 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${r.abbreviate !== !1 ? "bg-dc-primary text-white" : "bg-dc-surface text-dc-text hover:bg-dc-border"}`,
583
584
  children: "Yes"
584
585
  }
@@ -587,7 +588,7 @@ function me({
587
588
  "button",
588
589
  {
589
590
  type: "button",
590
- onClick: () => a({ abbreviate: !1 }),
591
+ onClick: () => o({ abbreviate: !1 }),
591
592
  className: `dc:flex-1 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc:transition-colors ${r.abbreviate === !1 ? "bg-dc-primary text-white" : "bg-dc-surface text-dc-text hover:bg-dc-border"}`,
592
593
  children: "No"
593
594
  }
@@ -603,7 +604,7 @@ function me({
603
604
  type: "button",
604
605
  onClick: () => {
605
606
  const d = r.decimals ?? 2;
606
- d > 0 && a({ decimals: d - 1 });
607
+ d > 0 && o({ decimals: d - 1 });
607
608
  },
608
609
  disabled: (r.decimals ?? 2) <= 0,
609
610
  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",
@@ -616,7 +617,7 @@ function me({
616
617
  type: "button",
617
618
  onClick: () => {
618
619
  const d = r.decimals ?? 2;
619
- d < 4 && a({ decimals: d + 1 });
620
+ d < 4 && o({ decimals: d + 1 });
620
621
  },
621
622
  disabled: (r.decimals ?? 2) >= 4,
622
623
  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",
@@ -639,7 +640,7 @@ export {
639
640
  ne as P,
640
641
  Y as S,
641
642
  ie as a,
642
- ae as b,
643
+ oe as b,
643
644
  te as c,
644
645
  F as d,
645
646
  $ as e,
@@ -649,9 +650,9 @@ export {
649
650
  Q as i,
650
651
  le as j,
651
652
  ue as k,
652
- oe as p,
653
+ ae as p,
653
654
  de as s,
654
655
  ee as t,
655
656
  q as u
656
657
  };
657
- //# sourceMappingURL=charts-core-BfxnhMfd.js.map
658
+ //# sourceMappingURL=charts-core-8jDh3mKC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"charts-core-8jDh3mKC.js","sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/hooks/useCubeFieldLabel.ts","../../../src/client/utils/chartUtils.ts","../../../src/client/utils/chartConstants.ts","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/utils/targetUtils.ts","../../../src/client/components/AnalysisBuilder/SectionHeading.tsx","../../../src/client/components/charts/AxisFormatControls.tsx"],"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 * 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","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}","// 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 } 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\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\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 height = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && height > 0) {\n setContainerSize({ width, height })\n setIsReady(true)\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 } = entry.contentRect\n if (width > 0 && height > 0) {\n setContainerSize({ width, height })\n if (!isReady) {\n setIsReady(true)\n }\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 resizeObserver?.disconnect()\n }\n }, [isReady])\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 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}","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}","/**\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","/**\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 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"],"names":["sizeClasses","LoadingIndicator","size","className","jsx","useCubeFieldLabel","context","useContext","CubeMetaContext","useMemo","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","formatTimeValue","granularity","str","isoStr","date","year","month","day","hours","minutes","quarter","seconds","milliseconds","getFieldGranularity","queryObject","fieldName","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","seriesKeys","CHART_COLORS","CHART_COLORS_GRADIENT","POSITIVE_COLOR","NEGATIVE_COLOR","CHART_MARGINS","ChartContainer","children","height","containerRef","useRef","isReady","setIsReady","useState","containerSize","setContainerSize","useLayoutEffect","mounted","resizeObserver","measureAndSetReady","rect","width","entries","entry","ResponsiveContainer","containerStyle","error","jsxs","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","SectionHeading","getLocaleCurrencySymbol","AxisFormatControls","onChange","axisLabel","previewValue","currencySymbol","preview","handleChange","updates","unitButtons","e","btn","current"],"mappings":"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"}
@@ -135,27 +135,27 @@ const m = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set(), f = {
135
135
  }
136
136
  // Charts with no external deps: table, activityGrid, kpiNumber, kpiDelta, kpiText, markdown, retentionHeatmap
137
137
  }, o = {
138
- bar: () => import("./chart-bar-Ctiy2tpQ.js"),
139
- line: () => import("./chart-line-B0YOZ88n.js"),
140
- area: () => import("./chart-area-B_64FScj.js"),
141
- pie: () => import("./chart-pie-CImB6r4F.js"),
142
- scatter: () => import("./chart-scatter-gAlYkQcW.js"),
143
- radar: () => import("./chart-radar-BE6xsFiF.js"),
144
- radialBar: () => import("./chart-radial-bar-BEEwtFDc.js"),
145
- treemap: () => import("./chart-tree-map-Bv_PYe0c.js"),
146
- bubble: () => import("./chart-bubble-CO7qvWR9.js").then((a) => a.B),
147
- table: () => import("./chart-data-table-bclSKgkZ.js"),
148
- activityGrid: () => import("./chart-activity-grid-BUc21L0U.js"),
149
- kpiNumber: () => import("./chart-kpi-number-DbSmomE8.js").then((a) => a.K),
150
- kpiDelta: () => import("./chart-kpi-delta-jmz-CK8X.js"),
151
- kpiText: () => import("./chart-kpi-text-erI9U7PZ.js"),
138
+ bar: () => import("./chart-bar-B4grbo6Q.js").then((a) => a.a),
139
+ line: () => import("./chart-line-K0ACw4cV.js"),
140
+ area: () => import("./chart-area-ZZp1libT.js"),
141
+ pie: () => import("./chart-pie-DC7axSwd.js"),
142
+ scatter: () => import("./chart-scatter-CXqFltJg.js"),
143
+ radar: () => import("./chart-radar-BDKgpLw5.js"),
144
+ radialBar: () => import("./chart-radial-bar-BYNng7Nz.js"),
145
+ treemap: () => import("./chart-tree-map-D_SeBBD-.js"),
146
+ bubble: () => import("./chart-bubble-BGGAQQUQ.js").then((a) => a.B),
147
+ table: () => import("./chart-data-table-BcH_h6kZ.js"),
148
+ activityGrid: () => import("./chart-activity-grid-CCGyWo1c.js"),
149
+ kpiNumber: () => import("./chart-kpi-number-B8u4tWmu.js").then((a) => a.K),
150
+ kpiDelta: () => import("./chart-kpi-delta-BJMQKPor.js"),
151
+ kpiText: () => import("./chart-kpi-text--r1d4zAz.js"),
152
152
  markdown: () => import("./chart-markdown-CiPhRY9s.js"),
153
- funnel: () => import("./chart-funnel-FvDvq015.js"),
154
- sankey: () => import("./chart-sankey-Dt3KaYrH.js"),
155
- sunburst: () => import("./chart-sunburst-D0Lvdjwu.js"),
156
- heatmap: () => import("./chart-heat-map-GpFE-PFB.js"),
153
+ funnel: () => import("./chart-funnel-DI8RMacf.js"),
154
+ sankey: () => import("./chart-sankey-CpsKerey.js"),
155
+ sunburst: () => import("./chart-sunburst-DSsO2CzY.js"),
156
+ heatmap: () => import("./chart-heat-map-D3xNV9ep.js"),
157
157
  retentionHeatmap: () => import("./RetentionHeatmap-BiqfhGYk.js"),
158
- retentionCombined: () => import("./RetentionCombinedChart-DsWhPI0q.js")
158
+ retentionCombined: () => import("./RetentionCombinedChart-DpEKFYsd.js")
159
159
  };
160
160
  function u(a) {
161
161
  const e = f[a], r = ({ height: n }) => /* @__PURE__ */ t(
@@ -238,4 +238,4 @@ export {
238
238
  v as i,
239
239
  k as p
240
240
  };
241
- //# sourceMappingURL=charts-loader-DCGbL50r.js.map
241
+ //# sourceMappingURL=charts-loader-DpJr9z2e.js.map