drizzle-cube 0.4.42 → 0.4.44
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/README.md +1 -1
- package/dist/adapters/compiler-CA6iopu7.cjs +198 -0
- package/dist/adapters/{mcp-transport-tB5a7Het.js → compiler-O3T1u7jl.js} +1172 -1779
- package/dist/adapters/express/index.cjs +2 -2
- package/dist/adapters/express/index.js +27 -26
- package/dist/adapters/fastify/index.cjs +2 -2
- package/dist/adapters/fastify/index.js +26 -25
- package/dist/adapters/{google-Dgo9-Kb5.cjs → google-BOAwi9Ib.cjs} +1 -1
- package/dist/adapters/{google-CT4kgmBf.js → google-CBfBGU4F.js} +1 -1
- package/dist/adapters/{handler-dHHEEbG9.cjs → handler-BO2nq6IS.cjs} +2 -2
- package/dist/adapters/{handler-fto6TSVn.js → handler-CjVc3ytc.js} +4 -4
- package/dist/adapters/hono/index.cjs +2 -2
- package/dist/adapters/hono/index.js +30 -29
- package/dist/adapters/mcp-tools.cjs +1 -0
- package/dist/adapters/mcp-tools.d.ts +128 -0
- package/dist/adapters/mcp-tools.js +69 -0
- package/dist/adapters/mcp-transport--zhJJHJc.js +370 -0
- package/dist/adapters/mcp-transport-MOoCDu2M.cjs +58 -0
- package/dist/adapters/mcp-transport.d.ts +44 -0
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +23 -22
- package/dist/{server/openai-DKpZPCay.cjs → adapters/openai-4JP2B6pB.cjs} +1 -1
- package/dist/adapters/{openai-Ckpe7iU7.js → openai-BAnEZgKZ.js} +1 -1
- package/dist/adapters/{openai-Bc8qwEKW.cjs → openai-C4BD8xnN.cjs} +1 -1
- package/dist/adapters/{openai-DxeVtl8X.js → openai-CaSQEduB.js} +1 -1
- package/dist/adapters/{utils-_2o905Fi.js → utils-C7Nrw9Wb.js} +7 -3
- package/dist/adapters/{utils-2MwxiQ2o.cjs → utils-tNZ6Cvzw.cjs} +1 -1
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.js +1 -1
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/{DashboardEditModal-4zzjtZRR.js → DashboardEditModal-BTdV528l.js} +1421 -1396
- package/dist/client/chunks/DashboardEditModal-BTdV528l.js.map +1 -0
- package/dist/client/chunks/{FieldSearchModal-trURu9Sa.js → FieldSearchModal-D75vy4Wb.js} +4 -4
- package/dist/client/chunks/{FieldSearchModal-trURu9Sa.js.map → FieldSearchModal-D75vy4Wb.js.map} +1 -1
- package/dist/client/chunks/KpiDelta-Bk8bzKYM.js +2 -0
- package/dist/client/chunks/KpiNumber-CKF-8e_T.js +2 -0
- package/dist/client/chunks/KpiText-Iz1vIvu_.js +2 -0
- package/dist/client/chunks/{RetentionCombinedChart-B1hUYaXt.js → RetentionCombinedChart-DIhK5pD8.js} +3 -3
- package/dist/client/chunks/{RetentionCombinedChart-B1hUYaXt.js.map → RetentionCombinedChart-DIhK5pD8.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-Dn2ocjVf.js → RetentionHeatmap-CyREolyP.js} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-Dn2ocjVf.js.map → RetentionHeatmap-CyREolyP.js.map} +1 -1
- package/dist/client/chunks/SchemaVisualization-B1GUT-FM.js +2 -0
- package/dist/client/chunks/SchemaVisualizationLazy-DymwT34e.js +2 -0
- package/dist/client/chunks/{analysis-builder-B7XSIMkr.js → analysis-builder-C1CJ0c7L.js} +52 -52
- package/dist/client/chunks/{analysis-builder-B7XSIMkr.js.map → analysis-builder-C1CJ0c7L.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-DaqtrLxd.js → analysis-builder-shared-rkjJfWLT.js} +9 -9
- package/dist/client/chunks/{analysis-builder-shared-DaqtrLxd.js.map → analysis-builder-shared-rkjJfWLT.js.map} +1 -1
- package/dist/client/chunks/{chart-activity-grid-wR2Twpo7.js → chart-activity-grid-DLktOINm.js} +2 -2
- package/dist/client/chunks/{chart-activity-grid-wR2Twpo7.js.map → chart-activity-grid-DLktOINm.js.map} +1 -1
- package/dist/client/chunks/{chart-area-e9ysnatQ.js → chart-area-BwYaflNk.js} +3 -3
- package/dist/client/chunks/{chart-area-e9ysnatQ.js.map → chart-area-BwYaflNk.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-CPt67rLR.js → chart-bar-BiENfFgE.js} +4 -4
- package/dist/client/chunks/{chart-bar-CPt67rLR.js.map → chart-bar-BiENfFgE.js.map} +1 -1
- package/dist/client/chunks/{chart-box-plot-Dp_nqQen.js → chart-box-plot-BJF1tBXC.js} +3 -3
- package/dist/client/chunks/{chart-box-plot-Dp_nqQen.js.map → chart-box-plot-BJF1tBXC.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-CYQ8loeS.js → chart-bubble-DQQhGVDJ.js} +3 -3
- package/dist/client/chunks/{chart-bubble-CYQ8loeS.js.map → chart-bubble-DQQhGVDJ.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-DTeSf7C5.js → chart-candlestick-C2UuXbLe.js} +3 -3
- package/dist/client/chunks/{chart-candlestick-DTeSf7C5.js.map → chart-candlestick-C2UuXbLe.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-BSWS08cI.js → chart-config-activity-grid-DJOU3TEz.js} +2 -2
- package/dist/client/chunks/{chart-config-activity-grid-BSWS08cI.js.map → chart-config-activity-grid-DJOU3TEz.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-DKwgcHp4.js → chart-config-area-CWnWVT6a.js} +2 -2
- package/dist/client/chunks/{chart-config-area-DKwgcHp4.js.map → chart-config-area-CWnWVT6a.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-deTjEhap.js → chart-config-bar-C-7Dr1Ho.js} +2 -2
- package/dist/client/chunks/{chart-config-bar-deTjEhap.js.map → chart-config-bar-C-7Dr1Ho.js.map} +1 -1
- package/dist/client/chunks/{chart-config-box-plot-DU4iWk3V.js → chart-config-box-plot-mVOwmLdu.js} +2 -2
- package/dist/client/chunks/{chart-config-box-plot-DU4iWk3V.js.map → chart-config-box-plot-mVOwmLdu.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-B8FSHSW-.js → chart-config-bubble-BPE2CeiD.js} +2 -2
- package/dist/client/chunks/{chart-config-bubble-B8FSHSW-.js.map → chart-config-bubble-BPE2CeiD.js.map} +1 -1
- package/dist/client/chunks/{chart-config-candlestick-BGfyWFft.js → chart-config-candlestick-BSB9DRy2.js} +2 -2
- package/dist/client/chunks/{chart-config-candlestick-BGfyWFft.js.map → chart-config-candlestick-BSB9DRy2.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-DKRcGa8t.js → chart-config-data-table-Bhdx5Hem.js} +2 -2
- package/dist/client/chunks/{chart-config-data-table-DKRcGa8t.js.map → chart-config-data-table-Bhdx5Hem.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-Bt4iGFo_.js → chart-config-funnel-Cl-v-bm1.js} +2 -2
- package/dist/client/chunks/{chart-config-funnel-Bt4iGFo_.js.map → chart-config-funnel-Cl-v-bm1.js.map} +1 -1
- package/dist/client/chunks/{chart-config-gauge-Bk4Jjp3W.js → chart-config-gauge-CdrUTJMJ.js} +2 -2
- package/dist/client/chunks/{chart-config-gauge-Bk4Jjp3W.js.map → chart-config-gauge-CdrUTJMJ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-CkHsqkrY.js → chart-config-heat-map-DGE3NzoF.js} +2 -2
- package/dist/client/chunks/{chart-config-heat-map-CkHsqkrY.js.map → chart-config-heat-map-DGE3NzoF.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-CkUX98JV.js → chart-config-kpi-delta-DMrQerUW.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-delta-CkUX98JV.js.map → chart-config-kpi-delta-DMrQerUW.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DcxyiUgs.js → chart-config-kpi-number-DCytCytn.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-number-DcxyiUgs.js.map → chart-config-kpi-number-DCytCytn.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-DI4mj8CN.js → chart-config-kpi-text-KdKQUvHo.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-text-DI4mj8CN.js.map → chart-config-kpi-text-KdKQUvHo.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line--j7-dLue.js → chart-config-line-Bl9VDAdz.js} +2 -2
- package/dist/client/chunks/{chart-config-line--j7-dLue.js.map → chart-config-line-Bl9VDAdz.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-DUjvVjV4.js → chart-config-markdown-BX26b94i.js} +2 -2
- package/dist/client/chunks/{chart-config-markdown-DUjvVjV4.js.map → chart-config-markdown-BX26b94i.js.map} +1 -1
- package/dist/client/chunks/{chart-config-measure-profile-B9FKBNGc.js → chart-config-measure-profile-DwtRhEFh.js} +2 -2
- package/dist/client/chunks/{chart-config-measure-profile-B9FKBNGc.js.map → chart-config-measure-profile-DwtRhEFh.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-yU4jipl9.js → chart-config-pie-BzBcqPMJ.js} +2 -2
- package/dist/client/chunks/{chart-config-pie-yU4jipl9.js.map → chart-config-pie-BzBcqPMJ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-R9Fkc8wL.js → chart-config-radar-6ZOgt__z.js} +2 -2
- package/dist/client/chunks/{chart-config-radar-R9Fkc8wL.js.map → chart-config-radar-6ZOgt__z.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-DeoXfpIp.js → chart-config-radial-bar-Df6Eta7N.js} +2 -2
- package/dist/client/chunks/{chart-config-radial-bar-DeoXfpIp.js.map → chart-config-radial-bar-Df6Eta7N.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-CXEsxo6s.js → chart-config-sankey-DgqKBFvN.js} +2 -2
- package/dist/client/chunks/{chart-config-sankey-CXEsxo6s.js.map → chart-config-sankey-DgqKBFvN.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-MVUFupub.js → chart-config-scatter-D5nVLDvi.js} +2 -2
- package/dist/client/chunks/{chart-config-scatter-MVUFupub.js.map → chart-config-scatter-D5nVLDvi.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-Z_gqIY5u.js → chart-config-sunburst-Ca3FX9nW.js} +2 -2
- package/dist/client/chunks/{chart-config-sunburst-Z_gqIY5u.js.map → chart-config-sunburst-Ca3FX9nW.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-BD-xAeIy.js → chart-config-tree-map-Bjy4QNa3.js} +2 -2
- package/dist/client/chunks/{chart-config-tree-map-BD-xAeIy.js.map → chart-config-tree-map-Bjy4QNa3.js.map} +1 -1
- package/dist/client/chunks/{chart-config-waterfall-CHwVkXZc.js → chart-config-waterfall-C5K2eqR7.js} +2 -2
- package/dist/client/chunks/{chart-config-waterfall-CHwVkXZc.js.map → chart-config-waterfall-C5K2eqR7.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-BZ7StNWv.js → chart-data-table-2iCsn0CF.js} +1099 -933
- package/dist/client/chunks/chart-data-table-2iCsn0CF.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-C9JRW79j.js → chart-funnel-poyOf7-e.js} +3 -3
- package/dist/client/chunks/{chart-funnel-C9JRW79j.js.map → chart-funnel-poyOf7-e.js.map} +1 -1
- package/dist/client/chunks/{chart-gauge-_Xdgk_qI.js → chart-gauge-D5J4gRky.js} +3 -3
- package/dist/client/chunks/{chart-gauge-_Xdgk_qI.js.map → chart-gauge-D5J4gRky.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-BOMQeUDL.js → chart-heat-map-BAMVhLGG.js} +3 -3
- package/dist/client/chunks/{chart-heat-map-BOMQeUDL.js.map → chart-heat-map-BAMVhLGG.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-C2tdpWki.js → chart-kpi-delta-KQjUIeal.js} +71 -73
- package/dist/client/chunks/{chart-kpi-delta-C2tdpWki.js.map → chart-kpi-delta-KQjUIeal.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-BUNKM7yg.js → chart-kpi-number-CsQgV_x3.js} +62 -63
- package/dist/client/chunks/{chart-kpi-number-BUNKM7yg.js.map → chart-kpi-number-CsQgV_x3.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-COF8iN0K.js → chart-kpi-text-BR0IyeUU.js} +26 -27
- package/dist/client/chunks/{chart-kpi-text-COF8iN0K.js.map → chart-kpi-text-BR0IyeUU.js.map} +1 -1
- package/dist/client/chunks/{chart-line-D3SEwXDS.js → chart-line-B5_WntY5.js} +4 -4
- package/dist/client/chunks/{chart-line-D3SEwXDS.js.map → chart-line-B5_WntY5.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-DMekYkKz.js → chart-markdown-B6bENbel.js} +2 -2
- package/dist/client/chunks/{chart-markdown-DMekYkKz.js.map → chart-markdown-B6bENbel.js.map} +1 -1
- package/dist/client/chunks/{chart-measure-profile-BPhI1Z9s.js → chart-measure-profile-yWk-obNb.js} +4 -4
- package/dist/client/chunks/{chart-measure-profile-BPhI1Z9s.js.map → chart-measure-profile-yWk-obNb.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-COl3Rmdk.js → chart-pie-BodrUoHv.js} +4 -4
- package/dist/client/chunks/{chart-pie-COl3Rmdk.js.map → chart-pie-BodrUoHv.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-BKZXylBB.js → chart-radar-gG3zfLud.js} +4 -4
- package/dist/client/chunks/{chart-radar-BKZXylBB.js.map → chart-radar-gG3zfLud.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-CMfC7SPd.js → chart-radial-bar-C2IPCV8c.js} +4 -4
- package/dist/client/chunks/{chart-radial-bar-CMfC7SPd.js.map → chart-radial-bar-C2IPCV8c.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-8nRYnupt.js → chart-sankey-BOyxfG1Q.js} +3 -3
- package/dist/client/chunks/{chart-sankey-8nRYnupt.js.map → chart-sankey-BOyxfG1Q.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-xQMa3dUt.js → chart-scatter-B8OwlsAX.js} +4 -4
- package/dist/client/chunks/{chart-scatter-xQMa3dUt.js.map → chart-scatter-B8OwlsAX.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-BGhJ4fui.js → chart-sunburst-D9lGEOCc.js} +4 -4
- package/dist/client/chunks/{chart-sunburst-BGhJ4fui.js.map → chart-sunburst-D9lGEOCc.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-Cn1pmrAw.js → chart-tree-map-DZaKy9he.js} +4 -4
- package/dist/client/chunks/{chart-tree-map-Cn1pmrAw.js.map → chart-tree-map-DZaKy9he.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-C2nVN4pn.js → chart-waterfall-BCdUx4DC.js} +4 -4
- package/dist/client/chunks/{chart-waterfall-C2nVN4pn.js.map → chart-waterfall-BCdUx4DC.js.map} +1 -1
- package/dist/client/chunks/{charts-core-Cy3rHADX.js → charts-core-C5Yokk-x.js} +2 -2
- package/dist/client/chunks/{charts-core-Cy3rHADX.js.map → charts-core-C5Yokk-x.js.map} +1 -1
- package/dist/client/chunks/{core-BdWfCZ3y.js → core-DcfMGTVa.js} +2 -2
- package/dist/client/chunks/{core-BdWfCZ3y.js.map → core-DcfMGTVa.js.map} +1 -1
- package/dist/client/chunks/{dist-BWPE2m_X.js → dist-eZurnOde.js} +1 -1
- package/dist/client/chunks/{dist-BWPE2m_X.js.map → dist-eZurnOde.js.map} +1 -1
- package/dist/client/chunks/exceljs.min-CcjgM-qg.js +31986 -0
- package/dist/client/chunks/exceljs.min-CcjgM-qg.js.map +1 -0
- package/dist/client/chunks/{javascript-O1RIRkZr.js → javascript-DFvvCuoP.js} +1 -1
- package/dist/client/chunks/{javascript-O1RIRkZr.js.map → javascript-DFvvCuoP.js.map} +1 -1
- package/dist/client/chunks/{json-C5bX2tt1.js → json-BBm9TlrA.js} +1 -1
- package/dist/client/chunks/{json-C5bX2tt1.js.map → json-BBm9TlrA.js.map} +1 -1
- package/dist/client/chunks/{rolldown-runtime-lc2dmIiU.js → rolldown-runtime-CCl2IeXn.js} +5 -2
- package/dist/client/chunks/{schema-visualization-DVdfx6N8.js → schema-visualization-t1KiOORo.js} +261 -265
- package/dist/client/chunks/{schema-visualization-DVdfx6N8.js.map → schema-visualization-t1KiOORo.js.map} +1 -1
- package/dist/client/chunks/{sql-D2qikO5q.js → sql-k0GA6oZ_.js} +1 -1
- package/dist/client/chunks/{sql-D2qikO5q.js.map → sql-k0GA6oZ_.js.map} +1 -1
- package/dist/client/chunks/{syntaxHighlighting-BYYWYmjr.js → syntaxHighlighting-CnDujqwg.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-BYYWYmjr.js.map → syntaxHighlighting-CnDujqwg.js.map} +1 -1
- package/dist/client/chunks/{useDebounce-Bel8J05v.js → useDebounce-CKqkM42n.js} +11 -14
- package/dist/client/chunks/{useDebounce-Bel8J05v.js.map → useDebounce-CKqkM42n.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-CxdzY2N0.js → useExplainAI-DBIfYwz-.js} +12 -12
- package/dist/client/chunks/{useExplainAI-CxdzY2N0.js.map → useExplainAI-DBIfYwz-.js.map} +1 -1
- package/dist/client/chunks/{utils-CMkS7h9x.js → utils--qCr8Yn5.js} +2 -2
- package/dist/client/chunks/utils--qCr8Yn5.js.map +1 -0
- package/dist/client/chunks/{vendor-BoWEubRu.js → vendor-BRlsCGnK.js} +46 -46
- package/dist/client/chunks/{vendor-BoWEubRu.js.map → vendor-BRlsCGnK.js.map} +1 -1
- package/dist/client/components.js +3 -3
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.js +168 -168
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/types.d.ts +6 -0
- package/dist/client/utils/exportXlsx.d.ts +20 -0
- package/dist/client/utils/index.d.ts +1 -0
- package/dist/client/utils.js +7 -7
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +2 -2
- package/dist/server/index.js +8 -4
- package/dist/server/{openai-DqCEogm0.js → openai-CqZg6zYL.js} +1 -1
- package/dist/server/{openai-0HbLlZq6.cjs → openai-D9Zjuby1.cjs} +1 -1
- package/dist/{adapters/openai-C96O8M75.cjs → server/openai-DmuEbFd6.cjs} +1 -1
- package/dist/server/{openai-DnGeU9PT.js → openai-rwauPzCT.js} +1 -1
- package/package.json +11 -1
- package/dist/adapters/mcp-transport-ro4OL4BW.cjs +0 -255
- package/dist/client/chunks/DashboardEditModal-4zzjtZRR.js.map +0 -1
- package/dist/client/chunks/chart-data-table-BZ7StNWv.js.map +0 -1
- package/dist/client/chunks/utils-CMkS7h9x.js.map +0 -1
- /package/dist/adapters/{anthropic-BIva8k1r.cjs → anthropic-Cto4Jxqt.cjs} +0 -0
- /package/dist/adapters/{anthropic-B_rg0BhK.js → anthropic-DpEbCVvF.js} +0 -0
- /package/dist/adapters/{dist-Boc63-1q.cjs → dist-BnyV9wfA.cjs} +0 -0
- /package/dist/adapters/{dist-De5fzUEM.js → dist-DjVh2RFz.js} +0 -0
package/dist/client/chunks/{chart-activity-grid-wR2Twpo7.js → chart-activity-grid-DLktOINm.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-CCl2IeXn.js";
|
|
2
2
|
import t, { createContext as n, useCallback as r, useContext as i, useEffect as a, useLayoutEffect as o, useMemo as s, useRef as c, useState as l } from "react";
|
|
3
3
|
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
4
4
|
import { max as f, min as p, scaleQuantize as m, select as h } from "d3";
|
|
@@ -803,4 +803,4 @@ var z = {
|
|
|
803
803
|
//#endregion
|
|
804
804
|
export { _ as A, w as C, k as D, O as E, T as O, D as S, y as T, A as _, U as a, b, z as c, j as d, L as f, R as g, M as h, W as i, g as k, N as l, I as m, B as n, H as o, P as p, V as r, G as s, K as t, F as u, C as v, v as w, E as x, x as y };
|
|
805
805
|
|
|
806
|
-
//# sourceMappingURL=chart-activity-grid-
|
|
806
|
+
//# sourceMappingURL=chart-activity-grid-DLktOINm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-activity-grid-wR2Twpo7.js","names":[],"sources":["../../../src/client/providers/CubeMetaContext.tsx","../../../src/client/utils/chartUtils.ts","../../../src/client/hooks/useCubeFieldLabel.ts","../../../src/client/theme/index.ts","../../../src/client/utils/chartConstants.ts","../../../src/client/components/charts/ActivityGridChart.tsx"],"sourcesContent":["/**\n * CubeMetaContext - Metadata context definitions.\n *\n * Split from CubeMetaProvider so consumers can access metadata context\n * without pulling in TanStack Query dependencies.\n */\n\nimport { createContext, useContext } from 'react'\nimport type { CubeMeta, FieldLabelMap } from '../types'\n\nexport interface CubeMetaContextValue {\n meta: CubeMeta | null\n labelMap: FieldLabelMap\n metaLoading: boolean\n metaError: string | null\n getFieldLabel: (fieldName: string) => string\n refetchMeta: () => void\n}\n\nexport const CubeMetaContext = createContext<CubeMetaContextValue | null>(null)\n\nexport function useCubeMeta() {\n const context = useContext(CubeMetaContext)\n if (!context) {\n throw new Error('useCubeMeta must be used within CubeMetaProvider')\n }\n return context\n}\n","import type { FieldLabelMap, AxisFormatConfig } from '../types'\n\n// Utility function to check if a value is a valid numeric value (not null, undefined, or NaN)\n// This is used to preserve null values instead of converting them to 0\nexport function isValidNumericValue(value: any): boolean {\n return value !== null && value !== undefined && !isNaN(Number(value))\n}\n\n// Utility function to parse numeric value from data, preserving nulls\n// Returns null for null/undefined/NaN values, otherwise returns the numeric value\nexport function parseNumericValue(value: any): number | null {\n if (value === null || value === undefined) return null\n const num = typeof value === 'string' ? parseFloat(value) : Number(value)\n return isNaN(num) ? null : num\n}\n\n// Utility function to format numeric values for display in charts\n// Rounds to at most 2 decimal places, preserves integers\nexport function formatNumericValue(value: any): string {\n if (value === null || value === undefined) return 'No data'\n const num = typeof value === 'number' ? value : parseFloat(value)\n if (isNaN(num)) return String(value)\n if (Number.isInteger(num)) return num.toLocaleString()\n // Round to at most 2 decimal places, remove trailing zeros\n return parseFloat(num.toFixed(2)).toLocaleString()\n}\n\n/**\n * Format a numeric value for axis/tooltip display with configurable formatting\n *\n * @param value - The numeric value to format\n * @param config - Optional formatting configuration\n * @param locale - Optional locale string (defaults to browser locale)\n * @returns Formatted string representation of the value\n *\n * @example\n * formatAxisValue(1250000, { unit: 'currency', abbreviate: true }) // \"$1.25M\"\n * formatAxisValue(0.75, { unit: 'percent', decimals: 1 }) // \"75.0%\"\n * formatAxisValue(1234567, { abbreviate: true, decimals: 2 }) // \"1.23M\"\n */\nexport function formatAxisValue(\n value: number | null | undefined,\n config?: AxisFormatConfig,\n locale?: string\n): string {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return 'No data'\n }\n\n // Handle non-numeric values\n const num = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(num)) {\n return String(value)\n }\n\n // Handle special cases\n if (!isFinite(num)) {\n return num > 0 ? '∞' : '-∞'\n }\n\n // Get locale (default to browser locale)\n const effectiveLocale = locale || (typeof navigator !== 'undefined' ? navigator.language : 'en-US')\n\n // If no config provided, use default formatting\n if (!config) {\n return formatNumericValue(value)\n }\n\n const { unit, abbreviate = true, decimals, customPrefix, customSuffix } = config\n\n // Calculate the display value and suffix for abbreviation\n // Default to true for abbreviation when config is provided\n let displayValue = num\n let abbreviationSuffix = ''\n\n if (abbreviate) {\n const absNum = Math.abs(num)\n if (absNum >= 1_000_000_000) {\n displayValue = num / 1_000_000_000\n abbreviationSuffix = 'B'\n } else if (absNum >= 1_000_000) {\n displayValue = num / 1_000_000\n abbreviationSuffix = 'M'\n } else if (absNum >= 1_000) {\n displayValue = num / 1_000\n abbreviationSuffix = 'K'\n }\n }\n\n // Determine decimal places\n // If decimals is undefined, use auto (2 for non-integers, 0 for integers after abbreviation)\n const effectiveDecimals = decimals !== undefined\n ? decimals\n : (Number.isInteger(displayValue) ? 0 : 2)\n\n // Format based on unit type\n switch (unit) {\n case 'currency': {\n // Use Intl.NumberFormat for currency\n // Currency code is determined by locale (USD for en-US, EUR for de-DE, etc.)\n const currencyCode = getCurrencyCodeForLocale(effectiveLocale)\n\n if (abbreviate && abbreviationSuffix) {\n // For abbreviated currency, format the number part and add suffix\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n // Insert abbreviation suffix before any trailing currency symbol or at end\n // Handle both \"$1.25\" -> \"$1.25M\" and \"1.25 €\" -> \"1.25M €\"\n const parts = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n }).formatToParts(displayValue)\n const hasTrailingCurrency = parts[parts.length - 1]?.type === 'currency'\n if (hasTrailingCurrency) {\n // Currency symbol is at the end (e.g., \"1.25 €\")\n return formatted.replace(/(\\s*[^\\d\\s]+)$/, abbreviationSuffix + '$1')\n }\n return formatted + abbreviationSuffix\n }\n\n return new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n }\n\n case 'percent': {\n // Format as percentage (multiply by 100 if value is 0-1 range, otherwise use as-is)\n // Assume values > 1 are already percentages, values <= 1 need multiplication\n const percentValue = Math.abs(displayValue) <= 1 && !abbreviate ? displayValue * 100 : displayValue\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(percentValue)\n return formatted + abbreviationSuffix + '%'\n }\n\n case 'custom': {\n // Apply custom prefix/suffix\n const prefix = customPrefix || ''\n const suffix = customSuffix || ''\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return prefix + formatted + abbreviationSuffix + suffix\n }\n\n case 'number':\n default: {\n // Standard number formatting with locale-aware grouping\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return formatted + abbreviationSuffix\n }\n }\n}\n\n/**\n * Get the currency code for a given locale\n * Maps common locales to their default currency\n */\nfunction getCurrencyCodeForLocale(locale: string): string {\n // Extract language and region from locale (e.g., \"en-US\" -> [\"en\", \"US\"])\n const parts = locale.split('-')\n const region = parts[1]?.toUpperCase()\n\n // Map regions to currencies\n const currencyMap: Record<string, string> = {\n 'US': 'USD',\n 'CA': 'CAD',\n 'GB': 'GBP',\n 'UK': 'GBP',\n 'AU': 'AUD',\n 'NZ': 'NZD',\n 'EU': 'EUR',\n 'DE': 'EUR',\n 'FR': 'EUR',\n 'IT': 'EUR',\n 'ES': 'EUR',\n 'NL': 'EUR',\n 'BE': 'EUR',\n 'AT': 'EUR',\n 'IE': 'EUR',\n 'PT': 'EUR',\n 'FI': 'EUR',\n 'JP': 'JPY',\n 'CN': 'CNY',\n 'KR': 'KRW',\n 'IN': 'INR',\n 'BR': 'BRL',\n 'MX': 'MXN',\n 'CH': 'CHF',\n 'SE': 'SEK',\n 'NO': 'NOK',\n 'DK': 'DKK',\n 'PL': 'PLN',\n 'RU': 'RUB',\n 'ZA': 'ZAR',\n 'SG': 'SGD',\n 'HK': 'HKD',\n 'TW': 'TWD',\n 'TH': 'THB',\n 'MY': 'MYR',\n 'PH': 'PHP',\n 'ID': 'IDR',\n 'VN': 'VND',\n 'AE': 'AED',\n 'SA': 'SAR',\n 'IL': 'ILS',\n 'TR': 'TRY',\n }\n\n return currencyMap[region] || 'USD'\n}\n\n/**\n * Create a tick formatter function for Recharts axes\n * Returns a function that can be used as tickFormatter prop\n */\nexport function createAxisTickFormatter(config?: AxisFormatConfig): (value: any) => string {\n return (value: any) => formatAxisValue(value, config)\n}\n\n// Utility function to get field label from field name\nexport function getFieldLabel(fieldName: string, labelMap: FieldLabelMap): string {\n return labelMap[fieldName] || fieldName\n}\n\n// Utility function to transform series keys to use labels\nexport function transformSeriesKeysWithLabels(seriesKeys: string[], labelMap: FieldLabelMap): string[] {\n return seriesKeys.map(key => getFieldLabel(key, labelMap))\n}\n\n// Utility function to format time values for better display using known granularity\nexport function formatTimeValue(value: any, granularity?: string): string {\n\n if (!value) return 'Unknown'\n \n const str = String(value)\n \n // Check if it's a timestamp (ISO format or PostgreSQL format)\n // Handles formats like: \"2025-04-01T00:00:00.000\" or \"2023-02-01 00:00:00+00\"\n if (str.match(/^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}/)) {\n // Convert PostgreSQL format to ISO format if needed\n let isoStr = str\n if (str.includes(' ')) {\n // Convert \"2023-02-01 00:00:00+00\" to \"2023-02-01T00:00:00Z\"\n isoStr = str.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n // Ensure the timestamp ends with 'Z' if not present\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n const date = new Date(isoStr)\n \n // Ensure we're working with valid date\n if (isNaN(date.getTime())) {\n return str\n }\n \n // Use UTC methods on the properly UTC-parsed date\n const year = date.getUTCFullYear()\n const month = String(date.getUTCMonth() + 1).padStart(2, '0')\n const day = String(date.getUTCDate()).padStart(2, '0')\n const hours = date.getUTCHours()\n const minutes = date.getUTCMinutes()\n \n // Format based on known granularity if provided\n if (granularity) {\n switch (granularity.toLowerCase()) {\n case 'year':\n return `${year}`\n case 'quarter': {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n case 'month':\n return `${year}-${month}`\n case 'week':\n // For week, we could calculate week number, but let's use date for simplicity\n return `${year}-${month}-${day}`\n case 'day':\n return `${year}-${month}-${day}`\n case 'hour':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n case 'minute':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n default:\n // Unknown granularity, fall back to heuristic\n break\n }\n }\n \n // Fallback heuristic if granularity not provided or unknown\n const seconds = date.getUTCSeconds()\n const milliseconds = date.getUTCMilliseconds()\n \n // If it's the first day of the month at exactly midnight UTC, it's likely a month granularity\n if (day === '01' && hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Check if it's also first month of a quarter (quarter granularity)\n if (month === '01' || month === '04' || month === '07' || month === '10') {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n // Month granularity\n return `${year}-${month}`\n }\n \n // If it's exactly midnight UTC, it's likely a day granularity\n if (hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n return `${year}-${month}-${day}`\n }\n \n // If it has time components, include them (hour/minute granularity)\n if (minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Hour granularity\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n }\n \n // Full timestamp\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n }\n \n // Return as-is if not a timestamp\n return str\n}\n\n// Helper function to get granularity for a field from the query timeDimensions\nexport function getFieldGranularity(queryObject: any, fieldName: string): string | undefined {\n try {\n if (queryObject?.timeDimensions) {\n // Find the timeDimension that matches this field\n const timeDim = queryObject.timeDimensions.find((td: any) => {\n // Check if field name matches the dimension or dimension with granularity suffix\n return fieldName === td.dimension || \n fieldName.startsWith(td.dimension.replace('.', '_')) ||\n fieldName === `${td.dimension}_${td.granularity}`\n })\n \n if (timeDim?.granularity) {\n return timeDim.granularity\n }\n }\n \n // Fallback: extract granularity from field name suffix if present\n const granularityMatch = fieldName.match(/_([a-z]+)$/)\n if (granularityMatch) {\n const suffix = granularityMatch[1]\n // Only return if it's a valid granularity\n if (['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second'].includes(suffix)) {\n return suffix\n }\n }\n \n return undefined\n } catch {\n return undefined\n }\n}\n\n// Transform data for charts with proper type handling\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartData(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName\n) {\n if (!data || data.length === 0) return []\n\n const granularity = getFieldGranularity(queryObject, xAxisField)\n\n return data.map((row: any) => {\n const transformed: any = {\n name: formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown',\n }\n\n yAxisFields.forEach(field => {\n const displayName = getFieldLabelFn(field)\n if (displayName === '__proto__' || displayName === 'constructor' || displayName === 'prototype') return\n // Preserve null values instead of converting to 0\n transformed[displayName] = parseNumericValue(row[field])\n })\n\n return transformed\n })\n}\n\nexport interface ChartSeriesResult {\n data: any[]\n seriesKeys: string[]\n hasDimensions: boolean\n}\n\n// Advanced data transformation that handles both measures and dimensions on Y-axis\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartDataWithSeries(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n seriesFields?: string[], // New optional parameter for explicit series fields\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName // Function to get field labels\n): ChartSeriesResult {\n if (!data || data.length === 0) {\n return { data: [], seriesKeys: [], hasDimensions: false }\n }\n\n const originalQuery = queryObject || {}\n const queryDimensions = [\n ...(originalQuery.dimensions || []),\n ...(originalQuery.timeDimensions?.map((td: any) => td.dimension) || [])\n ]\n const queryMeasures = originalQuery.measures || []\n\n // Use explicit series fields if provided, otherwise no dimension-based series\n const yAxisMeasures = yAxisFields.filter(field => queryMeasures.includes(field))\n const yAxisDimensions = (seriesFields || []).filter(field => queryDimensions.includes(field))\n\n // Handle complex case with dimensions on Y-axis\n if (yAxisDimensions.length > 0) {\n // Group data by X-axis field and create separate series for dimension values\n const groupedData: { [key: string]: any } = {}\n\n data.forEach((row: any) => {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n const xValue = formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown'\n if (xValue === '__proto__' || xValue === 'constructor' || xValue === 'prototype') return\n if (!groupedData[xValue]) {\n groupedData[xValue] = { name: String(xValue) }\n }\n\n // Add measures - preserve nulls for individual measures\n yAxisMeasures.forEach(measure => {\n const displayName = getFieldLabelFn(measure)\n if (displayName === '__proto__' || displayName === 'constructor' || displayName === 'prototype') return\n const measureValue = parseNumericValue(row[measure])\n\n // For aggregation: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][displayName]\n\n groupedData[xValue][displayName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(displayName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][displayName] = null\n }\n })\n\n // Add dimensions as separate series (aggregate measure values by dimension)\n yAxisDimensions.forEach(dimension => {\n const dimValue = row[dimension]\n if (dimValue !== undefined && dimValue !== null) {\n const seriesName = String(dimValue)\n // Aggregate the first measure for this dimension value, or use totalCost if available\n const measureToAggregate = yAxisMeasures[0] || queryMeasures.find((m: string) =>\n m.includes('totalCost') || m.includes('count') || m.includes('sum')\n ) || queryMeasures[0]\n\n if (measureToAggregate) {\n if (seriesName === '__proto__' || seriesName === 'constructor' || seriesName === 'prototype') return\n const measureValue = parseNumericValue(row[measureToAggregate])\n\n // For dimension series: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][seriesName]\n\n groupedData[xValue][seriesName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(seriesName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][seriesName] = null\n }\n }\n }\n })\n })\n \n const chartData = Object.values(groupedData)\n \n // Get all series keys for rendering\n // When dimensions are on Y-axis, only show dimension series, not measures\n // The measures are the values being aggregated for each dimension series\n const dimensionSeries = Array.from(new Set(\n data.flatMap((row: any) => \n yAxisDimensions.map(dimension => {\n const value = row[dimension]\n return value !== undefined && value !== null \n ? String(value)\n : null\n }).filter((value): value is string => value !== null)\n )\n ))\n \n return {\n data: chartData,\n seriesKeys: dimensionSeries,\n hasDimensions: true\n }\n }\n \n // Standard measures-only path\n const chartData = transformChartData(data, xAxisField, yAxisFields, queryObject, getFieldLabelFn)\n const seriesKeys = yAxisFields.map(field => getFieldLabelFn(field))\n \n return {\n data: chartData,\n seriesKeys,\n hasDimensions: false\n }\n}","/**\n * Optimized hook that only subscribes to field label functionality\n * from CubeMeta context. This prevents re-renders when unrelated\n * contexts (CubeApi, Features) change.\n *\n * Use this instead of useCubeContext() when you only need getFieldLabel.\n */\n\nimport { useContext, useMemo } from 'react'\nimport { CubeMetaContext, type CubeMetaContextValue } from '../providers/CubeMetaContext'\n\n/**\n * Returns a stable reference to the getFieldLabel function.\n * Components using this hook will only re-render when the field label\n * mapping actually changes, not when unrelated API or feature contexts update.\n *\n * @returns Function to get human-readable label for a field name\n * @throws Error if used outside CubeProvider\n */\nexport function useCubeFieldLabel(): (fieldName: string) => string {\n const context = useContext(CubeMetaContext) as CubeMetaContextValue | null\n\n if (!context) {\n throw new Error('useCubeFieldLabel must be used within CubeProvider')\n }\n\n // Return stable reference - only changes when getFieldLabel itself changes\n return useMemo(() => context.getFieldLabel, [context.getFieldLabel])\n}\n","/**\n * Theme utilities and TypeScript types for drizzle-cube theming system\n */\n\n/**\n * Semantic color tokens used throughout drizzle-cube components\n */\nexport interface ThemeColorTokens {\n // Surface colors\n surface: string\n surfaceSecondary: string\n surfaceTertiary: string\n surfaceHover: string\n\n // Text colors\n text: string\n textSecondary: string\n textMuted: string\n textDisabled: string\n\n // Border colors\n border: string\n borderSecondary: string\n borderHover: string\n\n // Primary colors\n primary: string\n primaryHover: string\n primaryContent: string\n\n // Semantic state colors\n success: string\n successBg: string\n successBorder: string\n\n warning: string\n warningBg: string\n warningBorder: string\n\n error: string\n errorBg: string\n errorBorder: string\n\n info: string\n infoBg: string\n infoBorder: string\n\n // Danger colors\n danger: string\n dangerHover: string\n dangerBg: string\n\n // Overlay colors\n overlay: string\n overlayLight: string\n}\n\n/**\n * Theme configuration interface\n */\nexport interface ThemeConfig {\n name: string\n colors: Partial<ThemeColorTokens>\n}\n\n/**\n * Get the current value of a theme CSS variable\n */\nexport function getThemeVariable(variableName: string): string {\n if (typeof window === 'undefined') return ''\n\n return getComputedStyle(document.documentElement)\n .getPropertyValue(`--dc-${variableName}`)\n .trim()\n}\n\n/**\n * Set a theme CSS variable\n */\nexport function setThemeVariable(variableName: string, value: string): void {\n if (typeof window === 'undefined') return\n\n document.documentElement.style.setProperty(`--dc-${variableName}`, value)\n}\n\n/**\n * Apply a complete theme configuration\n */\nexport function applyTheme(theme: ThemeConfig): void {\n if (typeof window === 'undefined') return\n\n Object.entries(theme.colors).forEach(([key, value]) => {\n if (value) {\n // Convert camelCase to kebab-case\n const cssVarName = key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)\n setThemeVariable(cssVarName, value)\n }\n })\n}\n\n/**\n * Reset theme to defaults by removing custom properties\n */\nexport function resetTheme(): void {\n if (typeof window === 'undefined') return\n\n const styleElement = document.documentElement.style\n const properties = Array.from(styleElement)\n\n properties.forEach(prop => {\n if (prop.startsWith('--dc-')) {\n styleElement.removeProperty(prop)\n }\n })\n}\n\n/**\n * Theme type definition\n */\nexport type Theme = 'light' | 'dark' | 'neon'\n\n/**\n * Get the current theme\n */\nexport function getTheme(): Theme {\n if (typeof window === 'undefined') return 'light'\n\n // Check localStorage first\n const stored = localStorage.getItem('theme')\n if (stored === 'dark' || stored === 'neon' || stored === 'light') {\n return stored\n }\n\n // Check for data-theme attribute\n const dataTheme = document.documentElement.getAttribute('data-theme')\n if (dataTheme === 'dark' || dataTheme === 'neon') {\n return dataTheme\n }\n\n // Check for dark class\n if (document.documentElement.classList.contains('dark') ||\n document.body.classList.contains('dark')) {\n return 'dark'\n }\n\n // Check for neon class\n if (document.documentElement.classList.contains('neon') ||\n document.body.classList.contains('neon')) {\n return 'neon'\n }\n\n // Check system preference\n if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return 'dark'\n }\n\n return 'light'\n}\n\n/**\n * Set the theme\n */\nexport function setTheme(theme: Theme): void {\n if (typeof window === 'undefined') return\n\n // Remove all theme classes\n document.documentElement.classList.remove('dark', 'neon')\n\n // Set data-theme attribute\n document.documentElement.setAttribute('data-theme', theme)\n\n // Add appropriate class for backwards compatibility\n if (theme === 'dark' || theme === 'neon') {\n document.documentElement.classList.add(theme)\n }\n\n // Persist to localStorage\n localStorage.setItem('theme', theme)\n}\n\n/**\n * Detect if dark mode is currently active (backwards compatibility)\n * @deprecated Use getTheme() instead\n */\nexport function isDarkMode(): boolean {\n const theme = getTheme()\n return theme === 'dark' || theme === 'neon'\n}\n\n/**\n * Watch for theme changes\n */\nexport function watchThemeChanges(callback: (theme: Theme) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n\n // Watch for class changes on html element\n const observer = new MutationObserver(() => {\n callback(getTheme())\n })\n\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme']\n })\n\n // Watch for system preference changes\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const mediaListener = () => callback(getTheme())\n mediaQuery.addEventListener('change', mediaListener)\n\n // Return cleanup function\n return () => {\n observer.disconnect()\n mediaQuery.removeEventListener('change', mediaListener)\n }\n}\n\n/**\n * Example theme configurations\n */\nexport const THEME_PRESETS = {\n light: {\n name: 'light' as const,\n colors: {\n surface: '#ffffff',\n surfaceSecondary: '#f9fafb',\n text: '#111827',\n textSecondary: '#374151',\n textMuted: '#6b7280',\n border: '#e5e7eb',\n primary: '#3b82f6',\n primaryHover: '#2563eb',\n }\n },\n dark: {\n name: 'dark' as const,\n colors: {\n surface: '#1e293b',\n surfaceSecondary: '#334155',\n text: '#f1f5f9',\n textSecondary: '#e2e8f0',\n textMuted: '#cbd5e1',\n border: '#475569',\n primary: '#60a5fa',\n primaryHover: '#3b82f6',\n }\n },\n neon: {\n name: 'neon' as const,\n colors: {\n surface: '#0a0118',\n surfaceSecondary: '#1a0f2e',\n surfaceTertiary: '#2a1f3e',\n text: '#ffffff',\n textSecondary: '#e0e0ff',\n textMuted: '#b0b0d0',\n border: '#ff00ff',\n borderSecondary: '#00ffff',\n primary: '#00ffff',\n primaryHover: '#00cccc',\n primaryContent: '#000000',\n success: '#00ff00',\n warning: '#ffff00',\n error: '#ff0066',\n info: '#00ffff',\n danger: '#ff1493',\n }\n }\n} as const\n","// Default color palette for charts - used as fallback when no dashboard palette is specified\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS = [\n '#3b82f6', // blue\n '#10b981', // green\n '#f59e0b', // yellow\n '#ef4444', // red\n '#8b5cf6', // purple\n '#f97316', // orange\n '#06b6d4', // cyan\n '#84cc16', // lime\n]\n\n// Default gradient colors for continuous numeric scales - used as fallback\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS_GRADIENT = [\n '#440154', // dark purple\n '#414487', // purple-blue\n '#2a788e', // teal\n '#22a884', // green-teal \n '#7ad151', // green\n '#fde725', // yellow\n]\n\n// Colors for positive/negative values\nexport const POSITIVE_COLOR = '#10b981' // green\nexport const NEGATIVE_COLOR = '#ef4444' // red\n\nexport const CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 5\n}\n\nexport const RESPONSIVE_CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 60 // Extra space for rotated labels\n}","import 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 onDataPointClick,\n drillEnabled\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', drillEnabled ? 'pointer' : 'default')\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 } else if (drillEnabled) {\n // Set cursor for drill even without tooltips\n rect.style('cursor', 'pointer')\n }\n\n // Add drill click handler\n if (drillEnabled && onDataPointClick && cell) {\n rect.on('click', function(event) {\n onDataPointClick({\n dataPoint: { [valueField]: cell.value, [dateField]: cell.date },\n clickedField: valueField,\n xValue: cell.label,\n position: { x: event.pageX, y: event.pageY },\n nativeEvent: event as unknown as React.MouseEvent\n })\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: string\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, drillEnabled, onDataPointClick])\n\n if (!data || data.length === 0) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data available</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in 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=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Required</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Granularity Too High</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">Activity grids work best with hour, day, week, month, or quarter granularity</div>\n <div className=\"dc:text-xs text-dc-text-secondary dc:mt-1\">Please choose a lower granularity for your time dimension</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:w-full dc:flex dc:flex-col dc:relative\" style={{ height, minHeight: '250px', overflow: 'hidden', width: '100%' }}>\n <div ref={containerRef} className=\"dc:w-full dc:h-full dc:relative dc:overflow-x-auto\" style={{ width: '100%' }}>\n <svg ref={svgRef} className=\"dc:h-full\" />\n {!dimensionsReady && (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center\">\n <div className=\"text-dc-text-muted dc:text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default ActivityGridChart"],"mappings":";;;;;AAmBA,IAAa,IAAkB,EAA2C,KAAK;AAE/E,SAAgB,IAAc;CAC5B,IAAM,IAAU,EAAW,EAAgB;AAC3C,KAAI,CAAC,EACH,OAAU,MAAM,mDAAmD;AAErE,QAAO;;;;ACtBT,SAAgB,EAAoB,GAAqB;AACvD,QAAO,KAAU,QAA+B,CAAC,MAAM,OAAO,EAAM,CAAC;;AAKvE,SAAgB,EAAkB,GAA2B;AAC3D,KAAI,KAAU,KAA6B,QAAO;CAClD,IAAM,IAAM,OAAO,KAAU,WAAW,WAAW,EAAM,GAAG,OAAO,EAAM;AACzE,QAAO,MAAM,EAAI,GAAG,OAAO;;AAK7B,SAAgB,EAAmB,GAAoB;AACrD,KAAI,KAAU,KAA6B,QAAO;CAClD,IAAM,IAAM,OAAO,KAAU,WAAW,IAAQ,WAAW,EAAM;AAIjE,QAHI,MAAM,EAAI,GAAS,OAAO,EAAM,GAChC,OAAO,UAAU,EAAI,GAAS,EAAI,gBAAgB,GAE/C,WAAW,EAAI,QAAQ,EAAE,CAAC,CAAC,gBAAgB;;AAgBpD,SAAgB,EACd,GACA,GACA,GACQ;AAER,KAAI,KAAU,KACZ,QAAO;CAIT,IAAM,IAAM,OAAO,KAAU,WAAW,IAAQ,WAAW,OAAO,EAAM,CAAC;AACzE,KAAI,MAAM,EAAI,CACZ,QAAO,OAAO,EAAM;AAItB,KAAI,CAAC,SAAS,EAAI,CAChB,QAAO,IAAM,IAAI,MAAM;CAIzB,IAAM,IAAkB,MAAW,OAAO,YAAc,MAAc,UAAU,WAAW;AAG3F,KAAI,CAAC,EACH,QAAO,EAAmB,EAAM;CAGlC,IAAM,EAAE,SAAM,gBAAa,IAAM,aAAU,iBAAc,oBAAiB,GAItE,IAAe,GACf,IAAqB;AAEzB,KAAI,GAAY;EACd,IAAM,IAAS,KAAK,IAAI,EAAI;AAC5B,EAAI,KAAU,OACZ,IAAe,IAAM,KACrB,IAAqB,OACZ,KAAU,OACnB,IAAe,IAAM,KACrB,IAAqB,OACZ,KAAU,QACnB,IAAe,IAAM,KACrB,IAAqB;;CAMzB,IAAM,IAAoB,MAAa,KAAA,IAElC,OAAO,UAAU,EAAa,GAAG,IAAI,IADtC;AAIJ,SAAQ,GAAR;EACE,KAAK,YAAY;GAGf,IAAM,IAAe,EAAyB,EAAgB;AAE9D,OAAI,KAAc,GAAoB;IAEpC,IAAM,IAAY,IAAI,KAAK,aAAa,GAAiB;KACvD,OAAO;KACP,UAAU;KACV,uBAAuB;KACvB,uBAAuB;KACxB,CAAC,CAAC,OAAO,EAAa,EAGjB,IAAQ,IAAI,KAAK,aAAa,GAAiB;KACnD,OAAO;KACP,UAAU;KACX,CAAC,CAAC,cAAc,EAAa;AAM9B,WAL4B,EAAM,EAAM,SAAS,IAAI,SAAS,aAGrD,EAAU,QAAQ,kBAAkB,IAAqB,KAAK,GAEhE,IAAY;;AAGrB,UAAO,IAAI,KAAK,aAAa,GAAiB;IAC5C,OAAO;IACP,UAAU;IACV,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa;;EAGzB,KAAK,WAAW;GAGd,IAAM,IAAe,KAAK,IAAI,EAAa,IAAI,KAAK,CAAC,IAAa,IAAe,MAAM;AAKvF,UAJkB,IAAI,KAAK,aAAa,GAAiB;IACvD,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa,GACJ,IAAqB;;EAG1C,KAAK,UAAU;GAEb,IAAM,IAAS,KAAgB,IACzB,IAAS,KAAgB;AAK/B,UAAO,IAJW,IAAI,KAAK,aAAa,GAAiB;IACvD,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa,GACK,IAAqB;;EAInD,QAME,QAJkB,IAAI,KAAK,aAAa,GAAiB;GACvD,uBAAuB;GACvB,uBAAuB;GACxB,CAAC,CAAC,OAAO,EAAa,GACJ;;;AASzB,SAAS,EAAyB,GAAwB;AAmDxD,QA7C4C;EAC1C,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACP,CA/Ca,EAAO,MAAM,IAAI,CACV,IAAI,aAAa,KAgDR;;AAOhC,SAAgB,EAAwB,GAAmD;AACzF,SAAQ,MAAe,EAAgB,GAAO,EAAO;;AAIvD,SAAgB,EAAc,GAAmB,GAAiC;AAChF,QAAO,EAAS,MAAc;;AAIhC,SAAgB,EAA8B,GAAsB,GAAmC;AACrG,QAAO,EAAW,KAAI,MAAO,EAAc,GAAK,EAAS,CAAC;;AAI5D,SAAgB,EAAgB,GAAY,GAA8B;AAExE,KAAI,CAAC,EAAO,QAAO;CAEnB,IAAM,IAAM,OAAO,EAAM;AAIzB,KAAI,EAAI,MAAM,0CAA0C,EAAE;EAExD,IAAI,IAAS;AAMb,EALI,EAAI,SAAS,IAAI,KAEnB,IAAS,EAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,kBAAkB,IAAI,GAG/E,CAAC,EAAO,SAAS,IAAI,IAAI,CAAC,EAAO,SAAS,IAAI,KAChD,KAAkB;EAEpB,IAAM,IAAO,IAAI,KAAK,EAAO;AAG7B,MAAI,MAAM,EAAK,SAAS,CAAC,CACvB,QAAO;EAIT,IAAM,IAAO,EAAK,gBAAgB,EAC5B,IAAQ,OAAO,EAAK,aAAa,GAAG,EAAE,CAAC,SAAS,GAAG,IAAI,EACvD,IAAM,OAAO,EAAK,YAAY,CAAC,CAAC,SAAS,GAAG,IAAI,EAChD,IAAQ,EAAK,aAAa,EAC1B,IAAU,EAAK,eAAe;AAGpC,MAAI,EACF,SAAQ,EAAY,aAAa,EAAjC;GACE,KAAK,OACH,QAAO,GAAG;GACZ,KAAK,UAEH,QAAO,GAAG,EAAK,IADC,KAAK,MAAM,EAAK,aAAa,GAAG,EAAE,GAAG;GAGvD,KAAK,QACH,QAAO,GAAG,EAAK,GAAG;GACpB,KAAK,OAEH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG;GAC7B,KAAK,MACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG;GAC7B,KAAK,OACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC;GACnE,KAAK,SACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;GACtG,QAEE;;EAKN,IAAM,IAAU,EAAK,eAAe,EAC9B,IAAe,EAAK,oBAAoB;AAyB9C,SAtBI,MAAQ,QAAQ,MAAU,KAAK,MAAY,KAAK,MAAY,KAAK,MAAiB,IAEhF,MAAU,QAAQ,MAAU,QAAQ,MAAU,QAAQ,MAAU,OAE3D,GAAG,EAAK,IADC,KAAK,MAAM,EAAK,aAAa,GAAG,EAAE,GAAG,MAIhD,GAAG,EAAK,GAAG,MAIhB,MAAU,KAAK,MAAY,KAAK,MAAY,KAAK,MAAiB,IAC7D,GAAG,EAAK,GAAG,EAAM,GAAG,MAIzB,MAAY,KAAK,MAAY,KAAK,MAAiB,IAE9C,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,OAI5D,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;;AAItG,QAAO;;AAIT,SAAgB,EAAoB,GAAkB,GAAuC;AAC3F,KAAI;AACF,MAAI,GAAa,gBAAgB;GAE/B,IAAM,IAAU,EAAY,eAAe,MAAM,MAExC,MAAc,EAAG,aACjB,EAAU,WAAW,EAAG,UAAU,QAAQ,KAAK,IAAI,CAAC,IACpD,MAAc,GAAG,EAAG,UAAU,GAAG,EAAG,cAC3C;AAEF,OAAI,GAAS,YACX,QAAO,EAAQ;;EAKnB,IAAM,IAAmB,EAAU,MAAM,aAAa;AACtD,MAAI,GAAkB;GACpB,IAAM,IAAS,EAAiB;AAEhC,OAAI;IAAC;IAAQ;IAAW;IAAS;IAAQ;IAAO;IAAQ;IAAU;IAAS,CAAC,SAAS,EAAO,CAC1F,QAAO;;AAIX;SACM;AACN;;;AAMJ,SAAgB,EACd,GACA,GACA,GACA,GACA,KAAkD,MAAc,GAChE;AACA,KAAI,CAAC,KAAQ,EAAK,WAAW,EAAG,QAAO,EAAE;CAEzC,IAAM,IAAc,EAAoB,GAAa,EAAW;AAEhE,QAAO,EAAK,KAAK,MAAa;EAC5B,IAAM,IAAmB,EACvB,MAAM,EAAgB,EAAI,IAAa,EAAY,IAAI,EAAI,MAAe,WAC3E;AASD,SAPA,EAAY,SAAQ,MAAS;GAC3B,IAAM,IAAc,EAAgB,EAAM;AACtC,SAAgB,eAAe,MAAgB,iBAAiB,MAAgB,gBAEpF,EAAY,KAAe,EAAkB,EAAI,GAAO;IACxD,EAEK;GACP;;AAWJ,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,KAAkD,MAAc,GAC7C;AACnB,KAAI,CAAC,KAAQ,EAAK,WAAW,EAC3B,QAAO;EAAE,MAAM,EAAE;EAAE,YAAY,EAAE;EAAE,eAAe;EAAO;CAG3D,IAAM,IAAgB,KAAe,EAAE,EACjC,IAAkB,CACtB,GAAI,EAAc,cAAc,EAAE,EAClC,GAAI,EAAc,gBAAgB,KAAK,MAAY,EAAG,UAAU,IAAI,EAAE,CACvE,EACK,IAAgB,EAAc,YAAY,EAAE,EAG5C,IAAgB,EAAY,QAAO,MAAS,EAAc,SAAS,EAAM,CAAC,EAC1E,KAAmB,KAAgB,EAAE,EAAE,QAAO,MAAS,EAAgB,SAAS,EAAM,CAAC;AAG7F,KAAI,EAAgB,SAAS,GAAG;EAE9B,IAAM,IAAsC,EAAE;AA2E9C,SAzEA,EAAK,SAAS,MAAa;GACzB,IAAM,IAAc,EAAoB,GAAa,EAAW,EAC1D,IAAS,EAAgB,EAAI,IAAa,EAAY,IAAI,EAAI,MAAe;AAC/E,SAAW,eAAe,MAAW,iBAAiB,MAAW,gBAChE,EAAY,OACf,EAAY,KAAU,EAAE,MAAM,OAAO,EAAO,EAAE,GAIhD,EAAc,SAAQ,MAAW;IAC/B,IAAM,IAAc,EAAgB,EAAQ;AAC5C,QAAI,MAAgB,eAAe,MAAgB,iBAAiB,MAAgB,YAAa;IACjG,IAAM,IAAe,EAAkB,EAAI,GAAS;AAGpD,QAAI,MAAiB,MAAM;KACzB,IAAM,IAAe,EAAY,GAAQ;AAEzC,OAAY,GAAQ,KAAgB,KAAiB,OACjD,IACA,IAAe;WACR,KAAe,EAAY,OAEtC,EAAY,GAAQ,KAAe;KAErC,EAGF,EAAgB,SAAQ,MAAa;IACnC,IAAM,IAAW,EAAI;AACrB,QAAI,KAAuC,MAAM;KAC/C,IAAM,IAAa,OAAO,EAAS,EAE7B,IAAqB,EAAc,MAAM,EAAc,MAAM,MACjE,EAAE,SAAS,YAAY,IAAI,EAAE,SAAS,QAAQ,IAAI,EAAE,SAAS,MAAM,CACpE,IAAI,EAAc;AAEnB,SAAI,GAAoB;AACtB,UAAI,MAAe,eAAe,MAAe,iBAAiB,MAAe,YAAa;MAC9F,IAAM,IAAe,EAAkB,EAAI,GAAoB;AAG/D,UAAI,MAAiB,MAAM;OACzB,IAAM,IAAe,EAAY,GAAQ;AAEzC,SAAY,GAAQ,KAAe,KAAiB,OAChD,IACA,IAAe;aACR,KAAc,EAAY,OAErC,EAAY,GAAQ,KAAc;;;KAIxC;IACF,EAkBK;GACL,MAjBgB,OAAO,OAAO,EAAY;GAkB1C,YAbsB,MAAM,KAAK,IAAI,IACrC,EAAK,SAAS,MACZ,EAAgB,KAAI,MAAa;IAC/B,IAAM,IAAQ,EAAI;AAClB,WAAO,KAAiC,OAEpC,OADA,OAAO,EAAM;KAEjB,CAAC,QAAQ,MAA2B,MAAU,KAAK,CACtD,CACF,CAAC;GAKA,eAAe;GAChB;;AAOH,QAAO;EACL,MAJgB,EAAmB,GAAM,GAAY,GAAa,GAAa,EAAgB;EAK/F,YAJiB,EAAY,KAAI,MAAS,EAAgB,EAAM,CAAC;EAKjE,eAAe;EAChB;;;;ACxfH,SAAgB,IAAmD;CACjE,IAAM,IAAU,EAAW,EAAgB;AAE3C,KAAI,CAAC,EACH,OAAU,MAAM,qDAAqD;AAIvE,QAAO,QAAc,EAAQ,eAAe,CAAC,EAAQ,cAAc,CAAC;;;;ACyCtE,SAAgB,EAAiB,GAA8B;AAG7D,QAFI,OAAO,SAAW,MAAoB,KAEnC,iBAAiB,SAAS,gBAAgB,CAC9C,iBAAiB,QAAQ,IAAe,CACxC,MAAM;;AAMX,SAAgB,EAAiB,GAAsB,GAAqB;AACtE,QAAO,SAAW,OAEtB,SAAS,gBAAgB,MAAM,YAAY,QAAQ,KAAgB,EAAM;;AAM3E,SAAgB,EAAW,GAA0B;AAC/C,QAAO,SAAW,OAEtB,OAAO,QAAQ,EAAM,OAAO,CAAC,SAAS,CAAC,GAAK,OAAW;AACrD,EAAI,KAGF,EADmB,EAAI,QAAQ,WAAU,MAAU,IAAI,EAAO,aAAa,GAAG,EACjD,EAAM;GAErC;;AAMJ,SAAgB,IAAmB;AACjC,KAAI,OAAO,SAAW,IAAa;CAEnC,IAAM,IAAe,SAAS,gBAAgB;AAC3B,OAAM,KAAK,EAAa,CAEhC,SAAQ,MAAQ;AACzB,EAAI,EAAK,WAAW,QAAQ,IAC1B,EAAa,eAAe,EAAK;GAEnC;;AAWJ,SAAgB,IAAkB;AAChC,KAAI,OAAO,SAAW,IAAa,QAAO;CAG1C,IAAM,IAAS,aAAa,QAAQ,QAAQ;AAC5C,KAAI,MAAW,UAAU,MAAW,UAAU,MAAW,QACvD,QAAO;CAIT,IAAM,IAAY,SAAS,gBAAgB,aAAa,aAAa;AAsBrE,QArBI,MAAc,UAAU,MAAc,SACjC,IAIL,SAAS,gBAAgB,UAAU,SAAS,OAAO,IACnD,SAAS,KAAK,UAAU,SAAS,OAAO,GACnC,SAIL,SAAS,gBAAgB,UAAU,SAAS,OAAO,IACnD,SAAS,KAAK,UAAU,SAAS,OAAO,GACnC,SAIL,OAAO,WAAW,+BAA+B,CAAC,UAC7C,SAGF;;AAMT,SAAgB,EAAS,GAAoB;AACvC,QAAO,SAAW,QAGtB,SAAS,gBAAgB,UAAU,OAAO,QAAQ,OAAO,EAGzD,SAAS,gBAAgB,aAAa,cAAc,EAAM,GAGtD,MAAU,UAAU,MAAU,WAChC,SAAS,gBAAgB,UAAU,IAAI,EAAM,EAI/C,aAAa,QAAQ,SAAS,EAAM;;AAOtC,SAAgB,IAAsB;CACpC,IAAM,IAAQ,GAAU;AACxB,QAAO,MAAU,UAAU,MAAU;;AAMvC,SAAgB,EAAkB,GAA8C;AAC9E,KAAI,OAAO,SAAW,IAAa,cAAa;CAGhD,IAAM,IAAW,IAAI,uBAAuB;AAC1C,IAAS,GAAU,CAAC;GACpB;AAEF,GAAS,QAAQ,SAAS,iBAAiB;EACzC,YAAY;EACZ,iBAAiB,CAAC,SAAS,aAAa;EACzC,CAAC;CAGF,IAAM,IAAa,OAAO,WAAW,+BAA+B,EAC9D,UAAsB,EAAS,GAAU,CAAC;AAIhD,QAHA,EAAW,iBAAiB,UAAU,EAAc,QAGvC;AAEX,EADA,EAAS,YAAY,EACrB,EAAW,oBAAoB,UAAU,EAAc;;;AAO3D,IAAa,IAAgB;CAC3B,OAAO;EACL,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,SAAS;GACT,cAAc;GACf;EACF;CACD,MAAM;EACJ,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,SAAS;GACT,cAAc;GACf;EACF;CACD,MAAM;EACJ,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,iBAAiB;GACjB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,iBAAiB;GACjB,SAAS;GACT,cAAc;GACd,gBAAgB;GAChB,SAAS;GACT,SAAS;GACT,OAAO;GACP,MAAM;GACN,QAAQ;GACT;EACF;CACF,EC1QY,IAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAIY,IAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAAiB,WACjB,IAAiB,WAEjB,IAAgB;CAC3B,KAAK;CACL,OAAO;CACP,MAAM;CACN,QAAQ;CACT,EAEY,IAA2B;CACtC,KAAK;CACL,OAAO;CACP,MAAM;CACN,QAAQ;gDCTJ,IAAoB,EAAM,KAAK,SAA2B,EAC9D,SACA,gBACA,mBAAgB,EAAE,EAClB,gBACA,YAAS,QACT,iBACA,qBACA,mBACa;CACb,IAAM,IAAS,EAA6B,KAAK,EAC3C,IAAe,EAA8B,KAAK,EAClD,CAAC,GAAY,KAAiB,EAAS;EAAE,OAAO;EAAG,QAAQ;EAAG,CAAC,EAC/D,CAAC,GAAiB,KAAsB,EAAS,GAAM,EACvD,CAAC,GAAc,KAAmB,EAAgB,QAAQ,EAE1D,IAAgB,GAAmB;AAGzC,UACE,EAAgB,GAAU,CAAC,EACX,GAAmB,MAAU;AAC3C,IAAgB,EAAM;GACtB,GAED,EAAE,CAAC;CAEN,IAAM,IAAoB,SAAe;EACvC,aAAa,GAAe,eAAe;EAC3C,YAAY,GAAe,cAAc;EACzC,YAAY,GAAe,cAAc;EAC1C,GAAG;EAAC,GAAe;EAAa,GAAe;EAAY,GAAe;EAAW,CAAC;AA8CvF,CA3CA,QAAsB;EACpB,IAAI,IAAa,GAEb,GACA,GAEE,UAAyB;AAC7B,OAAI,EAAa,SAAS;IACxB,IAAM,EAAE,UAAO,cAAW,EAAa,QAAQ,uBAAuB;AAEtE,QAAI,IAAQ,KAAK,IAAS,EAGxB,QAFA,EAAc;KAAE;KAAO;KAAQ,CAAC,EAChC,EAAmB,GAAK,EACjB;;AAGX,UAAO;;AAKT,MAAI,CAFY,GAAkB,IAElB,IAAa,IAAY;GACvC,IAAM,UAAqB;AAGzB,IAAI,CAFe,GAAkB,IAElB,IAAa,OAC9B,KACA,IAAY,iBAAiB;AAC3B,SAAQ,sBAAsB,EAAa;OAC1C,KAAK,EAAW;;AAIvB,OAAQ,sBAAsB,EAAa;;AAG7C,eAAa;AAEX,GADI,KAAO,qBAAqB,EAAM,EAClC,KAAW,aAAa,EAAU;;IAEvC,EAAE,CAAC,EAGN,QAAgB;EACd,IAAI,IAAwC,MAEtC,UAAyB;AAC7B,OAAI,EAAa,SAAS;IACxB,IAAM,EAAE,UAAO,cAAW,EAAa,QAAQ,uBAAuB;AACtE,IAAI,IAAQ,KAAK,IAAS,MACxB,EAAc;KAAE;KAAO;KAAQ,CAAC,EAC3B,KACH,EAAmB,GAAK;;;AAchC,SARI,EAAa,YACf,IAAiB,IAAI,qBAAqB,GAAkB,CAAC,EAC7D,EAAe,QAAQ,EAAa,QAAQ,EAC5C,GAAkB,GAGpB,OAAO,iBAAiB,UAAU,EAAiB,QAEtC;AAIX,GAHI,KACF,EAAe,YAAY,EAE7B,OAAO,oBAAoB,UAAU,EAAiB;;IAEvD,CAAC,EAAgB,CAAC;CAGrB,IAAM,KAAc,MACX,KAAK,MAAM,EAAK,UAAU,GAAG,EAAE,GAAG,GAGrC,KAAqB,MACjB,EAAK,UAAU,GAAG,IAAK,GAG3B,KAAkB,MAAuB;EAE7C,IAAM,IAAa,EAAK,SAAS;AACjC,SAAO,KAAK,OAAO,IAAa,KAAK,EAAE,GAAG;IAItC,IAAiB,GAAa,MAA4C;AAC9E,UAAQ,GAAa,aAAa,EAAlC;GACE,KAAK,OAEH,QAAO;GAET,KAAK,UAEH,QAAO;IACL,WAAW,MAAe,EAAK,aAAa;IAC5C,WAAW,MAAe,EAAW,EAAK,GAAG;IAC7C,SAAS,EAAE;IACX,SAAS;KAAC;KAAM;KAAM;KAAM;KAAK;IACjC,UAAU,MAAkB,IAAI,EAAM,UAAU,CAAC,MAAM,GAAG;IAC1D,UAAU,MAAkB;KAAC;KAAM;KAAM;KAAM;KAAK,CAAC,MAAU;IAC/D,WAAW;IACX,YAAY;IACb;GAEH,KAAK,QAGH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAU,EAAW,EAAK;AAChC,YAAO,IAAO,KAAK;;IAErB,WAAW,MAAe,EAAkB,EAAK,GAAG;IACpD,SAAS,EAAE;IACX,SAAS;KAAC;KAAW;KAAW;KAAU;IAC1C,UAAU,MAED,IADS,IAAQ;IAG1B,UAAU,MAAkB;KAAC;KAAW;KAAW;KAAU,CAAC,MAAU;IACxE,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,GAAG;IACxD;GAEH,KAAK,OAEH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAQ,EAAK,UAAU,GAAG;AAChC,YAAO,IAAO,MAAM;;IAEtB,WAAW,MAAe,EAAe,EAAK,GAAG;IACjD,SAAS,EAAE;IACX,SAAS;KAAC;KAAU;KAAU;KAAU;KAAU;KAAS;IAC3D,UAAU,MAEW;KAAC;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAI,CADjE,IAAQ,MAEI,MAAM;IAElC,UAAU,MAAkB;KAAC;KAAU;KAAU;KAAU;KAAU;KAAS,CAAC,MAAU;IACzF,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,KAAK,MAEH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,EAAE,SAAM,YAAS,EAAc,EAAK;AAC1C,YAAO,IAAO,MAAM;;IAEtB,WAAW,MAAe,EAAK,QAAQ;IACvC,SAAS,EAAE;IACX,SAAS;KAAC;KAAO;KAAO;KAAO;KAAO;KAAO;KAAO;KAAM;IAC1D,UAAU,MAED,GADM,IAAQ;IAGvB,UAAU,MAAkB;KAAC;KAAO;KAAO;KAAO;KAAO;KAAO;KAAO;KAAM,CAAC,MAAU;IACxF,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,KAAK,OAEH,QAAO;IACL,WAAW,MAAe;KAExB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAQ,EAAK,UAAU,GAAG,GAC1B,IAAM,EAAK,SAAS;AAC1B,YAAO,IAAO,MAAQ,IAAQ,MAAM;;IAEtC,WAAW,MAAe,KAAK,MAAM,EAAK,UAAU,GAAG,EAAE;IACzD,SAAS,EAAE;IACX,SAAS;KAAC;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAQ;IACjF,UAAU,MAGD,GADK,IAAQ;IAGtB,UAAU,MAAkB;KAAC;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAQ,CAAC,MAAU;IAC/G,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,QACE,QAAO;;IAEV,EAAE,CAAC,EAGA,KAAiB,MAA+C;EACpE,IAAM,IAAI,IAAI,KAAK,KAAK,IAAI,EAAK,aAAa,EAAE,EAAK,UAAU,EAAE,EAAK,SAAS,CAAC,CAAC,EAC3E,IAAS,EAAE,WAAW,IAAI;AAChC,IAAE,WAAW,EAAE,YAAY,GAAG,IAAI,EAAO;EACzC,IAAM,IAAO,EAAE,gBAAgB,EACzB,IAAY,IAAI,KAAK,KAAK,IAAI,GAAM,GAAG,EAAE,CAAC;AAEhD,SAAO;GAAE;GAAM,MADF,KAAK,OAAQ,EAAE,SAAS,GAAG,EAAU,SAAS,IAAI,QAAY,KAAK,EAAE;GAC7D;;AAubvB,KApbA,QAAgB;AASd,MARI,CAAC,KAAQ,EAAK,WAAW,KAAK,CAAC,EAAO,WAAW,CAAC,KAAmB,EAAW,UAAU,MAK9F,EAAO,EAAO,QAAQ,CAAC,UAAU,IAAI,CAAC,QAAQ,EAG1C,CAAC,GAAa,aAAa,CAAC,GAAa,YAC3C;EAGF,IAAM,IAAY,MAAM,QAAQ,EAAY,UAAU,GAAG,EAAY,UAAU,KAAK,EAAY,WAC1F,IAAa,MAAM,QAAQ,EAAY,WAAW,GAAG,EAAY,WAAW,KAAK,EAAY;AAGnG,MAAI,CAAC,KAAa,CAAC,EACjB;EA2BF,IAAM,WAvB4B;AAChC,OAAI,CAAC,GAAa,kBAAkB,EAAY,eAAe,WAAW,EACxE,QAAO;GAIT,IAAM,IAAU,EAAY,eAAe,MAAM,MAC/C,EAAG,cAAc,KAAa,EAAG,UAAU,SAAS,EAAU,CAC/D;AAED,OAAI,KAAW,EAAQ,YACrB,QAAO,EAAQ;GAIjB,IAAM,IAAe,EAAY,eAAe;AAKhD,UAJI,KAAgB,EAAa,cACxB,EAAa,cAGf;MAGqC,EACxC,IAAc,EAAe,EAAiB;AAGpD,MAAI,CAAC,EACH;EAKF,IAAM,IAAuB,EAAK,KAAI,MAAQ;GAC5C,IAAM,IAAY,EAAK,IACjB,IAAQ,OAAO,EAAK,MAAgB,WACtC,WAAW,EAAK,GAAY,GAC3B,EAAK,MAAe,GAGrB;AACJ,OAAI,OAAO,KAAc,UAAU;IAEjC,IAAI,IAAS;AAOb,IANI,EAAU,SAAS,IAAI,KACzB,IAAS,EAAU,QAAQ,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,kBAAkB,IAAI,GAErF,CAAC,EAAO,SAAS,IAAI,IAAI,CAAC,EAAO,SAAS,IAAI,KAChD,KAAkB,MAEpB,IAAO,IAAI,KAAK,EAAO;SAEvB,KAAO,IAAI,KAAK,EAAU;AAW5B,UAPI,MAAM,EAAK,SAAS,CAAC,GAChB,OAMF;IACL,GAJQ,EAAY,SAAS,EAAK;IAKlC,GAJQ,EAAY,SAAS,EAAK;IAKlC;IACA;IACA,OAAO,EAAgB,GAAW,EAAiB;IACpD;IACD,CAAC,QAAQ,MAA2B,MAAS,KAAK;AAGpD,MAAI,EAAS,WAAW,EAAG;EAG3B,IAAM,IAAO,EAAI,IAAU,MAAK,EAAE,EAAE,IAAI,GAClC,IAAO,EAAI,IAAU,MAAK,EAAE,EAAE,IAAI,GA+BlC,IA1BgB,CAAC,GAAG,IAAI,IAAI,EAAS,KAAI,MAAQ,EAAK,EAAE,CAAC,CAAC,CAAC,MAAM,EA6BjE,IAAY,EAAe,SAAS,EAAY,aAAa,EAAe,SAAS,KAAK,GAC1F,KAAc,IAAO,IAAO,KAAK,EAAY,cAAc,IAAO,KAAQ,GAE1E,IAAS;GACb,GAAG;GACH,MAAM;GACN,QAAQ;GACR,KAAK,EAAY,wBAAwB,KAAK;GAC9C,OAAO;GACR,EAEK,IAAiB,EAAW,QAAQ,EAAO,OAAO,EAAO,OACzD,IAAkB,EAAW,SAAS,EAAO,MAAM,EAAO,QAG5D,GACA;AAEJ,MAAI,EAAkB,YAAY;GAGhC,IAAM,IAAS,IAAiB,GAC1B,IAAS,IAAkB,GAC3B,IAAQ,KAAK,IAAI,GAAQ,EAAO;AAItC,GADA,IAAiB,EAAY,YAAY,GACzC,IAAkB,EAAY,aAAa;SACtC;GAML,IAAM,IAHG;IAAE,OAAO;IAAI,QAAQ;IAAI,EAM5B,IAAS,IAAiB,GAC1B,IAAS,IAAkB,GAC3B,IAAQ,KAAK,IAAI,GAAQ,EAAO;AAOtC,GAJA,IAAiB,KAAK,IAAI,EAAY,OAAO,KAAK,IAAI,IAAa,EAAY,YAAY,EAAM,CAAC,EAClG,IAAkB,KAAK,IAAI,EAAY,QAAQ,KAAK,IAAI,IAAa,EAAY,aAAa,EAAM,CAAC,EAGjG,MAAqB,UAAU,IAAiB,EAAY,UAC9D,IAAiB,EAAY;;EAKjC,IAAM,IAAkB,EAAe,SAAS,KAAkB,EAAe,SAAS,KAAK,GAIzF,IADwB,IAAkB,IACP,IAAkB,EAAO,OAAO,EAAO,QAAQ,EAAW,OAO7F,IAJM,EAAO,EAAO,QAAQ,CAC/B,KAAK,SAAS,EAAS,CACvB,KAAK,UAAU,EAAW,OAAO,CAEtB,OAAO,IAAI,CACtB,KAAK,aAAa,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,GAAG,EAGzD,IAAS,EAAS,KAAI,MAAK,EAAE,MAAM,EACnC,IAAW,EAAI,EAAO,IAAI,GAC1B,IAAW,EAAI,EAAO,IAAI,GAE1B,IAAa,GAAuB,CACvC,OAAO,CAAC,GAAU,EAAS,CAAC,CAC5B,MAAM,GAAc,YAAY,EAAsB,EAGnD,oBAAU,IAAI,KAAuB;AAC3C,IAAS,SAAQ,MAAQ;GACvB,IAAM,IAAM,GAAG,EAAK,EAAE,GAAG,EAAK;AAC9B,KAAQ,IAAI,GAAK,EAAK;IACtB;EAGF,IAAM,KAAiB,GAAiB,MACxB,iBAAiB,SAAS,gBAAgB,CAAC,iBAAiB,EAAQ,CAAC,MAAM,IACzE,GAGZ,IAAS,MAAiB,SAC1B,IAAY,IACd,EAAc,mBAAmB,UAAU,GAC3C,EAAc,uBAAuB,UAAU,EAC7C,IAAY,EAAc,eAAe,UAAU,EAEnD,IAAiB,IACnB,EAAc,qBAAqB,UAAU,GAC7C,EAAc,qBAAqB,UAAU,EAC3C,IAAkB,IACpB,EAAc,eAAe,UAAU,GACvC,EAAc,WAAW,UAAU,EAGjC,IAAU,EAAO,OAAO,CAAC,OAAO,MAAM,CACzC,KAAK,SAAS,wBAAwB,CACtC,MAAM,YAAY,WAAW,CAC7B,MAAM,WAAW,MAAM,CACvB,MAAM,cAAc,qBAAqB,CACzC,MAAM,SAAS,QAAQ,CACvB,MAAM,iBAAiB,MAAM,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,kBAAkB,OAAO,CAC/B,MAAM,WAAW,EAAE,CACnB,MAAM,WAAW,IAAK,EAGnB,oBAAgB,IAAI,KAAqB;AAC/C,IAAe,SAAS,GAAG,MAAU;AACnC,KAAc,IAAI,GAAG,EAAM;IAC3B;AAGF,OAAK,IAAM,KAAK,EACd,MAAK,IAAI,IAAI,GAAM,KAAK,GAAM,KAAK;GACjC,IAAM,IAAM,GAAG,EAAE,GAAG,KACd,IAAO,EAAQ,IAAI,EAAI,EACvB,IAAS,EAAc,IAAI,EAAE,IAAI,GAEjC,IAAO,EAAE,OAAO,OAAO,CAC1B,KAAK,KAAK,KAAU,IAAiB,GAAG,CACxC,KAAK,MAAM,IAAI,MAAS,IAAkB,GAAG,CAC7C,KAAK,SAAS,EAAe,CAC7B,KAAK,UAAU,EAAgB,CAC/B,KAAK,MAAM,EAAE,CACb,KAAK,MAAM,EAAE,CACb,MAAM,QAAQ,IAAO,EAAW,EAAK,MAAM,GAAG,EAAe,CAC7D,MAAM,UAAU,EAAgB,CAChC,MAAM,gBAAgB,EAAE;AA+C3B,GA5CI,EAAkB,cACpB,EACG,MAAM,UAAU,IAAe,YAAY,UAAU,CACrD,GAAG,aAAa,SAAS,GAAO;AAK/B,QAJA,EAAO,KAAK,CACT,MAAM,UAAU,OAAO,CACvB,MAAM,gBAAgB,EAAE,EAEvB,GAAM;KACR,IAAM,IAAiB,CACrB,WAAW,EAAK,MAAM,YACtB,GAAG,EAAc,EAAW,CAAC,IAAI,EAAK,QACvC,CAAC,KAAK,OAAO;AAEd,OACG,KAAK,EAAe,CACpB,MAAM,QAAS,EAAM,QAAQ,KAAM,KAAK,CACxC,MAAM,OAAQ,EAAM,QAAQ,KAAM,KAAK,CACvC,YAAY,CACZ,SAAS,IAAI,CACb,MAAM,WAAW,EAAE;;KAExB,CACD,GAAG,aAAa,SAAS,GAAO;AAC/B,MACG,MAAM,QAAS,EAAM,QAAQ,KAAM,KAAK,CACxC,MAAM,OAAQ,EAAM,QAAQ,KAAM,KAAK;KAC1C,CACD,GAAG,YAAY,WAAW;AAKzB,IAJA,EAAO,KAAK,CACT,MAAM,UAAU,EAAgB,CAChC,MAAM,gBAAgB,EAAE,EAE3B,EACG,YAAY,CACZ,SAAS,IAAI,CACb,MAAM,WAAW,EAAE;KACtB,GACK,KAET,EAAK,MAAM,UAAU,UAAU,EAI7B,KAAgB,KAAoB,KACtC,EAAK,GAAG,SAAS,SAAS,GAAO;AAC/B,MAAiB;KACf,WAAW;OAAG,IAAa,EAAK;OAAQ,IAAY,EAAK;MAAM;KAC/D,cAAc;KACd,QAAQ,EAAK;KACb,UAAU;MAAE,GAAG,EAAM;MAAO,GAAG,EAAM;MAAO;KAC5C,aAAa;KACd,CAAC;KACF;;AAMR,MAAI,EAAkB,YAAY;AAChC,OAAI,EAAY,yBAAyB,EAAY,cAAc;IAKjE,IAAM,oBAAa,IAAI,KAAuB;AAC9C,SAAK,IAAM,KAAK,GAAgB;KAC9B,IAAM,IAAO,EAAY,aAAa,EAAE;AAIxC,KAHK,EAAW,IAAI,EAAK,IACvB,EAAW,IAAI,GAAM,EAAE,CAAC,EAE1B,EAAW,IAAI,EAAK,CAAE,KAAK,EAAE;;AAK/B,SAAK,IAAM,KAAK,GAAgB;KAC9B,IAAM,IAAS,EAAc,IAAI,EAAE,IAAI;AACvC,OAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAU,IAAiB,KAAK,IAAiB,EAAE,CAC7D,KAAK,KAAK,GAAG,CACb,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;AAIjC,SAAK,IAAM,CAAC,GAAM,MAAY,EAC5B,KAAI,EAAQ,SAAS,GAAG;KAEtB,IAAM,IAAa,KAAK,IAAI,GAAG,EAAQ,KAAI,MAAK,EAAc,IAAI,EAAE,IAAI,EAAE,CAAC,EACrE,IAAW,KAAK,IAAI,GAAG,EAAQ,KAAI,MAAK,EAAc,IAAI,EAAE,IAAI,EAAE,CAAC,EACnE,KAAe,IAAa,KAAY,GAG1C;AACJ,SAAI,IAAO,MAAM;MAEf,IAAM,IAAa,KAAK,MAAM,IAAO,IAAI;AAGzC,UAAY,GADO;OAAC;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAM,CADzF,IAAO,MAEa,GAAG,IAAI,EAAW,UAAU,CAAC,MAAM,GAAG;WAGxE,KAAY,IAAI,EAAK,UAAU,CAAC,MAAM,GAAG;AAa3C,KAVA,EAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAe,IAAiB,KAAK,IAAiB,EAAE,CAClE,KAAK,KAAK,IAAI,CACd,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,eAAe,OAAO,CAC5B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAU,EAGd,EAAQ,SAAS,KACnB,EAAE,OAAO,OAAO,CACb,KAAK,MAAM,KAAc,IAAiB,GAAG,CAC7C,KAAK,MAAM,KAAY,IAAiB,KAAK,EAAe,CAC5D,KAAK,MAAM,IAAI,CACf,KAAK,MAAM,IAAI,CACf,MAAM,UAAU,EAAU,CAC1B,MAAM,gBAAgB,EAAE,CACxB,MAAM,WAAW,GAAI;;UAIzB;IAEL,IAAM,IAAa,KAAK,IAAI,GAAG,KAAK,MAAM,EAAe,SAAS,GAAG,CAAC;AACtE,SAAK,IAAI,IAAI,GAAG,IAAI,EAAe,QAAQ,KAAK,GAAY;KAC1D,IAAM,IAAI,EAAe;AACzB,OAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAK,IAAiB,KAAK,IAAiB,EAAE,CACxD,KAAK,KAAK,GAAG,CACb,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;;AAKnC,QAAK,IAAI,IAAI,GAAM,KAAK,GAAM,IAC5B,GAAE,OAAO,OAAO,CACb,KAAK,KAAK,GAAG,CACb,KAAK,MAAM,IAAI,MAAS,IAAkB,KAAK,IAAkB,EAAE,CACnE,KAAK,eAAe,MAAM,CAC1B,KAAK,MAAM,QAAQ,CACnB,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;AAKnC,eAAa;AACX,KAAQ,QAAQ;;IAEjB;EAAC;EAAM;EAAa;EAAe;EAAa;EAAY;EAAiB;EAAmB;EAAc;EAAc;EAAe;EAAgB;EAAc;EAAiB,CAAC,EAE1L,CAAC,KAAQ,EAAK,WAAW,EAC3B,QACE,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAsC;IAAuB,CAAA,EAC5E,kBAAC,OAAD;IAAK,WAAU;cAAoC;IAAgD,CAAA,CAC/F;;EACF,CAAA;AAMV,KAAI,EADmB,GAAa,aAAa,GAAa,YAE5D,QACE,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAsC;IAA4B,CAAA,EACjF,kBAAC,OAAD;IAAK,WAAU;cAAoC;IAA2D,CAAA,CAC1G;;EACF,CAAA;CAKV,IAAM,IAAY,MAAM,QAAQ,EAAY,UAAU,GAAG,EAAY,UAAU,KAAK,EAAY;AAoBhG,SAnB6B,GAAa,gBAAgB,MAAM,MAC9D,EAAG,cAAc,KAAa,EAAG,UAAU,SAAS,EAAU,CAC/D,EAAE,eAAe,QAEQ,aAAa,KAAK,SAExC,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAsC;KAA0B,CAAA;IAC/E,kBAAC,OAAD;KAAK,WAAU;eAAoC;KAAkF,CAAA;IACrI,kBAAC,OAAD;KAAK,WAAU;eAA4C;KAA+D,CAAA;IACtH;;EACF,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;EAA4C,OAAO;GAAE;GAAQ,WAAW;GAAS,UAAU;GAAU,OAAO;GAAQ;YACjI,kBAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAAqD,OAAO,EAAE,OAAO,QAAQ;aAA/G,CACE,kBAAC,OAAD;IAAK,KAAK;IAAQ,WAAU;IAAc,CAAA,EACzC,CAAC,KACA,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAgC;KAAmC,CAAA;IAC9E,CAAA,CAEJ;;EACF,CAAA;EAER"}
|
|
1
|
+
{"version":3,"file":"chart-activity-grid-DLktOINm.js","names":[],"sources":["../../../src/client/providers/CubeMetaContext.tsx","../../../src/client/utils/chartUtils.ts","../../../src/client/hooks/useCubeFieldLabel.ts","../../../src/client/theme/index.ts","../../../src/client/utils/chartConstants.ts","../../../src/client/components/charts/ActivityGridChart.tsx"],"sourcesContent":["/**\n * CubeMetaContext - Metadata context definitions.\n *\n * Split from CubeMetaProvider so consumers can access metadata context\n * without pulling in TanStack Query dependencies.\n */\n\nimport { createContext, useContext } from 'react'\nimport type { CubeMeta, FieldLabelMap } from '../types'\n\nexport interface CubeMetaContextValue {\n meta: CubeMeta | null\n labelMap: FieldLabelMap\n metaLoading: boolean\n metaError: string | null\n getFieldLabel: (fieldName: string) => string\n refetchMeta: () => void\n}\n\nexport const CubeMetaContext = createContext<CubeMetaContextValue | null>(null)\n\nexport function useCubeMeta() {\n const context = useContext(CubeMetaContext)\n if (!context) {\n throw new Error('useCubeMeta must be used within CubeMetaProvider')\n }\n return context\n}\n","import type { FieldLabelMap, AxisFormatConfig } from '../types'\n\n// Utility function to check if a value is a valid numeric value (not null, undefined, or NaN)\n// This is used to preserve null values instead of converting them to 0\nexport function isValidNumericValue(value: any): boolean {\n return value !== null && value !== undefined && !isNaN(Number(value))\n}\n\n// Utility function to parse numeric value from data, preserving nulls\n// Returns null for null/undefined/NaN values, otherwise returns the numeric value\nexport function parseNumericValue(value: any): number | null {\n if (value === null || value === undefined) return null\n const num = typeof value === 'string' ? parseFloat(value) : Number(value)\n return isNaN(num) ? null : num\n}\n\n// Utility function to format numeric values for display in charts\n// Rounds to at most 2 decimal places, preserves integers\nexport function formatNumericValue(value: any): string {\n if (value === null || value === undefined) return 'No data'\n const num = typeof value === 'number' ? value : parseFloat(value)\n if (isNaN(num)) return String(value)\n if (Number.isInteger(num)) return num.toLocaleString()\n // Round to at most 2 decimal places, remove trailing zeros\n return parseFloat(num.toFixed(2)).toLocaleString()\n}\n\n/**\n * Format a numeric value for axis/tooltip display with configurable formatting\n *\n * @param value - The numeric value to format\n * @param config - Optional formatting configuration\n * @param locale - Optional locale string (defaults to browser locale)\n * @returns Formatted string representation of the value\n *\n * @example\n * formatAxisValue(1250000, { unit: 'currency', abbreviate: true }) // \"$1.25M\"\n * formatAxisValue(0.75, { unit: 'percent', decimals: 1 }) // \"75.0%\"\n * formatAxisValue(1234567, { abbreviate: true, decimals: 2 }) // \"1.23M\"\n */\nexport function formatAxisValue(\n value: number | null | undefined,\n config?: AxisFormatConfig,\n locale?: string\n): string {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return 'No data'\n }\n\n // Handle non-numeric values\n const num = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(num)) {\n return String(value)\n }\n\n // Handle special cases\n if (!isFinite(num)) {\n return num > 0 ? '∞' : '-∞'\n }\n\n // Get locale (default to browser locale)\n const effectiveLocale = locale || (typeof navigator !== 'undefined' ? navigator.language : 'en-US')\n\n // If no config provided, use default formatting\n if (!config) {\n return formatNumericValue(value)\n }\n\n const { unit, abbreviate = true, decimals, customPrefix, customSuffix } = config\n\n // Calculate the display value and suffix for abbreviation\n // Default to true for abbreviation when config is provided\n let displayValue = num\n let abbreviationSuffix = ''\n\n if (abbreviate) {\n const absNum = Math.abs(num)\n if (absNum >= 1_000_000_000) {\n displayValue = num / 1_000_000_000\n abbreviationSuffix = 'B'\n } else if (absNum >= 1_000_000) {\n displayValue = num / 1_000_000\n abbreviationSuffix = 'M'\n } else if (absNum >= 1_000) {\n displayValue = num / 1_000\n abbreviationSuffix = 'K'\n }\n }\n\n // Determine decimal places\n // If decimals is undefined, use auto (2 for non-integers, 0 for integers after abbreviation)\n const effectiveDecimals = decimals !== undefined\n ? decimals\n : (Number.isInteger(displayValue) ? 0 : 2)\n\n // Format based on unit type\n switch (unit) {\n case 'currency': {\n // Use Intl.NumberFormat for currency\n // Currency code is determined by locale (USD for en-US, EUR for de-DE, etc.)\n const currencyCode = getCurrencyCodeForLocale(effectiveLocale)\n\n if (abbreviate && abbreviationSuffix) {\n // For abbreviated currency, format the number part and add suffix\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n // Insert abbreviation suffix before any trailing currency symbol or at end\n // Handle both \"$1.25\" -> \"$1.25M\" and \"1.25 €\" -> \"1.25M €\"\n const parts = new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n }).formatToParts(displayValue)\n const hasTrailingCurrency = parts[parts.length - 1]?.type === 'currency'\n if (hasTrailingCurrency) {\n // Currency symbol is at the end (e.g., \"1.25 €\")\n return formatted.replace(/(\\s*[^\\d\\s]+)$/, abbreviationSuffix + '$1')\n }\n return formatted + abbreviationSuffix\n }\n\n return new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode,\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n }\n\n case 'percent': {\n // Format as percentage (multiply by 100 if value is 0-1 range, otherwise use as-is)\n // Assume values > 1 are already percentages, values <= 1 need multiplication\n const percentValue = Math.abs(displayValue) <= 1 && !abbreviate ? displayValue * 100 : displayValue\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(percentValue)\n return formatted + abbreviationSuffix + '%'\n }\n\n case 'custom': {\n // Apply custom prefix/suffix\n const prefix = customPrefix || ''\n const suffix = customSuffix || ''\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return prefix + formatted + abbreviationSuffix + suffix\n }\n\n case 'number':\n default: {\n // Standard number formatting with locale-aware grouping\n const formatted = new Intl.NumberFormat(effectiveLocale, {\n minimumFractionDigits: effectiveDecimals,\n maximumFractionDigits: effectiveDecimals,\n }).format(displayValue)\n return formatted + abbreviationSuffix\n }\n }\n}\n\n/**\n * Get the currency code for a given locale\n * Maps common locales to their default currency\n */\nfunction getCurrencyCodeForLocale(locale: string): string {\n // Extract language and region from locale (e.g., \"en-US\" -> [\"en\", \"US\"])\n const parts = locale.split('-')\n const region = parts[1]?.toUpperCase()\n\n // Map regions to currencies\n const currencyMap: Record<string, string> = {\n 'US': 'USD',\n 'CA': 'CAD',\n 'GB': 'GBP',\n 'UK': 'GBP',\n 'AU': 'AUD',\n 'NZ': 'NZD',\n 'EU': 'EUR',\n 'DE': 'EUR',\n 'FR': 'EUR',\n 'IT': 'EUR',\n 'ES': 'EUR',\n 'NL': 'EUR',\n 'BE': 'EUR',\n 'AT': 'EUR',\n 'IE': 'EUR',\n 'PT': 'EUR',\n 'FI': 'EUR',\n 'JP': 'JPY',\n 'CN': 'CNY',\n 'KR': 'KRW',\n 'IN': 'INR',\n 'BR': 'BRL',\n 'MX': 'MXN',\n 'CH': 'CHF',\n 'SE': 'SEK',\n 'NO': 'NOK',\n 'DK': 'DKK',\n 'PL': 'PLN',\n 'RU': 'RUB',\n 'ZA': 'ZAR',\n 'SG': 'SGD',\n 'HK': 'HKD',\n 'TW': 'TWD',\n 'TH': 'THB',\n 'MY': 'MYR',\n 'PH': 'PHP',\n 'ID': 'IDR',\n 'VN': 'VND',\n 'AE': 'AED',\n 'SA': 'SAR',\n 'IL': 'ILS',\n 'TR': 'TRY',\n }\n\n return currencyMap[region] || 'USD'\n}\n\n/**\n * Create a tick formatter function for Recharts axes\n * Returns a function that can be used as tickFormatter prop\n */\nexport function createAxisTickFormatter(config?: AxisFormatConfig): (value: any) => string {\n return (value: any) => formatAxisValue(value, config)\n}\n\n// Utility function to get field label from field name\nexport function getFieldLabel(fieldName: string, labelMap: FieldLabelMap): string {\n return labelMap[fieldName] || fieldName\n}\n\n// Utility function to transform series keys to use labels\nexport function transformSeriesKeysWithLabels(seriesKeys: string[], labelMap: FieldLabelMap): string[] {\n return seriesKeys.map(key => getFieldLabel(key, labelMap))\n}\n\n// Utility function to format time values for better display using known granularity\nexport function formatTimeValue(value: any, granularity?: string): string {\n\n if (!value) return 'Unknown'\n \n const str = String(value)\n \n // Check if it's a timestamp (ISO format or PostgreSQL format)\n // Handles formats like: \"2025-04-01T00:00:00.000\" or \"2023-02-01 00:00:00+00\"\n if (str.match(/^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}/)) {\n // Convert PostgreSQL format to ISO format if needed\n let isoStr = str\n if (str.includes(' ')) {\n // Convert \"2023-02-01 00:00:00+00\" to \"2023-02-01T00:00:00Z\"\n isoStr = str.replace(' ', 'T').replace('+00', 'Z').replace(/\\+\\d{2}:\\d{2}$/, 'Z')\n }\n // Ensure the timestamp ends with 'Z' if not present\n if (!isoStr.endsWith('Z') && !isoStr.includes('+')) {\n isoStr = isoStr + 'Z'\n }\n const date = new Date(isoStr)\n \n // Ensure we're working with valid date\n if (isNaN(date.getTime())) {\n return str\n }\n \n // Use UTC methods on the properly UTC-parsed date\n const year = date.getUTCFullYear()\n const month = String(date.getUTCMonth() + 1).padStart(2, '0')\n const day = String(date.getUTCDate()).padStart(2, '0')\n const hours = date.getUTCHours()\n const minutes = date.getUTCMinutes()\n \n // Format based on known granularity if provided\n if (granularity) {\n switch (granularity.toLowerCase()) {\n case 'year':\n return `${year}`\n case 'quarter': {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n case 'month':\n return `${year}-${month}`\n case 'week':\n // For week, we could calculate week number, but let's use date for simplicity\n return `${year}-${month}-${day}`\n case 'day':\n return `${year}-${month}-${day}`\n case 'hour':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n case 'minute':\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n default:\n // Unknown granularity, fall back to heuristic\n break\n }\n }\n \n // Fallback heuristic if granularity not provided or unknown\n const seconds = date.getUTCSeconds()\n const milliseconds = date.getUTCMilliseconds()\n \n // If it's the first day of the month at exactly midnight UTC, it's likely a month granularity\n if (day === '01' && hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Check if it's also first month of a quarter (quarter granularity)\n if (month === '01' || month === '04' || month === '07' || month === '10') {\n const quarter = Math.floor(date.getUTCMonth() / 3) + 1\n return `${year}-Q${quarter}`\n }\n // Month granularity\n return `${year}-${month}`\n }\n \n // If it's exactly midnight UTC, it's likely a day granularity\n if (hours === 0 && minutes === 0 && seconds === 0 && milliseconds === 0) {\n return `${year}-${month}-${day}`\n }\n \n // If it has time components, include them (hour/minute granularity)\n if (minutes === 0 && seconds === 0 && milliseconds === 0) {\n // Hour granularity\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:00`\n }\n \n // Full timestamp\n return `${year}-${month}-${day} ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`\n }\n \n // Return as-is if not a timestamp\n return str\n}\n\n// Helper function to get granularity for a field from the query timeDimensions\nexport function getFieldGranularity(queryObject: any, fieldName: string): string | undefined {\n try {\n if (queryObject?.timeDimensions) {\n // Find the timeDimension that matches this field\n const timeDim = queryObject.timeDimensions.find((td: any) => {\n // Check if field name matches the dimension or dimension with granularity suffix\n return fieldName === td.dimension || \n fieldName.startsWith(td.dimension.replace('.', '_')) ||\n fieldName === `${td.dimension}_${td.granularity}`\n })\n \n if (timeDim?.granularity) {\n return timeDim.granularity\n }\n }\n \n // Fallback: extract granularity from field name suffix if present\n const granularityMatch = fieldName.match(/_([a-z]+)$/)\n if (granularityMatch) {\n const suffix = granularityMatch[1]\n // Only return if it's a valid granularity\n if (['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second'].includes(suffix)) {\n return suffix\n }\n }\n \n return undefined\n } catch {\n return undefined\n }\n}\n\n// Transform data for charts with proper type handling\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartData(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName\n) {\n if (!data || data.length === 0) return []\n\n const granularity = getFieldGranularity(queryObject, xAxisField)\n\n return data.map((row: any) => {\n const transformed: any = {\n name: formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown',\n }\n\n yAxisFields.forEach(field => {\n const displayName = getFieldLabelFn(field)\n if (displayName === '__proto__' || displayName === 'constructor' || displayName === 'prototype') return\n // Preserve null values instead of converting to 0\n transformed[displayName] = parseNumericValue(row[field])\n })\n\n return transformed\n })\n}\n\nexport interface ChartSeriesResult {\n data: any[]\n seriesKeys: string[]\n hasDimensions: boolean\n}\n\n// Advanced data transformation that handles both measures and dimensions on Y-axis\n// NOTE: Preserves null values to allow charts to handle gaps/missing data appropriately\nexport function transformChartDataWithSeries(\n data: any[],\n xAxisField: string,\n yAxisFields: string[],\n queryObject: any,\n seriesFields?: string[], // New optional parameter for explicit series fields\n getFieldLabelFn: (fieldName: string) => string = (fieldName) => fieldName // Function to get field labels\n): ChartSeriesResult {\n if (!data || data.length === 0) {\n return { data: [], seriesKeys: [], hasDimensions: false }\n }\n\n const originalQuery = queryObject || {}\n const queryDimensions = [\n ...(originalQuery.dimensions || []),\n ...(originalQuery.timeDimensions?.map((td: any) => td.dimension) || [])\n ]\n const queryMeasures = originalQuery.measures || []\n\n // Use explicit series fields if provided, otherwise no dimension-based series\n const yAxisMeasures = yAxisFields.filter(field => queryMeasures.includes(field))\n const yAxisDimensions = (seriesFields || []).filter(field => queryDimensions.includes(field))\n\n // Handle complex case with dimensions on Y-axis\n if (yAxisDimensions.length > 0) {\n // Group data by X-axis field and create separate series for dimension values\n const groupedData: { [key: string]: any } = {}\n\n data.forEach((row: any) => {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n const xValue = formatTimeValue(row[xAxisField], granularity) || row[xAxisField] || 'Unknown'\n if (xValue === '__proto__' || xValue === 'constructor' || xValue === 'prototype') return\n if (!groupedData[xValue]) {\n groupedData[xValue] = { name: String(xValue) }\n }\n\n // Add measures - preserve nulls for individual measures\n yAxisMeasures.forEach(measure => {\n const displayName = getFieldLabelFn(measure)\n if (displayName === '__proto__' || displayName === 'constructor' || displayName === 'prototype') return\n const measureValue = parseNumericValue(row[measure])\n\n // For aggregation: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][displayName]\n\n groupedData[xValue][displayName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(displayName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][displayName] = null\n }\n })\n\n // Add dimensions as separate series (aggregate measure values by dimension)\n yAxisDimensions.forEach(dimension => {\n const dimValue = row[dimension]\n if (dimValue !== undefined && dimValue !== null) {\n const seriesName = String(dimValue)\n // Aggregate the first measure for this dimension value, or use totalCost if available\n const measureToAggregate = yAxisMeasures[0] || queryMeasures.find((m: string) =>\n m.includes('totalCost') || m.includes('count') || m.includes('sum')\n ) || queryMeasures[0]\n\n if (measureToAggregate) {\n if (seriesName === '__proto__' || seriesName === 'constructor' || seriesName === 'prototype') return\n const measureValue = parseNumericValue(row[measureToAggregate])\n\n // For dimension series: sum non-null values, preserve null if all are null\n if (measureValue !== null) {\n const currentValue = groupedData[xValue][seriesName]\n\n groupedData[xValue][seriesName] = (currentValue === null || currentValue === undefined)\n ? measureValue\n : currentValue + measureValue\n } else if (!(seriesName in groupedData[xValue])) {\n // Only set to null if no value exists yet\n groupedData[xValue][seriesName] = null\n }\n }\n }\n })\n })\n \n const chartData = Object.values(groupedData)\n \n // Get all series keys for rendering\n // When dimensions are on Y-axis, only show dimension series, not measures\n // The measures are the values being aggregated for each dimension series\n const dimensionSeries = Array.from(new Set(\n data.flatMap((row: any) => \n yAxisDimensions.map(dimension => {\n const value = row[dimension]\n return value !== undefined && value !== null \n ? String(value)\n : null\n }).filter((value): value is string => value !== null)\n )\n ))\n \n return {\n data: chartData,\n seriesKeys: dimensionSeries,\n hasDimensions: true\n }\n }\n \n // Standard measures-only path\n const chartData = transformChartData(data, xAxisField, yAxisFields, queryObject, getFieldLabelFn)\n const seriesKeys = yAxisFields.map(field => getFieldLabelFn(field))\n \n return {\n data: chartData,\n seriesKeys,\n hasDimensions: false\n }\n}","/**\n * Optimized hook that only subscribes to field label functionality\n * from CubeMeta context. This prevents re-renders when unrelated\n * contexts (CubeApi, Features) change.\n *\n * Use this instead of useCubeContext() when you only need getFieldLabel.\n */\n\nimport { useContext, useMemo } from 'react'\nimport { CubeMetaContext, type CubeMetaContextValue } from '../providers/CubeMetaContext'\n\n/**\n * Returns a stable reference to the getFieldLabel function.\n * Components using this hook will only re-render when the field label\n * mapping actually changes, not when unrelated API or feature contexts update.\n *\n * @returns Function to get human-readable label for a field name\n * @throws Error if used outside CubeProvider\n */\nexport function useCubeFieldLabel(): (fieldName: string) => string {\n const context = useContext(CubeMetaContext) as CubeMetaContextValue | null\n\n if (!context) {\n throw new Error('useCubeFieldLabel must be used within CubeProvider')\n }\n\n // Return stable reference - only changes when getFieldLabel itself changes\n return useMemo(() => context.getFieldLabel, [context.getFieldLabel])\n}\n","/**\n * Theme utilities and TypeScript types for drizzle-cube theming system\n */\n\n/**\n * Semantic color tokens used throughout drizzle-cube components\n */\nexport interface ThemeColorTokens {\n // Surface colors\n surface: string\n surfaceSecondary: string\n surfaceTertiary: string\n surfaceHover: string\n\n // Text colors\n text: string\n textSecondary: string\n textMuted: string\n textDisabled: string\n\n // Border colors\n border: string\n borderSecondary: string\n borderHover: string\n\n // Primary colors\n primary: string\n primaryHover: string\n primaryContent: string\n\n // Semantic state colors\n success: string\n successBg: string\n successBorder: string\n\n warning: string\n warningBg: string\n warningBorder: string\n\n error: string\n errorBg: string\n errorBorder: string\n\n info: string\n infoBg: string\n infoBorder: string\n\n // Danger colors\n danger: string\n dangerHover: string\n dangerBg: string\n\n // Overlay colors\n overlay: string\n overlayLight: string\n}\n\n/**\n * Theme configuration interface\n */\nexport interface ThemeConfig {\n name: string\n colors: Partial<ThemeColorTokens>\n}\n\n/**\n * Get the current value of a theme CSS variable\n */\nexport function getThemeVariable(variableName: string): string {\n if (typeof window === 'undefined') return ''\n\n return getComputedStyle(document.documentElement)\n .getPropertyValue(`--dc-${variableName}`)\n .trim()\n}\n\n/**\n * Set a theme CSS variable\n */\nexport function setThemeVariable(variableName: string, value: string): void {\n if (typeof window === 'undefined') return\n\n document.documentElement.style.setProperty(`--dc-${variableName}`, value)\n}\n\n/**\n * Apply a complete theme configuration\n */\nexport function applyTheme(theme: ThemeConfig): void {\n if (typeof window === 'undefined') return\n\n Object.entries(theme.colors).forEach(([key, value]) => {\n if (value) {\n // Convert camelCase to kebab-case\n const cssVarName = key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)\n setThemeVariable(cssVarName, value)\n }\n })\n}\n\n/**\n * Reset theme to defaults by removing custom properties\n */\nexport function resetTheme(): void {\n if (typeof window === 'undefined') return\n\n const styleElement = document.documentElement.style\n const properties = Array.from(styleElement)\n\n properties.forEach(prop => {\n if (prop.startsWith('--dc-')) {\n styleElement.removeProperty(prop)\n }\n })\n}\n\n/**\n * Theme type definition\n */\nexport type Theme = 'light' | 'dark' | 'neon'\n\n/**\n * Get the current theme\n */\nexport function getTheme(): Theme {\n if (typeof window === 'undefined') return 'light'\n\n // Check localStorage first\n const stored = localStorage.getItem('theme')\n if (stored === 'dark' || stored === 'neon' || stored === 'light') {\n return stored\n }\n\n // Check for data-theme attribute\n const dataTheme = document.documentElement.getAttribute('data-theme')\n if (dataTheme === 'dark' || dataTheme === 'neon') {\n return dataTheme\n }\n\n // Check for dark class\n if (document.documentElement.classList.contains('dark') ||\n document.body.classList.contains('dark')) {\n return 'dark'\n }\n\n // Check for neon class\n if (document.documentElement.classList.contains('neon') ||\n document.body.classList.contains('neon')) {\n return 'neon'\n }\n\n // Check system preference\n if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return 'dark'\n }\n\n return 'light'\n}\n\n/**\n * Set the theme\n */\nexport function setTheme(theme: Theme): void {\n if (typeof window === 'undefined') return\n\n // Remove all theme classes\n document.documentElement.classList.remove('dark', 'neon')\n\n // Set data-theme attribute\n document.documentElement.setAttribute('data-theme', theme)\n\n // Add appropriate class for backwards compatibility\n if (theme === 'dark' || theme === 'neon') {\n document.documentElement.classList.add(theme)\n }\n\n // Persist to localStorage\n localStorage.setItem('theme', theme)\n}\n\n/**\n * Detect if dark mode is currently active (backwards compatibility)\n * @deprecated Use getTheme() instead\n */\nexport function isDarkMode(): boolean {\n const theme = getTheme()\n return theme === 'dark' || theme === 'neon'\n}\n\n/**\n * Watch for theme changes\n */\nexport function watchThemeChanges(callback: (theme: Theme) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n\n // Watch for class changes on html element\n const observer = new MutationObserver(() => {\n callback(getTheme())\n })\n\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme']\n })\n\n // Watch for system preference changes\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const mediaListener = () => callback(getTheme())\n mediaQuery.addEventListener('change', mediaListener)\n\n // Return cleanup function\n return () => {\n observer.disconnect()\n mediaQuery.removeEventListener('change', mediaListener)\n }\n}\n\n/**\n * Example theme configurations\n */\nexport const THEME_PRESETS = {\n light: {\n name: 'light' as const,\n colors: {\n surface: '#ffffff',\n surfaceSecondary: '#f9fafb',\n text: '#111827',\n textSecondary: '#374151',\n textMuted: '#6b7280',\n border: '#e5e7eb',\n primary: '#3b82f6',\n primaryHover: '#2563eb',\n }\n },\n dark: {\n name: 'dark' as const,\n colors: {\n surface: '#1e293b',\n surfaceSecondary: '#334155',\n text: '#f1f5f9',\n textSecondary: '#e2e8f0',\n textMuted: '#cbd5e1',\n border: '#475569',\n primary: '#60a5fa',\n primaryHover: '#3b82f6',\n }\n },\n neon: {\n name: 'neon' as const,\n colors: {\n surface: '#0a0118',\n surfaceSecondary: '#1a0f2e',\n surfaceTertiary: '#2a1f3e',\n text: '#ffffff',\n textSecondary: '#e0e0ff',\n textMuted: '#b0b0d0',\n border: '#ff00ff',\n borderSecondary: '#00ffff',\n primary: '#00ffff',\n primaryHover: '#00cccc',\n primaryContent: '#000000',\n success: '#00ff00',\n warning: '#ffff00',\n error: '#ff0066',\n info: '#00ffff',\n danger: '#ff1493',\n }\n }\n} as const\n","// Default color palette for charts - used as fallback when no dashboard palette is specified\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS = [\n '#3b82f6', // blue\n '#10b981', // green\n '#f59e0b', // yellow\n '#ef4444', // red\n '#8b5cf6', // purple\n '#f97316', // orange\n '#06b6d4', // cyan\n '#84cc16', // lime\n]\n\n// Default gradient colors for continuous numeric scales - used as fallback\n// These are now part of the 'default' palette in the unified color palette system\nexport const CHART_COLORS_GRADIENT = [\n '#440154', // dark purple\n '#414487', // purple-blue\n '#2a788e', // teal\n '#22a884', // green-teal \n '#7ad151', // green\n '#fde725', // yellow\n]\n\n// Colors for positive/negative values\nexport const POSITIVE_COLOR = '#10b981' // green\nexport const NEGATIVE_COLOR = '#ef4444' // red\n\nexport const CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 5\n}\n\nexport const RESPONSIVE_CHART_MARGINS = {\n top: 5,\n right: 30,\n left: 20,\n bottom: 60 // Extra space for rotated labels\n}","import 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 onDataPointClick,\n drillEnabled\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', drillEnabled ? 'pointer' : 'default')\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 } else if (drillEnabled) {\n // Set cursor for drill even without tooltips\n rect.style('cursor', 'pointer')\n }\n\n // Add drill click handler\n if (drillEnabled && onDataPointClick && cell) {\n rect.on('click', function(event) {\n onDataPointClick({\n dataPoint: { [valueField]: cell.value, [dateField]: cell.date },\n clickedField: valueField,\n xValue: cell.label,\n position: { x: event.pageX, y: event.pageY },\n nativeEvent: event as unknown as React.MouseEvent\n })\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: string\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, drillEnabled, onDataPointClick])\n\n if (!data || data.length === 0) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data available</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">No data points to display in 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=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Configuration Required</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:w-full\"\n style={{ height }}\n >\n <div className=\"dc:text-center text-dc-text-muted\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Granularity Too High</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">Activity grids work best with hour, day, week, month, or quarter granularity</div>\n <div className=\"dc:text-xs text-dc-text-secondary dc:mt-1\">Please choose a lower granularity for your time dimension</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:w-full dc:flex dc:flex-col dc:relative\" style={{ height, minHeight: '250px', overflow: 'hidden', width: '100%' }}>\n <div ref={containerRef} className=\"dc:w-full dc:h-full dc:relative dc:overflow-x-auto\" style={{ width: '100%' }}>\n <svg ref={svgRef} className=\"dc:h-full\" />\n {!dimensionsReady && (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center\">\n <div className=\"text-dc-text-muted dc:text-sm\">Measuring chart dimensions...</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default ActivityGridChart"],"mappings":";;;;;AAmBA,IAAa,IAAkB,EAA2C,KAAK;AAE/E,SAAgB,IAAc;CAC5B,IAAM,IAAU,EAAW,EAAgB;AAC3C,KAAI,CAAC,EACH,OAAU,MAAM,mDAAmD;AAErE,QAAO;;;;ACtBT,SAAgB,EAAoB,GAAqB;AACvD,QAAO,KAAU,QAA+B,CAAC,MAAM,OAAO,EAAM,CAAC;;AAKvE,SAAgB,EAAkB,GAA2B;AAC3D,KAAI,KAAU,KAA6B,QAAO;CAClD,IAAM,IAAM,OAAO,KAAU,WAAW,WAAW,EAAM,GAAG,OAAO,EAAM;AACzE,QAAO,MAAM,EAAI,GAAG,OAAO;;AAK7B,SAAgB,EAAmB,GAAoB;AACrD,KAAI,KAAU,KAA6B,QAAO;CAClD,IAAM,IAAM,OAAO,KAAU,WAAW,IAAQ,WAAW,EAAM;AAIjE,QAHI,MAAM,EAAI,GAAS,OAAO,EAAM,GAChC,OAAO,UAAU,EAAI,GAAS,EAAI,gBAAgB,GAE/C,WAAW,EAAI,QAAQ,EAAE,CAAC,CAAC,gBAAgB;;AAgBpD,SAAgB,EACd,GACA,GACA,GACQ;AAER,KAAI,KAAU,KACZ,QAAO;CAIT,IAAM,IAAM,OAAO,KAAU,WAAW,IAAQ,WAAW,OAAO,EAAM,CAAC;AACzE,KAAI,MAAM,EAAI,CACZ,QAAO,OAAO,EAAM;AAItB,KAAI,CAAC,SAAS,EAAI,CAChB,QAAO,IAAM,IAAI,MAAM;CAIzB,IAAM,IAAkB,MAAW,OAAO,YAAc,MAAc,UAAU,WAAW;AAG3F,KAAI,CAAC,EACH,QAAO,EAAmB,EAAM;CAGlC,IAAM,EAAE,SAAM,gBAAa,IAAM,aAAU,iBAAc,oBAAiB,GAItE,IAAe,GACf,IAAqB;AAEzB,KAAI,GAAY;EACd,IAAM,IAAS,KAAK,IAAI,EAAI;AAC5B,EAAI,KAAU,OACZ,IAAe,IAAM,KACrB,IAAqB,OACZ,KAAU,OACnB,IAAe,IAAM,KACrB,IAAqB,OACZ,KAAU,QACnB,IAAe,IAAM,KACrB,IAAqB;;CAMzB,IAAM,IAAoB,MAAa,KAAA,IAElC,OAAO,UAAU,EAAa,GAAG,IAAI,IADtC;AAIJ,SAAQ,GAAR;EACE,KAAK,YAAY;GAGf,IAAM,IAAe,EAAyB,EAAgB;AAE9D,OAAI,KAAc,GAAoB;IAEpC,IAAM,IAAY,IAAI,KAAK,aAAa,GAAiB;KACvD,OAAO;KACP,UAAU;KACV,uBAAuB;KACvB,uBAAuB;KACxB,CAAC,CAAC,OAAO,EAAa,EAGjB,IAAQ,IAAI,KAAK,aAAa,GAAiB;KACnD,OAAO;KACP,UAAU;KACX,CAAC,CAAC,cAAc,EAAa;AAM9B,WAL4B,EAAM,EAAM,SAAS,IAAI,SAAS,aAGrD,EAAU,QAAQ,kBAAkB,IAAqB,KAAK,GAEhE,IAAY;;AAGrB,UAAO,IAAI,KAAK,aAAa,GAAiB;IAC5C,OAAO;IACP,UAAU;IACV,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa;;EAGzB,KAAK,WAAW;GAGd,IAAM,IAAe,KAAK,IAAI,EAAa,IAAI,KAAK,CAAC,IAAa,IAAe,MAAM;AAKvF,UAJkB,IAAI,KAAK,aAAa,GAAiB;IACvD,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa,GACJ,IAAqB;;EAG1C,KAAK,UAAU;GAEb,IAAM,IAAS,KAAgB,IACzB,IAAS,KAAgB;AAK/B,UAAO,IAJW,IAAI,KAAK,aAAa,GAAiB;IACvD,uBAAuB;IACvB,uBAAuB;IACxB,CAAC,CAAC,OAAO,EAAa,GACK,IAAqB;;EAInD,QAME,QAJkB,IAAI,KAAK,aAAa,GAAiB;GACvD,uBAAuB;GACvB,uBAAuB;GACxB,CAAC,CAAC,OAAO,EAAa,GACJ;;;AASzB,SAAS,EAAyB,GAAwB;AAmDxD,QA7C4C;EAC1C,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACN,IAAM;EACP,CA/Ca,EAAO,MAAM,IAAI,CACV,IAAI,aAAa,KAgDR;;AAOhC,SAAgB,EAAwB,GAAmD;AACzF,SAAQ,MAAe,EAAgB,GAAO,EAAO;;AAIvD,SAAgB,EAAc,GAAmB,GAAiC;AAChF,QAAO,EAAS,MAAc;;AAIhC,SAAgB,EAA8B,GAAsB,GAAmC;AACrG,QAAO,EAAW,KAAI,MAAO,EAAc,GAAK,EAAS,CAAC;;AAI5D,SAAgB,EAAgB,GAAY,GAA8B;AAExE,KAAI,CAAC,EAAO,QAAO;CAEnB,IAAM,IAAM,OAAO,EAAM;AAIzB,KAAI,EAAI,MAAM,0CAA0C,EAAE;EAExD,IAAI,IAAS;AAMb,EALI,EAAI,SAAS,IAAI,KAEnB,IAAS,EAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,kBAAkB,IAAI,GAG/E,CAAC,EAAO,SAAS,IAAI,IAAI,CAAC,EAAO,SAAS,IAAI,KAChD,KAAkB;EAEpB,IAAM,IAAO,IAAI,KAAK,EAAO;AAG7B,MAAI,MAAM,EAAK,SAAS,CAAC,CACvB,QAAO;EAIT,IAAM,IAAO,EAAK,gBAAgB,EAC5B,IAAQ,OAAO,EAAK,aAAa,GAAG,EAAE,CAAC,SAAS,GAAG,IAAI,EACvD,IAAM,OAAO,EAAK,YAAY,CAAC,CAAC,SAAS,GAAG,IAAI,EAChD,IAAQ,EAAK,aAAa,EAC1B,IAAU,EAAK,eAAe;AAGpC,MAAI,EACF,SAAQ,EAAY,aAAa,EAAjC;GACE,KAAK,OACH,QAAO,GAAG;GACZ,KAAK,UAEH,QAAO,GAAG,EAAK,IADC,KAAK,MAAM,EAAK,aAAa,GAAG,EAAE,GAAG;GAGvD,KAAK,QACH,QAAO,GAAG,EAAK,GAAG;GACpB,KAAK,OAEH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG;GAC7B,KAAK,MACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG;GAC7B,KAAK,OACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC;GACnE,KAAK,SACH,QAAO,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;GACtG,QAEE;;EAKN,IAAM,IAAU,EAAK,eAAe,EAC9B,IAAe,EAAK,oBAAoB;AAyB9C,SAtBI,MAAQ,QAAQ,MAAU,KAAK,MAAY,KAAK,MAAY,KAAK,MAAiB,IAEhF,MAAU,QAAQ,MAAU,QAAQ,MAAU,QAAQ,MAAU,OAE3D,GAAG,EAAK,IADC,KAAK,MAAM,EAAK,aAAa,GAAG,EAAE,GAAG,MAIhD,GAAG,EAAK,GAAG,MAIhB,MAAU,KAAK,MAAY,KAAK,MAAY,KAAK,MAAiB,IAC7D,GAAG,EAAK,GAAG,EAAM,GAAG,MAIzB,MAAY,KAAK,MAAY,KAAK,MAAiB,IAE9C,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,OAI5D,GAAG,EAAK,GAAG,EAAM,GAAG,EAAI,GAAG,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;;AAItG,QAAO;;AAIT,SAAgB,EAAoB,GAAkB,GAAuC;AAC3F,KAAI;AACF,MAAI,GAAa,gBAAgB;GAE/B,IAAM,IAAU,EAAY,eAAe,MAAM,MAExC,MAAc,EAAG,aACjB,EAAU,WAAW,EAAG,UAAU,QAAQ,KAAK,IAAI,CAAC,IACpD,MAAc,GAAG,EAAG,UAAU,GAAG,EAAG,cAC3C;AAEF,OAAI,GAAS,YACX,QAAO,EAAQ;;EAKnB,IAAM,IAAmB,EAAU,MAAM,aAAa;AACtD,MAAI,GAAkB;GACpB,IAAM,IAAS,EAAiB;AAEhC,OAAI;IAAC;IAAQ;IAAW;IAAS;IAAQ;IAAO;IAAQ;IAAU;IAAS,CAAC,SAAS,EAAO,CAC1F,QAAO;;AAIX;SACM;AACN;;;AAMJ,SAAgB,EACd,GACA,GACA,GACA,GACA,KAAkD,MAAc,GAChE;AACA,KAAI,CAAC,KAAQ,EAAK,WAAW,EAAG,QAAO,EAAE;CAEzC,IAAM,IAAc,EAAoB,GAAa,EAAW;AAEhE,QAAO,EAAK,KAAK,MAAa;EAC5B,IAAM,IAAmB,EACvB,MAAM,EAAgB,EAAI,IAAa,EAAY,IAAI,EAAI,MAAe,WAC3E;AASD,SAPA,EAAY,SAAQ,MAAS;GAC3B,IAAM,IAAc,EAAgB,EAAM;AACtC,SAAgB,eAAe,MAAgB,iBAAiB,MAAgB,gBAEpF,EAAY,KAAe,EAAkB,EAAI,GAAO;IACxD,EAEK;GACP;;AAWJ,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,KAAkD,MAAc,GAC7C;AACnB,KAAI,CAAC,KAAQ,EAAK,WAAW,EAC3B,QAAO;EAAE,MAAM,EAAE;EAAE,YAAY,EAAE;EAAE,eAAe;EAAO;CAG3D,IAAM,IAAgB,KAAe,EAAE,EACjC,IAAkB,CACtB,GAAI,EAAc,cAAc,EAAE,EAClC,GAAI,EAAc,gBAAgB,KAAK,MAAY,EAAG,UAAU,IAAI,EAAE,CACvE,EACK,IAAgB,EAAc,YAAY,EAAE,EAG5C,IAAgB,EAAY,QAAO,MAAS,EAAc,SAAS,EAAM,CAAC,EAC1E,KAAmB,KAAgB,EAAE,EAAE,QAAO,MAAS,EAAgB,SAAS,EAAM,CAAC;AAG7F,KAAI,EAAgB,SAAS,GAAG;EAE9B,IAAM,IAAsC,EAAE;AA2E9C,SAzEA,EAAK,SAAS,MAAa;GACzB,IAAM,IAAc,EAAoB,GAAa,EAAW,EAC1D,IAAS,EAAgB,EAAI,IAAa,EAAY,IAAI,EAAI,MAAe;AAC/E,SAAW,eAAe,MAAW,iBAAiB,MAAW,gBAChE,EAAY,OACf,EAAY,KAAU,EAAE,MAAM,OAAO,EAAO,EAAE,GAIhD,EAAc,SAAQ,MAAW;IAC/B,IAAM,IAAc,EAAgB,EAAQ;AAC5C,QAAI,MAAgB,eAAe,MAAgB,iBAAiB,MAAgB,YAAa;IACjG,IAAM,IAAe,EAAkB,EAAI,GAAS;AAGpD,QAAI,MAAiB,MAAM;KACzB,IAAM,IAAe,EAAY,GAAQ;AAEzC,OAAY,GAAQ,KAAgB,KAAiB,OACjD,IACA,IAAe;WACR,KAAe,EAAY,OAEtC,EAAY,GAAQ,KAAe;KAErC,EAGF,EAAgB,SAAQ,MAAa;IACnC,IAAM,IAAW,EAAI;AACrB,QAAI,KAAuC,MAAM;KAC/C,IAAM,IAAa,OAAO,EAAS,EAE7B,IAAqB,EAAc,MAAM,EAAc,MAAM,MACjE,EAAE,SAAS,YAAY,IAAI,EAAE,SAAS,QAAQ,IAAI,EAAE,SAAS,MAAM,CACpE,IAAI,EAAc;AAEnB,SAAI,GAAoB;AACtB,UAAI,MAAe,eAAe,MAAe,iBAAiB,MAAe,YAAa;MAC9F,IAAM,IAAe,EAAkB,EAAI,GAAoB;AAG/D,UAAI,MAAiB,MAAM;OACzB,IAAM,IAAe,EAAY,GAAQ;AAEzC,SAAY,GAAQ,KAAe,KAAiB,OAChD,IACA,IAAe;aACR,KAAc,EAAY,OAErC,EAAY,GAAQ,KAAc;;;KAIxC;IACF,EAkBK;GACL,MAjBgB,OAAO,OAAO,EAAY;GAkB1C,YAbsB,MAAM,KAAK,IAAI,IACrC,EAAK,SAAS,MACZ,EAAgB,KAAI,MAAa;IAC/B,IAAM,IAAQ,EAAI;AAClB,WAAO,KAAiC,OAEpC,OADA,OAAO,EAAM;KAEjB,CAAC,QAAQ,MAA2B,MAAU,KAAK,CACtD,CACF,CAAC;GAKA,eAAe;GAChB;;AAOH,QAAO;EACL,MAJgB,EAAmB,GAAM,GAAY,GAAa,GAAa,EAAgB;EAK/F,YAJiB,EAAY,KAAI,MAAS,EAAgB,EAAM,CAAC;EAKjE,eAAe;EAChB;;;;ACxfH,SAAgB,IAAmD;CACjE,IAAM,IAAU,EAAW,EAAgB;AAE3C,KAAI,CAAC,EACH,OAAU,MAAM,qDAAqD;AAIvE,QAAO,QAAc,EAAQ,eAAe,CAAC,EAAQ,cAAc,CAAC;;;;ACyCtE,SAAgB,EAAiB,GAA8B;AAG7D,QAFI,OAAO,SAAW,MAAoB,KAEnC,iBAAiB,SAAS,gBAAgB,CAC9C,iBAAiB,QAAQ,IAAe,CACxC,MAAM;;AAMX,SAAgB,EAAiB,GAAsB,GAAqB;AACtE,QAAO,SAAW,OAEtB,SAAS,gBAAgB,MAAM,YAAY,QAAQ,KAAgB,EAAM;;AAM3E,SAAgB,EAAW,GAA0B;AAC/C,QAAO,SAAW,OAEtB,OAAO,QAAQ,EAAM,OAAO,CAAC,SAAS,CAAC,GAAK,OAAW;AACrD,EAAI,KAGF,EADmB,EAAI,QAAQ,WAAU,MAAU,IAAI,EAAO,aAAa,GAAG,EACjD,EAAM;GAErC;;AAMJ,SAAgB,IAAmB;AACjC,KAAI,OAAO,SAAW,IAAa;CAEnC,IAAM,IAAe,SAAS,gBAAgB;AAC3B,OAAM,KAAK,EAAa,CAEhC,SAAQ,MAAQ;AACzB,EAAI,EAAK,WAAW,QAAQ,IAC1B,EAAa,eAAe,EAAK;GAEnC;;AAWJ,SAAgB,IAAkB;AAChC,KAAI,OAAO,SAAW,IAAa,QAAO;CAG1C,IAAM,IAAS,aAAa,QAAQ,QAAQ;AAC5C,KAAI,MAAW,UAAU,MAAW,UAAU,MAAW,QACvD,QAAO;CAIT,IAAM,IAAY,SAAS,gBAAgB,aAAa,aAAa;AAsBrE,QArBI,MAAc,UAAU,MAAc,SACjC,IAIL,SAAS,gBAAgB,UAAU,SAAS,OAAO,IACnD,SAAS,KAAK,UAAU,SAAS,OAAO,GACnC,SAIL,SAAS,gBAAgB,UAAU,SAAS,OAAO,IACnD,SAAS,KAAK,UAAU,SAAS,OAAO,GACnC,SAIL,OAAO,WAAW,+BAA+B,CAAC,UAC7C,SAGF;;AAMT,SAAgB,EAAS,GAAoB;AACvC,QAAO,SAAW,QAGtB,SAAS,gBAAgB,UAAU,OAAO,QAAQ,OAAO,EAGzD,SAAS,gBAAgB,aAAa,cAAc,EAAM,GAGtD,MAAU,UAAU,MAAU,WAChC,SAAS,gBAAgB,UAAU,IAAI,EAAM,EAI/C,aAAa,QAAQ,SAAS,EAAM;;AAOtC,SAAgB,IAAsB;CACpC,IAAM,IAAQ,GAAU;AACxB,QAAO,MAAU,UAAU,MAAU;;AAMvC,SAAgB,EAAkB,GAA8C;AAC9E,KAAI,OAAO,SAAW,IAAa,cAAa;CAGhD,IAAM,IAAW,IAAI,uBAAuB;AAC1C,IAAS,GAAU,CAAC;GACpB;AAEF,GAAS,QAAQ,SAAS,iBAAiB;EACzC,YAAY;EACZ,iBAAiB,CAAC,SAAS,aAAa;EACzC,CAAC;CAGF,IAAM,IAAa,OAAO,WAAW,+BAA+B,EAC9D,UAAsB,EAAS,GAAU,CAAC;AAIhD,QAHA,EAAW,iBAAiB,UAAU,EAAc,QAGvC;AAEX,EADA,EAAS,YAAY,EACrB,EAAW,oBAAoB,UAAU,EAAc;;;AAO3D,IAAa,IAAgB;CAC3B,OAAO;EACL,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,SAAS;GACT,cAAc;GACf;EACF;CACD,MAAM;EACJ,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,SAAS;GACT,cAAc;GACf;EACF;CACD,MAAM;EACJ,MAAM;EACN,QAAQ;GACN,SAAS;GACT,kBAAkB;GAClB,iBAAiB;GACjB,MAAM;GACN,eAAe;GACf,WAAW;GACX,QAAQ;GACR,iBAAiB;GACjB,SAAS;GACT,cAAc;GACd,gBAAgB;GAChB,SAAS;GACT,SAAS;GACT,OAAO;GACP,MAAM;GACN,QAAQ;GACT;EACF;CACF,EC1QY,IAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAIY,IAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAAiB,WACjB,IAAiB,WAEjB,IAAgB;CAC3B,KAAK;CACL,OAAO;CACP,MAAM;CACN,QAAQ;CACT,EAEY,IAA2B;CACtC,KAAK;CACL,OAAO;CACP,MAAM;CACN,QAAQ;gDCTJ,IAAoB,EAAM,KAAK,SAA2B,EAC9D,SACA,gBACA,mBAAgB,EAAE,EAClB,gBACA,YAAS,QACT,iBACA,qBACA,mBACa;CACb,IAAM,IAAS,EAA6B,KAAK,EAC3C,IAAe,EAA8B,KAAK,EAClD,CAAC,GAAY,KAAiB,EAAS;EAAE,OAAO;EAAG,QAAQ;EAAG,CAAC,EAC/D,CAAC,GAAiB,KAAsB,EAAS,GAAM,EACvD,CAAC,GAAc,KAAmB,EAAgB,QAAQ,EAE1D,IAAgB,GAAmB;AAGzC,UACE,EAAgB,GAAU,CAAC,EACX,GAAmB,MAAU;AAC3C,IAAgB,EAAM;GACtB,GAED,EAAE,CAAC;CAEN,IAAM,IAAoB,SAAe;EACvC,aAAa,GAAe,eAAe;EAC3C,YAAY,GAAe,cAAc;EACzC,YAAY,GAAe,cAAc;EAC1C,GAAG;EAAC,GAAe;EAAa,GAAe;EAAY,GAAe;EAAW,CAAC;AA8CvF,CA3CA,QAAsB;EACpB,IAAI,IAAa,GAEb,GACA,GAEE,UAAyB;AAC7B,OAAI,EAAa,SAAS;IACxB,IAAM,EAAE,UAAO,cAAW,EAAa,QAAQ,uBAAuB;AAEtE,QAAI,IAAQ,KAAK,IAAS,EAGxB,QAFA,EAAc;KAAE;KAAO;KAAQ,CAAC,EAChC,EAAmB,GAAK,EACjB;;AAGX,UAAO;;AAKT,MAAI,CAFY,GAAkB,IAElB,IAAa,IAAY;GACvC,IAAM,UAAqB;AAGzB,IAAI,CAFe,GAAkB,IAElB,IAAa,OAC9B,KACA,IAAY,iBAAiB;AAC3B,SAAQ,sBAAsB,EAAa;OAC1C,KAAK,EAAW;;AAIvB,OAAQ,sBAAsB,EAAa;;AAG7C,eAAa;AAEX,GADI,KAAO,qBAAqB,EAAM,EAClC,KAAW,aAAa,EAAU;;IAEvC,EAAE,CAAC,EAGN,QAAgB;EACd,IAAI,IAAwC,MAEtC,UAAyB;AAC7B,OAAI,EAAa,SAAS;IACxB,IAAM,EAAE,UAAO,cAAW,EAAa,QAAQ,uBAAuB;AACtE,IAAI,IAAQ,KAAK,IAAS,MACxB,EAAc;KAAE;KAAO;KAAQ,CAAC,EAC3B,KACH,EAAmB,GAAK;;;AAchC,SARI,EAAa,YACf,IAAiB,IAAI,qBAAqB,GAAkB,CAAC,EAC7D,EAAe,QAAQ,EAAa,QAAQ,EAC5C,GAAkB,GAGpB,OAAO,iBAAiB,UAAU,EAAiB,QAEtC;AAIX,GAHI,KACF,EAAe,YAAY,EAE7B,OAAO,oBAAoB,UAAU,EAAiB;;IAEvD,CAAC,EAAgB,CAAC;CAGrB,IAAM,KAAc,MACX,KAAK,MAAM,EAAK,UAAU,GAAG,EAAE,GAAG,GAGrC,KAAqB,MACjB,EAAK,UAAU,GAAG,IAAK,GAG3B,KAAkB,MAAuB;EAE7C,IAAM,IAAa,EAAK,SAAS;AACjC,SAAO,KAAK,OAAO,IAAa,KAAK,EAAE,GAAG;IAItC,IAAiB,GAAa,MAA4C;AAC9E,UAAQ,GAAa,aAAa,EAAlC;GACE,KAAK,OAEH,QAAO;GAET,KAAK,UAEH,QAAO;IACL,WAAW,MAAe,EAAK,aAAa;IAC5C,WAAW,MAAe,EAAW,EAAK,GAAG;IAC7C,SAAS,EAAE;IACX,SAAS;KAAC;KAAM;KAAM;KAAM;KAAK;IACjC,UAAU,MAAkB,IAAI,EAAM,UAAU,CAAC,MAAM,GAAG;IAC1D,UAAU,MAAkB;KAAC;KAAM;KAAM;KAAM;KAAK,CAAC,MAAU;IAC/D,WAAW;IACX,YAAY;IACb;GAEH,KAAK,QAGH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAU,EAAW,EAAK;AAChC,YAAO,IAAO,KAAK;;IAErB,WAAW,MAAe,EAAkB,EAAK,GAAG;IACpD,SAAS,EAAE;IACX,SAAS;KAAC;KAAW;KAAW;KAAU;IAC1C,UAAU,MAED,IADS,IAAQ;IAG1B,UAAU,MAAkB;KAAC;KAAW;KAAW;KAAU,CAAC,MAAU;IACxE,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,GAAG;IACxD;GAEH,KAAK,OAEH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAQ,EAAK,UAAU,GAAG;AAChC,YAAO,IAAO,MAAM;;IAEtB,WAAW,MAAe,EAAe,EAAK,GAAG;IACjD,SAAS,EAAE;IACX,SAAS;KAAC;KAAU;KAAU;KAAU;KAAU;KAAS;IAC3D,UAAU,MAEW;KAAC;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAK;KAAI,CADjE,IAAQ,MAEI,MAAM;IAElC,UAAU,MAAkB;KAAC;KAAU;KAAU;KAAU;KAAU;KAAS,CAAC,MAAU;IACzF,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,KAAK,MAEH,QAAO;IACL,WAAW,MAAe;KACxB,IAAM,EAAE,SAAM,YAAS,EAAc,EAAK;AAC1C,YAAO,IAAO,MAAM;;IAEtB,WAAW,MAAe,EAAK,QAAQ;IACvC,SAAS,EAAE;IACX,SAAS;KAAC;KAAO;KAAO;KAAO;KAAO;KAAO;KAAO;KAAM;IAC1D,UAAU,MAED,GADM,IAAQ;IAGvB,UAAU,MAAkB;KAAC;KAAO;KAAO;KAAO;KAAO;KAAO;KAAO;KAAM,CAAC,MAAU;IACxF,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,KAAK,OAEH,QAAO;IACL,WAAW,MAAe;KAExB,IAAM,IAAO,EAAK,aAAa,EACzB,IAAQ,EAAK,UAAU,GAAG,GAC1B,IAAM,EAAK,SAAS;AAC1B,YAAO,IAAO,MAAQ,IAAQ,MAAM;;IAEtC,WAAW,MAAe,KAAK,MAAM,EAAK,UAAU,GAAG,EAAE;IACzD,SAAS,EAAE;IACX,SAAS;KAAC;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAQ;IACjF,UAAU,MAGD,GADK,IAAQ;IAGtB,UAAU,MAAkB;KAAC;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAS;KAAQ,CAAC,MAAU;IAC/G,WAAW;IACX,YAAY;IACZ,uBAAuB;IACvB,eAAe,MAAkB,KAAK,MAAM,IAAQ,IAAI;IACzD;GAEH,QACE,QAAO;;IAEV,EAAE,CAAC,EAGA,KAAiB,MAA+C;EACpE,IAAM,IAAI,IAAI,KAAK,KAAK,IAAI,EAAK,aAAa,EAAE,EAAK,UAAU,EAAE,EAAK,SAAS,CAAC,CAAC,EAC3E,IAAS,EAAE,WAAW,IAAI;AAChC,IAAE,WAAW,EAAE,YAAY,GAAG,IAAI,EAAO;EACzC,IAAM,IAAO,EAAE,gBAAgB,EACzB,IAAY,IAAI,KAAK,KAAK,IAAI,GAAM,GAAG,EAAE,CAAC;AAEhD,SAAO;GAAE;GAAM,MADF,KAAK,OAAQ,EAAE,SAAS,GAAG,EAAU,SAAS,IAAI,QAAY,KAAK,EAAE;GAC7D;;AAubvB,KApbA,QAAgB;AASd,MARI,CAAC,KAAQ,EAAK,WAAW,KAAK,CAAC,EAAO,WAAW,CAAC,KAAmB,EAAW,UAAU,MAK9F,EAAO,EAAO,QAAQ,CAAC,UAAU,IAAI,CAAC,QAAQ,EAG1C,CAAC,GAAa,aAAa,CAAC,GAAa,YAC3C;EAGF,IAAM,IAAY,MAAM,QAAQ,EAAY,UAAU,GAAG,EAAY,UAAU,KAAK,EAAY,WAC1F,IAAa,MAAM,QAAQ,EAAY,WAAW,GAAG,EAAY,WAAW,KAAK,EAAY;AAGnG,MAAI,CAAC,KAAa,CAAC,EACjB;EA2BF,IAAM,WAvB4B;AAChC,OAAI,CAAC,GAAa,kBAAkB,EAAY,eAAe,WAAW,EACxE,QAAO;GAIT,IAAM,IAAU,EAAY,eAAe,MAAM,MAC/C,EAAG,cAAc,KAAa,EAAG,UAAU,SAAS,EAAU,CAC/D;AAED,OAAI,KAAW,EAAQ,YACrB,QAAO,EAAQ;GAIjB,IAAM,IAAe,EAAY,eAAe;AAKhD,UAJI,KAAgB,EAAa,cACxB,EAAa,cAGf;MAGqC,EACxC,IAAc,EAAe,EAAiB;AAGpD,MAAI,CAAC,EACH;EAKF,IAAM,IAAuB,EAAK,KAAI,MAAQ;GAC5C,IAAM,IAAY,EAAK,IACjB,IAAQ,OAAO,EAAK,MAAgB,WACtC,WAAW,EAAK,GAAY,GAC3B,EAAK,MAAe,GAGrB;AACJ,OAAI,OAAO,KAAc,UAAU;IAEjC,IAAI,IAAS;AAOb,IANI,EAAU,SAAS,IAAI,KACzB,IAAS,EAAU,QAAQ,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,kBAAkB,IAAI,GAErF,CAAC,EAAO,SAAS,IAAI,IAAI,CAAC,EAAO,SAAS,IAAI,KAChD,KAAkB,MAEpB,IAAO,IAAI,KAAK,EAAO;SAEvB,KAAO,IAAI,KAAK,EAAU;AAW5B,UAPI,MAAM,EAAK,SAAS,CAAC,GAChB,OAMF;IACL,GAJQ,EAAY,SAAS,EAAK;IAKlC,GAJQ,EAAY,SAAS,EAAK;IAKlC;IACA;IACA,OAAO,EAAgB,GAAW,EAAiB;IACpD;IACD,CAAC,QAAQ,MAA2B,MAAS,KAAK;AAGpD,MAAI,EAAS,WAAW,EAAG;EAG3B,IAAM,IAAO,EAAI,IAAU,MAAK,EAAE,EAAE,IAAI,GAClC,IAAO,EAAI,IAAU,MAAK,EAAE,EAAE,IAAI,GA+BlC,IA1BgB,CAAC,GAAG,IAAI,IAAI,EAAS,KAAI,MAAQ,EAAK,EAAE,CAAC,CAAC,CAAC,MAAM,EA6BjE,IAAY,EAAe,SAAS,EAAY,aAAa,EAAe,SAAS,KAAK,GAC1F,KAAc,IAAO,IAAO,KAAK,EAAY,cAAc,IAAO,KAAQ,GAE1E,IAAS;GACb,GAAG;GACH,MAAM;GACN,QAAQ;GACR,KAAK,EAAY,wBAAwB,KAAK;GAC9C,OAAO;GACR,EAEK,IAAiB,EAAW,QAAQ,EAAO,OAAO,EAAO,OACzD,IAAkB,EAAW,SAAS,EAAO,MAAM,EAAO,QAG5D,GACA;AAEJ,MAAI,EAAkB,YAAY;GAGhC,IAAM,IAAS,IAAiB,GAC1B,IAAS,IAAkB,GAC3B,IAAQ,KAAK,IAAI,GAAQ,EAAO;AAItC,GADA,IAAiB,EAAY,YAAY,GACzC,IAAkB,EAAY,aAAa;SACtC;GAML,IAAM,IAHG;IAAE,OAAO;IAAI,QAAQ;IAAI,EAM5B,IAAS,IAAiB,GAC1B,IAAS,IAAkB,GAC3B,IAAQ,KAAK,IAAI,GAAQ,EAAO;AAOtC,GAJA,IAAiB,KAAK,IAAI,EAAY,OAAO,KAAK,IAAI,IAAa,EAAY,YAAY,EAAM,CAAC,EAClG,IAAkB,KAAK,IAAI,EAAY,QAAQ,KAAK,IAAI,IAAa,EAAY,aAAa,EAAM,CAAC,EAGjG,MAAqB,UAAU,IAAiB,EAAY,UAC9D,IAAiB,EAAY;;EAKjC,IAAM,IAAkB,EAAe,SAAS,KAAkB,EAAe,SAAS,KAAK,GAIzF,IADwB,IAAkB,IACP,IAAkB,EAAO,OAAO,EAAO,QAAQ,EAAW,OAO7F,IAJM,EAAO,EAAO,QAAQ,CAC/B,KAAK,SAAS,EAAS,CACvB,KAAK,UAAU,EAAW,OAAO,CAEtB,OAAO,IAAI,CACtB,KAAK,aAAa,aAAa,EAAO,KAAK,GAAG,EAAO,IAAI,GAAG,EAGzD,IAAS,EAAS,KAAI,MAAK,EAAE,MAAM,EACnC,IAAW,EAAI,EAAO,IAAI,GAC1B,IAAW,EAAI,EAAO,IAAI,GAE1B,IAAa,GAAuB,CACvC,OAAO,CAAC,GAAU,EAAS,CAAC,CAC5B,MAAM,GAAc,YAAY,EAAsB,EAGnD,oBAAU,IAAI,KAAuB;AAC3C,IAAS,SAAQ,MAAQ;GACvB,IAAM,IAAM,GAAG,EAAK,EAAE,GAAG,EAAK;AAC9B,KAAQ,IAAI,GAAK,EAAK;IACtB;EAGF,IAAM,KAAiB,GAAiB,MACxB,iBAAiB,SAAS,gBAAgB,CAAC,iBAAiB,EAAQ,CAAC,MAAM,IACzE,GAGZ,IAAS,MAAiB,SAC1B,IAAY,IACd,EAAc,mBAAmB,UAAU,GAC3C,EAAc,uBAAuB,UAAU,EAC7C,IAAY,EAAc,eAAe,UAAU,EAEnD,IAAiB,IACnB,EAAc,qBAAqB,UAAU,GAC7C,EAAc,qBAAqB,UAAU,EAC3C,IAAkB,IACpB,EAAc,eAAe,UAAU,GACvC,EAAc,WAAW,UAAU,EAGjC,IAAU,EAAO,OAAO,CAAC,OAAO,MAAM,CACzC,KAAK,SAAS,wBAAwB,CACtC,MAAM,YAAY,WAAW,CAC7B,MAAM,WAAW,MAAM,CACvB,MAAM,cAAc,qBAAqB,CACzC,MAAM,SAAS,QAAQ,CACvB,MAAM,iBAAiB,MAAM,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,kBAAkB,OAAO,CAC/B,MAAM,WAAW,EAAE,CACnB,MAAM,WAAW,IAAK,EAGnB,oBAAgB,IAAI,KAAqB;AAC/C,IAAe,SAAS,GAAG,MAAU;AACnC,KAAc,IAAI,GAAG,EAAM;IAC3B;AAGF,OAAK,IAAM,KAAK,EACd,MAAK,IAAI,IAAI,GAAM,KAAK,GAAM,KAAK;GACjC,IAAM,IAAM,GAAG,EAAE,GAAG,KACd,IAAO,EAAQ,IAAI,EAAI,EACvB,IAAS,EAAc,IAAI,EAAE,IAAI,GAEjC,IAAO,EAAE,OAAO,OAAO,CAC1B,KAAK,KAAK,KAAU,IAAiB,GAAG,CACxC,KAAK,MAAM,IAAI,MAAS,IAAkB,GAAG,CAC7C,KAAK,SAAS,EAAe,CAC7B,KAAK,UAAU,EAAgB,CAC/B,KAAK,MAAM,EAAE,CACb,KAAK,MAAM,EAAE,CACb,MAAM,QAAQ,IAAO,EAAW,EAAK,MAAM,GAAG,EAAe,CAC7D,MAAM,UAAU,EAAgB,CAChC,MAAM,gBAAgB,EAAE;AA+C3B,GA5CI,EAAkB,cACpB,EACG,MAAM,UAAU,IAAe,YAAY,UAAU,CACrD,GAAG,aAAa,SAAS,GAAO;AAK/B,QAJA,EAAO,KAAK,CACT,MAAM,UAAU,OAAO,CACvB,MAAM,gBAAgB,EAAE,EAEvB,GAAM;KACR,IAAM,IAAiB,CACrB,WAAW,EAAK,MAAM,YACtB,GAAG,EAAc,EAAW,CAAC,IAAI,EAAK,QACvC,CAAC,KAAK,OAAO;AAEd,OACG,KAAK,EAAe,CACpB,MAAM,QAAS,EAAM,QAAQ,KAAM,KAAK,CACxC,MAAM,OAAQ,EAAM,QAAQ,KAAM,KAAK,CACvC,YAAY,CACZ,SAAS,IAAI,CACb,MAAM,WAAW,EAAE;;KAExB,CACD,GAAG,aAAa,SAAS,GAAO;AAC/B,MACG,MAAM,QAAS,EAAM,QAAQ,KAAM,KAAK,CACxC,MAAM,OAAQ,EAAM,QAAQ,KAAM,KAAK;KAC1C,CACD,GAAG,YAAY,WAAW;AAKzB,IAJA,EAAO,KAAK,CACT,MAAM,UAAU,EAAgB,CAChC,MAAM,gBAAgB,EAAE,EAE3B,EACG,YAAY,CACZ,SAAS,IAAI,CACb,MAAM,WAAW,EAAE;KACtB,GACK,KAET,EAAK,MAAM,UAAU,UAAU,EAI7B,KAAgB,KAAoB,KACtC,EAAK,GAAG,SAAS,SAAS,GAAO;AAC/B,MAAiB;KACf,WAAW;OAAG,IAAa,EAAK;OAAQ,IAAY,EAAK;MAAM;KAC/D,cAAc;KACd,QAAQ,EAAK;KACb,UAAU;MAAE,GAAG,EAAM;MAAO,GAAG,EAAM;MAAO;KAC5C,aAAa;KACd,CAAC;KACF;;AAMR,MAAI,EAAkB,YAAY;AAChC,OAAI,EAAY,yBAAyB,EAAY,cAAc;IAKjE,IAAM,oBAAa,IAAI,KAAuB;AAC9C,SAAK,IAAM,KAAK,GAAgB;KAC9B,IAAM,IAAO,EAAY,aAAa,EAAE;AAIxC,KAHK,EAAW,IAAI,EAAK,IACvB,EAAW,IAAI,GAAM,EAAE,CAAC,EAE1B,EAAW,IAAI,EAAK,CAAE,KAAK,EAAE;;AAK/B,SAAK,IAAM,KAAK,GAAgB;KAC9B,IAAM,IAAS,EAAc,IAAI,EAAE,IAAI;AACvC,OAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAU,IAAiB,KAAK,IAAiB,EAAE,CAC7D,KAAK,KAAK,GAAG,CACb,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;AAIjC,SAAK,IAAM,CAAC,GAAM,MAAY,EAC5B,KAAI,EAAQ,SAAS,GAAG;KAEtB,IAAM,IAAa,KAAK,IAAI,GAAG,EAAQ,KAAI,MAAK,EAAc,IAAI,EAAE,IAAI,EAAE,CAAC,EACrE,IAAW,KAAK,IAAI,GAAG,EAAQ,KAAI,MAAK,EAAc,IAAI,EAAE,IAAI,EAAE,CAAC,EACnE,KAAe,IAAa,KAAY,GAG1C;AACJ,SAAI,IAAO,MAAM;MAEf,IAAM,IAAa,KAAK,MAAM,IAAO,IAAI;AAGzC,UAAY,GADO;OAAC;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAO;OAAM,CADzF,IAAO,MAEa,GAAG,IAAI,EAAW,UAAU,CAAC,MAAM,GAAG;WAGxE,KAAY,IAAI,EAAK,UAAU,CAAC,MAAM,GAAG;AAa3C,KAVA,EAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAe,IAAiB,KAAK,IAAiB,EAAE,CAClE,KAAK,KAAK,IAAI,CACd,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,eAAe,OAAO,CAC5B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAU,EAGd,EAAQ,SAAS,KACnB,EAAE,OAAO,OAAO,CACb,KAAK,MAAM,KAAc,IAAiB,GAAG,CAC7C,KAAK,MAAM,KAAY,IAAiB,KAAK,EAAe,CAC5D,KAAK,MAAM,IAAI,CACf,KAAK,MAAM,IAAI,CACf,MAAM,UAAU,EAAU,CAC1B,MAAM,gBAAgB,EAAE,CACxB,MAAM,WAAW,GAAI;;UAIzB;IAEL,IAAM,IAAa,KAAK,IAAI,GAAG,KAAK,MAAM,EAAe,SAAS,GAAG,CAAC;AACtE,SAAK,IAAI,IAAI,GAAG,IAAI,EAAe,QAAQ,KAAK,GAAY;KAC1D,IAAM,IAAI,EAAe;AACzB,OAAE,OAAO,OAAO,CACb,KAAK,KAAK,KAAK,IAAiB,KAAK,IAAiB,EAAE,CACxD,KAAK,KAAK,GAAG,CACb,KAAK,eAAe,SAAS,CAC7B,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;;AAKnC,QAAK,IAAI,IAAI,GAAM,KAAK,GAAM,IAC5B,GAAE,OAAO,OAAO,CACb,KAAK,KAAK,GAAG,CACb,KAAK,MAAM,IAAI,MAAS,IAAkB,KAAK,IAAkB,EAAE,CACnE,KAAK,eAAe,MAAM,CAC1B,KAAK,MAAM,QAAQ,CACnB,MAAM,aAAa,OAAO,CAC1B,MAAM,QAAQ,EAAU,CACxB,KAAK,EAAY,QAAQ,EAAE,CAAC;;AAKnC,eAAa;AACX,KAAQ,QAAQ;;IAEjB;EAAC;EAAM;EAAa;EAAe;EAAa;EAAY;EAAiB;EAAmB;EAAc;EAAc;EAAe;EAAgB;EAAc;EAAiB,CAAC,EAE1L,CAAC,KAAQ,EAAK,WAAW,EAC3B,QACE,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAsC;IAAuB,CAAA,EAC5E,kBAAC,OAAD;IAAK,WAAU;cAAoC;IAAgD,CAAA,CAC/F;;EACF,CAAA;AAMV,KAAI,EADmB,GAAa,aAAa,GAAa,YAE5D,QACE,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAsC;IAA4B,CAAA,EACjF,kBAAC,OAAD;IAAK,WAAU;cAAoC;IAA2D,CAAA,CAC1G;;EACF,CAAA;CAKV,IAAM,IAAY,MAAM,QAAQ,EAAY,UAAU,GAAG,EAAY,UAAU,KAAK,EAAY;AAoBhG,SAnB6B,GAAa,gBAAgB,MAAM,MAC9D,EAAG,cAAc,KAAa,EAAG,UAAU,SAAS,EAAU,CAC/D,EAAE,eAAe,QAEQ,aAAa,KAAK,SAExC,kBAAC,OAAD;EACE,WAAU;EACV,OAAO,EAAE,WAAQ;YAEjB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAsC;KAA0B,CAAA;IAC/E,kBAAC,OAAD;KAAK,WAAU;eAAoC;KAAkF,CAAA;IACrI,kBAAC,OAAD;KAAK,WAAU;eAA4C;KAA+D,CAAA;IACtH;;EACF,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAU;EAA4C,OAAO;GAAE;GAAQ,WAAW;GAAS,UAAU;GAAU,OAAO;GAAQ;YACjI,kBAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAAqD,OAAO,EAAE,OAAO,QAAQ;aAA/G,CACE,kBAAC,OAAD;IAAK,KAAK;IAAQ,WAAU;IAAc,CAAA,EACzC,CAAC,KACA,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAgC;KAAmC,CAAA;IAC9E,CAAA,CAEJ;;EACF,CAAA;EAER"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
2
|
-
import { D as t, _ as n, b as r, i, n as a, y as o } from "./chart-activity-grid-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-CCl2IeXn.js";
|
|
2
|
+
import { D as t, _ as n, b as r, i, n as a, y as o } from "./chart-activity-grid-DLktOINm.js";
|
|
3
3
|
import s, { startTransition as c, useLayoutEffect as l, useRef as u, useState as d } from "react";
|
|
4
4
|
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
5
5
|
import { Area as h, CartesianGrid as g, ComposedChart as _, Legend as v, Line as y, ResponsiveContainer as b, Tooltip as x, XAxis as S, YAxis as C } from "recharts";
|
|
@@ -446,4 +446,4 @@ var P = /* @__PURE__ */ e({ default: () => F }), F = s.memo(function({ data: e,
|
|
|
446
446
|
//#endregion
|
|
447
447
|
export { A as a, O as c, N as i, E as l, P as n, j as o, M as r, k as s, F as t, T as u };
|
|
448
448
|
|
|
449
|
-
//# sourceMappingURL=chart-area-
|
|
449
|
+
//# sourceMappingURL=chart-area-BwYaflNk.js.map
|