drizzle-cube 0.2.5 → 0.2.8

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/client/charts.js +15 -15
  2. package/dist/client/chunks/{chart-activitygridchart-BzL97Vnm.js → chart-activitygridchart-Cz4bEf3V.js} +219 -217
  3. package/dist/client/chunks/chart-activitygridchart-Cz4bEf3V.js.map +1 -0
  4. package/dist/client/chunks/{chart-activitygridchart-config-48WqIofo.js → chart-activitygridchart-config-BngZDVh_.js} +96 -90
  5. package/dist/client/chunks/chart-activitygridchart-config-BngZDVh_.js.map +1 -0
  6. package/dist/client/chunks/{chart-areachart-BtH3SvAM.js → chart-areachart-DLdolSnU.js} +3 -3
  7. package/dist/client/chunks/{chart-areachart-BtH3SvAM.js.map → chart-areachart-DLdolSnU.js.map} +1 -1
  8. package/dist/client/chunks/{chart-areachart-config-D8taXdn1.js → chart-areachart-config-DWN1E5ej.js} +2 -2
  9. package/dist/client/chunks/{chart-areachart-config-D8taXdn1.js.map → chart-areachart-config-DWN1E5ej.js.map} +1 -1
  10. package/dist/client/chunks/chart-barchart-Bdjz8DJp.js +171 -0
  11. package/dist/client/chunks/chart-barchart-Bdjz8DJp.js.map +1 -0
  12. package/dist/client/chunks/{chart-barchart-config-DjRZBtLb.js → chart-barchart-config-DZA0xTns.js} +2 -2
  13. package/dist/client/chunks/{chart-barchart-config-DjRZBtLb.js.map → chart-barchart-config-DZA0xTns.js.map} +1 -1
  14. package/dist/client/chunks/{chart-bubblechart-Lj_PnppP.js → chart-bubblechart-BlQkmqkI.js} +2 -2
  15. package/dist/client/chunks/{chart-bubblechart-Lj_PnppP.js.map → chart-bubblechart-BlQkmqkI.js.map} +1 -1
  16. package/dist/client/chunks/{chart-bubblechart-config-C6ck2qmg.js → chart-bubblechart-config-C79lfDSO.js} +2 -2
  17. package/dist/client/chunks/{chart-bubblechart-config-C6ck2qmg.js.map → chart-bubblechart-config-C79lfDSO.js.map} +1 -1
  18. package/dist/client/chunks/{chart-charttooltip-D9BKscsw.js → chart-charttooltip-k8soCd2n.js} +2 -2
  19. package/dist/client/chunks/{chart-charttooltip-D9BKscsw.js.map → chart-charttooltip-k8soCd2n.js.map} +1 -1
  20. package/dist/client/chunks/chart-datatable-Mo4gYCwa.js +249 -0
  21. package/dist/client/chunks/chart-datatable-Mo4gYCwa.js.map +1 -0
  22. package/dist/client/chunks/{chart-datatable-config-B5z0SlOJ.js → chart-datatable-config-DqGw99R3.js} +2 -2
  23. package/dist/client/chunks/{chart-datatable-config-B5z0SlOJ.js.map → chart-datatable-config-DqGw99R3.js.map} +1 -1
  24. package/dist/client/chunks/{chart-kpidelta-Bx-stIIk.js → chart-kpidelta-CTcuIO9G.js} +3 -3
  25. package/dist/client/chunks/{chart-kpidelta-Bx-stIIk.js.map → chart-kpidelta-CTcuIO9G.js.map} +1 -1
  26. package/dist/client/chunks/{chart-kpidelta-config-CnZfi_P2.js → chart-kpidelta-config-B-Y-LHmd.js} +2 -2
  27. package/dist/client/chunks/{chart-kpidelta-config-CnZfi_P2.js.map → chart-kpidelta-config-B-Y-LHmd.js.map} +1 -1
  28. package/dist/client/chunks/{chart-kpinumber-config-CVikHojM.js → chart-kpinumber-config-BaNaJMI6.js} +2 -2
  29. package/dist/client/chunks/{chart-kpinumber-config-CVikHojM.js.map → chart-kpinumber-config-BaNaJMI6.js.map} +1 -1
  30. package/dist/client/chunks/{chart-kpinumber-BrXgyKGP.js → chart-kpinumber-slEXt8C-.js} +5 -5
  31. package/dist/client/chunks/{chart-kpinumber-BrXgyKGP.js.map → chart-kpinumber-slEXt8C-.js.map} +1 -1
  32. package/dist/client/chunks/{chart-kpitext-config-B2MovXSw.js → chart-kpitext-config-BNywYqEW.js} +2 -2
  33. package/dist/client/chunks/{chart-kpitext-config-B2MovXSw.js.map → chart-kpitext-config-BNywYqEW.js.map} +1 -1
  34. package/dist/client/chunks/{chart-kpitext-_2tnYN_z.js → chart-kpitext-giq03TOK.js} +3 -3
  35. package/dist/client/chunks/{chart-kpitext-_2tnYN_z.js.map → chart-kpitext-giq03TOK.js.map} +1 -1
  36. package/dist/client/chunks/{chart-linechart-DBdIULsM.js → chart-linechart-BfnU6L-D.js} +4 -4
  37. package/dist/client/chunks/{chart-linechart-DBdIULsM.js.map → chart-linechart-BfnU6L-D.js.map} +1 -1
  38. package/dist/client/chunks/{chart-linechart-config-CVBVB7nS.js → chart-linechart-config-BL_1mjHF.js} +2 -2
  39. package/dist/client/chunks/{chart-linechart-config-CVBVB7nS.js.map → chart-linechart-config-BL_1mjHF.js.map} +1 -1
  40. package/dist/client/chunks/{chart-markdownchart-config-Cq5Sxrgq.js → chart-markdownchart-config-DtZOfYu4.js} +2 -2
  41. package/dist/client/chunks/{chart-markdownchart-config-Cq5Sxrgq.js.map → chart-markdownchart-config-DtZOfYu4.js.map} +1 -1
  42. package/dist/client/chunks/{chart-piechart-CzesCpZ_.js → chart-piechart-CZRDQxeB.js} +3 -3
  43. package/dist/client/chunks/{chart-piechart-CzesCpZ_.js.map → chart-piechart-CZRDQxeB.js.map} +1 -1
  44. package/dist/client/chunks/{chart-piechart-config-Bdd31Gdi.js → chart-piechart-config-Bg4jeIFo.js} +2 -2
  45. package/dist/client/chunks/{chart-piechart-config-Bdd31Gdi.js.map → chart-piechart-config-Bg4jeIFo.js.map} +1 -1
  46. package/dist/client/chunks/{chart-radarchart-B3WUEiTh.js → chart-radarchart-D5yRnY9j.js} +3 -3
  47. package/dist/client/chunks/{chart-radarchart-B3WUEiTh.js.map → chart-radarchart-D5yRnY9j.js.map} +1 -1
  48. package/dist/client/chunks/{chart-radarchart-config-BWyfn0ij.js → chart-radarchart-config-d6dLkI7B.js} +2 -2
  49. package/dist/client/chunks/{chart-radarchart-config-BWyfn0ij.js.map → chart-radarchart-config-d6dLkI7B.js.map} +1 -1
  50. package/dist/client/chunks/{chart-radialbarchart-DBiRcLd9.js → chart-radialbarchart-Djtcn7aH.js} +3 -3
  51. package/dist/client/chunks/{chart-radialbarchart-DBiRcLd9.js.map → chart-radialbarchart-Djtcn7aH.js.map} +1 -1
  52. package/dist/client/chunks/{chart-radialbarchart-config-lU2_NQCD.js → chart-radialbarchart-config-BGf97-BV.js} +2 -2
  53. package/dist/client/chunks/{chart-radialbarchart-config-lU2_NQCD.js.map → chart-radialbarchart-config-BGf97-BV.js.map} +1 -1
  54. package/dist/client/chunks/{chart-scatterchart-C_D9OqA1.js → chart-scatterchart-C83KgqYY.js} +2 -2
  55. package/dist/client/chunks/{chart-scatterchart-C_D9OqA1.js.map → chart-scatterchart-C83KgqYY.js.map} +1 -1
  56. package/dist/client/chunks/{chart-scatterchart-config-DtLnut1M.js → chart-scatterchart-config-DEIB74ot.js} +2 -2
  57. package/dist/client/chunks/{chart-scatterchart-config-DtLnut1M.js.map → chart-scatterchart-config-DEIB74ot.js.map} +1 -1
  58. package/dist/client/chunks/{chart-treemapchart-DJqy3Sy7.js → chart-treemapchart-BDKnKGTz.js} +3 -3
  59. package/dist/client/chunks/{chart-treemapchart-DJqy3Sy7.js.map → chart-treemapchart-BDKnKGTz.js.map} +1 -1
  60. package/dist/client/chunks/{chart-treemapchart-config-BEiIWQnR.js → chart-treemapchart-config-ppKPTB96.js} +2 -2
  61. package/dist/client/chunks/{chart-treemapchart-config-BEiIWQnR.js.map → chart-treemapchart-config-ppKPTB96.js.map} +1 -1
  62. package/dist/client/chunks/{charts-DFbr7EGW.js → charts-MJLpxe3r.js} +42 -42
  63. package/dist/client/chunks/{charts-DFbr7EGW.js.map → charts-MJLpxe3r.js.map} +1 -1
  64. package/dist/client/chunks/components-CXA6-jJq.js +9845 -0
  65. package/dist/client/chunks/components-CXA6-jJq.js.map +1 -0
  66. package/dist/client/chunks/{icons-D6z-_9sa.js → icons-B2XSxpVK.js} +213 -181
  67. package/dist/client/chunks/icons-B2XSxpVK.js.map +1 -0
  68. package/dist/client/chunks/{index-_pVwmFVW.js → index-CSeLP8gq.js} +2 -2
  69. package/dist/client/chunks/{index-_pVwmFVW.js.map → index-CSeLP8gq.js.map} +1 -1
  70. package/dist/client/components/AnalysisBuilder/AnalysisAxisDropZone.d.ts +27 -0
  71. package/dist/client/components/AnalysisBuilder/AnalysisChartConfigPanel.d.ts +21 -0
  72. package/dist/client/components/AnalysisBuilder/AnalysisFilterGroup.d.ts +20 -0
  73. package/dist/client/components/AnalysisBuilder/AnalysisFilterItem.d.ts +16 -0
  74. package/dist/client/components/AnalysisBuilder/AnalysisFilterSection.d.ts +12 -0
  75. package/dist/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +10 -0
  76. package/dist/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +12 -0
  77. package/dist/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +10 -0
  78. package/dist/client/components/AnalysisBuilder/BreakdownSection.d.ts +8 -0
  79. package/dist/client/components/AnalysisBuilder/FieldDetailPanel.d.ts +4 -0
  80. package/dist/client/components/AnalysisBuilder/FieldSearchItem.d.ts +6 -0
  81. package/dist/client/components/AnalysisBuilder/FieldSearchModal.d.ts +2 -0
  82. package/dist/client/components/AnalysisBuilder/MetricItemCard.d.ts +9 -0
  83. package/dist/client/components/AnalysisBuilder/MetricsSection.d.ts +8 -0
  84. package/dist/client/components/AnalysisBuilder/index.d.ts +3 -0
  85. package/dist/client/components/AnalysisBuilder/types.d.ts +366 -0
  86. package/dist/client/components/AnalysisBuilder/utils.d.ts +103 -0
  87. package/dist/client/components/ChartTypeSelector.d.ts +6 -1
  88. package/dist/client/components/DashboardGrid.d.ts +3 -2
  89. package/dist/client/components/DashboardPortletCard.d.ts +63 -0
  90. package/dist/client/components/QueryBuilder/CubeMetaExplorer.d.ts +2 -2
  91. package/dist/client/components/QueryBuilder/QueryPanel.d.ts +2 -2
  92. package/dist/client/components/QueryBuilder/types.d.ts +7 -138
  93. package/dist/client/components/RowManagedLayout.d.ts +19 -0
  94. package/dist/client/components/charts/DataTable.d.ts +1 -1
  95. package/dist/client/components.js +16 -9148
  96. package/dist/client/components.js.map +1 -1
  97. package/dist/client/hooks.js +2 -2
  98. package/dist/client/icons/types.d.ts +6 -0
  99. package/dist/client/icons.js +1 -1
  100. package/dist/client/index.d.ts +1 -0
  101. package/dist/client/index.js +3202 -49
  102. package/dist/client/index.js.map +1 -1
  103. package/dist/client/providers/CubeProvider.d.ts +4 -2
  104. package/dist/client/providers.js +1 -1
  105. package/dist/client/shared/chartDefaults.d.ts +64 -0
  106. package/dist/client/shared/components/QueryAnalysisPanel.d.ts +7 -0
  107. package/dist/client/shared/index.d.ts +10 -0
  108. package/dist/client/shared/types.d.ts +134 -0
  109. package/dist/client/shared/utils.d.ts +101 -0
  110. package/dist/client/styles.css +1 -1
  111. package/dist/client/types.d.ts +20 -0
  112. package/dist/client/utils/index.d.ts +1 -0
  113. package/dist/client/utils/pivotUtils.d.ts +78 -0
  114. package/dist/client-bundle-stats.html +1 -1
  115. package/package.json +1 -1
  116. package/dist/client/chunks/chart-activitygridchart-BzL97Vnm.js.map +0 -1
  117. package/dist/client/chunks/chart-activitygridchart-config-48WqIofo.js.map +0 -1
  118. package/dist/client/chunks/chart-barchart-DX6DIoIp.js +0 -177
  119. package/dist/client/chunks/chart-barchart-DX6DIoIp.js.map +0 -1
  120. package/dist/client/chunks/chart-datatable-BaECYDn2.js +0 -57
  121. package/dist/client/chunks/chart-datatable-BaECYDn2.js.map +0 -1
  122. package/dist/client/chunks/icons-D6z-_9sa.js.map +0 -1
@@ -0,0 +1,249 @@
1
+ import { jsx as r, jsxs as m } from "react/jsx-runtime";
2
+ import { useMemo as y } from "react";
3
+ import { c as N, u as k } from "./chart-activitygridchart-Cz4bEf3V.js";
4
+ import { a as C } from "./chart-activitygridchart-config-BngZDVh_.js";
5
+ function D(e) {
6
+ if (!e?.timeDimensions?.length) return null;
7
+ const t = e.timeDimensions.find((a) => a.granularity);
8
+ return !t?.granularity || !e.measures?.length ? null : {
9
+ timeDimension: t.dimension,
10
+ granularity: t.granularity,
11
+ dimensions: e.dimensions || [],
12
+ measures: e.measures
13
+ };
14
+ }
15
+ function S(e, t, a) {
16
+ const i = /* @__PURE__ */ new Set();
17
+ return e.forEach((n) => {
18
+ const s = n[t];
19
+ if (s != null) {
20
+ const o = N(s, a);
21
+ i.add(o);
22
+ }
23
+ }), Array.from(i).sort();
24
+ }
25
+ function P(e, t, a) {
26
+ const i = [];
27
+ return e.measures.length > 1 && i.push({
28
+ key: "__measure__",
29
+ label: "Measure",
30
+ isTimeColumn: !1,
31
+ isMeasureColumn: !0
32
+ }), e.dimensions.forEach((n) => {
33
+ i.push({
34
+ key: n,
35
+ label: a(n),
36
+ isTimeColumn: !1
37
+ });
38
+ }), t.forEach((n) => {
39
+ i.push({
40
+ key: n,
41
+ label: n,
42
+ isTimeColumn: !0
43
+ });
44
+ }), i;
45
+ }
46
+ function M(e, t) {
47
+ const a = /* @__PURE__ */ new Map();
48
+ return e.forEach((i) => {
49
+ const n = t.dimensions.length > 0 ? t.dimensions.map((o) => String(i[o] ?? "")).join("|") : "__all__";
50
+ a.has(n) || a.set(n, /* @__PURE__ */ new Map());
51
+ const s = i[t.timeDimension];
52
+ if (s != null) {
53
+ const o = N(s, t.granularity);
54
+ a.get(n).set(o, i);
55
+ }
56
+ }), a;
57
+ }
58
+ function E(e, t, a, i) {
59
+ const n = M(e, t), s = Array.from(n.keys()), o = [], l = t.measures.length, d = s.length;
60
+ return t.measures.forEach((c) => {
61
+ s.forEach((u, v) => {
62
+ const w = n.get(u), g = l > 1 ? `${c}|${u}` : u, f = {}, T = u === "__all__" ? [] : u.split("|");
63
+ t.dimensions.forEach((p, x) => {
64
+ f[p] = T[x] ?? "";
65
+ }), l > 1 && (f.__measure__ = i(c)), a.forEach((p) => {
66
+ const x = w.get(p);
67
+ f[p] = x?.[c] ?? null;
68
+ });
69
+ const h = v === 0, _ = h && l > 1 ? d : void 0;
70
+ o.push({
71
+ id: g,
72
+ measureField: c,
73
+ values: f,
74
+ isFirstInGroup: h,
75
+ dimensionRowSpan: _
76
+ });
77
+ });
78
+ }), o;
79
+ }
80
+ function F(e, t, a, i) {
81
+ if (!e || e.length === 0)
82
+ return { isPivoted: !0, columns: [], rows: [] };
83
+ const n = S(e, t.timeDimension, t.granularity), s = P(t, n, a), o = E(e, t, n, a);
84
+ return { isPivoted: !0, columns: s, rows: o };
85
+ }
86
+ function A(e, t) {
87
+ if (t?.cubes)
88
+ for (const a of t.cubes) {
89
+ const i = a.measures.find((n) => n.name === e);
90
+ if (i)
91
+ return i.type;
92
+ }
93
+ }
94
+ function B({
95
+ data: e,
96
+ chartConfig: t,
97
+ displayConfig: a = {},
98
+ queryObject: i,
99
+ height: n = 300
100
+ }) {
101
+ const { getFieldLabel: s, meta: o } = k(), l = y(
102
+ () => D(i),
103
+ [i]
104
+ ), d = a?.pivotTimeDimension !== !1, c = y(() => !l || !d ? null : F(e, l, s), [e, l, d, s, o]);
105
+ return !e || e.length === 0 ? /* @__PURE__ */ r(
106
+ "div",
107
+ {
108
+ className: "flex items-center justify-center w-full",
109
+ style: { height: n },
110
+ children: /* @__PURE__ */ m("div", { className: "text-center text-dc-text-muted", children: [
111
+ /* @__PURE__ */ r("div", { className: "text-sm font-semibold mb-1", children: "No data available" }),
112
+ /* @__PURE__ */ r("div", { className: "text-xs text-dc-text-secondary", children: "No data to display in table" })
113
+ ] })
114
+ }
115
+ ) : c?.isPivoted && c.columns.length > 0 ? /* @__PURE__ */ r(
116
+ I,
117
+ {
118
+ pivotedData: c,
119
+ height: n,
120
+ meta: o
121
+ }
122
+ ) : /* @__PURE__ */ r(
123
+ V,
124
+ {
125
+ data: e,
126
+ chartConfig: t,
127
+ height: n,
128
+ getFieldLabel: s
129
+ }
130
+ );
131
+ }
132
+ function I({
133
+ pivotedData: e,
134
+ height: t,
135
+ meta: a
136
+ }) {
137
+ const { columns: i, rows: n } = e;
138
+ return i.length === 0 || n.length === 0 ? /* @__PURE__ */ r(
139
+ "div",
140
+ {
141
+ className: "flex items-center justify-center w-full",
142
+ style: { height: t },
143
+ children: /* @__PURE__ */ m("div", { className: "text-center text-dc-text-muted", children: [
144
+ /* @__PURE__ */ r("div", { className: "text-sm font-semibold mb-1", children: "No data available" }),
145
+ /* @__PURE__ */ r("div", { className: "text-xs text-dc-text-secondary", children: "No data to display in table" })
146
+ ] })
147
+ }
148
+ ) : /* @__PURE__ */ r("div", { className: "w-full overflow-auto", style: { height: t }, children: /* @__PURE__ */ m("table", { className: "min-w-full divide-y border-dc-border", children: [
149
+ /* @__PURE__ */ r("thead", { className: "bg-dc-surface-secondary sticky top-0", children: /* @__PURE__ */ r("tr", { children: i.map((s) => /* @__PURE__ */ r(
150
+ "th",
151
+ {
152
+ className: `px-3 py-2 text-xs font-medium text-dc-text-muted uppercase tracking-wider whitespace-nowrap ${s.isTimeColumn ? "text-right" : "text-left"}`,
153
+ children: s.label
154
+ },
155
+ s.key
156
+ )) }) }),
157
+ /* @__PURE__ */ r("tbody", { className: "bg-dc-surface divide-y border-dc-border", children: n.map((s) => /* @__PURE__ */ r(
158
+ R,
159
+ {
160
+ row: s,
161
+ columns: i,
162
+ meta: a
163
+ },
164
+ s.id
165
+ )) })
166
+ ] }) });
167
+ }
168
+ function R({
169
+ row: e,
170
+ columns: t,
171
+ meta: a
172
+ }) {
173
+ const i = A(e.measureField, a), n = C(i);
174
+ return /* @__PURE__ */ r("tr", { className: "hover:bg-dc-surface-secondary", children: t.map((s) => {
175
+ const o = e.values[s.key];
176
+ return s.isMeasureColumn ? e.isFirstInGroup === !1 ? null : /* @__PURE__ */ r(
177
+ "td",
178
+ {
179
+ className: "px-3 py-2 whitespace-nowrap text-sm text-dc-text align-top",
180
+ rowSpan: e.dimensionRowSpan,
181
+ children: /* @__PURE__ */ m("div", { className: "flex items-center", children: [
182
+ /* @__PURE__ */ r(n, { className: "w-3.5 h-3.5 mr-1.5 text-dc-text-muted shrink-0" }),
183
+ /* @__PURE__ */ r("span", { children: o })
184
+ ] })
185
+ },
186
+ s.key
187
+ ) : s.isTimeColumn ? /* @__PURE__ */ r(
188
+ "td",
189
+ {
190
+ className: "px-3 py-2 whitespace-nowrap text-sm text-right text-dc-text",
191
+ children: b(o)
192
+ },
193
+ s.key
194
+ ) : /* @__PURE__ */ r(
195
+ "td",
196
+ {
197
+ className: "px-3 py-2 whitespace-nowrap text-sm text-dc-text",
198
+ children: b(o)
199
+ },
200
+ s.key
201
+ );
202
+ }) });
203
+ }
204
+ function b(e) {
205
+ return e == null ? "-" : typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : parseFloat(e.toFixed(2)).toLocaleString() : typeof e == "boolean" ? e ? "Yes" : "No" : String(e);
206
+ }
207
+ function V({
208
+ data: e,
209
+ chartConfig: t,
210
+ height: a,
211
+ getFieldLabel: i
212
+ }) {
213
+ const n = Object.keys(e[0] || {}), s = t?.xAxis && t.xAxis.length > 0 ? t.xAxis.filter((o) => n.includes(o)) : n;
214
+ return s.length === 0 ? /* @__PURE__ */ r(
215
+ "div",
216
+ {
217
+ className: "flex items-center justify-center w-full",
218
+ style: { height: a },
219
+ children: /* @__PURE__ */ m("div", { className: "text-center text-dc-text-muted", children: [
220
+ /* @__PURE__ */ r("div", { className: "text-sm font-semibold mb-1", children: "No columns available" }),
221
+ /* @__PURE__ */ r("div", { className: "text-xs text-dc-text-secondary", children: "Data structure is invalid" })
222
+ ] })
223
+ }
224
+ ) : /* @__PURE__ */ r("div", { className: "w-full overflow-auto", style: { height: a }, children: /* @__PURE__ */ m("table", { className: "min-w-full divide-y border-dc-border", children: [
225
+ /* @__PURE__ */ r("thead", { className: "bg-dc-surface-secondary sticky top-0", children: /* @__PURE__ */ r("tr", { children: s.map((o) => /* @__PURE__ */ r(
226
+ "th",
227
+ {
228
+ className: "px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider",
229
+ children: i(o)
230
+ },
231
+ o
232
+ )) }) }),
233
+ /* @__PURE__ */ r("tbody", { className: "bg-dc-surface divide-y border-dc-border", children: e.map((o, l) => /* @__PURE__ */ r("tr", { className: "hover:bg-dc-surface-secondary", children: s.map((d) => /* @__PURE__ */ r(
234
+ "td",
235
+ {
236
+ className: "px-3 py-2 whitespace-nowrap text-sm text-dc-text",
237
+ children: L(o[d])
238
+ },
239
+ d
240
+ )) }, l)) })
241
+ ] }) });
242
+ }
243
+ function L(e) {
244
+ return e == null ? "" : typeof e == "number" ? e.toLocaleString() : typeof e == "boolean" ? e ? "Yes" : "No" : String(e);
245
+ }
246
+ export {
247
+ B as default
248
+ };
249
+ //# sourceMappingURL=chart-datatable-Mo4gYCwa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-datatable-Mo4gYCwa.js","sources":["../../../src/client/utils/pivotUtils.ts","../../../src/client/components/charts/DataTable.tsx"],"sourcesContent":["/**\n * Pivot utilities for DataTable time dimension pivoting\n *\n * When a query includes a time dimension with granularity, transforms flat data\n * into a pivoted structure with time periods as columns.\n */\n\nimport type { CubeQuery } from '../types'\nimport type { CubeMeta } from '../hooks/useCubeMeta'\nimport { formatTimeValue } from './chartUtils'\n\n/**\n * Configuration for pivoting based on query structure\n */\nexport interface PivotConfig {\n /** Time dimension field name (e.g., \"Sales.date\") */\n timeDimension: string\n /** Time granularity (e.g., \"month\", \"day\", \"year\") */\n granularity: string\n /** Non-time dimension fields */\n dimensions: string[]\n /** Measure fields */\n measures: string[]\n}\n\n/**\n * Column definition for pivoted table\n */\nexport interface PivotColumn {\n /** Column key for data access */\n key: string\n /** Display label for column header */\n label: string\n /** Whether this is a time column (vs row identifier column) */\n isTimeColumn: boolean\n /** Whether this is the measure column */\n isMeasureColumn?: boolean\n}\n\n/**\n * Row in the pivoted table\n */\nexport interface PivotRow {\n /** Unique row identifier */\n id: string\n /** The measure field name (for icon lookup) */\n measureField: string\n /** Values keyed by column key */\n values: Record<string, any>\n /** Whether this is the first row in a dimension group (for row spanning) */\n isFirstInGroup?: boolean\n /** Number of rows to span for dimension cells (only set on first row in group) */\n dimensionRowSpan?: number\n}\n\n/**\n * Result of pivoting table data\n */\nexport interface PivotedTableData {\n /** Whether data was pivoted (has time dimension with granularity) */\n isPivoted: boolean\n /** Column definitions for the pivoted table */\n columns: PivotColumn[]\n /** Rows of pivoted data */\n rows: PivotRow[]\n}\n\n/**\n * Determines if a query has a time dimension with granularity that should trigger pivoting\n * @param queryObject The CubeQuery object\n * @returns PivotConfig if pivoting should occur, null otherwise\n */\nexport function hasTimeDimensionForPivot(queryObject?: CubeQuery): PivotConfig | null {\n if (!queryObject?.timeDimensions?.length) return null\n\n // Find the first time dimension with granularity\n const timeDim = queryObject.timeDimensions.find(td => td.granularity)\n if (!timeDim?.granularity) return null\n\n // Must have at least one measure to pivot\n if (!queryObject.measures?.length) return null\n\n return {\n timeDimension: timeDim.dimension,\n granularity: timeDim.granularity,\n dimensions: queryObject.dimensions || [],\n measures: queryObject.measures\n }\n}\n\n/**\n * Extracts unique time values from data and sorts them chronologically\n */\nfunction extractAndSortTimeValues(\n data: any[],\n timeDimension: string,\n granularity: string\n): string[] {\n const timeSet = new Set<string>()\n\n data.forEach(row => {\n const rawTime = row[timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, granularity)\n timeSet.add(formattedTime)\n }\n })\n\n // Sort chronologically - ISO date strings sort correctly alphabetically\n return Array.from(timeSet).sort()\n}\n\n/**\n * Builds column definitions for pivoted table\n * Order: Measure (if multiple) -> Dimensions -> Time columns\n */\nfunction buildColumns(\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotColumn[] {\n const columns: PivotColumn[] = []\n\n // Add measure column first (if multiple measures)\n if (config.measures.length > 1) {\n columns.push({\n key: '__measure__',\n label: 'Measure',\n isTimeColumn: false,\n isMeasureColumn: true\n })\n }\n\n // Add dimension columns\n config.dimensions.forEach(dim => {\n columns.push({\n key: dim,\n label: getFieldLabel(dim),\n isTimeColumn: false\n })\n })\n\n // Add time columns (already sorted chronologically)\n timeValues.forEach(timeVal => {\n columns.push({\n key: timeVal,\n label: timeVal,\n isTimeColumn: true\n })\n })\n\n return columns\n}\n\n/**\n * Groups data by dimension values, then by time period\n * Returns Map<dimensionKey, Map<formattedTime, dataRow>>\n */\nfunction groupByDimensions(\n data: any[],\n config: PivotConfig\n): Map<string, Map<string, any>> {\n const grouped = new Map<string, Map<string, any>>()\n\n data.forEach(row => {\n // Build dimension key from all dimension values\n const dimKey = config.dimensions.length > 0\n ? config.dimensions.map(dim => String(row[dim] ?? '')).join('|')\n : '__all__'\n\n // Get or create time map for this dimension combo\n if (!grouped.has(dimKey)) {\n grouped.set(dimKey, new Map())\n }\n\n // Store data point by formatted time value\n const rawTime = row[config.timeDimension]\n if (rawTime != null) {\n const formattedTime = formatTimeValue(rawTime, config.granularity)\n grouped.get(dimKey)!.set(formattedTime, row)\n }\n })\n\n return grouped\n}\n\n/**\n * Builds pivoted rows from grouped data\n * Rows are grouped by measure first (all Revenue rows together, all Quantity rows together)\n * Then within each measure group, rows are ordered by dimension values\n */\nfunction buildPivotedRows(\n data: any[],\n config: PivotConfig,\n timeValues: string[],\n getFieldLabel: (field: string) => string\n): PivotRow[] {\n // Group data by dimensions and time\n const grouped = groupByDimensions(data, config)\n const dimensionKeys = Array.from(grouped.keys())\n\n const rows: PivotRow[] = []\n const measureCount = config.measures.length\n const dimensionCount = dimensionKeys.length\n\n // Iterate over measures first, then dimensions\n // This groups all rows for one measure together\n config.measures.forEach((measure) => {\n dimensionKeys.forEach((dimensionKey, dimIndex) => {\n const timeData = grouped.get(dimensionKey)!\n const rowId = measureCount > 1\n ? `${measure}|${dimensionKey}`\n : dimensionKey\n\n const values: Record<string, any> = {}\n\n // Add dimension values\n const dimValues = dimensionKey === '__all__' ? [] : dimensionKey.split('|')\n config.dimensions.forEach((dim, idx) => {\n values[dim] = dimValues[idx] ?? ''\n })\n\n // Add measure name if multiple measures (for display in Measure column)\n if (measureCount > 1) {\n values['__measure__'] = getFieldLabel(measure)\n }\n\n // Add time period values\n timeValues.forEach(timeVal => {\n const dataPoint = timeData.get(timeVal)\n values[timeVal] = dataPoint?.[measure] ?? null\n })\n\n // Track grouping for row spanning (when multiple measures)\n // First row of each measure group should span all dimension rows\n const isFirstInGroup = dimIndex === 0\n const measureRowSpan = isFirstInGroup && measureCount > 1 ? dimensionCount : undefined\n\n rows.push({\n id: rowId,\n measureField: measure,\n values,\n isFirstInGroup,\n dimensionRowSpan: measureRowSpan\n })\n })\n })\n\n return rows\n}\n\n/**\n * Pivots flat data into time-columned table structure\n *\n * @param data Raw data array from query result\n * @param config Pivot configuration\n * @param getFieldLabel Function to get display label for a field\n * @param meta Optional cube metadata for looking up measure types\n * @returns Pivoted table data structure\n */\nexport function pivotTableData(\n data: any[],\n config: PivotConfig,\n getFieldLabel: (field: string) => string,\n _meta?: CubeMeta | null\n): PivotedTableData {\n if (!data || data.length === 0) {\n return { isPivoted: true, columns: [], rows: [] }\n }\n\n // Extract unique time values and sort chronologically\n const timeValues = extractAndSortTimeValues(data, config.timeDimension, config.granularity)\n\n // Build column definitions\n const columns = buildColumns(config, timeValues, getFieldLabel)\n\n // Build pivoted rows\n const rows = buildPivotedRows(data, config, timeValues, getFieldLabel)\n\n return { isPivoted: true, columns, rows }\n}\n\n/**\n * Looks up the measure type from metadata\n *\n * @param measureField The fully qualified measure field name (e.g., \"Sales.revenue\")\n * @param meta Cube metadata\n * @returns The measure type (e.g., \"sum\", \"count\", \"avg\") or undefined\n */\nexport function getMeasureType(measureField: string, meta: CubeMeta | null): string | undefined {\n if (!meta?.cubes) return undefined\n\n for (const cube of meta.cubes) {\n const measure = cube.measures.find(m => m.name === measureField)\n if (measure) {\n return measure.type\n }\n }\n\n return undefined\n}\n","/**\n * Data Table component with time dimension pivoting\n *\n * When a query includes a time dimension with granularity, the table\n * automatically pivots to show time periods as columns.\n */\n\nimport { useMemo } from 'react'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { getMeasureTypeIcon } from '../../icons'\nimport {\n hasTimeDimensionForPivot,\n pivotTableData,\n getMeasureType,\n type PivotedTableData,\n type PivotColumn,\n type PivotRow\n} from '../../utils/pivotUtils'\nimport type { ChartProps } from '../../types'\n\nexport default function DataTable({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = 300\n}: ChartProps) {\n const { getFieldLabel, meta } = useCubeContext()\n\n // Detect if we should pivot based on query structure\n const pivotConfig = useMemo(\n () => hasTimeDimensionForPivot(queryObject),\n [queryObject]\n )\n\n // Check if pivoting is enabled (default: true when time dimension present)\n const enablePivot = displayConfig?.pivotTimeDimension !== false\n\n // Compute pivoted data if applicable\n const pivotedData = useMemo<PivotedTableData | null>(() => {\n if (!pivotConfig || !enablePivot) return null\n return pivotTableData(data, pivotConfig, getFieldLabel, meta)\n }, [data, pivotConfig, enablePivot, getFieldLabel, meta])\n\n // Empty state\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n // Render pivoted table if applicable\n if (pivotedData?.isPivoted && pivotedData.columns.length > 0) {\n return (\n <PivotedTable\n pivotedData={pivotedData}\n height={height}\n meta={meta}\n />\n )\n }\n\n // Fallback to flat table rendering\n return (\n <FlatTable\n data={data}\n chartConfig={chartConfig}\n height={height}\n getFieldLabel={getFieldLabel}\n />\n )\n}\n\n/**\n * Pivoted table component - renders time dimension as columns\n */\nfunction PivotedTable({\n pivotedData,\n height,\n meta\n}: {\n pivotedData: PivotedTableData\n height: number | string\n meta: any\n}) {\n const { columns, rows } = pivotedData\n\n if (columns.length === 0 || rows.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data to display in table</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((col: PivotColumn) => (\n <th\n key={col.key}\n className={`px-3 py-2 text-xs font-medium text-dc-text-muted uppercase tracking-wider whitespace-nowrap ${\n col.isTimeColumn ? 'text-right' : 'text-left'\n }`}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {rows.map((row: PivotRow) => (\n <PivotedTableRow\n key={row.id}\n row={row}\n columns={columns}\n meta={meta}\n />\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Single row in the pivoted table\n * Supports row spanning for measure cells when grouped by measure\n */\nfunction PivotedTableRow({\n row,\n columns,\n meta\n}: {\n row: PivotRow\n columns: PivotColumn[]\n meta: any\n}) {\n // Get measure icon for this row\n const measureType = getMeasureType(row.measureField, meta)\n const MeasureIcon = getMeasureTypeIcon(measureType)\n\n return (\n <tr className=\"hover:bg-dc-surface-secondary\">\n {columns.map((col: PivotColumn) => {\n const value = row.values[col.key]\n\n // Measure column - show icon + label with row spanning\n if (col.isMeasureColumn) {\n // Skip this cell if not first in measure group\n if (row.isFirstInGroup === false) {\n return null\n }\n\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text align-top\"\n rowSpan={row.dimensionRowSpan}\n >\n <div className=\"flex items-center\">\n <MeasureIcon className=\"w-3.5 h-3.5 mr-1.5 text-dc-text-muted shrink-0\" />\n <span>{value}</span>\n </div>\n </td>\n )\n }\n\n // Time column - right-aligned, formatted values\n if (col.isTimeColumn) {\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-right text-dc-text\"\n >\n {formatPivotCellValue(value)}\n </td>\n )\n }\n\n // Dimension column - left-aligned (no row spanning)\n return (\n <td\n key={col.key}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatPivotCellValue(value)}\n </td>\n )\n })}\n </tr>\n )\n}\n\n/**\n * Format cell value for pivoted table display\n * Shows \"-\" for null/undefined values\n */\nfunction formatPivotCellValue(value: any): string {\n if (value === null || value === undefined) return '-'\n if (typeof value === 'number') {\n // Format with locale and up to 2 decimal places\n if (Number.isInteger(value)) {\n return value.toLocaleString()\n }\n return parseFloat(value.toFixed(2)).toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n\n/**\n * Flat table component - original non-pivoted table rendering\n */\nfunction FlatTable({\n data,\n chartConfig,\n height,\n getFieldLabel\n}: {\n data: any[]\n chartConfig?: { xAxis?: string[] }\n height: number | string\n getFieldLabel: (field: string) => string\n}) {\n // Use chartConfig.xAxis to filter columns, or show all if not specified\n const allColumns = Object.keys(data[0] || {})\n const columns = chartConfig?.xAxis && chartConfig.xAxis.length > 0\n ? chartConfig.xAxis.filter(col => allColumns.includes(col))\n : allColumns\n\n if (columns.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full\"\n style={{ height }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No columns available</div>\n <div className=\"text-xs text-dc-text-secondary\">Data structure is invalid</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full overflow-auto\" style={{ height }}>\n <table className=\"min-w-full divide-y border-dc-border\">\n <thead className=\"bg-dc-surface-secondary sticky top-0\">\n <tr>\n {columns.map((column) => (\n <th\n key={column}\n className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\"\n >\n {getFieldLabel(column)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"bg-dc-surface divide-y border-dc-border\">\n {data.map((row, index) => (\n <tr key={index} className=\"hover:bg-dc-surface-secondary\">\n {columns.map((column) => (\n <td\n key={column}\n className=\"px-3 py-2 whitespace-nowrap text-sm text-dc-text\"\n >\n {formatCellValue(row[column])}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * Format cell value for flat table display\n */\nfunction formatCellValue(value: any): string {\n if (value == null) return ''\n if (typeof value === 'number') {\n return value.toLocaleString()\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No'\n }\n return String(value)\n}\n"],"names":["hasTimeDimensionForPivot","queryObject","timeDim","td","extractAndSortTimeValues","data","timeDimension","granularity","timeSet","row","rawTime","formattedTime","formatTimeValue","buildColumns","config","timeValues","getFieldLabel","columns","dim","timeVal","groupByDimensions","grouped","dimKey","buildPivotedRows","dimensionKeys","rows","measureCount","dimensionCount","measure","dimensionKey","dimIndex","timeData","rowId","values","dimValues","idx","dataPoint","isFirstInGroup","measureRowSpan","pivotTableData","_meta","getMeasureType","measureField","meta","cube","m","DataTable","chartConfig","displayConfig","height","useCubeContext","pivotConfig","useMemo","enablePivot","pivotedData","jsx","jsxs","PivotedTable","FlatTable","col","PivotedTableRow","measureType","MeasureIcon","getMeasureTypeIcon","value","formatPivotCellValue","allColumns","column","index","formatCellValue"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { g as e } from "./chart-activitygridchart-config-48WqIofo.js";
1
+ import { g as e } from "./chart-activitygridchart-config-BngZDVh_.js";
2
2
  const s = {
3
3
  icon: e("table"),
4
4
  description: "Display detailed tabular data",
@@ -18,4 +18,4 @@ const s = {
18
18
  export {
19
19
  s as dataTableConfig
20
20
  };
21
- //# sourceMappingURL=chart-datatable-config-B5z0SlOJ.js.map
21
+ //# sourceMappingURL=chart-datatable-config-DqGw99R3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-datatable-config-B5z0SlOJ.js","sources":["../../../src/client/components/charts/DataTable.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the data table type\n */\nexport const dataTableConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('table'),\n description: 'Display detailed tabular data',\n useCase: 'Best for precise values, detailed analysis, sortable/filterable data exploration',\n dropZones: [\n {\n key: 'xAxis',\n label: 'Columns',\n description: 'All fields to display as columns',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'Drop fields to display as columns (or leave empty for all)'\n }\n ],\n displayOptions: ['hideHeader']\n}"],"names":["dataTableConfig","getChartTypeIcon"],"mappings":";AAMO,MAAMA,IAAmC;AAAA,EAC9C,MAAMC,EAAiB,OAAO;AAAA,EAC9B,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,aAAa,CAAC,aAAa,iBAAiB,SAAS;AAAA,MACrD,WAAW;AAAA,IAAA;AAAA,EACb;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAC/B;"}
1
+ {"version":3,"file":"chart-datatable-config-DqGw99R3.js","sources":["../../../src/client/components/charts/DataTable.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the data table type\n */\nexport const dataTableConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('table'),\n description: 'Display detailed tabular data',\n useCase: 'Best for precise values, detailed analysis, sortable/filterable data exploration',\n dropZones: [\n {\n key: 'xAxis',\n label: 'Columns',\n description: 'All fields to display as columns',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'Drop fields to display as columns (or leave empty for all)'\n }\n ],\n displayOptions: ['hideHeader']\n}"],"names":["dataTableConfig","getChartTypeIcon"],"mappings":";AAMO,MAAMA,IAAmC;AAAA,EAC9C,MAAMC,EAAiB,OAAO;AAAA,EAC9B,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,aAAa,CAAC,aAAa,iBAAiB,SAAS;AAAA,MACrD,WAAW;AAAA,IAAA;AAAA,EACb;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAC/B;"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as a, jsxs as c } from "react/jsx-runtime";
2
2
  import { useState as K, useRef as _, useEffect as te } from "react";
3
- import { a6 as ne, k as se } from "./icons-D6z-_9sa.js";
4
- import { u as re } from "./chart-activitygridchart-BzL97Vnm.js";
3
+ import { ac as ne, k as se } from "./icons-B2XSxpVK.js";
4
+ import { u as re } from "./chart-activitygridchart-Cz4bEf3V.js";
5
5
  function ie(s, r) {
6
6
  const e = new Date(s);
7
7
  switch (r.toLowerCase()) {
@@ -431,4 +431,4 @@ export {
431
431
  pe as K,
432
432
  ce as f
433
433
  };
434
- //# sourceMappingURL=chart-kpidelta-Bx-stIIk.js.map
434
+ //# sourceMappingURL=chart-kpidelta-CTcuIO9G.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-kpidelta-Bx-stIIk.js","sources":["../../../src/client/utils/periodUtils.ts","../../../src/client/components/charts/KpiDelta.tsx"],"sourcesContent":["/**\n * Utility functions for detecting incomplete time periods in KPI charts\n */\n\n/**\n * Get the end date of a period based on granularity\n * @param date - The date within the period\n * @param granularity - The time granularity (day, week, month, quarter, year)\n * @returns The end date of the period (end of day)\n */\nexport function getPeriodEndDate(date: Date, granularity: string): Date {\n const endDate = new Date(date)\n\n switch (granularity.toLowerCase()) {\n case 'day':\n // End of the same day\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'week':\n // End of the week (Saturday, assuming week starts Sunday)\n const dayOfWeek = endDate.getDay()\n const daysUntilSaturday = 6 - dayOfWeek\n endDate.setDate(endDate.getDate() + daysUntilSaturday)\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'month':\n // Last day of the month\n endDate.setMonth(endDate.getMonth() + 1, 0) // Set to day 0 of next month = last day of current month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'quarter':\n // Last day of the quarter\n const currentMonth = endDate.getMonth()\n const quarterEndMonth = Math.floor(currentMonth / 3) * 3 + 2 // 0->2, 3->5, 6->8, 9->11\n endDate.setMonth(quarterEndMonth + 1, 0) // Last day of quarter end month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'year':\n // December 31st\n endDate.setMonth(11, 31) // December 31\n endDate.setHours(23, 59, 59, 999)\n break\n\n default:\n // Unknown granularity - treat as complete\n endDate.setHours(23, 59, 59, 999)\n }\n\n return endDate\n}\n\n/**\n * Check if the last period in the data is complete based on granularity\n * @param lastDataPoint - The last data point in the sorted dataset\n * @param timeDimensionField - The field name containing the time value\n * @param granularity - The time granularity\n * @returns true if the period is complete, false if it's incomplete\n */\nexport function isLastPeriodComplete(\n lastDataPoint: any,\n timeDimensionField: string,\n granularity: string\n): boolean {\n if (!lastDataPoint || !timeDimensionField || !granularity) {\n return true // Assume complete if we can't determine\n }\n\n const timeValue = lastDataPoint[timeDimensionField]\n if (!timeValue) {\n return true // Assume complete if no time value\n }\n\n // Parse the time value\n const date = new Date(timeValue)\n if (isNaN(date.getTime())) {\n return true // Assume complete if invalid date\n }\n\n // Get the end of this period\n const periodEnd = getPeriodEndDate(date, granularity)\n\n // Compare with current time\n const now = new Date()\n\n // If the period end is in the future, the period is incomplete\n return periodEnd <= now\n}\n\n/**\n * Extract granularity from a query object\n * @param queryObject - The CubeQuery object\n * @param dimensionField - Optional specific dimension field to match\n * @returns The granularity string or null if not found\n */\nexport function getQueryGranularity(\n queryObject: any,\n dimensionField?: string\n): string | null {\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return null\n }\n\n // If a specific dimension field is provided, try to find its granularity\n if (dimensionField) {\n const matchingDim = queryObject.timeDimensions.find((td: any) =>\n td.dimension === dimensionField ||\n td.dimension?.includes(dimensionField) ||\n dimensionField?.includes(td.dimension)\n )\n if (matchingDim?.granularity) {\n return matchingDim.granularity\n }\n }\n\n // Fallback to first time dimension's granularity\n const firstTimeDim = queryObject.timeDimensions[0]\n return firstTimeDim?.granularity || null\n}\n\n/**\n * Filter data to exclude incomplete or last period\n * @param data - The data array sorted by time\n * @param timeDimensionField - The field containing time values\n * @param queryObject - The query object containing timeDimensions\n * @param useLastCompletePeriod - Whether to check for incomplete periods\n * @param skipLastPeriod - Whether to always skip the last period (overrides useLastCompletePeriod)\n * @returns Object with filtered data and whether filtering was applied\n */\nexport function filterIncompletePeriod(\n data: any[],\n timeDimensionField: string | undefined,\n queryObject: any,\n useLastCompletePeriod: boolean,\n skipLastPeriod: boolean = false\n): { filteredData: any[]; excludedIncompletePeriod: boolean; skippedLastPeriod: boolean; granularity: string | null } {\n // Default return - no filtering\n const noFilter = {\n filteredData: data,\n excludedIncompletePeriod: false,\n skippedLastPeriod: false,\n granularity: null\n }\n\n // Need at least 2 data points to filter\n if (data.length < 2) {\n return noFilter\n }\n\n const granularity = getQueryGranularity(queryObject, timeDimensionField)\n\n // If skipLastPeriod is enabled, always skip the last period\n if (skipLastPeriod) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: false,\n skippedLastPeriod: true,\n granularity\n }\n }\n\n // Skip incomplete period check if feature is disabled\n if (!useLastCompletePeriod) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimension field\n if (!timeDimensionField) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimensions in query\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return { ...noFilter, granularity }\n }\n\n if (!granularity) {\n return noFilter\n }\n\n // Check if last period is incomplete\n const lastRow = data[data.length - 1]\n if (!isLastPeriodComplete(lastRow, timeDimensionField, granularity)) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: true,\n skippedLastPeriod: false,\n granularity\n }\n }\n\n return { ...noFilter, granularity }\n}\n","import { useState, useRef, useEffect } from \"react\";\nimport { Icon } from \"@iconify/react\";\nimport infoCircleIcon from \"@iconify-icons/tabler/info-circle\";\nimport { useCubeContext } from \"../../providers/CubeProvider\";\nimport { filterIncompletePeriod } from \"../../utils/periodUtils\";\nimport type { ChartProps } from \"../../types\";\n\ninterface VarianceHistogramProps {\n values: number[];\n lastValue: number;\n positiveColor: string;\n negativeColor: string;\n formatValue: (value: number) => string;\n width: number;\n height: number;\n}\n\nfunction VarianceHistogram({\n values,\n lastValue,\n positiveColor,\n negativeColor,\n formatValue,\n width,\n height,\n}: VarianceHistogramProps) {\n // Limit to most recent N values to fit in the histogram\n // Calculate max bars based on width (minimum 8px per bar including gap)\n const maxBars = Math.max(10, Math.floor(width / 10));\n const limitedValues =\n values.length > maxBars\n ? values.slice(-maxBars) // Take the most recent values\n : values;\n\n // Calculate variance (difference) from current/last value for each point\n const variances = limitedValues.map((value) => value - lastValue);\n\n // Find min/max variance for scaling (include 0 as baseline)\n const minVariance = Math.min(...variances, 0);\n const maxVariance = Math.max(...variances, 0);\n const range = Math.max(Math.abs(minVariance), Math.abs(maxVariance));\n\n if (range === 0 || variances.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center bg-gray-50 rounded-sm border\"\n style={{ width: `${width}px`, height: `${height}px` }}\n >\n <span className=\"text-xs text-gray-500\">No variance data</span>\n </div>\n );\n }\n\n // Calculate bar dimensions\n const barGap = 2;\n const availableWidth = width - (limitedValues.length - 1) * barGap;\n const barWidth = Math.max(4, availableWidth / limitedValues.length);\n\n // Calculate where zero line should be positioned (as percentage from top)\n // If maxVariance = 67 and minVariance = -24, total range = 91\n // Zero should be at 67/91 = 73.6% from top\n const totalRange = maxVariance - minVariance;\n const zeroLinePercent =\n totalRange > 0 ? (maxVariance / totalRange) * 100 : 50;\n\n return (\n <div className=\"flex items-center space-x-2\">\n {/* Histogram bars */}\n <div\n className=\"relative\"\n style={{\n width: `${width}px`,\n height: `${height}px`,\n }}\n >\n {/* Zero line (represents current value) */}\n <div\n className=\"absolute left-0 right-0\"\n style={{\n height: \"1px\",\n top: `${zeroLinePercent}%`,\n backgroundColor: \"var(--dc-border)\",\n zIndex: 1,\n }}\n />\n\n {/* Variance bars - oldest to newest (left to right) */}\n {variances.map((variance, index) => {\n // Calculate bar height as proportion of total range\n const normalizedHeight = Math.abs(variance) / totalRange;\n const barHeight = Math.max(2, normalizedHeight * (height - 4));\n const isPositive = variance >= 0;\n const isLastValue = index === limitedValues.length - 1;\n const color = isPositive ? positiveColor : negativeColor;\n const xPosition = index * (barWidth + barGap);\n\n return (\n <div\n key={index}\n className=\"absolute rounded-xs\"\n style={{\n left: `${xPosition}px`,\n width: `${barWidth}px`,\n height: `${barHeight}px`,\n backgroundColor: color,\n opacity: isLastValue ? 1 : 0.6,\n // Position bar relative to zero line\n ...(isPositive\n ? { bottom: `${100 - zeroLinePercent}%` }\n : { top: `${zeroLinePercent}%` }),\n zIndex: 2,\n }}\n title={`${formatValue(limitedValues[index])}: ${variance >= 0 ? \"+\" : \"\"}${formatValue(variance)} vs current`}\n />\n );\n })}\n </div>\n\n {/* Variance labels on the right - show actual value difference */}\n <div\n className=\"flex flex-col justify-between text-xs text-dc-text-muted\"\n style={{ height: `${height}px` }}\n >\n <span>+{formatValue(maxVariance)}</span>\n <span>\n {minVariance < 0 ? \"\" : \"\"}\n {formatValue(minVariance)}\n </span>\n </div>\n </div>\n );\n}\n\nexport default function KpiDelta({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n}: ChartProps) {\n const [fontSize, setFontSize] = useState(32);\n const [textWidth, setTextWidth] = useState(250);\n const containerRef = useRef<HTMLDivElement>(null);\n const valueRef = useRef<HTMLDivElement>(null);\n const { getFieldLabel } = useCubeContext();\n\n // Calculate font size and text width based on container dimensions\n useEffect(() => {\n const updateDimensions = () => {\n if (containerRef.current) {\n const container = containerRef.current;\n const rect = container.getBoundingClientRect();\n const containerWidth = rect.width;\n const containerHeight = rect.height;\n\n if (containerWidth > 0 && containerHeight > 0) {\n const widthBasedSize = containerWidth / 4;\n const heightBasedSize = containerHeight / 4;\n const baseFontSize = Math.min(widthBasedSize, heightBasedSize);\n const clampedFontSize = Math.max(28, Math.min(baseFontSize, 140));\n setFontSize(clampedFontSize);\n\n setTimeout(() => {\n if (valueRef.current) {\n const textRect = valueRef.current.getBoundingClientRect();\n const measuredWidth = textRect.width;\n // Scale histogram width with container, accounting for labels on the right (~60px)\n const maxHistogramWidth = containerWidth - 100; // Leave room for padding and labels\n const effectiveWidth = Math.max(\n measuredWidth,\n Math.min(maxHistogramWidth, containerWidth * 0.7),\n );\n setTextWidth(Math.max(100, effectiveWidth)); // Minimum 100px\n }\n }, 10);\n }\n }\n };\n\n const timer = setTimeout(updateDimensions, 50);\n\n const resizeObserver = new ResizeObserver(() => {\n setTimeout(updateDimensions, 10);\n });\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current);\n }\n\n return () => {\n clearTimeout(timer);\n resizeObserver.disconnect();\n };\n }, [data, chartConfig]);\n\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">\n No data points to display\n </div>\n </div>\n </div>\n );\n }\n\n // Extract value and dimension fields from chart config\n let valueFields: string[] = [];\n let dimensionFields: string[] = [];\n\n if (chartConfig?.yAxis) {\n valueFields = Array.isArray(chartConfig.yAxis)\n ? chartConfig.yAxis\n : [chartConfig.yAxis];\n }\n\n if (chartConfig?.xAxis) {\n dimensionFields = Array.isArray(chartConfig.xAxis)\n ? chartConfig.xAxis\n : [chartConfig.xAxis];\n }\n\n if (valueFields.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-danger-bg)\",\n color: \"var(--dc-danger)\",\n borderColor: \"var(--dc-danger-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">No measure field configured</div>\n </div>\n </div>\n );\n }\n\n const valueField = valueFields[0];\n const dimensionField = dimensionFields[0]; // Optional\n\n // Sort data by dimension if available (for time series)\n let sortedData = [...data];\n if (dimensionField) {\n sortedData = sortedData.sort((a, b) => {\n const aVal = a[dimensionField];\n const bVal = b[dimensionField];\n if (aVal < bVal) return -1;\n if (aVal > bVal) return 1;\n return 0;\n });\n }\n\n // Filter out incomplete or last period if enabled\n const { useLastCompletePeriod = true, skipLastPeriod = false } =\n displayConfig;\n const {\n filteredData,\n excludedIncompletePeriod,\n skippedLastPeriod,\n granularity,\n } = filterIncompletePeriod(\n sortedData,\n dimensionField,\n queryObject,\n useLastCompletePeriod,\n skipLastPeriod,\n );\n\n // Use filtered data for calculations\n const dataToUse = filteredData;\n\n // Extract values from filtered data\n const values = dataToUse\n .map((row) => row[valueField])\n .filter((val) => val !== null && val !== undefined && !isNaN(Number(val)))\n .map((val) => Number(val));\n\n if (values.length < 2) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-warning-bg)\",\n color: \"var(--dc-warning)\",\n borderColor: \"var(--dc-warning-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Insufficient Data</div>\n <div className=\"text-xs\">\n Delta calculation requires at least 2 data points\n </div>\n <div className=\"text-xs\">Current data points: {values.length}</div>\n </div>\n </div>\n );\n }\n\n // Calculate delta between last and second-last values\n const lastValue = values[values.length - 1];\n const secondLastValue = values[values.length - 2];\n const absoluteChange = lastValue - secondLastValue;\n const percentageChange =\n secondLastValue !== 0\n ? (absoluteChange / Math.abs(secondLastValue)) * 100\n : 0;\n\n const isPositiveChange = absoluteChange >= 0;\n\n // Format number with appropriate units and decimals\n const formatNumber = (value: number | null | undefined): string => {\n // If custom formatValue is provided, use it exclusively\n if (displayConfig.formatValue) {\n return displayConfig.formatValue(value);\n }\n\n // Null handling: Show placeholder for missing data\n if (value === null || value === undefined) {\n return \"—\";\n }\n\n const decimals = displayConfig.decimals ?? 0;\n const prefix = displayConfig.prefix ?? \"\";\n\n let formattedValue: string;\n\n if (Math.abs(value) >= 1e9) {\n formattedValue = (value / 1e9).toFixed(decimals) + \"B\";\n } else if (Math.abs(value) >= 1e6) {\n formattedValue = (value / 1e6).toFixed(decimals) + \"M\";\n } else if (Math.abs(value) >= 1e3) {\n formattedValue = (value / 1e3).toFixed(decimals) + \"K\";\n } else {\n formattedValue = value.toFixed(decimals);\n }\n\n return prefix + formattedValue;\n };\n\n // Get colors from palette\n const getPositiveColor = (): string => {\n if (\n displayConfig.positiveColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.positiveColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#10b981\"; // Default green\n };\n\n const getNegativeColor = (): string => {\n if (\n displayConfig.negativeColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.negativeColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#ef4444\"; // Default red\n };\n\n const positiveColor = getPositiveColor();\n const negativeColor = getNegativeColor();\n const currentColor = isPositiveChange ? positiveColor : negativeColor;\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col items-center justify-center w-full h-full p-4\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n {/* Field Label */}\n <div\n className=\"text-dc-text-secondary font-bold text-center mb-2 flex items-center justify-center gap-1\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n }}\n >\n <span>\n {(() => {\n const label = getFieldLabel(valueField);\n return label && label.length > 1 ? label : valueField;\n })()}\n </span>\n {(excludedIncompletePeriod || skippedLastPeriod) && (\n <span\n title={\n skippedLastPeriod\n ? `Excludes last ${granularity || \"period\"}`\n : `Excludes current incomplete ${granularity}`\n }\n className=\"cursor-help\"\n >\n <Icon\n icon={infoCircleIcon}\n className=\"w-4 h-4 text-dc-text-muted opacity-70\"\n />\n </span>\n )}\n </div>\n\n {/* Main KPI Value and Delta */}\n <div className=\"flex items-center justify-center space-x-4 mb-2\">\n {/* Main KPI Value */}\n <div\n ref={valueRef}\n className=\"font-bold leading-none\"\n style={{\n fontSize: `${fontSize}px`,\n color: \"var(--dc-text)\", // Keep main value neutral\n }}\n >\n {formatNumber(lastValue)}\n </div>\n\n {/* Delta Information */}\n <div className=\"flex items-center space-x-1\">\n {/* Arrow */}\n <div\n className=\"font-bold\"\n style={{\n color: currentColor,\n fontSize: `${fontSize * 0.35}px`,\n }}\n >\n {isPositiveChange ? \"▲\" : \"▼\"}\n </div>\n\n {/* Delta Values */}\n <div className=\"text-left\">\n <div\n className=\"font-bold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.35}px`,\n color: currentColor,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {formatNumber(absoluteChange)}\n </div>\n <div\n className=\"font-semibold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.28}px`,\n color: currentColor,\n opacity: 0.8,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {percentageChange.toFixed(1)}%\n </div>\n </div>\n </div>\n </div>\n\n {/* Unit/Suffix (hidden when formatValue is provided) */}\n {displayConfig.suffix && !displayConfig.formatValue && (\n <div\n className=\"text-dc-text-muted text-center mb-3\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n opacity: 0.8,\n }}\n >\n {displayConfig.suffix}\n </div>\n )}\n\n {/* Variance Histogram */}\n {displayConfig.showHistogram !== false && values.length > 2 && (\n <div className=\"mt-2 w-full flex justify-center overflow-hidden\">\n <VarianceHistogram\n values={values}\n lastValue={lastValue}\n positiveColor={positiveColor}\n negativeColor={negativeColor}\n formatValue={formatNumber}\n width={textWidth}\n height={64}\n />\n </div>\n )}\n </div>\n );\n}\n"],"names":["getPeriodEndDate","date","granularity","endDate","daysUntilSaturday","currentMonth","quarterEndMonth","isLastPeriodComplete","lastDataPoint","timeDimensionField","timeValue","getQueryGranularity","queryObject","dimensionField","matchingDim","td","filterIncompletePeriod","data","useLastCompletePeriod","skipLastPeriod","noFilter","lastRow","VarianceHistogram","values","lastValue","positiveColor","negativeColor","formatValue","width","height","maxBars","limitedValues","variances","value","minVariance","maxVariance","jsx","barGap","availableWidth","barWidth","totalRange","zeroLinePercent","jsxs","variance","index","normalizedHeight","barHeight","isPositive","isLastValue","color","xPosition","KpiDelta","chartConfig","displayConfig","colorPalette","fontSize","setFontSize","useState","textWidth","setTextWidth","containerRef","useRef","valueRef","getFieldLabel","useCubeContext","useEffect","updateDimensions","rect","containerWidth","containerHeight","widthBasedSize","heightBasedSize","baseFontSize","clampedFontSize","measuredWidth","maxHistogramWidth","effectiveWidth","timer","resizeObserver","valueFields","dimensionFields","valueField","sortedData","a","b","aVal","bVal","filteredData","excludedIncompletePeriod","skippedLastPeriod","row","val","secondLastValue","absoluteChange","percentageChange","isPositiveChange","formatNumber","decimals","prefix","formattedValue","getPositiveColor","colorIndex","getNegativeColor","currentColor","label","Icon","infoCircleIcon"],"mappings":"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"}
1
+ {"version":3,"file":"chart-kpidelta-CTcuIO9G.js","sources":["../../../src/client/utils/periodUtils.ts","../../../src/client/components/charts/KpiDelta.tsx"],"sourcesContent":["/**\n * Utility functions for detecting incomplete time periods in KPI charts\n */\n\n/**\n * Get the end date of a period based on granularity\n * @param date - The date within the period\n * @param granularity - The time granularity (day, week, month, quarter, year)\n * @returns The end date of the period (end of day)\n */\nexport function getPeriodEndDate(date: Date, granularity: string): Date {\n const endDate = new Date(date)\n\n switch (granularity.toLowerCase()) {\n case 'day':\n // End of the same day\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'week':\n // End of the week (Saturday, assuming week starts Sunday)\n const dayOfWeek = endDate.getDay()\n const daysUntilSaturday = 6 - dayOfWeek\n endDate.setDate(endDate.getDate() + daysUntilSaturday)\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'month':\n // Last day of the month\n endDate.setMonth(endDate.getMonth() + 1, 0) // Set to day 0 of next month = last day of current month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'quarter':\n // Last day of the quarter\n const currentMonth = endDate.getMonth()\n const quarterEndMonth = Math.floor(currentMonth / 3) * 3 + 2 // 0->2, 3->5, 6->8, 9->11\n endDate.setMonth(quarterEndMonth + 1, 0) // Last day of quarter end month\n endDate.setHours(23, 59, 59, 999)\n break\n\n case 'year':\n // December 31st\n endDate.setMonth(11, 31) // December 31\n endDate.setHours(23, 59, 59, 999)\n break\n\n default:\n // Unknown granularity - treat as complete\n endDate.setHours(23, 59, 59, 999)\n }\n\n return endDate\n}\n\n/**\n * Check if the last period in the data is complete based on granularity\n * @param lastDataPoint - The last data point in the sorted dataset\n * @param timeDimensionField - The field name containing the time value\n * @param granularity - The time granularity\n * @returns true if the period is complete, false if it's incomplete\n */\nexport function isLastPeriodComplete(\n lastDataPoint: any,\n timeDimensionField: string,\n granularity: string\n): boolean {\n if (!lastDataPoint || !timeDimensionField || !granularity) {\n return true // Assume complete if we can't determine\n }\n\n const timeValue = lastDataPoint[timeDimensionField]\n if (!timeValue) {\n return true // Assume complete if no time value\n }\n\n // Parse the time value\n const date = new Date(timeValue)\n if (isNaN(date.getTime())) {\n return true // Assume complete if invalid date\n }\n\n // Get the end of this period\n const periodEnd = getPeriodEndDate(date, granularity)\n\n // Compare with current time\n const now = new Date()\n\n // If the period end is in the future, the period is incomplete\n return periodEnd <= now\n}\n\n/**\n * Extract granularity from a query object\n * @param queryObject - The CubeQuery object\n * @param dimensionField - Optional specific dimension field to match\n * @returns The granularity string or null if not found\n */\nexport function getQueryGranularity(\n queryObject: any,\n dimensionField?: string\n): string | null {\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return null\n }\n\n // If a specific dimension field is provided, try to find its granularity\n if (dimensionField) {\n const matchingDim = queryObject.timeDimensions.find((td: any) =>\n td.dimension === dimensionField ||\n td.dimension?.includes(dimensionField) ||\n dimensionField?.includes(td.dimension)\n )\n if (matchingDim?.granularity) {\n return matchingDim.granularity\n }\n }\n\n // Fallback to first time dimension's granularity\n const firstTimeDim = queryObject.timeDimensions[0]\n return firstTimeDim?.granularity || null\n}\n\n/**\n * Filter data to exclude incomplete or last period\n * @param data - The data array sorted by time\n * @param timeDimensionField - The field containing time values\n * @param queryObject - The query object containing timeDimensions\n * @param useLastCompletePeriod - Whether to check for incomplete periods\n * @param skipLastPeriod - Whether to always skip the last period (overrides useLastCompletePeriod)\n * @returns Object with filtered data and whether filtering was applied\n */\nexport function filterIncompletePeriod(\n data: any[],\n timeDimensionField: string | undefined,\n queryObject: any,\n useLastCompletePeriod: boolean,\n skipLastPeriod: boolean = false\n): { filteredData: any[]; excludedIncompletePeriod: boolean; skippedLastPeriod: boolean; granularity: string | null } {\n // Default return - no filtering\n const noFilter = {\n filteredData: data,\n excludedIncompletePeriod: false,\n skippedLastPeriod: false,\n granularity: null\n }\n\n // Need at least 2 data points to filter\n if (data.length < 2) {\n return noFilter\n }\n\n const granularity = getQueryGranularity(queryObject, timeDimensionField)\n\n // If skipLastPeriod is enabled, always skip the last period\n if (skipLastPeriod) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: false,\n skippedLastPeriod: true,\n granularity\n }\n }\n\n // Skip incomplete period check if feature is disabled\n if (!useLastCompletePeriod) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimension field\n if (!timeDimensionField) {\n return { ...noFilter, granularity }\n }\n\n // Skip if no time dimensions in query\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return { ...noFilter, granularity }\n }\n\n if (!granularity) {\n return noFilter\n }\n\n // Check if last period is incomplete\n const lastRow = data[data.length - 1]\n if (!isLastPeriodComplete(lastRow, timeDimensionField, granularity)) {\n return {\n filteredData: data.slice(0, -1),\n excludedIncompletePeriod: true,\n skippedLastPeriod: false,\n granularity\n }\n }\n\n return { ...noFilter, granularity }\n}\n","import { useState, useRef, useEffect } from \"react\";\nimport { Icon } from \"@iconify/react\";\nimport infoCircleIcon from \"@iconify-icons/tabler/info-circle\";\nimport { useCubeContext } from \"../../providers/CubeProvider\";\nimport { filterIncompletePeriod } from \"../../utils/periodUtils\";\nimport type { ChartProps } from \"../../types\";\n\ninterface VarianceHistogramProps {\n values: number[];\n lastValue: number;\n positiveColor: string;\n negativeColor: string;\n formatValue: (value: number) => string;\n width: number;\n height: number;\n}\n\nfunction VarianceHistogram({\n values,\n lastValue,\n positiveColor,\n negativeColor,\n formatValue,\n width,\n height,\n}: VarianceHistogramProps) {\n // Limit to most recent N values to fit in the histogram\n // Calculate max bars based on width (minimum 8px per bar including gap)\n const maxBars = Math.max(10, Math.floor(width / 10));\n const limitedValues =\n values.length > maxBars\n ? values.slice(-maxBars) // Take the most recent values\n : values;\n\n // Calculate variance (difference) from current/last value for each point\n const variances = limitedValues.map((value) => value - lastValue);\n\n // Find min/max variance for scaling (include 0 as baseline)\n const minVariance = Math.min(...variances, 0);\n const maxVariance = Math.max(...variances, 0);\n const range = Math.max(Math.abs(minVariance), Math.abs(maxVariance));\n\n if (range === 0 || variances.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center bg-gray-50 rounded-sm border\"\n style={{ width: `${width}px`, height: `${height}px` }}\n >\n <span className=\"text-xs text-gray-500\">No variance data</span>\n </div>\n );\n }\n\n // Calculate bar dimensions\n const barGap = 2;\n const availableWidth = width - (limitedValues.length - 1) * barGap;\n const barWidth = Math.max(4, availableWidth / limitedValues.length);\n\n // Calculate where zero line should be positioned (as percentage from top)\n // If maxVariance = 67 and minVariance = -24, total range = 91\n // Zero should be at 67/91 = 73.6% from top\n const totalRange = maxVariance - minVariance;\n const zeroLinePercent =\n totalRange > 0 ? (maxVariance / totalRange) * 100 : 50;\n\n return (\n <div className=\"flex items-center space-x-2\">\n {/* Histogram bars */}\n <div\n className=\"relative\"\n style={{\n width: `${width}px`,\n height: `${height}px`,\n }}\n >\n {/* Zero line (represents current value) */}\n <div\n className=\"absolute left-0 right-0\"\n style={{\n height: \"1px\",\n top: `${zeroLinePercent}%`,\n backgroundColor: \"var(--dc-border)\",\n zIndex: 1,\n }}\n />\n\n {/* Variance bars - oldest to newest (left to right) */}\n {variances.map((variance, index) => {\n // Calculate bar height as proportion of total range\n const normalizedHeight = Math.abs(variance) / totalRange;\n const barHeight = Math.max(2, normalizedHeight * (height - 4));\n const isPositive = variance >= 0;\n const isLastValue = index === limitedValues.length - 1;\n const color = isPositive ? positiveColor : negativeColor;\n const xPosition = index * (barWidth + barGap);\n\n return (\n <div\n key={index}\n className=\"absolute rounded-xs\"\n style={{\n left: `${xPosition}px`,\n width: `${barWidth}px`,\n height: `${barHeight}px`,\n backgroundColor: color,\n opacity: isLastValue ? 1 : 0.6,\n // Position bar relative to zero line\n ...(isPositive\n ? { bottom: `${100 - zeroLinePercent}%` }\n : { top: `${zeroLinePercent}%` }),\n zIndex: 2,\n }}\n title={`${formatValue(limitedValues[index])}: ${variance >= 0 ? \"+\" : \"\"}${formatValue(variance)} vs current`}\n />\n );\n })}\n </div>\n\n {/* Variance labels on the right - show actual value difference */}\n <div\n className=\"flex flex-col justify-between text-xs text-dc-text-muted\"\n style={{ height: `${height}px` }}\n >\n <span>+{formatValue(maxVariance)}</span>\n <span>\n {minVariance < 0 ? \"\" : \"\"}\n {formatValue(minVariance)}\n </span>\n </div>\n </div>\n );\n}\n\nexport default function KpiDelta({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n}: ChartProps) {\n const [fontSize, setFontSize] = useState(32);\n const [textWidth, setTextWidth] = useState(250);\n const containerRef = useRef<HTMLDivElement>(null);\n const valueRef = useRef<HTMLDivElement>(null);\n const { getFieldLabel } = useCubeContext();\n\n // Calculate font size and text width based on container dimensions\n useEffect(() => {\n const updateDimensions = () => {\n if (containerRef.current) {\n const container = containerRef.current;\n const rect = container.getBoundingClientRect();\n const containerWidth = rect.width;\n const containerHeight = rect.height;\n\n if (containerWidth > 0 && containerHeight > 0) {\n const widthBasedSize = containerWidth / 4;\n const heightBasedSize = containerHeight / 4;\n const baseFontSize = Math.min(widthBasedSize, heightBasedSize);\n const clampedFontSize = Math.max(28, Math.min(baseFontSize, 140));\n setFontSize(clampedFontSize);\n\n setTimeout(() => {\n if (valueRef.current) {\n const textRect = valueRef.current.getBoundingClientRect();\n const measuredWidth = textRect.width;\n // Scale histogram width with container, accounting for labels on the right (~60px)\n const maxHistogramWidth = containerWidth - 100; // Leave room for padding and labels\n const effectiveWidth = Math.max(\n measuredWidth,\n Math.min(maxHistogramWidth, containerWidth * 0.7),\n );\n setTextWidth(Math.max(100, effectiveWidth)); // Minimum 100px\n }\n }, 10);\n }\n }\n };\n\n const timer = setTimeout(updateDimensions, 50);\n\n const resizeObserver = new ResizeObserver(() => {\n setTimeout(updateDimensions, 10);\n });\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current);\n }\n\n return () => {\n clearTimeout(timer);\n resizeObserver.disconnect();\n };\n }, [data, chartConfig]);\n\n if (!data || data.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n <div className=\"text-center text-dc-text-muted\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">\n No data points to display\n </div>\n </div>\n </div>\n );\n }\n\n // Extract value and dimension fields from chart config\n let valueFields: string[] = [];\n let dimensionFields: string[] = [];\n\n if (chartConfig?.yAxis) {\n valueFields = Array.isArray(chartConfig.yAxis)\n ? chartConfig.yAxis\n : [chartConfig.yAxis];\n }\n\n if (chartConfig?.xAxis) {\n dimensionFields = Array.isArray(chartConfig.xAxis)\n ? chartConfig.xAxis\n : [chartConfig.xAxis];\n }\n\n if (valueFields.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-danger-bg)\",\n color: \"var(--dc-danger)\",\n borderColor: \"var(--dc-danger-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">No measure field configured</div>\n </div>\n </div>\n );\n }\n\n const valueField = valueFields[0];\n const dimensionField = dimensionFields[0]; // Optional\n\n // Sort data by dimension if available (for time series)\n let sortedData = [...data];\n if (dimensionField) {\n sortedData = sortedData.sort((a, b) => {\n const aVal = a[dimensionField];\n const bVal = b[dimensionField];\n if (aVal < bVal) return -1;\n if (aVal > bVal) return 1;\n return 0;\n });\n }\n\n // Filter out incomplete or last period if enabled\n const { useLastCompletePeriod = true, skipLastPeriod = false } =\n displayConfig;\n const {\n filteredData,\n excludedIncompletePeriod,\n skippedLastPeriod,\n granularity,\n } = filterIncompletePeriod(\n sortedData,\n dimensionField,\n queryObject,\n useLastCompletePeriod,\n skipLastPeriod,\n );\n\n // Use filtered data for calculations\n const dataToUse = filteredData;\n\n // Extract values from filtered data\n const values = dataToUse\n .map((row) => row[valueField])\n .filter((val) => val !== null && val !== undefined && !isNaN(Number(val)))\n .map((val) => Number(val));\n\n if (values.length < 2) {\n return (\n <div\n className=\"flex items-center justify-center w-full h-full\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n backgroundColor: \"var(--dc-warning-bg)\",\n color: \"var(--dc-warning)\",\n borderColor: \"var(--dc-warning-border)\",\n }}\n >\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Insufficient Data</div>\n <div className=\"text-xs\">\n Delta calculation requires at least 2 data points\n </div>\n <div className=\"text-xs\">Current data points: {values.length}</div>\n </div>\n </div>\n );\n }\n\n // Calculate delta between last and second-last values\n const lastValue = values[values.length - 1];\n const secondLastValue = values[values.length - 2];\n const absoluteChange = lastValue - secondLastValue;\n const percentageChange =\n secondLastValue !== 0\n ? (absoluteChange / Math.abs(secondLastValue)) * 100\n : 0;\n\n const isPositiveChange = absoluteChange >= 0;\n\n // Format number with appropriate units and decimals\n const formatNumber = (value: number | null | undefined): string => {\n // If custom formatValue is provided, use it exclusively\n if (displayConfig.formatValue) {\n return displayConfig.formatValue(value);\n }\n\n // Null handling: Show placeholder for missing data\n if (value === null || value === undefined) {\n return \"—\";\n }\n\n const decimals = displayConfig.decimals ?? 0;\n const prefix = displayConfig.prefix ?? \"\";\n\n let formattedValue: string;\n\n if (Math.abs(value) >= 1e9) {\n formattedValue = (value / 1e9).toFixed(decimals) + \"B\";\n } else if (Math.abs(value) >= 1e6) {\n formattedValue = (value / 1e6).toFixed(decimals) + \"M\";\n } else if (Math.abs(value) >= 1e3) {\n formattedValue = (value / 1e3).toFixed(decimals) + \"K\";\n } else {\n formattedValue = value.toFixed(decimals);\n }\n\n return prefix + formattedValue;\n };\n\n // Get colors from palette\n const getPositiveColor = (): string => {\n if (\n displayConfig.positiveColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.positiveColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#10b981\"; // Default green\n };\n\n const getNegativeColor = (): string => {\n if (\n displayConfig.negativeColorIndex !== undefined &&\n colorPalette?.colors\n ) {\n const colorIndex = displayConfig.negativeColorIndex;\n if (colorIndex >= 0 && colorIndex < colorPalette.colors.length) {\n return colorPalette.colors[colorIndex];\n }\n }\n return \"#ef4444\"; // Default red\n };\n\n const positiveColor = getPositiveColor();\n const negativeColor = getNegativeColor();\n const currentColor = isPositiveChange ? positiveColor : negativeColor;\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col items-center justify-center w-full h-full p-4\"\n style={{\n height: height === \"100%\" ? \"100%\" : height,\n minHeight: height === \"100%\" ? \"200px\" : undefined,\n }}\n >\n {/* Field Label */}\n <div\n className=\"text-dc-text-secondary font-bold text-center mb-2 flex items-center justify-center gap-1\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n }}\n >\n <span>\n {(() => {\n const label = getFieldLabel(valueField);\n return label && label.length > 1 ? label : valueField;\n })()}\n </span>\n {(excludedIncompletePeriod || skippedLastPeriod) && (\n <span\n title={\n skippedLastPeriod\n ? `Excludes last ${granularity || \"period\"}`\n : `Excludes current incomplete ${granularity}`\n }\n className=\"cursor-help\"\n >\n <Icon\n icon={infoCircleIcon}\n className=\"w-4 h-4 text-dc-text-muted opacity-70\"\n />\n </span>\n )}\n </div>\n\n {/* Main KPI Value and Delta */}\n <div className=\"flex items-center justify-center space-x-4 mb-2\">\n {/* Main KPI Value */}\n <div\n ref={valueRef}\n className=\"font-bold leading-none\"\n style={{\n fontSize: `${fontSize}px`,\n color: \"var(--dc-text)\", // Keep main value neutral\n }}\n >\n {formatNumber(lastValue)}\n </div>\n\n {/* Delta Information */}\n <div className=\"flex items-center space-x-1\">\n {/* Arrow */}\n <div\n className=\"font-bold\"\n style={{\n color: currentColor,\n fontSize: `${fontSize * 0.35}px`,\n }}\n >\n {isPositiveChange ? \"▲\" : \"▼\"}\n </div>\n\n {/* Delta Values */}\n <div className=\"text-left\">\n <div\n className=\"font-bold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.35}px`,\n color: currentColor,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {formatNumber(absoluteChange)}\n </div>\n <div\n className=\"font-semibold leading-tight\"\n style={{\n fontSize: `${fontSize * 0.28}px`,\n color: currentColor,\n opacity: 0.8,\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {percentageChange.toFixed(1)}%\n </div>\n </div>\n </div>\n </div>\n\n {/* Unit/Suffix (hidden when formatValue is provided) */}\n {displayConfig.suffix && !displayConfig.formatValue && (\n <div\n className=\"text-dc-text-muted text-center mb-3\"\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.2\",\n opacity: 0.8,\n }}\n >\n {displayConfig.suffix}\n </div>\n )}\n\n {/* Variance Histogram */}\n {displayConfig.showHistogram !== false && values.length > 2 && (\n <div className=\"mt-2 w-full flex justify-center overflow-hidden\">\n <VarianceHistogram\n values={values}\n lastValue={lastValue}\n positiveColor={positiveColor}\n negativeColor={negativeColor}\n formatValue={formatNumber}\n width={textWidth}\n height={64}\n />\n </div>\n )}\n </div>\n );\n}\n"],"names":["getPeriodEndDate","date","granularity","endDate","daysUntilSaturday","currentMonth","quarterEndMonth","isLastPeriodComplete","lastDataPoint","timeDimensionField","timeValue","getQueryGranularity","queryObject","dimensionField","matchingDim","td","filterIncompletePeriod","data","useLastCompletePeriod","skipLastPeriod","noFilter","lastRow","VarianceHistogram","values","lastValue","positiveColor","negativeColor","formatValue","width","height","maxBars","limitedValues","variances","value","minVariance","maxVariance","jsx","barGap","availableWidth","barWidth","totalRange","zeroLinePercent","jsxs","variance","index","normalizedHeight","barHeight","isPositive","isLastValue","color","xPosition","KpiDelta","chartConfig","displayConfig","colorPalette","fontSize","setFontSize","useState","textWidth","setTextWidth","containerRef","useRef","valueRef","getFieldLabel","useCubeContext","useEffect","updateDimensions","rect","containerWidth","containerHeight","widthBasedSize","heightBasedSize","baseFontSize","clampedFontSize","measuredWidth","maxHistogramWidth","effectiveWidth","timer","resizeObserver","valueFields","dimensionFields","valueField","sortedData","a","b","aVal","bVal","filteredData","excludedIncompletePeriod","skippedLastPeriod","row","val","secondLastValue","absoluteChange","percentageChange","isPositiveChange","formatNumber","decimals","prefix","formattedValue","getPositiveColor","colorIndex","getNegativeColor","currentColor","label","Icon","infoCircleIcon"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { g as a } from "./chart-activitygridchart-config-48WqIofo.js";
1
+ import { g as a } from "./chart-activitygridchart-config-BngZDVh_.js";
2
2
  const i = {
3
3
  icon: a("kpiDelta"),
4
4
  description: "Display change between latest and previous values with trend indicators",
@@ -95,4 +95,4 @@ const i = {
95
95
  export {
96
96
  i as kpiDeltaConfig
97
97
  };
98
- //# sourceMappingURL=chart-kpidelta-config-CnZfi_P2.js.map
98
+ //# sourceMappingURL=chart-kpidelta-config-B-Y-LHmd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-kpidelta-config-CnZfi_P2.js","sources":["../../../src/client/components/charts/KpiDelta.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the KPI Delta chart type\n */\nexport const kpiDeltaConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('kpiDelta'),\n description: 'Display change between latest and previous values with trend indicators',\n useCase: 'Perfect for showing performance changes over time, such as revenue growth, user acquisition changes, or other metrics where the trend and delta are more important than the absolute value',\n dropZones: [\n {\n key: 'yAxis',\n label: 'Value',\n description: 'Measure to track changes for',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'Drop a measure here'\n },\n {\n key: 'xAxis',\n label: 'Dimension (optional)',\n description: 'Dimension for ordering data (typically time)',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop a dimension for ordering'\n }\n ],\n displayOptionsConfig: [\n {\n key: 'prefix',\n label: 'Prefix',\n type: 'string',\n placeholder: 'e.g., $, €, #',\n description: 'Text to display before the number'\n },\n {\n key: 'suffix',\n label: 'Suffix',\n type: 'string',\n placeholder: 'e.g., %, units, items',\n description: 'Text to display after the number'\n },\n {\n key: 'decimals',\n label: 'Decimal Places',\n type: 'number',\n defaultValue: 1,\n min: 0,\n max: 10,\n step: 1,\n description: 'Number of decimal places to display'\n },\n {\n key: 'positiveColorIndex',\n label: 'Positive Change Color',\n type: 'paletteColor',\n defaultValue: 2, // Typically green in most palettes\n description: 'Color for positive changes (increases)'\n },\n {\n key: 'negativeColorIndex',\n label: 'Negative Change Color', \n type: 'paletteColor',\n defaultValue: 3, // Typically red in most palettes\n description: 'Color for negative changes (decreases)'\n },\n {\n key: 'showHistogram',\n label: 'Show Variance Histogram',\n type: 'boolean',\n defaultValue: true,\n description: 'Display historical variance chart below the delta'\n },\n {\n key: 'useLastCompletePeriod',\n label: 'Use Last Complete Period',\n type: 'boolean',\n defaultValue: true,\n description: 'Exclude current incomplete period from delta calculation (e.g., partial week/month)'\n },\n {\n key: 'skipLastPeriod',\n label: 'Skip Last Period',\n type: 'boolean',\n defaultValue: false,\n description: 'Always exclude the last period regardless of completeness'\n }\n ],\n displayOptions: ['hideHeader'],\n validate: (config: any) => {\n if (!config.yAxis || (Array.isArray(config.yAxis) && config.yAxis.length === 0)) {\n return {\n isValid: false,\n message: 'A measure is required for KPI Delta charts'\n }\n }\n \n return { isValid: true }\n }\n}"],"names":["kpiDeltaConfig","getChartTypeIcon","config"],"mappings":";AAMO,MAAMA,IAAkC;AAAA,EAC7C,MAAMC,EAAiB,UAAU;AAAA,EACjC,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa,CAAC,SAAS;AAAA,MACvB,WAAW;AAAA,IAAA;AAAA,IAEb;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,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,cAAc;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAAA,EAC7B,UAAU,CAACC,MACL,CAACA,EAAO,SAAU,MAAM,QAAQA,EAAO,KAAK,KAAKA,EAAO,MAAM,WAAW,IACpE;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,EAAA,IAIN,EAAE,SAAS,GAAA;AAEtB;"}
1
+ {"version":3,"file":"chart-kpidelta-config-B-Y-LHmd.js","sources":["../../../src/client/components/charts/KpiDelta.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the KPI Delta chart type\n */\nexport const kpiDeltaConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('kpiDelta'),\n description: 'Display change between latest and previous values with trend indicators',\n useCase: 'Perfect for showing performance changes over time, such as revenue growth, user acquisition changes, or other metrics where the trend and delta are more important than the absolute value',\n dropZones: [\n {\n key: 'yAxis',\n label: 'Value',\n description: 'Measure to track changes for',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'Drop a measure here'\n },\n {\n key: 'xAxis',\n label: 'Dimension (optional)',\n description: 'Dimension for ordering data (typically time)',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'Drop a dimension for ordering'\n }\n ],\n displayOptionsConfig: [\n {\n key: 'prefix',\n label: 'Prefix',\n type: 'string',\n placeholder: 'e.g., $, €, #',\n description: 'Text to display before the number'\n },\n {\n key: 'suffix',\n label: 'Suffix',\n type: 'string',\n placeholder: 'e.g., %, units, items',\n description: 'Text to display after the number'\n },\n {\n key: 'decimals',\n label: 'Decimal Places',\n type: 'number',\n defaultValue: 1,\n min: 0,\n max: 10,\n step: 1,\n description: 'Number of decimal places to display'\n },\n {\n key: 'positiveColorIndex',\n label: 'Positive Change Color',\n type: 'paletteColor',\n defaultValue: 2, // Typically green in most palettes\n description: 'Color for positive changes (increases)'\n },\n {\n key: 'negativeColorIndex',\n label: 'Negative Change Color', \n type: 'paletteColor',\n defaultValue: 3, // Typically red in most palettes\n description: 'Color for negative changes (decreases)'\n },\n {\n key: 'showHistogram',\n label: 'Show Variance Histogram',\n type: 'boolean',\n defaultValue: true,\n description: 'Display historical variance chart below the delta'\n },\n {\n key: 'useLastCompletePeriod',\n label: 'Use Last Complete Period',\n type: 'boolean',\n defaultValue: true,\n description: 'Exclude current incomplete period from delta calculation (e.g., partial week/month)'\n },\n {\n key: 'skipLastPeriod',\n label: 'Skip Last Period',\n type: 'boolean',\n defaultValue: false,\n description: 'Always exclude the last period regardless of completeness'\n }\n ],\n displayOptions: ['hideHeader'],\n validate: (config: any) => {\n if (!config.yAxis || (Array.isArray(config.yAxis) && config.yAxis.length === 0)) {\n return {\n isValid: false,\n message: 'A measure is required for KPI Delta charts'\n }\n }\n \n return { isValid: true }\n }\n}"],"names":["kpiDeltaConfig","getChartTypeIcon","config"],"mappings":";AAMO,MAAMA,IAAkC;AAAA,EAC7C,MAAMC,EAAiB,UAAU;AAAA,EACjC,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa,CAAC,SAAS;AAAA,MACvB,WAAW;AAAA,IAAA;AAAA,IAEb;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,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,cAAc;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAAA,EAC7B,UAAU,CAACC,MACL,CAACA,EAAO,SAAU,MAAM,QAAQA,EAAO,KAAK,KAAKA,EAAO,MAAM,WAAW,IACpE;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,EAAA,IAIN,EAAE,SAAS,GAAA;AAEtB;"}
@@ -1,4 +1,4 @@
1
- import { g as e } from "./chart-activitygridchart-config-48WqIofo.js";
1
+ import { g as e } from "./chart-activitygridchart-config-BngZDVh_.js";
2
2
  const a = {
3
3
  icon: e("kpiNumber"),
4
4
  description: "Display key performance indicators as large numbers",
@@ -73,4 +73,4 @@ const a = {
73
73
  export {
74
74
  a as kpiNumberConfig
75
75
  };
76
- //# sourceMappingURL=chart-kpinumber-config-CVikHojM.js.map
76
+ //# sourceMappingURL=chart-kpinumber-config-BaNaJMI6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-kpinumber-config-CVikHojM.js","sources":["../../../src/client/components/charts/KpiNumber.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the KPI Number chart type\n */\nexport const kpiNumberConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('kpiNumber'),\n description: 'Display key performance indicators as large numbers',\n useCase: 'Perfect for showing important metrics like revenue, user count, or other key business metrics in a prominent, easy-to-read format',\n dropZones: [\n {\n key: 'yAxis',\n label: 'Value',\n description: 'Measure to display as KPI number',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'Drop a measure here'\n }\n ],\n displayOptionsConfig: [\n {\n key: 'target',\n label: 'Target Value',\n type: 'string',\n placeholder: 'e.g., 100',\n description: 'Target value to compare against (first value used if multiple provided)'\n },\n {\n key: 'prefix',\n label: 'Prefix',\n type: 'string',\n placeholder: 'e.g., $, €, #',\n description: 'Text to display before the number'\n },\n {\n key: 'suffix',\n label: 'Suffix',\n type: 'string',\n placeholder: 'e.g., %, units, items',\n description: 'Text to display after the number'\n },\n {\n key: 'decimals',\n label: 'Decimal Places',\n type: 'number',\n defaultValue: 0,\n min: 0,\n max: 10,\n step: 1,\n description: 'Number of decimal places to display'\n },\n {\n key: 'valueColorIndex',\n label: 'Value Color',\n type: 'paletteColor',\n defaultValue: 0,\n description: 'Color from the dashboard palette for the KPI value text'\n },\n {\n key: 'useLastCompletePeriod',\n label: 'Use Last Complete Period',\n type: 'boolean',\n defaultValue: true,\n description: 'Exclude current incomplete period from aggregation (e.g., partial week/month)'\n },\n {\n key: 'skipLastPeriod',\n label: 'Skip Last Period',\n type: 'boolean',\n defaultValue: false,\n description: 'Always exclude the last period regardless of completeness'\n }\n ],\n displayOptions: ['hideHeader']\n}"],"names":["kpiNumberConfig","getChartTypeIcon"],"mappings":";AAMO,MAAMA,IAAmC;AAAA,EAC9C,MAAMC,EAAiB,WAAW;AAAA,EAClC,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,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,cAAc;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAC/B;"}
1
+ {"version":3,"file":"chart-kpinumber-config-BaNaJMI6.js","sources":["../../../src/client/components/charts/KpiNumber.config.tsx"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { getChartTypeIcon } from '../../icons'\n\n/**\n * Configuration for the KPI Number chart type\n */\nexport const kpiNumberConfig: ChartTypeConfig = {\n icon: getChartTypeIcon('kpiNumber'),\n description: 'Display key performance indicators as large numbers',\n useCase: 'Perfect for showing important metrics like revenue, user count, or other key business metrics in a prominent, easy-to-read format',\n dropZones: [\n {\n key: 'yAxis',\n label: 'Value',\n description: 'Measure to display as KPI number',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'Drop a measure here'\n }\n ],\n displayOptionsConfig: [\n {\n key: 'target',\n label: 'Target Value',\n type: 'string',\n placeholder: 'e.g., 100',\n description: 'Target value to compare against (first value used if multiple provided)'\n },\n {\n key: 'prefix',\n label: 'Prefix',\n type: 'string',\n placeholder: 'e.g., $, €, #',\n description: 'Text to display before the number'\n },\n {\n key: 'suffix',\n label: 'Suffix',\n type: 'string',\n placeholder: 'e.g., %, units, items',\n description: 'Text to display after the number'\n },\n {\n key: 'decimals',\n label: 'Decimal Places',\n type: 'number',\n defaultValue: 0,\n min: 0,\n max: 10,\n step: 1,\n description: 'Number of decimal places to display'\n },\n {\n key: 'valueColorIndex',\n label: 'Value Color',\n type: 'paletteColor',\n defaultValue: 0,\n description: 'Color from the dashboard palette for the KPI value text'\n },\n {\n key: 'useLastCompletePeriod',\n label: 'Use Last Complete Period',\n type: 'boolean',\n defaultValue: true,\n description: 'Exclude current incomplete period from aggregation (e.g., partial week/month)'\n },\n {\n key: 'skipLastPeriod',\n label: 'Skip Last Period',\n type: 'boolean',\n defaultValue: false,\n description: 'Always exclude the last period regardless of completeness'\n }\n ],\n displayOptions: ['hideHeader']\n}"],"names":["kpiNumberConfig","getChartTypeIcon"],"mappings":";AAMO,MAAMA,IAAmC;AAAA,EAC9C,MAAMC,EAAiB,WAAW;AAAA,EAClC,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,IACT;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,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,cAAc;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,IAEf;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAEF,gBAAgB,CAAC,YAAY;AAC/B;"}