drizzle-cube 0.3.13 → 0.3.16
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.
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.d.ts +8 -1
- package/dist/adapters/express/index.js +162 -99
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.d.ts +8 -1
- package/dist/adapters/fastify/index.js +183 -96
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.d.ts +8 -1
- package/dist/adapters/hono/index.js +198 -142
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +29 -1
- package/dist/adapters/nextjs/index.js +251 -132
- package/dist/adapters/utils.d.ts +100 -1
- package/dist/adapters/validation-Bgauxvm6.cjs +214 -0
- package/dist/adapters/{compiler-DTOU8IsK.js → validation-_UkKJ2pC.js} +9582 -5295
- package/dist/client/adapters/index.d.ts +2 -0
- package/dist/client/adapters/retentionModeAdapter.d.ts +3 -0
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/RetentionCombinedChart-DirfDaZH.js +256 -0
- package/dist/client/chunks/RetentionCombinedChart-DirfDaZH.js.map +1 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js +47 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js +178 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js +28 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js.map +1 -0
- package/dist/client/chunks/analysis-builder-APeCxkEH.js +6939 -0
- package/dist/client/chunks/analysis-builder-APeCxkEH.js.map +1 -0
- package/dist/client/chunks/analysis-builder-shared-DEovRjrp.js +2779 -0
- package/dist/client/chunks/analysis-builder-shared-DEovRjrp.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js → chart-activity-grid-BnweuBvr.js} +11 -11
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js.map → chart-activity-grid-BnweuBvr.js.map} +1 -1
- package/dist/client/chunks/{chart-area-cPrJnhLj.js → chart-area-DLmXFWWy.js} +2 -2
- package/dist/client/chunks/{chart-area-cPrJnhLj.js.map → chart-area-DLmXFWWy.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-D68HFPpa.js → chart-bar-7y0-F27Q.js} +2 -2
- package/dist/client/chunks/{chart-bar-D68HFPpa.js.map → chart-bar-7y0-F27Q.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js → chart-bubble-3jYKCA2B.js} +2 -2
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js.map → chart-bubble-3jYKCA2B.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js → chart-config-activity-grid-BBSNCbkb.js} +2 -2
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js.map → chart-config-activity-grid-BBSNCbkb.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js → chart-config-area-CyyJOO2T.js} +2 -2
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js.map → chart-config-area-CyyJOO2T.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js → chart-config-bar-BJKGnfLt.js} +2 -2
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js.map → chart-config-bar-BJKGnfLt.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js → chart-config-bubble-CuSsCHZ4.js} +2 -2
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js.map → chart-config-bubble-CuSsCHZ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js → chart-config-data-table-BhgqwoqT.js} +2 -2
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js.map → chart-config-data-table-BhgqwoqT.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js → chart-config-funnel-BlSQYng0.js} +4 -4
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js.map → chart-config-funnel-BlSQYng0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js → chart-config-heat-map-DHQGFZhX.js} +2 -2
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js.map → chart-config-heat-map-DHQGFZhX.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js → chart-config-kpi-delta-yTA5ug_l.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js.map → chart-config-kpi-delta-yTA5ug_l.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js → chart-config-kpi-number-nVAwDXzq.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js.map → chart-config-kpi-number-nVAwDXzq.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js → chart-config-kpi-text-DZjqsx-b.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js.map → chart-config-kpi-text-DZjqsx-b.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js → chart-config-line-DR0ThxZy.js} +2 -2
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js.map → chart-config-line-DR0ThxZy.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js → chart-config-markdown-DZxdGNVQ.js} +2 -2
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js.map → chart-config-markdown-DZxdGNVQ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js → chart-config-pie-BM5lgH-w.js} +2 -2
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js.map → chart-config-pie-BM5lgH-w.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js → chart-config-radar-BBAVIF0S.js} +2 -2
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js.map → chart-config-radar-BBAVIF0S.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js → chart-config-radial-bar-CTwjDRnB.js} +2 -2
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js.map → chart-config-radial-bar-CTwjDRnB.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js → chart-config-sankey-CNAgsMQ4.js} +2 -2
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js.map → chart-config-sankey-CNAgsMQ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js → chart-config-scatter-CWvN2E-X.js} +2 -2
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js.map → chart-config-scatter-CWvN2E-X.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js → chart-config-sunburst-W_SKwaj0.js} +4 -4
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js.map → chart-config-sunburst-W_SKwaj0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js → chart-config-tree-map-CLmRvvMR.js} +2 -2
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js.map → chart-config-tree-map-CLmRvvMR.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js → chart-data-table-rUFLqysu.js} +4 -4
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js.map → chart-data-table-rUFLqysu.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js → chart-funnel-C7zGBfSw.js} +2 -2
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js.map → chart-funnel-C7zGBfSw.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js → chart-heat-map-B-l8hK8b.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js.map → chart-heat-map-B-l8hK8b.js.map} +1 -1
- package/dist/client/chunks/chart-kpi-delta-sfZEvQZm.js +351 -0
- package/dist/client/chunks/chart-kpi-delta-sfZEvQZm.js.map +1 -0
- package/dist/client/chunks/chart-kpi-number-BxGNOtzI.js +473 -0
- package/dist/client/chunks/chart-kpi-number-BxGNOtzI.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js → chart-kpi-text-BLQ_CWQP.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js.map → chart-kpi-text-BLQ_CWQP.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DqqE7ky9.js → chart-line-FSEpBk6Y.js} +5 -5
- package/dist/client/chunks/{chart-line-DqqE7ky9.js.map → chart-line-FSEpBk6Y.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js → chart-pie-BRQEH9e-.js} +2 -2
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js.map → chart-pie-BRQEH9e-.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js → chart-radar-DgsFyiIP.js} +2 -2
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js.map → chart-radar-DgsFyiIP.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js → chart-radial-bar-CUMoXyl9.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js.map → chart-radial-bar-CUMoXyl9.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js → chart-sankey-IAKDEe7A.js} +2 -2
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js.map → chart-sankey-IAKDEe7A.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js → chart-scatter-D6XwOD2W.js} +15 -15
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js.map → chart-scatter-D6XwOD2W.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js → chart-sunburst-CP_pnj0S.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js.map → chart-sunburst-CP_pnj0S.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js → chart-tree-map-DQMsn47a.js} +30 -30
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js.map → chart-tree-map-DQMsn47a.js.map} +1 -1
- package/dist/client/chunks/chartConfigRegistry-BumUIPw4.js +44 -0
- package/dist/client/chunks/{chartConfigRegistry-CiOq-PqX.js.map → chartConfigRegistry-BumUIPw4.js.map} +1 -1
- package/dist/client/chunks/charts-Dk_9XrA7.js +230 -0
- package/dist/client/chunks/charts-Dk_9XrA7.js.map +1 -0
- package/dist/client/chunks/{charts-core-CXrhEEVF.js → charts-core-CjQZBxmv.js} +10 -10
- package/dist/client/chunks/{charts-core-CXrhEEVF.js.map → charts-core-CjQZBxmv.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-BtsnUO4Q.js → charts-loader-ChTUa_-G.js} +30 -28
- package/dist/client/chunks/charts-loader-ChTUa_-G.js.map +1 -0
- package/dist/client/chunks/{components-BDrlf9Er.js → components-BKZ7EAg0.js} +3575 -3208
- package/dist/client/chunks/components-BKZ7EAg0.js.map +1 -0
- package/dist/client/chunks/{core-B8zw0qRf.js → core-BRC075EG.js} +2 -2
- package/dist/client/chunks/{core-B8zw0qRf.js.map → core-BRC075EG.js.map} +1 -1
- package/dist/client/chunks/hooks-D7APQ8uS.js +150 -0
- package/dist/client/chunks/{hooks-B8Zw5PfL.js.map → hooks-D7APQ8uS.js.map} +1 -1
- package/dist/client/chunks/{icons-NzFHtqeM.js → icons-DRreo6m8.js} +128 -112
- package/dist/client/chunks/{icons-NzFHtqeM.js.map → icons-DRreo6m8.js.map} +1 -1
- package/dist/client/chunks/{providers-CqCiJTEj.js → providers-Cj7PQfXn.js} +2 -2
- package/dist/client/chunks/{providers-CqCiJTEj.js.map → providers-Cj7PQfXn.js.map} +1 -1
- package/dist/client/chunks/retention-CzCo8262.js +120 -0
- package/dist/client/chunks/retention-CzCo8262.js.map +1 -0
- package/dist/client/chunks/{useDirtyStateTracking-C_mitVwh.js → useDirtyStateTracking-ZSi3voVl.js} +101 -99
- package/dist/client/chunks/useDirtyStateTracking-ZSi3voVl.js.map +1 -0
- package/dist/client/chunks/{vendor-DzzxS7Ay.js → vendor-cTQhZ_G3.js} +549 -541
- package/dist/client/chunks/vendor-cTQhZ_G3.js.map +1 -0
- package/dist/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +3 -1
- package/dist/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +36 -0
- package/dist/client/components/AnalysisBuilder/RetentionModeContent.d.ts +71 -0
- package/dist/client/components/AnalysisBuilder/types.d.ts +99 -0
- package/dist/client/components/DebugModal.d.ts +2 -1
- package/dist/client/components/charts/RetentionCombinedChart.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionCombinedChart.d.ts +14 -0
- package/dist/client/components/charts/RetentionHeatmap.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionHeatmap.d.ts +7 -0
- package/dist/client/components.js +2 -2
- package/dist/client/hooks/queries/index.d.ts +2 -1
- package/dist/client/hooks/queries/useDryRunQuery.d.ts +26 -0
- package/dist/client/hooks/queries/useExplainQuery.d.ts +3 -1
- package/dist/client/hooks/queries/useFlowQuery.d.ts +5 -0
- package/dist/client/hooks/queries/useRetentionQuery.d.ts +67 -0
- package/dist/client/hooks/useAnalysisBuilderHook.d.ts +61 -0
- package/dist/client/hooks/useAnalysisQueryExecution.d.ts +42 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons/customIcons.d.ts +7 -0
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +11 -11
- package/dist/client/providers.js +1 -1
- package/dist/client/stores/analysisBuilderStore.d.ts +86 -1
- package/dist/client/stores/dashboardStore.d.ts +2 -1
- package/dist/client/stores/slices/index.d.ts +2 -0
- package/dist/client/stores/slices/retentionSlice.d.ts +66 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/types/analysisConfig.d.ts +29 -4
- package/dist/client/types/funnel.d.ts +5 -0
- package/dist/client/types/retention.d.ts +301 -0
- package/dist/client/types.d.ts +6 -3
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +101 -79
- package/dist/server/index.d.ts +427 -0
- package/dist/server/index.js +9140 -4934
- package/package.json +5 -2
- package/dist/adapters/compiler-CO13DaEb.cjs +0 -192
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js +0 -6013
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js +0 -2540
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js.map +0 -1
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js +0 -435
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js.map +0 -1
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js +0 -392
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js.map +0 -1
- package/dist/client/chunks/chartConfigRegistry-CiOq-PqX.js +0 -44
- package/dist/client/chunks/charts-loader-BtsnUO4Q.js.map +0 -1
- package/dist/client/chunks/charts-xNubY0vm.js +0 -226
- package/dist/client/chunks/charts-xNubY0vm.js.map +0 -1
- package/dist/client/chunks/components-BDrlf9Er.js.map +0 -1
- package/dist/client/chunks/hooks-B8Zw5PfL.js +0 -123
- package/dist/client/chunks/useDirtyStateTracking-C_mitVwh.js.map +0 -1
- package/dist/client/chunks/vendor-DzzxS7Ay.js.map +0 -1
package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js → chart-activity-grid-BnweuBvr.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as h, jsxs as z } from "react/jsx-runtime";
|
|
2
2
|
import xe, { useRef as se, useState as G, useEffect as V, useMemo as pe, useLayoutEffect as we, useCallback as ve } from "react";
|
|
3
3
|
import { select as Y, max as ae, min as oe, scaleQuantize as be } from "d3";
|
|
4
|
-
import { u as Fe,
|
|
4
|
+
import { u as Fe, d as Me, h as Te } from "./charts-core-CjQZBxmv.js";
|
|
5
5
|
import { g as ke, w as We } from "./theme-Dp3hFed1.js";
|
|
6
6
|
const Qe = xe.memo(function({
|
|
7
7
|
data: T,
|
|
@@ -11,11 +11,11 @@ const Qe = xe.memo(function({
|
|
|
11
11
|
height: H = "100%",
|
|
12
12
|
colorPalette: I
|
|
13
13
|
}) {
|
|
14
|
-
const
|
|
14
|
+
const A = se(null), b = se(null), [W, E] = G({ width: 0, height: 0 }), [L, q] = G(!1), [J, U] = G("light"), O = Fe();
|
|
15
15
|
V(() => (U(ke()), We((e) => {
|
|
16
16
|
U(e);
|
|
17
17
|
})), []);
|
|
18
|
-
const
|
|
18
|
+
const C = pe(() => ({
|
|
19
19
|
showTooltip: v?.showTooltip ?? !0,
|
|
20
20
|
showLabels: v?.showLabels ?? !0,
|
|
21
21
|
fitToWidth: v?.fitToWidth ?? !1
|
|
@@ -169,7 +169,7 @@ const Qe = xe.memo(function({
|
|
|
169
169
|
return { year: s, week: g };
|
|
170
170
|
};
|
|
171
171
|
if (V(() => {
|
|
172
|
-
if (!T || T.length === 0 || !
|
|
172
|
+
if (!T || T.length === 0 || !A.current || !L || W.width === 0 || (Y(A.current).selectAll("*").remove(), !u?.dateField || !u?.valueField))
|
|
173
173
|
return;
|
|
174
174
|
const n = Array.isArray(u.dateField) ? u.dateField[0] : u.dateField, e = Array.isArray(u.valueField) ? u.valueField[0] : u.valueField;
|
|
175
175
|
if (!n || !e)
|
|
@@ -220,14 +220,14 @@ const Qe = xe.memo(function({
|
|
|
220
220
|
right: 10
|
|
221
221
|
}, $ = W.width - x.left - x.right, K = W.height - x.top - x.bottom;
|
|
222
222
|
let c, D;
|
|
223
|
-
if (
|
|
223
|
+
if (C.fitToWidth) {
|
|
224
224
|
const t = $ / B, r = K / P, a = Math.min(t, r);
|
|
225
225
|
c = i.cellWidth * a, D = i.cellHeight * a;
|
|
226
226
|
} else {
|
|
227
227
|
const r = { width: 16, height: 16 }, a = 24, l = $ / B, p = K / P, w = Math.min(l, p);
|
|
228
228
|
c = Math.max(r.width, Math.min(a, i.cellWidth * w)), D = Math.max(r.height, Math.min(a, i.cellHeight * w)), s === "week" && c < r.width && (c = r.width);
|
|
229
229
|
}
|
|
230
|
-
const ee = m.length * c + (m.length - 1) * 4, de = ee > $ ? ee + x.left + x.right : W.width, N = Y(
|
|
230
|
+
const ee = m.length * c + (m.length - 1) * 4, de = ee > $ ? ee + x.left + x.right : W.width, N = Y(A.current).attr("width", de).attr("height", W.height).append("g").attr("transform", `translate(${x.left},${x.top})`), te = g.map((t) => t.value), ue = oe(te) || 0, he = ae(te) || 1, me = be().domain([ue, he]).range(I?.gradient || Te), re = /* @__PURE__ */ new Map();
|
|
231
231
|
g.forEach((t) => {
|
|
232
232
|
const r = `${t.x}-${t.y}`;
|
|
233
233
|
re.set(r, t);
|
|
@@ -239,7 +239,7 @@ const Qe = xe.memo(function({
|
|
|
239
239
|
for (const t of m)
|
|
240
240
|
for (let r = y; r <= f; r++) {
|
|
241
241
|
const a = `${t}-${r}`, l = re.get(a), p = S.get(t) || 0, w = N.append("rect").attr("x", p * (c + 4)).attr("y", (r - y) * (D + 4)).attr("width", c).attr("height", D).attr("rx", 2).attr("ry", 2).style("fill", l ? me(l.value) : ye).style("stroke", ne).style("stroke-width", 1);
|
|
242
|
-
|
|
242
|
+
C.showTooltip && w.style("cursor", "pointer").on("mouseover", function(d) {
|
|
243
243
|
if (Y(this).style("stroke", "#000").style("stroke-width", 2), l) {
|
|
244
244
|
const M = [
|
|
245
245
|
`<strong>${l.label}</strong>`,
|
|
@@ -253,7 +253,7 @@ const Qe = xe.memo(function({
|
|
|
253
253
|
Y(this).style("stroke", ne).style("stroke-width", 1), R.transition().duration(200).style("opacity", 0);
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
|
-
if (
|
|
256
|
+
if (C.showLabels) {
|
|
257
257
|
if (i.hasHierarchicalLabels && i.getYearFromX) {
|
|
258
258
|
const t = /* @__PURE__ */ new Map();
|
|
259
259
|
for (const r of m) {
|
|
@@ -288,7 +288,7 @@ const Qe = xe.memo(function({
|
|
|
288
288
|
return () => {
|
|
289
289
|
R.remove();
|
|
290
290
|
};
|
|
291
|
-
}, [T, u, v, k, W, L,
|
|
291
|
+
}, [T, u, v, k, W, L, C, I, J, O, _]), !T || T.length === 0)
|
|
292
292
|
return /* @__PURE__ */ h(
|
|
293
293
|
"div",
|
|
294
294
|
{
|
|
@@ -327,11 +327,11 @@ const Qe = xe.memo(function({
|
|
|
327
327
|
] })
|
|
328
328
|
}
|
|
329
329
|
) : /* @__PURE__ */ h("div", { className: "w-full flex flex-col relative", style: { height: H, minHeight: "250px", overflow: "hidden", width: "100%" }, children: /* @__PURE__ */ z("div", { ref: b, className: "w-full h-full relative overflow-x-auto", style: { width: "100%" }, children: [
|
|
330
|
-
/* @__PURE__ */ h("svg", { ref:
|
|
330
|
+
/* @__PURE__ */ h("svg", { ref: A, className: "h-full" }),
|
|
331
331
|
!L && /* @__PURE__ */ h("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ h("div", { className: "text-dc-text-muted text-sm", children: "Measuring chart dimensions..." }) })
|
|
332
332
|
] }) });
|
|
333
333
|
});
|
|
334
334
|
export {
|
|
335
335
|
Qe as default
|
|
336
336
|
};
|
|
337
|
-
//# sourceMappingURL=chart-activity-grid-
|
|
337
|
+
//# sourceMappingURL=chart-activity-grid-BnweuBvr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-activity-grid-CuPARsr1.js","sources":["../../../src/client/components/charts/ActivityGridChart.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState, useMemo, useCallback } from 'react'\nimport { select, scaleQuantize, max, min, transition as _transition } from 'd3'\n// _transition import is for side effects only - it extends Selection.prototype with .transition() method\nimport { CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants'\nimport { formatTimeValue } from '../../utils/chartUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport { getTheme, watchThemeChanges, type Theme } from '../../theme'\nimport type { ChartProps } from '../../types'\n\ninterface GridCell {\n x: number\n y: number\n value: number\n date: Date\n label: string\n}\n\ninterface GridMapping {\n extractX: (date: Date) => number\n extractY: (date: Date) => number\n xLabels: string[]\n yLabels: string[]\n xFormat: (value: number) => string\n yFormat: (value: number) => string\n cellWidth: number\n cellHeight: number\n hasHierarchicalLabels?: boolean\n getYearFromX?: (value: number) => number\n}\n\nconst ActivityGridChart = React.memo(function ActivityGridChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const svgRef = useRef<SVGSVGElement | null>(null)\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [dimensionsReady, setDimensionsReady] = useState(false)\n const [currentTheme, setCurrentTheme] = useState<Theme>('light')\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Watch for theme changes\n useEffect(() => {\n setCurrentTheme(getTheme())\n const unwatch = watchThemeChanges((theme) => {\n setCurrentTheme(theme)\n })\n return unwatch\n }, [])\n\n const safeDisplayConfig = useMemo(() => ({\n showTooltip: displayConfig?.showTooltip ?? true,\n showLabels: displayConfig?.showLabels ?? true,\n fitToWidth: displayConfig?.fitToWidth ?? false\n }), [displayConfig?.showTooltip, displayConfig?.showLabels, displayConfig?.fitToWidth])\n\n // Enhanced dimension measurement with retry mechanism\n useLayoutEffect(() => {\n let retryCount = 0\n const maxRetries = 10\n let rafId: number\n let timeoutId: ReturnType<typeof setTimeout>\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n \n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n setDimensionsReady(true)\n return true\n }\n }\n return false\n }\n \n const success = updateDimensions()\n \n if (!success && retryCount < maxRetries) {\n const retryWithRaf = () => {\n const rafSuccess = updateDimensions()\n \n if (!rafSuccess && retryCount < maxRetries) {\n retryCount++\n timeoutId = setTimeout(() => {\n rafId = requestAnimationFrame(retryWithRaf)\n }, 50 * retryCount)\n }\n }\n \n rafId = requestAnimationFrame(retryWithRaf)\n }\n \n return () => {\n if (rafId) cancelAnimationFrame(rafId)\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [])\n\n // ResizeObserver for dynamic resizing\n useEffect(() => {\n let resizeObserver: ResizeObserver | null = null\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n }\n \n if (containerRef.current) {\n resizeObserver = new ResizeObserver(() => updateDimensions())\n resizeObserver.observe(containerRef.current)\n updateDimensions()\n }\n\n window.addEventListener('resize', updateDimensions)\n \n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n window.removeEventListener('resize', updateDimensions)\n }\n }, [dimensionsReady])\n\n // Helper functions for grid coordinate extraction\n const getQuarter = (date: Date): number => {\n return Math.floor(date.getMonth() / 3) + 1 // 1-4\n }\n\n const getMonthOfQuarter = (date: Date): number => {\n return (date.getMonth() % 3) + 1 // 1-3\n }\n\n const getWeekOfMonth = (date: Date): number => {\n // Always start from week 1 for the first week of the month, regardless of day offset\n const dayOfMonth = date.getDate()\n return Math.floor((dayOfMonth - 1) / 7) + 1 // 1-5 typically\n }\n\n // Get granularity mapping based on time dimension\n const getGridMapping = useCallback((granularity: string): GridMapping | null => {\n switch (granularity?.toLowerCase()) {\n case 'year':\n // Year granularity is not useful for activity grids\n return null\n \n case 'quarter':\n // Quarter granularity: years × quarters\n return {\n extractX: (date: Date) => date.getFullYear(),\n extractY: (date: Date) => getQuarter(date) - 1, // 0-3 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Q1', 'Q2', 'Q3', 'Q4'],\n xFormat: (value: number) => `'${value.toString().slice(-2)}`, // '24 instead of 2024\n yFormat: (value: number) => ['Q1', 'Q2', 'Q3', 'Q4'][value] || '',\n cellWidth: 16,\n cellHeight: 16\n }\n \n case 'month':\n // Month granularity: quarters × months of quarter\n // Show years above and quarters (Q1, Q2, Q3, Q4) as columns with hierarchical labels\n return {\n extractX: (date: Date) => {\n const year = date.getFullYear()\n const quarter = getQuarter(date) // 1-4\n return year * 10 + quarter // e.g., 20241, 20242, 20243, 20244 (only 4 per year)\n },\n extractY: (date: Date) => getMonthOfQuarter(date) - 1, // 0-2 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Month 1', 'Month 2', 'Month 3'],\n xFormat: (value: number) => {\n const quarter = value % 10\n return `Q${quarter}` // Just show Q1, Q2, Q3, Q4 for individual columns\n },\n yFormat: (value: number) => ['Month 1', 'Month 2', 'Month 3'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Flag to indicate we need special handling\n getYearFromX: (value: number) => Math.floor(value / 10) // Helper to get year for grouping\n }\n \n case 'week':\n // Week granularity: months × weeks of month (same structure as quarters but with months as columns)\n return {\n extractX: (date: Date) => {\n const year = date.getFullYear()\n const month = date.getMonth() + 1\n return year * 100 + month // e.g., 202401, 202402, etc.\n },\n extractY: (date: Date) => getWeekOfMonth(date) - 1, // 0-5 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5'],\n xFormat: (value: number) => {\n const month = value % 100\n const monthNames = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']\n return monthNames[month - 1] || ''\n },\n yFormat: (value: number) => ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Add hierarchical labels like month view\n getYearFromX: (value: number) => Math.floor(value / 100) // Helper to get year for grouping\n }\n \n case 'day':\n // Day granularity: weeks × days of week with hierarchical year/week labels\n return {\n extractX: (date: Date) => {\n const { year, week } = getWeekOfYear(date)\n return year * 100 + week // e.g., 202401, 202402, etc.\n },\n extractY: (date: Date) => date.getDay(), // 0-6 (Sun-Sat)\n xLabels: [], // Will be determined from data\n yLabels: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n xFormat: (value: number) => {\n const week = value % 100\n return `${week}`\n },\n yFormat: (value: number) => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Add hierarchical labels\n getYearFromX: (value: number) => Math.floor(value / 100) // Helper to get year for grouping\n }\n\n case 'hour':\n // Hour granularity: days × 3-hour blocks with hierarchical year/month labels\n return {\n extractX: (date: Date) => {\n // Get day as YYYYMMDD number for unique day identification\n const year = date.getFullYear()\n const month = date.getMonth() + 1\n const day = date.getDate()\n return year * 10000 + month * 100 + day // e.g., 20240115\n },\n extractY: (date: Date) => Math.floor(date.getHours() / 3), // 0-7 for 8 three-hour blocks\n xLabels: [], // Will be determined from data\n yLabels: ['00-03', '03-06', '06-09', '09-12', '12-15', '15-18', '18-21', '21-00'],\n xFormat: (value: number) => {\n // Format YYYYMMDD as just the day number\n const day = value % 100\n return `${day}`\n },\n yFormat: (value: number) => ['00-03', '03-06', '06-09', '09-12', '12-15', '15-18', '18-21', '21-00'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Show year/month grouping above\n getYearFromX: (value: number) => Math.floor(value / 100) // Extract YYYYMM for month grouping\n }\n\n default:\n return null\n }\n }, [])\n\n // Helper function to get week of year with correct year (1-53)\n const getWeekOfYear = (date: Date): { year: number, week: number } => {\n const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))\n const dayNum = d.getUTCDay() || 7\n d.setUTCDate(d.getUTCDate() + 4 - dayNum)\n const year = d.getUTCFullYear()\n const yearStart = new Date(Date.UTC(year, 0, 1))\n const week = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7)\n return { year, week }\n }\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n // Clear previous chart\n select(svgRef.current).selectAll('*').remove()\n\n // Validate chartConfig\n if (!chartConfig?.dateField || !chartConfig?.valueField) {\n return\n }\n\n const dateField = Array.isArray(chartConfig.dateField) ? chartConfig.dateField[0] : chartConfig.dateField\n const valueField = Array.isArray(chartConfig.valueField) ? chartConfig.valueField[0] : chartConfig.valueField\n\n\n if (!dateField || !valueField) {\n return\n }\n\n // Get granularity directly from the query's time dimensions\n const getQueryGranularity = () => {\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return 'day'\n }\n \n // Find the time dimension that matches our dateField\n const timeDim = queryObject.timeDimensions.find((td: any) => \n td.dimension === dateField || td.dimension.includes(dateField)\n )\n \n if (timeDim && timeDim.granularity) {\n return timeDim.granularity\n }\n \n // Fallback to first time dimension's granularity\n const firstTimeDim = queryObject.timeDimensions[0]\n if (firstTimeDim && firstTimeDim.granularity) {\n return firstTimeDim.granularity\n }\n \n return 'day'\n }\n \n const queryGranularity = getQueryGranularity()\n const gridMapping = getGridMapping(queryGranularity)\n \n // Handle unsupported granularity\n if (!gridMapping) {\n return\n }\n \n\n // Transform data for grid\n const gridData: GridCell[] = data.map(item => {\n const dateValue = item[dateField]\n const value = typeof item[valueField] === 'string' \n ? parseFloat(item[valueField]) \n : (item[valueField] || 0)\n \n // Parse the date\n let date: Date\n if (typeof dateValue === 'string') {\n // Handle different date formats\n let isoStr = dateValue\n if (dateValue.includes(' ')) {\n isoStr = dateValue.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n date = new Date(isoStr)\n } else {\n date = new Date(dateValue)\n }\n\n // Skip invalid dates\n if (isNaN(date.getTime())) {\n return null\n }\n\n const x = gridMapping.extractX(date)\n const y = gridMapping.extractY(date)\n \n return {\n x,\n y,\n value,\n date,\n label: formatTimeValue(dateValue, queryGranularity)\n }\n }).filter((cell): cell is GridCell => cell !== null)\n\n\n if (gridData.length === 0) return\n\n // Calculate grid dimensions\n const maxY = max(gridData, d => d.y) || 0\n const minY = min(gridData, d => d.y) || 0\n\n\n // Generate complete X range first so we can calculate proper grid width\n const getCompleteXRange = (): number[] => {\n const dataXValues = [...new Set(gridData.map(cell => cell.x))].sort()\n \n if (queryGranularity === 'quarter') {\n // For quarters: only show quarters that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'month') {\n // For months: only show quarters that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'week') {\n // For weeks: only show months that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'day') {\n // For days: only show the actual weeks that have data to avoid discontinuities\n return dataXValues\n }\n \n // For other granularities, use the actual data values\n return dataXValues\n }\n \n const completeXRange = getCompleteXRange()\n \n // Calculate grid dimensions based on complete X range\n const gridWidth = completeXRange.length * gridMapping.cellWidth + (completeXRange.length - 1) * 4\n const gridHeight = (maxY - minY + 1) * gridMapping.cellHeight + (maxY - minY) * 4\n\n const margin = { \n ...CHART_MARGINS, \n left: 60, // Space for Y-axis labels\n bottom: 10, // Reduced since labels are at top\n top: gridMapping.hasHierarchicalLabels ? 40 : 25, // Extra space for hierarchical labels\n right: 10\n }\n \n const availableWidth = dimensions.width - margin.left - margin.right\n const availableHeight = dimensions.height - margin.top - margin.bottom\n\n // Scale the grid to fit the available space\n let finalCellWidth: number\n let finalCellHeight: number\n\n if (safeDisplayConfig.fitToWidth) {\n // Fit to Width mode: Calculate cell size to perfectly fit both dimensions\n // Remove min/max constraints and let blocks scale to optimal size\n const scaleX = availableWidth / gridWidth\n const scaleY = availableHeight / gridHeight\n const scale = Math.min(scaleX, scaleY)\n\n // Use the scale to calculate cell size, maintaining 1:1 aspect ratio\n finalCellWidth = gridMapping.cellWidth * scale\n finalCellHeight = gridMapping.cellHeight * scale\n } else {\n // Default mode: Use minimum/maximum size constraints with scrolling\n const getMinCellSize = () => {\n return { width: 16, height: 16 } // Same size for all views\n }\n\n const minCellSize = getMinCellSize()\n const maxCellSize = 24\n\n const scaleX = availableWidth / gridWidth\n const scaleY = availableHeight / gridHeight\n const scale = Math.min(scaleX, scaleY)\n\n // Calculate final cell size with constraints\n finalCellWidth = Math.max(minCellSize.width, Math.min(maxCellSize, gridMapping.cellWidth * scale))\n finalCellHeight = Math.max(minCellSize.height, Math.min(maxCellSize, gridMapping.cellHeight * scale))\n\n // For week view, prefer scrolling over tiny cells\n if (queryGranularity === 'week' && finalCellWidth < minCellSize.width) {\n finalCellWidth = minCellSize.width\n }\n }\n \n // Calculate actual grid dimensions with the final cell sizes\n const actualGridWidth = completeXRange.length * finalCellWidth + (completeXRange.length - 1) * 4\n \n // Determine if we need horizontal scrolling\n const needsHorizontalScroll = actualGridWidth > availableWidth\n const svgWidth = needsHorizontalScroll ? actualGridWidth + margin.left + margin.right : dimensions.width\n \n\n const svg = select(svgRef.current)\n .attr('width', svgWidth)\n .attr('height', dimensions.height)\n\n const g = svg.append('g')\n .attr('transform', `translate(${margin.left},${margin.top})`)\n\n // Set up color scale\n const values = gridData.map(d => d.value)\n const minValue = min(values) || 0\n const maxValue = max(values) || 1\n\n const colorScale = scaleQuantize<string>()\n .domain([minValue, maxValue])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n\n // Create grid data map for quick lookup\n const gridMap = new Map<string, GridCell>()\n gridData.forEach(cell => {\n const key = `${cell.x}-${cell.y}`\n gridMap.set(key, cell)\n })\n\n // Get theme colors from CSS variables\n const getThemeColor = (varName: string, fallback: string) => {\n const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return value || fallback\n }\n\n const isDark = currentTheme !== 'light'\n const textColor = isDark\n ? getThemeColor('--dc-text-muted', '#cbd5e1') // Lighter text for dark mode\n : getThemeColor('--dc-text-secondary', '#374151') // Darker text for light mode\n const lineColor = getThemeColor('--dc-border', '#e5e7eb')\n // Use theme-aware colors for empty cells: light gray in light mode, slightly lighter than bg in dark mode\n const emptyCellColor = isDark\n ? getThemeColor('--dc-bg-secondary', '#1e293b') // Slightly lighter than dark background\n : getThemeColor('--dc-bg-secondary', '#f3f4f6') // Very light gray in light mode\n const cellStrokeColor = isDark\n ? getThemeColor('--dc-border', '#334155') // Subtle border in dark mode\n : getThemeColor('--dc-bg', '#ffffff') // White border in light mode\n\n // Create tooltip\n const tooltip = select('body').append('div')\n .attr('class', 'activity-grid-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n\n // Create a mapping from X values to their position indices for proper spacing\n const xValueToIndex = new Map<number, number>()\n completeXRange.forEach((x, index) => {\n xValueToIndex.set(x, index)\n })\n \n // Render grid cells for the complete X range\n for (const x of completeXRange) {\n for (let y = minY; y <= maxY; y++) {\n const key = `${x}-${y}`\n const cell = gridMap.get(key)\n const xIndex = xValueToIndex.get(x) || 0\n \n const rect = g.append('rect')\n .attr('x', xIndex * (finalCellWidth + 4))\n .attr('y', (y - minY) * (finalCellHeight + 4))\n .attr('width', finalCellWidth)\n .attr('height', finalCellHeight)\n .attr('rx', 2)\n .attr('ry', 2)\n .style('fill', cell ? colorScale(cell.value) : emptyCellColor)\n .style('stroke', cellStrokeColor)\n .style('stroke-width', 1)\n\n // Add hover effects and tooltips\n if (safeDisplayConfig.showTooltip) {\n rect\n .style('cursor', 'pointer')\n .on('mouseover', function(event) {\n select(this)\n .style('stroke', '#000')\n .style('stroke-width', 2)\n\n if (cell) {\n const tooltipContent = [\n `<strong>${cell.label}</strong>`,\n `${getFieldLabel(valueField)}: ${cell.value}`\n ].join('<br>')\n\n tooltip\n .html(tooltipContent)\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n }\n })\n .on('mousemove', function(event) {\n tooltip\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n })\n .on('mouseout', function() {\n select(this)\n .style('stroke', cellStrokeColor)\n .style('stroke-width', 1)\n\n tooltip\n .transition()\n .duration(200)\n .style('opacity', 0)\n })\n }\n }\n }\n\n // Add axis labels if enabled\n if (safeDisplayConfig.showLabels) {\n if (gridMapping.hasHierarchicalLabels && gridMapping.getYearFromX) {\n // Special handling for quarter view with hierarchical labels\n // Use the complete X range to show all quarters/months\n \n // Group quarters by year\n const yearGroups = new Map<number, number[]>()\n for (const x of completeXRange) {\n const year = gridMapping.getYearFromX(x)\n if (!yearGroups.has(year)) {\n yearGroups.set(year, [])\n }\n yearGroups.get(year)!.push(x)\n }\n \n \n // Draw column labels (Q1-Q4 for months, Jan-Dec for weeks)\n for (const x of completeXRange) {\n const xIndex = xValueToIndex.get(x) || 0\n g.append('text')\n .attr('x', xIndex * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -8)\n .attr('text-anchor', 'middle')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.xFormat(x))\n }\n\n // Draw year group labels above quarters\n for (const [year, xValues] of yearGroups) {\n if (xValues.length > 0) {\n // Get the index positions for proper spacing\n const startIndex = Math.min(...xValues.map(x => xValueToIndex.get(x) || 0))\n const endIndex = Math.max(...xValues.map(x => xValueToIndex.get(x) || 0))\n const centerIndex = (startIndex + endIndex) / 2\n\n // Year label (or year/month for hour granularity)\n let labelText = ''\n if (year > 9999) {\n // For hour granularity, year is encoded as YYYYMM\n const actualYear = Math.floor(year / 100)\n const month = year % 100\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n labelText = `${monthNames[month - 1]} '${actualYear.toString().slice(-2)}`\n } else {\n // For other granularities, just show the year\n labelText = `'${year.toString().slice(-2)}`\n }\n\n g.append('text')\n .attr('x', centerIndex * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -25)\n .attr('text-anchor', 'middle')\n .style('font-size', '12px')\n .style('font-weight', 'bold')\n .style('fill', textColor)\n .text(labelText)\n\n // Optional: Add a subtle line to group quarters under the year\n if (xValues.length > 1) {\n g.append('line')\n .attr('x1', startIndex * (finalCellWidth + 4))\n .attr('x2', endIndex * (finalCellWidth + 4) + finalCellWidth)\n .attr('y1', -20)\n .attr('y2', -20)\n .style('stroke', lineColor)\n .style('stroke-width', 1)\n .style('opacity', 0.3)\n }\n }\n }\n } else {\n // Regular X-axis labels for other granularities\n const xLabelStep = Math.max(1, Math.floor(completeXRange.length / 10))\n for (let i = 0; i < completeXRange.length; i += xLabelStep) {\n const x = completeXRange[i]\n g.append('text')\n .attr('x', i * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -8)\n .attr('text-anchor', 'middle')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.xFormat(x))\n }\n }\n\n // Y-axis labels (left) - same for all granularities\n for (let y = minY; y <= maxY; y++) {\n g.append('text')\n .attr('x', -8)\n .attr('y', (y - minY) * (finalCellHeight + 4) + finalCellHeight / 2)\n .attr('text-anchor', 'end')\n .attr('dy', '.35em')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.yFormat(y))\n }\n }\n\n // Cleanup function\n return () => {\n tooltip.remove()\n }\n }, [data, chartConfig, displayConfig, queryObject, dimensions, dimensionsReady, safeDisplayConfig, colorPalette, currentTheme, getFieldLabel, getGridMapping])\n\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 points to display in activity grid</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.dateField && chartConfig?.valueField\n if (!hasValidConfig) {\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\">Configuration Required</div>\n <div className=\"text-xs text-dc-text-secondary\">Activity grid requires a time dimension and a measure</div>\n </div>\n </div>\n )\n }\n\n // Check if granularity is supported\n const dateField = Array.isArray(chartConfig.dateField) ? chartConfig.dateField[0] : chartConfig.dateField\n const granularityFromQuery = queryObject?.timeDimensions?.find((td: any) => \n td.dimension === dateField || td.dimension.includes(dateField)\n )?.granularity || 'day'\n \n if (granularityFromQuery?.toLowerCase() === 'year') {\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\">Granularity Too High</div>\n <div className=\"text-xs text-dc-text-secondary\">Activity grids work best with hour, day, week, month, or quarter granularity</div>\n <div className=\"text-xs text-dc-text-secondary mt-1\">Please choose a lower granularity for your time dimension</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full flex flex-col relative\" style={{ height, minHeight: '250px', overflow: 'hidden', width: '100%' }}>\n <div ref={containerRef} className=\"w-full h-full relative overflow-x-auto\" style={{ width: '100%' }}>\n <svg ref={svgRef} className=\"h-full\" />\n {!dimensionsReady && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"text-dc-text-muted text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default ActivityGridChart"],"names":["ActivityGridChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","svgRef","useRef","containerRef","dimensions","setDimensions","useState","dimensionsReady","setDimensionsReady","currentTheme","setCurrentTheme","getFieldLabel","useCubeFieldLabel","useEffect","getTheme","watchThemeChanges","theme","safeDisplayConfig","useMemo","useLayoutEffect","retryCount","maxRetries","rafId","timeoutId","updateDimensions","width","retryWithRaf","resizeObserver","getQuarter","date","getMonthOfQuarter","getWeekOfMonth","dayOfMonth","getGridMapping","useCallback","granularity","value","year","quarter","month","week","getWeekOfYear","day","d","dayNum","yearStart","select","dateField","valueField","queryGranularity","timeDim","td","firstTimeDim","gridMapping","gridData","item","dateValue","isoStr","x","y","formatTimeValue","cell","maxY","max","minY","min","completeXRange","dataXValues","gridWidth","gridHeight","margin","availableWidth","availableHeight","finalCellWidth","finalCellHeight","scaleX","scaleY","scale","minCellSize","maxCellSize","actualGridWidth","svgWidth","g","values","minValue","maxValue","colorScale","scaleQuantize","CHART_COLORS_GRADIENT","gridMap","key","getThemeColor","varName","fallback","isDark","textColor","lineColor","emptyCellColor","cellStrokeColor","tooltip","xValueToIndex","index","xIndex","rect","event","tooltipContent","yearGroups","xValues","startIndex","endIndex","centerIndex","labelText","actualYear","xLabelStep","i","jsx","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-activity-grid-BnweuBvr.js","sources":["../../../src/client/components/charts/ActivityGridChart.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState, useMemo, useCallback } from 'react'\nimport { select, scaleQuantize, max, min, transition as _transition } from 'd3'\n// _transition import is for side effects only - it extends Selection.prototype with .transition() method\nimport { CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants'\nimport { formatTimeValue } from '../../utils/chartUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport { getTheme, watchThemeChanges, type Theme } from '../../theme'\nimport type { ChartProps } from '../../types'\n\ninterface GridCell {\n x: number\n y: number\n value: number\n date: Date\n label: string\n}\n\ninterface GridMapping {\n extractX: (date: Date) => number\n extractY: (date: Date) => number\n xLabels: string[]\n yLabels: string[]\n xFormat: (value: number) => string\n yFormat: (value: number) => string\n cellWidth: number\n cellHeight: number\n hasHierarchicalLabels?: boolean\n getYearFromX?: (value: number) => number\n}\n\nconst ActivityGridChart = React.memo(function ActivityGridChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const svgRef = useRef<SVGSVGElement | null>(null)\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [dimensionsReady, setDimensionsReady] = useState(false)\n const [currentTheme, setCurrentTheme] = useState<Theme>('light')\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Watch for theme changes\n useEffect(() => {\n setCurrentTheme(getTheme())\n const unwatch = watchThemeChanges((theme) => {\n setCurrentTheme(theme)\n })\n return unwatch\n }, [])\n\n const safeDisplayConfig = useMemo(() => ({\n showTooltip: displayConfig?.showTooltip ?? true,\n showLabels: displayConfig?.showLabels ?? true,\n fitToWidth: displayConfig?.fitToWidth ?? false\n }), [displayConfig?.showTooltip, displayConfig?.showLabels, displayConfig?.fitToWidth])\n\n // Enhanced dimension measurement with retry mechanism\n useLayoutEffect(() => {\n let retryCount = 0\n const maxRetries = 10\n let rafId: number\n let timeoutId: ReturnType<typeof setTimeout>\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n \n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n setDimensionsReady(true)\n return true\n }\n }\n return false\n }\n \n const success = updateDimensions()\n \n if (!success && retryCount < maxRetries) {\n const retryWithRaf = () => {\n const rafSuccess = updateDimensions()\n \n if (!rafSuccess && retryCount < maxRetries) {\n retryCount++\n timeoutId = setTimeout(() => {\n rafId = requestAnimationFrame(retryWithRaf)\n }, 50 * retryCount)\n }\n }\n \n rafId = requestAnimationFrame(retryWithRaf)\n }\n \n return () => {\n if (rafId) cancelAnimationFrame(rafId)\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [])\n\n // ResizeObserver for dynamic resizing\n useEffect(() => {\n let resizeObserver: ResizeObserver | null = null\n \n const updateDimensions = () => {\n if (containerRef.current) {\n const { width, height } = containerRef.current.getBoundingClientRect()\n if (width > 0 && height > 0) {\n setDimensions({ width, height })\n if (!dimensionsReady) {\n setDimensionsReady(true)\n }\n }\n }\n }\n \n if (containerRef.current) {\n resizeObserver = new ResizeObserver(() => updateDimensions())\n resizeObserver.observe(containerRef.current)\n updateDimensions()\n }\n\n window.addEventListener('resize', updateDimensions)\n \n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n window.removeEventListener('resize', updateDimensions)\n }\n }, [dimensionsReady])\n\n // Helper functions for grid coordinate extraction\n const getQuarter = (date: Date): number => {\n return Math.floor(date.getMonth() / 3) + 1 // 1-4\n }\n\n const getMonthOfQuarter = (date: Date): number => {\n return (date.getMonth() % 3) + 1 // 1-3\n }\n\n const getWeekOfMonth = (date: Date): number => {\n // Always start from week 1 for the first week of the month, regardless of day offset\n const dayOfMonth = date.getDate()\n return Math.floor((dayOfMonth - 1) / 7) + 1 // 1-5 typically\n }\n\n // Get granularity mapping based on time dimension\n const getGridMapping = useCallback((granularity: string): GridMapping | null => {\n switch (granularity?.toLowerCase()) {\n case 'year':\n // Year granularity is not useful for activity grids\n return null\n \n case 'quarter':\n // Quarter granularity: years × quarters\n return {\n extractX: (date: Date) => date.getFullYear(),\n extractY: (date: Date) => getQuarter(date) - 1, // 0-3 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Q1', 'Q2', 'Q3', 'Q4'],\n xFormat: (value: number) => `'${value.toString().slice(-2)}`, // '24 instead of 2024\n yFormat: (value: number) => ['Q1', 'Q2', 'Q3', 'Q4'][value] || '',\n cellWidth: 16,\n cellHeight: 16\n }\n \n case 'month':\n // Month granularity: quarters × months of quarter\n // Show years above and quarters (Q1, Q2, Q3, Q4) as columns with hierarchical labels\n return {\n extractX: (date: Date) => {\n const year = date.getFullYear()\n const quarter = getQuarter(date) // 1-4\n return year * 10 + quarter // e.g., 20241, 20242, 20243, 20244 (only 4 per year)\n },\n extractY: (date: Date) => getMonthOfQuarter(date) - 1, // 0-2 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Month 1', 'Month 2', 'Month 3'],\n xFormat: (value: number) => {\n const quarter = value % 10\n return `Q${quarter}` // Just show Q1, Q2, Q3, Q4 for individual columns\n },\n yFormat: (value: number) => ['Month 1', 'Month 2', 'Month 3'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Flag to indicate we need special handling\n getYearFromX: (value: number) => Math.floor(value / 10) // Helper to get year for grouping\n }\n \n case 'week':\n // Week granularity: months × weeks of month (same structure as quarters but with months as columns)\n return {\n extractX: (date: Date) => {\n const year = date.getFullYear()\n const month = date.getMonth() + 1\n return year * 100 + month // e.g., 202401, 202402, etc.\n },\n extractY: (date: Date) => getWeekOfMonth(date) - 1, // 0-5 for indexing\n xLabels: [], // Will be determined from data\n yLabels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5'],\n xFormat: (value: number) => {\n const month = value % 100\n const monthNames = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']\n return monthNames[month - 1] || ''\n },\n yFormat: (value: number) => ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Add hierarchical labels like month view\n getYearFromX: (value: number) => Math.floor(value / 100) // Helper to get year for grouping\n }\n \n case 'day':\n // Day granularity: weeks × days of week with hierarchical year/week labels\n return {\n extractX: (date: Date) => {\n const { year, week } = getWeekOfYear(date)\n return year * 100 + week // e.g., 202401, 202402, etc.\n },\n extractY: (date: Date) => date.getDay(), // 0-6 (Sun-Sat)\n xLabels: [], // Will be determined from data\n yLabels: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n xFormat: (value: number) => {\n const week = value % 100\n return `${week}`\n },\n yFormat: (value: number) => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Add hierarchical labels\n getYearFromX: (value: number) => Math.floor(value / 100) // Helper to get year for grouping\n }\n\n case 'hour':\n // Hour granularity: days × 3-hour blocks with hierarchical year/month labels\n return {\n extractX: (date: Date) => {\n // Get day as YYYYMMDD number for unique day identification\n const year = date.getFullYear()\n const month = date.getMonth() + 1\n const day = date.getDate()\n return year * 10000 + month * 100 + day // e.g., 20240115\n },\n extractY: (date: Date) => Math.floor(date.getHours() / 3), // 0-7 for 8 three-hour blocks\n xLabels: [], // Will be determined from data\n yLabels: ['00-03', '03-06', '06-09', '09-12', '12-15', '15-18', '18-21', '21-00'],\n xFormat: (value: number) => {\n // Format YYYYMMDD as just the day number\n const day = value % 100\n return `${day}`\n },\n yFormat: (value: number) => ['00-03', '03-06', '06-09', '09-12', '12-15', '15-18', '18-21', '21-00'][value] || '',\n cellWidth: 16,\n cellHeight: 16,\n hasHierarchicalLabels: true, // Show year/month grouping above\n getYearFromX: (value: number) => Math.floor(value / 100) // Extract YYYYMM for month grouping\n }\n\n default:\n return null\n }\n }, [])\n\n // Helper function to get week of year with correct year (1-53)\n const getWeekOfYear = (date: Date): { year: number, week: number } => {\n const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))\n const dayNum = d.getUTCDay() || 7\n d.setUTCDate(d.getUTCDate() + 4 - dayNum)\n const year = d.getUTCFullYear()\n const yearStart = new Date(Date.UTC(year, 0, 1))\n const week = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7)\n return { year, week }\n }\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n // Clear previous chart\n select(svgRef.current).selectAll('*').remove()\n\n // Validate chartConfig\n if (!chartConfig?.dateField || !chartConfig?.valueField) {\n return\n }\n\n const dateField = Array.isArray(chartConfig.dateField) ? chartConfig.dateField[0] : chartConfig.dateField\n const valueField = Array.isArray(chartConfig.valueField) ? chartConfig.valueField[0] : chartConfig.valueField\n\n\n if (!dateField || !valueField) {\n return\n }\n\n // Get granularity directly from the query's time dimensions\n const getQueryGranularity = () => {\n if (!queryObject?.timeDimensions || queryObject.timeDimensions.length === 0) {\n return 'day'\n }\n \n // Find the time dimension that matches our dateField\n const timeDim = queryObject.timeDimensions.find((td: any) => \n td.dimension === dateField || td.dimension.includes(dateField)\n )\n \n if (timeDim && timeDim.granularity) {\n return timeDim.granularity\n }\n \n // Fallback to first time dimension's granularity\n const firstTimeDim = queryObject.timeDimensions[0]\n if (firstTimeDim && firstTimeDim.granularity) {\n return firstTimeDim.granularity\n }\n \n return 'day'\n }\n \n const queryGranularity = getQueryGranularity()\n const gridMapping = getGridMapping(queryGranularity)\n \n // Handle unsupported granularity\n if (!gridMapping) {\n return\n }\n \n\n // Transform data for grid\n const gridData: GridCell[] = data.map(item => {\n const dateValue = item[dateField]\n const value = typeof item[valueField] === 'string' \n ? parseFloat(item[valueField]) \n : (item[valueField] || 0)\n \n // Parse the date\n let date: Date\n if (typeof dateValue === 'string') {\n // Handle different date formats\n let isoStr = dateValue\n if (dateValue.includes(' ')) {\n isoStr = dateValue.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n date = new Date(isoStr)\n } else {\n date = new Date(dateValue)\n }\n\n // Skip invalid dates\n if (isNaN(date.getTime())) {\n return null\n }\n\n const x = gridMapping.extractX(date)\n const y = gridMapping.extractY(date)\n \n return {\n x,\n y,\n value,\n date,\n label: formatTimeValue(dateValue, queryGranularity)\n }\n }).filter((cell): cell is GridCell => cell !== null)\n\n\n if (gridData.length === 0) return\n\n // Calculate grid dimensions\n const maxY = max(gridData, d => d.y) || 0\n const minY = min(gridData, d => d.y) || 0\n\n\n // Generate complete X range first so we can calculate proper grid width\n const getCompleteXRange = (): number[] => {\n const dataXValues = [...new Set(gridData.map(cell => cell.x))].sort()\n \n if (queryGranularity === 'quarter') {\n // For quarters: only show quarters that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'month') {\n // For months: only show quarters that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'week') {\n // For weeks: only show months that have data to avoid gaps\n return dataXValues\n }\n \n if (queryGranularity === 'day') {\n // For days: only show the actual weeks that have data to avoid discontinuities\n return dataXValues\n }\n \n // For other granularities, use the actual data values\n return dataXValues\n }\n \n const completeXRange = getCompleteXRange()\n \n // Calculate grid dimensions based on complete X range\n const gridWidth = completeXRange.length * gridMapping.cellWidth + (completeXRange.length - 1) * 4\n const gridHeight = (maxY - minY + 1) * gridMapping.cellHeight + (maxY - minY) * 4\n\n const margin = { \n ...CHART_MARGINS, \n left: 60, // Space for Y-axis labels\n bottom: 10, // Reduced since labels are at top\n top: gridMapping.hasHierarchicalLabels ? 40 : 25, // Extra space for hierarchical labels\n right: 10\n }\n \n const availableWidth = dimensions.width - margin.left - margin.right\n const availableHeight = dimensions.height - margin.top - margin.bottom\n\n // Scale the grid to fit the available space\n let finalCellWidth: number\n let finalCellHeight: number\n\n if (safeDisplayConfig.fitToWidth) {\n // Fit to Width mode: Calculate cell size to perfectly fit both dimensions\n // Remove min/max constraints and let blocks scale to optimal size\n const scaleX = availableWidth / gridWidth\n const scaleY = availableHeight / gridHeight\n const scale = Math.min(scaleX, scaleY)\n\n // Use the scale to calculate cell size, maintaining 1:1 aspect ratio\n finalCellWidth = gridMapping.cellWidth * scale\n finalCellHeight = gridMapping.cellHeight * scale\n } else {\n // Default mode: Use minimum/maximum size constraints with scrolling\n const getMinCellSize = () => {\n return { width: 16, height: 16 } // Same size for all views\n }\n\n const minCellSize = getMinCellSize()\n const maxCellSize = 24\n\n const scaleX = availableWidth / gridWidth\n const scaleY = availableHeight / gridHeight\n const scale = Math.min(scaleX, scaleY)\n\n // Calculate final cell size with constraints\n finalCellWidth = Math.max(minCellSize.width, Math.min(maxCellSize, gridMapping.cellWidth * scale))\n finalCellHeight = Math.max(minCellSize.height, Math.min(maxCellSize, gridMapping.cellHeight * scale))\n\n // For week view, prefer scrolling over tiny cells\n if (queryGranularity === 'week' && finalCellWidth < minCellSize.width) {\n finalCellWidth = minCellSize.width\n }\n }\n \n // Calculate actual grid dimensions with the final cell sizes\n const actualGridWidth = completeXRange.length * finalCellWidth + (completeXRange.length - 1) * 4\n \n // Determine if we need horizontal scrolling\n const needsHorizontalScroll = actualGridWidth > availableWidth\n const svgWidth = needsHorizontalScroll ? actualGridWidth + margin.left + margin.right : dimensions.width\n \n\n const svg = select(svgRef.current)\n .attr('width', svgWidth)\n .attr('height', dimensions.height)\n\n const g = svg.append('g')\n .attr('transform', `translate(${margin.left},${margin.top})`)\n\n // Set up color scale\n const values = gridData.map(d => d.value)\n const minValue = min(values) || 0\n const maxValue = max(values) || 1\n\n const colorScale = scaleQuantize<string>()\n .domain([minValue, maxValue])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n\n // Create grid data map for quick lookup\n const gridMap = new Map<string, GridCell>()\n gridData.forEach(cell => {\n const key = `${cell.x}-${cell.y}`\n gridMap.set(key, cell)\n })\n\n // Get theme colors from CSS variables\n const getThemeColor = (varName: string, fallback: string) => {\n const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return value || fallback\n }\n\n const isDark = currentTheme !== 'light'\n const textColor = isDark\n ? getThemeColor('--dc-text-muted', '#cbd5e1') // Lighter text for dark mode\n : getThemeColor('--dc-text-secondary', '#374151') // Darker text for light mode\n const lineColor = getThemeColor('--dc-border', '#e5e7eb')\n // Use theme-aware colors for empty cells: light gray in light mode, slightly lighter than bg in dark mode\n const emptyCellColor = isDark\n ? getThemeColor('--dc-bg-secondary', '#1e293b') // Slightly lighter than dark background\n : getThemeColor('--dc-bg-secondary', '#f3f4f6') // Very light gray in light mode\n const cellStrokeColor = isDark\n ? getThemeColor('--dc-border', '#334155') // Subtle border in dark mode\n : getThemeColor('--dc-bg', '#ffffff') // White border in light mode\n\n // Create tooltip\n const tooltip = select('body').append('div')\n .attr('class', 'activity-grid-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n\n // Create a mapping from X values to their position indices for proper spacing\n const xValueToIndex = new Map<number, number>()\n completeXRange.forEach((x, index) => {\n xValueToIndex.set(x, index)\n })\n \n // Render grid cells for the complete X range\n for (const x of completeXRange) {\n for (let y = minY; y <= maxY; y++) {\n const key = `${x}-${y}`\n const cell = gridMap.get(key)\n const xIndex = xValueToIndex.get(x) || 0\n \n const rect = g.append('rect')\n .attr('x', xIndex * (finalCellWidth + 4))\n .attr('y', (y - minY) * (finalCellHeight + 4))\n .attr('width', finalCellWidth)\n .attr('height', finalCellHeight)\n .attr('rx', 2)\n .attr('ry', 2)\n .style('fill', cell ? colorScale(cell.value) : emptyCellColor)\n .style('stroke', cellStrokeColor)\n .style('stroke-width', 1)\n\n // Add hover effects and tooltips\n if (safeDisplayConfig.showTooltip) {\n rect\n .style('cursor', 'pointer')\n .on('mouseover', function(event) {\n select(this)\n .style('stroke', '#000')\n .style('stroke-width', 2)\n\n if (cell) {\n const tooltipContent = [\n `<strong>${cell.label}</strong>`,\n `${getFieldLabel(valueField)}: ${cell.value}`\n ].join('<br>')\n\n tooltip\n .html(tooltipContent)\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n }\n })\n .on('mousemove', function(event) {\n tooltip\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 10) + 'px')\n })\n .on('mouseout', function() {\n select(this)\n .style('stroke', cellStrokeColor)\n .style('stroke-width', 1)\n\n tooltip\n .transition()\n .duration(200)\n .style('opacity', 0)\n })\n }\n }\n }\n\n // Add axis labels if enabled\n if (safeDisplayConfig.showLabels) {\n if (gridMapping.hasHierarchicalLabels && gridMapping.getYearFromX) {\n // Special handling for quarter view with hierarchical labels\n // Use the complete X range to show all quarters/months\n \n // Group quarters by year\n const yearGroups = new Map<number, number[]>()\n for (const x of completeXRange) {\n const year = gridMapping.getYearFromX(x)\n if (!yearGroups.has(year)) {\n yearGroups.set(year, [])\n }\n yearGroups.get(year)!.push(x)\n }\n \n \n // Draw column labels (Q1-Q4 for months, Jan-Dec for weeks)\n for (const x of completeXRange) {\n const xIndex = xValueToIndex.get(x) || 0\n g.append('text')\n .attr('x', xIndex * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -8)\n .attr('text-anchor', 'middle')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.xFormat(x))\n }\n\n // Draw year group labels above quarters\n for (const [year, xValues] of yearGroups) {\n if (xValues.length > 0) {\n // Get the index positions for proper spacing\n const startIndex = Math.min(...xValues.map(x => xValueToIndex.get(x) || 0))\n const endIndex = Math.max(...xValues.map(x => xValueToIndex.get(x) || 0))\n const centerIndex = (startIndex + endIndex) / 2\n\n // Year label (or year/month for hour granularity)\n let labelText = ''\n if (year > 9999) {\n // For hour granularity, year is encoded as YYYYMM\n const actualYear = Math.floor(year / 100)\n const month = year % 100\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n labelText = `${monthNames[month - 1]} '${actualYear.toString().slice(-2)}`\n } else {\n // For other granularities, just show the year\n labelText = `'${year.toString().slice(-2)}`\n }\n\n g.append('text')\n .attr('x', centerIndex * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -25)\n .attr('text-anchor', 'middle')\n .style('font-size', '12px')\n .style('font-weight', 'bold')\n .style('fill', textColor)\n .text(labelText)\n\n // Optional: Add a subtle line to group quarters under the year\n if (xValues.length > 1) {\n g.append('line')\n .attr('x1', startIndex * (finalCellWidth + 4))\n .attr('x2', endIndex * (finalCellWidth + 4) + finalCellWidth)\n .attr('y1', -20)\n .attr('y2', -20)\n .style('stroke', lineColor)\n .style('stroke-width', 1)\n .style('opacity', 0.3)\n }\n }\n }\n } else {\n // Regular X-axis labels for other granularities\n const xLabelStep = Math.max(1, Math.floor(completeXRange.length / 10))\n for (let i = 0; i < completeXRange.length; i += xLabelStep) {\n const x = completeXRange[i]\n g.append('text')\n .attr('x', i * (finalCellWidth + 4) + finalCellWidth / 2)\n .attr('y', -8)\n .attr('text-anchor', 'middle')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.xFormat(x))\n }\n }\n\n // Y-axis labels (left) - same for all granularities\n for (let y = minY; y <= maxY; y++) {\n g.append('text')\n .attr('x', -8)\n .attr('y', (y - minY) * (finalCellHeight + 4) + finalCellHeight / 2)\n .attr('text-anchor', 'end')\n .attr('dy', '.35em')\n .style('font-size', '10px')\n .style('fill', textColor)\n .text(gridMapping.yFormat(y))\n }\n }\n\n // Cleanup function\n return () => {\n tooltip.remove()\n }\n }, [data, chartConfig, displayConfig, queryObject, dimensions, dimensionsReady, safeDisplayConfig, colorPalette, currentTheme, getFieldLabel, getGridMapping])\n\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 points to display in activity grid</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.dateField && chartConfig?.valueField\n if (!hasValidConfig) {\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\">Configuration Required</div>\n <div className=\"text-xs text-dc-text-secondary\">Activity grid requires a time dimension and a measure</div>\n </div>\n </div>\n )\n }\n\n // Check if granularity is supported\n const dateField = Array.isArray(chartConfig.dateField) ? chartConfig.dateField[0] : chartConfig.dateField\n const granularityFromQuery = queryObject?.timeDimensions?.find((td: any) => \n td.dimension === dateField || td.dimension.includes(dateField)\n )?.granularity || 'day'\n \n if (granularityFromQuery?.toLowerCase() === 'year') {\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\">Granularity Too High</div>\n <div className=\"text-xs text-dc-text-secondary\">Activity grids work best with hour, day, week, month, or quarter granularity</div>\n <div className=\"text-xs text-dc-text-secondary mt-1\">Please choose a lower granularity for your time dimension</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"w-full flex flex-col relative\" style={{ height, minHeight: '250px', overflow: 'hidden', width: '100%' }}>\n <div ref={containerRef} className=\"w-full h-full relative overflow-x-auto\" style={{ width: '100%' }}>\n <svg ref={svgRef} className=\"h-full\" />\n {!dimensionsReady && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"text-dc-text-muted text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default ActivityGridChart"],"names":["ActivityGridChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","svgRef","useRef","containerRef","dimensions","setDimensions","useState","dimensionsReady","setDimensionsReady","currentTheme","setCurrentTheme","getFieldLabel","useCubeFieldLabel","useEffect","getTheme","watchThemeChanges","theme","safeDisplayConfig","useMemo","useLayoutEffect","retryCount","maxRetries","rafId","timeoutId","updateDimensions","width","retryWithRaf","resizeObserver","getQuarter","date","getMonthOfQuarter","getWeekOfMonth","dayOfMonth","getGridMapping","useCallback","granularity","value","year","quarter","month","week","getWeekOfYear","day","d","dayNum","yearStart","select","dateField","valueField","queryGranularity","timeDim","td","firstTimeDim","gridMapping","gridData","item","dateValue","isoStr","x","y","formatTimeValue","cell","maxY","max","minY","min","completeXRange","dataXValues","gridWidth","gridHeight","margin","availableWidth","availableHeight","finalCellWidth","finalCellHeight","scaleX","scaleY","scale","minCellSize","maxCellSize","actualGridWidth","svgWidth","g","values","minValue","maxValue","colorScale","scaleQuantize","CHART_COLORS_GRADIENT","gridMap","key","getThemeColor","varName","fallback","isDark","textColor","lineColor","emptyCellColor","cellStrokeColor","tooltip","xValueToIndex","index","xIndex","rect","event","tooltipContent","yearGroups","xValues","startIndex","endIndex","centerIndex","labelText","actualYear","xLabelStep","i","jsx","jsxs"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as t, jsxs as n, Fragment as K } from "react/jsx-runtime";
|
|
2
2
|
import X, { useState as $ } from "react";
|
|
3
3
|
import { ComposedChart as q, CartesianGrid as B, XAxis as U, YAxis as D, Legend as J, Area as Q, Line as j } from "recharts";
|
|
4
|
-
import { u as Z, t as C,
|
|
4
|
+
import { u as Z, t as C, C as P, p as ee, s as te, a as se, f as N, b as re, c as k } from "./charts-core-CjQZBxmv.js";
|
|
5
5
|
const de = X.memo(function({
|
|
6
6
|
data: b,
|
|
7
7
|
chartConfig: s,
|
|
@@ -187,4 +187,4 @@ const de = X.memo(function({
|
|
|
187
187
|
export {
|
|
188
188
|
de as default
|
|
189
189
|
};
|
|
190
|
-
//# sourceMappingURL=chart-area-
|
|
190
|
+
//# sourceMappingURL=chart-area-DLmXFWWy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-area-cPrJnhLj.js","sources":["../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst AreaChart = React.memo(function AreaChart({ \n data, \n chartConfig, \n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n \n try {\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in area chart</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let yAxisFields: string[]\n let seriesFields: string[] = []\n \n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">Invalid or missing chart axis configuration</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || !yAxisFields || yAxisFields.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">Missing required X-axis or Y-axis fields</div>\n </div>\n </div>\n )\n }\n\n // Use shared function to transform data and handle series\n const { data: chartData, seriesKeys } = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = chartConfig?.yAxisAssignment || {}\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n seriesKeyToField[label] = field\n })\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Disable stacking when dual Y-axis is used (areas on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No valid data</div>\n <div className=\"text-xs text-dc-text-secondary\">No valid data points for area chart after transformation</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n const stackOffset = effectiveIsPercentStack ? ('expand' as const) : undefined\n\n return (\n <ChartContainer height={height}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" />}\n <XAxis dataKey=\"name\" tick={{ fontSize: 12 }} angle={-45} textAnchor=\"end\" height={60} />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n stroke={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fill={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 0.6 : 0.1) : 0.3}\n strokeWidth={2}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={safeDisplayConfig.connectNulls}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'AreaChart rendering error\n return (\n <div className=\"flex flex-col items-center justify-center w-full text-dc-error p-4\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Area Chart Error</div>\n <div className=\"text-xs mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default AreaChart"],"names":["AreaChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","hoveredLegend","setHoveredLegend","useState","getFieldLabel","useCubeFieldLabel","stackType","shouldStack","isPercentStack","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","jsx","jsxs","xAxisField","yAxisFields","seriesFields","chartData","seriesKeys","transformChartDataWithSeries","yAxisAssignment","seriesKeyToField","field","label","hasRightAxis","leftAxisFields","f","rightAxisFields","effectiveShouldStack","effectiveIsPercentStack","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","index","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","v","value","formatAxisValue","ChartTooltip","name","originalField","formatConfig","Legend","o","seriesKey","axisId","Area","CHART_COLORS","Fragment","Line","error"],"mappings":";;;;AAUA,MAAMA,KAAYC,EAAM,KAAK,SAAmB;AAAA,EAC9C,MAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC,IAAgB,CAAA;AAAA,EAChB,aAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,cAAAC;AACF,GAAe;AACb,QAAM,CAACC,GAAeC,CAAgB,IAAIC,EAAwB,IAAI,GAEhEC,IAAgBC,EAAA;AAEtB,MAAI;AAEF,UAAMC,IAAYT,GAAe,cAAcA,GAAe,UAAU,WAAW,SAC7EU,IAAcD,MAAc,QAC5BE,IAAiBF,MAAc,WAE/BG,IAAoB;AAAA,MACxB,YAAYZ,GAAe,cAAc;AAAA,MACzC,UAAUA,GAAe,YAAY;AAAA,MACrC,aAAaA,GAAe,eAAe;AAAA,MAC3C,cAAcA,GAAe,gBAAgB;AAAA,IAAA,GAIzCa,IAAkBb,GAAe,iBACjCc,IAAmBd,GAAe;AAExC,QAAI,CAACF,KAAQA,EAAK,WAAW;AAC3B,aACE,gBAAAiB,EAAC,OAAA,EAAI,WAAU,8DAA6D,OAAO,EAAE,QAAAb,EAAA,GACnF,UAAA,gBAAAc,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,QAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,qBAAiB;AAAA,QAC7D,gBAAAA,EAAC,OAAA,EAAI,WAAU,kCAAiC,UAAA,0CAAA,CAAuC;AAAA,MAAA,EAAA,CACzF,EAAA,CACF;AAKJ,QAAIE,GACAC,GACAC,IAAyB,CAAA;AAE7B,QAAIpB,GAAa,SAASA,GAAa;AAErC,MAAAkB,IAAa,MAAM,QAAQlB,EAAY,KAAK,IAAIA,EAAY,MAAM,CAAC,IAAIA,EAAY,OACnFmB,IAAc,MAAM,QAAQnB,EAAY,KAAK,IAAIA,EAAY,QAAQ,CAACA,EAAY,KAAK,GACvFoB,IAAepB,EAAY,UAAU,CAAA;AAAA,aAC5BA,GAAa,KAAKA,GAAa;AAExC,MAAAkB,IAAalB,EAAY,GACzBmB,IAAc,MAAM,QAAQnB,EAAY,CAAC,IAAIA,EAAY,IAAI,CAACA,EAAY,CAAC;AAAA;AAE3E,aACE,gBAAAgB,EAAC,OAAA,EAAI,WAAU,2DAA0D,OAAO,EAAE,QAAAb,EAAA,GAChF,UAAA,gBAAAc,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,QAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,uBAAmB;AAAA,QAC/D,gBAAAA,EAAC,OAAA,EAAI,WAAU,WAAU,UAAA,8CAAA,CAA2C;AAAA,MAAA,EAAA,CACtE,EAAA,CACF;AAIJ,QAAI,CAACE,KAAc,CAACC,KAAeA,EAAY,WAAW;AACxD,aACE,gBAAAH,EAAC,OAAA,EAAI,WAAU,2DAA0D,OAAO,EAAE,QAAAb,EAAA,GAChF,UAAA,gBAAAc,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,QAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,uBAAmB;AAAA,QAC/D,gBAAAA,EAAC,OAAA,EAAI,WAAU,WAAU,UAAA,2CAAA,CAAwC;AAAA,MAAA,EAAA,CACnE,EAAA,CACF;AAKJ,UAAM,EAAE,MAAMK,GAAW,YAAAC,EAAA,IAAeC;AAAA,MACtCxB;AAAA,MACAmB;AAAA,MACAC;AAAA,MACAjB;AAAA,MACAkB;AAAA,MACAZ;AAAA,IAAA,GAIIgB,IAAkBxB,GAAa,mBAAmB,CAAA,GAGlDyB,IAA2C,CAAA;AACjD,IAAAN,EAAY,QAAQ,CAACO,MAAU;AAC7B,YAAMC,IAAQnB,EAAckB,CAAK;AACjC,MAAAD,EAAiBE,CAAK,IAAID;AAAA,IAC5B,CAAC;AAGD,UAAME,IAAeT,EAAY,KAAK,CAACO,MAAUF,EAAgBE,CAAK,MAAM,OAAO,GAG7EG,IAAiBV,EAAY,OAAO,CAACW,OAAON,EAAgBM,CAAC,KAAK,YAAY,MAAM,GACpFC,IAAkBZ,EAAY,OAAO,CAACW,MAAMN,EAAgBM,CAAC,MAAM,OAAO,GAG1EE,IAAuBrB,KAAe,CAACiB,GACvCK,IAA0BrB,KAAkB,CAACgB,GAG7CM,IAAarB,EAAkB,YAG/BsB,IAAe;AAAA,MACnB,GAAGC;AAAA,MACH,MAAM;AAAA;AAAA,MACN,OAAOR,IAAe,KAAK;AAAA;AAAA,IAAA,GAIvBS,IAAeC,GAAkBrC,GAAe,UAAU,EAAE,GAC5DsC,IAAgBC,GAAmBH,GAAchB,EAAU,MAAM;AAGvE,QAAIoB,IAAoBpB;AASxB,WARIkB,EAAc,SAAS,MACzBE,IAAoBpB,EAAU,IAAI,CAACqB,GAAWC,OAAW;AAAA,MACvD,GAAGD;AAAA,MACH,UAAUH,EAAcI,CAAK,KAAK;AAAA,IAAA,EAClC,IAIA,CAACtB,KAAaA,EAAU,WAAW,IAEnC,gBAAAL,EAAC,OAAA,EAAI,WAAU,8DAA6D,OAAO,EAAE,QAAAb,EAAA,GACnF,UAAA,gBAAAc,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,iBAAa;AAAA,MACzD,gBAAAA,EAAC,OAAA,EAAI,WAAU,kCAAiC,UAAA,2DAAA,CAAwD;AAAA,IAAA,EAAA,CAC1G,EAAA,CACF,IAQF,gBAAAA,EAAC4B,MAAe,QAAAzC,GACd,UAAA,gBAAAc,EAAC4B,KAAc,MAAMJ,GAAmB,QAAQN,GAAc,aAJ9CF,IAA2B,WAAqB,QAK7D,UAAA;AAAA,MAAApB,EAAkB,YAAY,gBAAAG,EAAC8B,GAAA,EAAc,iBAAgB,OAAM;AAAA,MACpE,gBAAA9B,EAAC+B,GAAA,EAAM,SAAQ,QAAO,MAAM,EAAE,UAAU,GAAA,GAAM,OAAO,KAAK,YAAW,OAAM,QAAQ,IAAI;AAAA,MACvF,gBAAA/B;AAAA,QAACgC;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,aAAY;AAAA,UACZ,MAAM,EAAE,UAAU,GAAA;AAAA,UAClB,eACEf,IACI,CAACgB,MAAM,IAAIA,IAAI,KAAK,QAAQ,CAAC,CAAC,MAC9BnC,IACE,CAACoC,MAAUC,EAAgBD,GAAOpC,CAAe,IACjD;AAAA,UAER,QAAQmB,IAA0B,CAAC,GAAG,CAAC,IAAI;AAAA,UAC3C,OACEA,IACI,SACAJ,EAAe,SAAS,IACtB;AAAA,YACE,OAAOf,GAAiB,SAASN,EAAcqB,EAAe,CAAC,CAAC;AAAA,YAChE,OAAO;AAAA,YACP,UAAU;AAAA,YACV,OAAO,EAAE,YAAY,UAAU,UAAU,OAAA;AAAA,UAAO,IAElD;AAAA,QAAA;AAAA,MAAA;AAAA,MAGTD,KACC,gBAAAZ;AAAA,QAACgC;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,aAAY;AAAA,UACZ,MAAM,EAAE,UAAU,GAAA;AAAA,UAClB,eAAejC,IAAmB,CAACmC,MAAUC,EAAgBD,GAAOnC,CAAgB,IAAI;AAAA,UACxF,OACEgB,EAAgB,SAAS,IACrB;AAAA,YACE,OAAOhB,GAAkB,SAASP,EAAcuB,EAAgB,CAAC,CAAC;AAAA,YAClE,OAAO;AAAA,YACP,UAAU;AAAA,YACV,OAAO,EAAE,YAAY,UAAU,UAAU,OAAA;AAAA,UAAO,IAElD;AAAA,QAAA;AAAA,MAAA;AAAA,MAITlB,EAAkB,eACjB,gBAAAG;AAAA,QAACoC;AAAA,QAAA;AAAA,UACC,WAAW,CAACF,GAAYG,MAAc;AAEpC,gBAAIH,KAAU;AACZ,qBAAO,CAAC,WAAWG,CAAI;AAEzB,gBAAIA,MAAS;AAEX,qBAAO,CAACF,EAAgBD,GAAOpC,CAAe,GAAG,cAAc;AAGjE,gBAAImB,KAA2B,OAAOiB,KAAU;AAC9C,qBAAO,CAAC,IAAIA,IAAQ,KAAK,QAAQ,CAAC,CAAC,KAAKG,CAAI;AAG9C,kBAAMC,IAAgB7B,EAAiB4B,CAAI,GAErCE,KADSD,KAAiB9B,EAAgB8B,CAAa,MAAM,UAAU,UAAU,YACvD,UAAUvC,IAAmBD;AAC7D,mBAAO,CAACqC,EAAgBD,GAAOK,CAAY,GAAGF,CAAI;AAAA,UACpD;AAAA,QAAA;AAAA,MAAA;AAAA,MAGHnB,KACC,gBAAAlB;AAAA,QAACwC;AAAA,QAAA;AAAA,UACC,cAAc,EAAE,UAAU,QAAQ,YAAY,OAAA;AAAA,UAC9C,UAAS;AAAA,UACT,UAAU;AAAA,UACV,QAAO;AAAA,UACP,OAAM;AAAA,UACN,eAAc;AAAA,UACd,cAAc,CAACC,MAAMnD,EAAiB,OAAOmD,EAAE,WAAW,EAAE,CAAC;AAAA,UAC7D,cAAc,MAAMnD,EAAiB,IAAI;AAAA,QAAA;AAAA,MAAA;AAAA,MAG5CgB,EAAW,IAAI,CAACoC,GAAWf,MAAU;AAEpC,cAAMW,IAAgB7B,EAAiBiC,CAAS,GAC1CC,IAASL,KAAiB9B,EAAgB8B,CAAa,MAAM,UAAU,UAAU;AACvF,eACE,gBAAAtC;AAAA,UAAC4C;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,SAASF;AAAA,YACT,SAASC;AAAA,YACT,SAAS3B,IAAuB,UAAU;AAAA,YAC1C,QACG5B,GAAc,UAAUA,EAAa,OAAOuC,IAAQvC,EAAa,OAAO,MAAM,KAC/EyD,EAAalB,IAAQkB,EAAa,MAAM;AAAA,YAE1C,MACGzD,GAAc,UAAUA,EAAa,OAAOuC,IAAQvC,EAAa,OAAO,MAAM,KAC/EyD,EAAalB,IAAQkB,EAAa,MAAM;AAAA,YAE1C,aAAaxD,IAAiBA,MAAkBqD,IAAY,MAAM,MAAO;AAAA,YACzE,aAAa;AAAA,YACb,eAAerD,IAAiBA,MAAkBqD,IAAY,IAAI,MAAO;AAAA,YACzE,cAAc7C,EAAkB;AAAA,UAAA;AAAA,UAhB3B6C;AAAA,QAAA;AAAA,MAmBX,CAAC;AAAA,MACAnB,EAAc,SAAS,KACtB,gBAAAtB,EAAA6C,GAAA,EAEE,UAAA;AAAA,QAAA,gBAAA9C;AAAA,UAAC+C;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,SAAQ;AAAA,YACR,QAAO;AAAA,YACP,aAAa;AAAA,YACb,KAAK;AAAA,YACL,WAAW;AAAA,YACX,cAAc;AAAA,UAAA;AAAA,QAAA;AAAA,QAGhB,gBAAA/C;AAAA,UAAC+C;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,QAAO;AAAA,YACP,aAAa;AAAA,YACb,iBAAgB;AAAA,YAChB,KAAK;AAAA,YACL,WAAW;AAAA,YACX,cAAc;AAAA,UAAA;AAAA,QAAA;AAAA,MAChB,EAAA,CACF;AAAA,IAAA,EAAA,CAEJ,EAAA,CACF;AAAA,EAEJ,SAASC,GAAO;AAEd,WACE,gBAAAhD,EAAC,OAAA,EAAI,WAAU,sEAAqE,OAAO,EAAE,QAAAb,EAAA,GAC3F,UAAA,gBAAAc,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,oBAAgB;AAAA,MAC5D,gBAAAA,EAAC,SAAI,WAAU,gBAAgB,uBAAiB,QAAQgD,EAAM,UAAU,0BAAA,CAA0B;AAAA,MAClG,gBAAAhD,EAAC,OAAA,EAAI,WAAU,8BAA6B,UAAA,mCAAA,CAAgC;AAAA,IAAA,EAAA,CAC9E,EAAA,CACF;AAAA,EAEJ;AACF,CAAC;"}
|
|
1
|
+
{"version":3,"file":"chart-area-DLmXFWWy.js","sources":["../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst AreaChart = React.memo(function AreaChart({ \n data, \n chartConfig, \n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n \n try {\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in area chart</div>\n </div>\n </div>\n )\n }\n\n // Validate chartConfig - support both legacy and new formats\n let xAxisField: string\n let yAxisFields: string[]\n let seriesFields: string[] = []\n \n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">Invalid or missing chart axis configuration</div>\n </div>\n </div>\n )\n }\n\n if (!xAxisField || !yAxisFields || yAxisFields.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">Missing required X-axis or Y-axis fields</div>\n </div>\n </div>\n )\n }\n\n // Use shared function to transform data and handle series\n const { data: chartData, seriesKeys } = transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = chartConfig?.yAxisAssignment || {}\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n seriesKeyToField[label] = field\n })\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Disable stacking when dual Y-axis is used (areas on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No valid data</div>\n <div className=\"text-xs text-dc-text-secondary\">No valid data points for area chart after transformation</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n const stackOffset = effectiveIsPercentStack ? ('expand' as const) : undefined\n\n return (\n <ChartContainer height={height}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" />}\n <XAxis dataKey=\"name\" tick={{ fontSize: 12 }} angle={-45} textAnchor=\"end\" height={60} />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n stroke={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fill={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 0.6 : 0.1) : 0.3}\n strokeWidth={2}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={safeDisplayConfig.connectNulls}\n />\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n )\n } catch (error) {\n // 'AreaChart rendering error\n return (\n <div className=\"flex flex-col items-center justify-center w-full text-dc-error p-4\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Area Chart Error</div>\n <div className=\"text-xs mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default AreaChart"],"names":["AreaChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","hoveredLegend","setHoveredLegend","useState","getFieldLabel","useCubeFieldLabel","stackType","shouldStack","isPercentStack","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","jsx","jsxs","xAxisField","yAxisFields","seriesFields","chartData","seriesKeys","transformChartDataWithSeries","yAxisAssignment","seriesKeyToField","field","label","hasRightAxis","leftAxisFields","f","rightAxisFields","effectiveShouldStack","effectiveIsPercentStack","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","index","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","v","value","formatAxisValue","ChartTooltip","name","originalField","formatConfig","Legend","o","seriesKey","axisId","Area","CHART_COLORS","Fragment","Line","error"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as t, jsxs as d, Fragment as Z } from "react/jsx-runtime";
|
|
2
2
|
import ee, { useState as te, useMemo as A } from "react";
|
|
3
3
|
import { ComposedChart as se, CartesianGrid as re, XAxis as ie, YAxis as C, Legend as ae, Bar as ne, Cell as le, Line as H } from "recharts";
|
|
4
|
-
import { u as oe, t as de, i as ce,
|
|
4
|
+
import { u as oe, t as de, i as ce, C as xe, p as me, s as fe, a as he, f as S, b as ue, N as ge, P as K, c as P } from "./charts-core-CjQZBxmv.js";
|
|
5
5
|
const ke = ee.memo(function({
|
|
6
6
|
data: m,
|
|
7
7
|
chartConfig: r,
|
|
@@ -213,4 +213,4 @@ const ke = ee.memo(function({
|
|
|
213
213
|
export {
|
|
214
214
|
ke as default
|
|
215
215
|
};
|
|
216
|
-
//# sourceMappingURL=chart-bar-
|
|
216
|
+
//# sourceMappingURL=chart-bar-7y0-F27Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-bar-D68HFPpa.js","sources":["../../../src/client/components/charts/BarChart.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react'\nimport { ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Cell, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, POSITIVE_COLOR, NEGATIVE_COLOR, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst BarChart = React.memo(function BarChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n // Validate chartConfig - support both legacy and new formats\n // Do validation but don't early return yet (hooks must come first)\n const { xAxisField, yAxisFields, seriesFields, configError } = useMemo(() => {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let configError: string | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n configError = 'Invalid or missing chart axis configuration'\n }\n\n if (!configError && (!xAxisField || !yAxisFields || yAxisFields.length === 0)) {\n configError = 'Missing required X-axis or Y-axis fields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, configError }\n }, [chartConfig])\n\n // Transform data (will be empty arrays if config is invalid)\n const { data: transformedData, seriesKeys } = useMemo(() => {\n if (configError || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, configError])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Null handling: Filter out data points where ALL measure values are null\n // This prevents rendering empty bars and makes the chart clearer\n const { chartData, skippedCount } = useMemo(() => {\n if (transformedData.length === 0 || seriesKeys.length === 0) {\n return { chartData: [], skippedCount: 0 }\n }\n const filtered = transformedData.filter(row => {\n // Keep the row if at least one series has a valid numeric value\n return seriesKeys.some(key => isValidNumericValue(row[key]))\n })\n const skipped = transformedData.length - filtered.length\n return { chartData: filtered, skippedCount: skipped }\n }, [transformedData, seriesKeys])\n\n // Now handle early returns AFTER all hooks\n try {\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in bar chart</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n // Disable stacking when dual Y-axis is used (bars on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n const stackOffset = effectiveIsPercentStack ? 'expand' as const : undefined\n\n // Check if we should use positive/negative coloring\n // This is enabled when we have single series data with mixed positive/negative values\n const usePositiveNegativeColoring = seriesKeys.length === 1 && chartData.some(row => {\n const value = row[seriesKeys[0]]\n return typeof value === 'number' && value < 0\n })\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No valid data</div>\n <div className=\"text-xs text-dc-text-secondary\">No valid data points for bar chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"relative w-full\" style={{ height }}>\n <ChartContainer height={skippedCount > 0 ? `calc(100% - 20px)` : \"100%\"}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" />\n )}\n <XAxis\n dataKey=\"name\"\n tick={{ fontSize: 12 }}\n angle={-45}\n textAnchor=\"end\"\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Bar\n key={seriesKey}\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n fill={\n usePositiveNegativeColoring\n ? POSITIVE_COLOR\n : (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n >\n {usePositiveNegativeColoring &&\n chartData.map((entry, entryIndex) => {\n const value = entry[seriesKey]\n const fillColor = typeof value === 'number' && value < 0 ? NEGATIVE_COLOR : POSITIVE_COLOR\n return (\n <Cell\n key={`cell-${entryIndex}`}\n fill={fillColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n </Bar>\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n {skippedCount > 0 && (\n <div className=\"text-xs text-dc-text-muted text-center mt-1\">\n {skippedCount} data point{skippedCount !== 1 ? 's' : ''} with no values hidden\n </div>\n )}\n </div>\n )\n } catch (error) {\n // 'BarChart rendering error\n return (\n <div className=\"flex flex-col items-center justify-center w-full text-dc-error p-4\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Bar Chart Error</div>\n <div className=\"text-xs mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default BarChart"],"names":["BarChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","hoveredLegend","setHoveredLegend","useState","getFieldLabel","useCubeFieldLabel","stackType","shouldStack","isPercentStack","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","xAxisField","yAxisFields","seriesFields","configError","useMemo","transformedData","seriesKeys","transformChartDataWithSeries","yAxisAssignment","seriesKeyToField","mapping","field","label","hasRightAxis","leftAxisFields","f","rightAxisFields","chartData","skippedCount","filtered","row","key","isValidNumericValue","skipped","jsx","jsxs","effectiveShouldStack","effectiveIsPercentStack","stackOffset","usePositiveNegativeColoring","value","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","index","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","v","formatAxisValue","ChartTooltip","name","originalField","formatConfig","Legend","o","seriesKey","axisId","Bar","POSITIVE_COLOR","CHART_COLORS","entry","entryIndex","fillColor","NEGATIVE_COLOR","Cell","Fragment","Line","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-bar-7y0-F27Q.js","sources":["../../../src/client/components/charts/BarChart.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react'\nimport { ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Cell, Legend } from 'recharts'\nimport ChartContainer from './ChartContainer'\nimport ChartTooltip from './ChartTooltip'\nimport { CHART_COLORS, POSITIVE_COLOR, NEGATIVE_COLOR, CHART_MARGINS } from '../../utils/chartConstants'\nimport { transformChartDataWithSeries, isValidNumericValue, formatAxisValue } from '../../utils/chartUtils'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport type { ChartProps } from '../../types'\n\nconst BarChart = React.memo(function BarChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Determine stacking from stackType (new) or stacked (legacy)\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const shouldStack = stackType !== 'none'\n const isPercentStack = stackType === 'percent'\n\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true\n }\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n // Validate chartConfig - support both legacy and new formats\n // Do validation but don't early return yet (hooks must come first)\n const { xAxisField, yAxisFields, seriesFields, configError } = useMemo(() => {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let configError: string | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n configError = 'Invalid or missing chart axis configuration'\n }\n\n if (!configError && (!xAxisField || !yAxisFields || yAxisFields.length === 0)) {\n configError = 'Missing required X-axis or Y-axis fields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, configError }\n }, [chartConfig])\n\n // Transform data (will be empty arrays if config is invalid)\n const { data: transformedData, seriesKeys } = useMemo(() => {\n if (configError || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, configError])\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig (memoized to prevent object recreation)\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField: Record<string, string> = useMemo(() => {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n const label = getFieldLabel(field)\n mapping[label] = field\n })\n return mapping\n }, [yAxisFields, getFieldLabel])\n\n // Determine if we need a right Y-axis\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n\n // Get fields for left and right axes for labels\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n\n // Null handling: Filter out data points where ALL measure values are null\n // This prevents rendering empty bars and makes the chart clearer\n const { chartData, skippedCount } = useMemo(() => {\n if (transformedData.length === 0 || seriesKeys.length === 0) {\n return { chartData: [], skippedCount: 0 }\n }\n const filtered = transformedData.filter(row => {\n // Keep the row if at least one series has a valid numeric value\n return seriesKeys.some(key => isValidNumericValue(row[key]))\n })\n const skipped = transformedData.length - filtered.length\n return { chartData: filtered, skippedCount: skipped }\n }, [transformedData, seriesKeys])\n\n // Now handle early returns AFTER all hooks\n try {\n if (!data || data.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No data available</div>\n <div className=\"text-xs text-dc-text-secondary\">No data points to display in bar chart</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-warning\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Configuration Error</div>\n <div className=\"text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n // Determine stack offset for percentage stacking\n // Disable stacking when dual Y-axis is used (bars on different axes can't be stacked)\n const effectiveShouldStack = shouldStack && !hasRightAxis\n const effectiveIsPercentStack = isPercentStack && !hasRightAxis\n const stackOffset = effectiveIsPercentStack ? 'expand' as const : undefined\n\n // Check if we should use positive/negative coloring\n // This is enabled when we have single series data with mixed positive/negative values\n const usePositiveNegativeColoring = seriesKeys.length === 1 && chartData.some(row => {\n const value = row[seriesKeys[0]]\n return typeof value === 'number' && value < 0\n })\n\n // Determine if legend will be shown\n const showLegend = safeDisplayConfig.showLegend\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n \n // Process target values and add to chart data\n const targetValues = parseTargetValues(displayConfig?.target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n \n // Add target data to chart data if targets exist\n let enhancedChartData = chartData\n if (spreadTargets.length > 0) {\n enhancedChartData = chartData.map((dataPoint, index) => ({\n ...dataPoint,\n __target: spreadTargets[index] || null\n }))\n }\n \n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <div className=\"flex items-center justify-center w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">No valid data</div>\n <div className=\"text-xs text-dc-text-secondary\">No valid data points for bar chart after transformation</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"relative w-full\" style={{ height }}>\n <ChartContainer height={skippedCount > 0 ? `calc(100% - 20px)` : \"100%\"}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset}>\n {safeDisplayConfig.showGrid && (\n <CartesianGrid strokeDasharray=\"3 3\" />\n )}\n <XAxis\n dataKey=\"name\"\n tick={{ fontSize: 12 }}\n angle={-45}\n textAnchor=\"end\"\n height={60}\n />\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n tick={{ fontSize: 12 }}\n tickFormatter={\n effectiveIsPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={effectiveIsPercentStack ? [0, 1] : undefined}\n label={\n effectiveIsPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px' }\n }\n : undefined\n }\n />\n )}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: any) => {\n // Handle null values in tooltip\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n // Format as percentage when using percent stacking\n if (effectiveIsPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = seriesKeyToField[name]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }}\n />\n )}\n {showLegend && (\n <Legend \n wrapperStyle={{ fontSize: '12px', paddingTop: '25px' }}\n iconType=\"rect\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n {seriesKeys.map((seriesKey, index) => {\n // Look up the original field name to get its axis assignment\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n return (\n <Bar\n key={seriesKey}\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={effectiveShouldStack ? 'stack' : undefined}\n fill={\n usePositiveNegativeColoring\n ? POSITIVE_COLOR\n : (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n >\n {usePositiveNegativeColoring &&\n chartData.map((entry, entryIndex) => {\n const value = entry[seriesKey]\n const fillColor = typeof value === 'number' && value < 0 ? NEGATIVE_COLOR : POSITIVE_COLOR\n return (\n <Cell\n key={`cell-${entryIndex}`}\n fill={fillColor}\n fillOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n />\n )\n })}\n </Bar>\n )\n })}\n {spreadTargets.length > 0 && (\n <>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </>\n )}\n </ComposedChart>\n </ChartContainer>\n {skippedCount > 0 && (\n <div className=\"text-xs text-dc-text-muted text-center mt-1\">\n {skippedCount} data point{skippedCount !== 1 ? 's' : ''} with no values hidden\n </div>\n )}\n </div>\n )\n } catch (error) {\n // 'BarChart rendering error\n return (\n <div className=\"flex flex-col items-center justify-center w-full text-dc-error p-4\" style={{ height }}>\n <div className=\"text-center\">\n <div className=\"text-sm font-semibold mb-1\">Bar Chart Error</div>\n <div className=\"text-xs mb-2\">{error instanceof Error ? error.message : 'Unknown rendering error'}</div>\n <div className=\"text-xs text-dc-text-muted\">Check the data and configuration</div>\n </div>\n </div>\n )\n }\n})\n\nexport default BarChart"],"names":["BarChart","React","data","chartConfig","displayConfig","queryObject","height","colorPalette","hoveredLegend","setHoveredLegend","useState","getFieldLabel","useCubeFieldLabel","stackType","shouldStack","isPercentStack","safeDisplayConfig","leftYAxisFormat","rightYAxisFormat","xAxisField","yAxisFields","seriesFields","configError","useMemo","transformedData","seriesKeys","transformChartDataWithSeries","yAxisAssignment","seriesKeyToField","mapping","field","label","hasRightAxis","leftAxisFields","f","rightAxisFields","chartData","skippedCount","filtered","row","key","isValidNumericValue","skipped","jsx","jsxs","effectiveShouldStack","effectiveIsPercentStack","stackOffset","usePositiveNegativeColoring","value","showLegend","chartMargins","CHART_MARGINS","targetValues","parseTargetValues","spreadTargets","spreadTargetValues","enhancedChartData","dataPoint","index","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","v","formatAxisValue","ChartTooltip","name","originalField","formatConfig","Legend","o","seriesKey","axisId","Bar","POSITIVE_COLOR","CHART_COLORS","entry","entryIndex","fillColor","NEGATIVE_COLOR","Cell","Fragment","Line","error"],"mappings":"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"}
|