drizzle-cube 0.7.1 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/ActivityGridChart.config-DXUUgx0N.cjs +1 -0
- package/dist/adapters/ActivityGridChart.config-Dyozu3VW.js +2 -0
- package/dist/adapters/AreaChart.config-Di5odBXp.cjs +1 -0
- package/dist/adapters/AreaChart.config-KEaXP_4K.js +2 -0
- package/dist/adapters/BarChart.config-B-hBHykR.cjs +1 -0
- package/dist/adapters/BarChart.config-C5sqbn0A.js +2 -0
- package/dist/adapters/BoxPlotChart.config-B1R4Br7L.js +2 -0
- package/dist/adapters/BoxPlotChart.config-C82Fhd3c.cjs +1 -0
- package/dist/adapters/BubbleChart.config-CoBxmmfp.js +2 -0
- package/dist/adapters/BubbleChart.config-DfOnNjL-.cjs +1 -0
- package/dist/adapters/CandlestickChart.config-C5ggV_3j.cjs +1 -0
- package/dist/adapters/CandlestickChart.config-ZaJpWVuL.js +2 -0
- package/dist/adapters/DataTable.config-Cx2_ACdY.cjs +1 -0
- package/dist/adapters/DataTable.config-DkAgD-iz.js +2 -0
- package/dist/adapters/FunnelChart.config-CvzcECUB.js +2 -0
- package/dist/adapters/FunnelChart.config-DVH7IFnb.cjs +1 -0
- package/dist/adapters/GaugeChart.config-Csx8rt8o.cjs +1 -0
- package/dist/adapters/GaugeChart.config-DEmrNgMa.js +2 -0
- package/dist/adapters/HeatMapChart.config-BfD_dpP7.js +2 -0
- package/dist/adapters/HeatMapChart.config-D_jlyPJL.cjs +1 -0
- package/dist/adapters/KpiDelta.config-CVBdUL_n.cjs +1 -0
- package/dist/adapters/KpiDelta.config-D4dCXOxl.js +2 -0
- package/dist/adapters/KpiNumber.config-BK5pgIKz.cjs +1 -0
- package/dist/adapters/KpiNumber.config-D6XqjZrm.js +2 -0
- package/dist/adapters/KpiText.config-ChphMwG5.js +2 -0
- package/dist/adapters/KpiText.config-fO1wc6FH.cjs +1 -0
- package/dist/adapters/LineChart.config-CXJrgz1s.js +2 -0
- package/dist/adapters/LineChart.config-Cg_h-SiJ.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-ByPjX-4O.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-Df2yY9AT.js +2 -0
- package/dist/adapters/MeasureProfileChart.config-BBWGIteF.cjs +1 -0
- package/dist/adapters/MeasureProfileChart.config-C9OFbN9Z.js +2 -0
- package/dist/adapters/PieChart.config-C6jJj6xm.js +2 -0
- package/dist/adapters/PieChart.config-CmCw_8eN.cjs +1 -0
- package/dist/adapters/ProportionBarChart.config-B9NEyFEe.js +2 -0
- package/dist/adapters/ProportionBarChart.config-C3GAVPWn.cjs +1 -0
- package/dist/adapters/RadarChart.config-5AMwEqUJ.cjs +1 -0
- package/dist/adapters/RadarChart.config-Ct_b7IM5.js +2 -0
- package/dist/adapters/RadialBarChart.config-Bp-Sl0cm.js +2 -0
- package/dist/adapters/RadialBarChart.config-D14yoexI.cjs +1 -0
- package/dist/adapters/RecordsTable.config-D2-qmG06.cjs +1 -0
- package/dist/adapters/RecordsTable.config-DIwoqZCU.js +2 -0
- package/dist/adapters/RetentionCombinedChart.config-BWHipi5M.cjs +1 -0
- package/dist/adapters/RetentionCombinedChart.config-D40UgTcl.js +2 -0
- package/dist/adapters/RetentionHeatmap.config-GlnSLrjn.js +2 -0
- package/dist/adapters/RetentionHeatmap.config-MlhZf26c.cjs +1 -0
- package/dist/adapters/SankeyChart.config-Bf1_NHiv.js +2 -0
- package/dist/adapters/SankeyChart.config-BoYf6BFE.cjs +1 -0
- package/dist/adapters/ScatterChart.config-CV2rdGJp.js +2 -0
- package/dist/adapters/ScatterChart.config-DywduGF3.cjs +1 -0
- package/dist/adapters/SunburstChart.config-CrqiE1UZ.js +2 -0
- package/dist/adapters/SunburstChart.config-D5tbF_GJ.cjs +1 -0
- package/dist/adapters/TreeMapChart.config-BJ8HnZU0.cjs +1 -0
- package/dist/adapters/TreeMapChart.config-DxgIqIIj.js +2 -0
- package/dist/adapters/WaterfallChart.config-Cns8fLFu.js +2 -0
- package/dist/adapters/WaterfallChart.config-D_kdL9SN.cjs +1 -0
- package/dist/adapters/compiler-BxZHh0UD.cjs +166 -0
- package/dist/adapters/{compiler-DiYxWAKg.js → compiler-CBGD_4Et.js} +1389 -1923
- package/dist/adapters/core/http-port.d.ts +34 -7
- package/dist/adapters/core/index.cjs +1 -1
- package/dist/adapters/core/index.d.ts +1 -0
- package/dist/adapters/core/index.js +2 -2
- package/dist/adapters/core/rest-handlers.d.ts +1 -1
- package/dist/adapters/core-CIGuwGuI.cjs +1 -0
- package/dist/adapters/{core-BOPRmxPc.js → core-DAAnqPyN.js} +81 -65
- package/dist/adapters/express/index.cjs +2 -2
- package/dist/adapters/express/index.d.ts +11 -2
- package/dist/adapters/express/index.js +14 -14
- package/dist/adapters/fastify/index.cjs +2 -2
- package/dist/adapters/fastify/index.d.ts +11 -2
- package/dist/adapters/fastify/index.js +29 -29
- package/dist/{server/google-eKAc20al.js → adapters/google-DRY7jnOh.js} +46 -28
- package/dist/adapters/{google-BhvizbFR.cjs → google-PsZzwedr.cjs} +2 -2
- package/dist/adapters/handler-BcYTw6zB.cjs +25 -0
- package/dist/adapters/{handler-DGud-C-w.js → handler-eA0VJDHj.js} +363 -266
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +9 -9
- package/dist/adapters/mcp-tools-handlers.d.ts +10 -3
- package/dist/adapters/mcp-tools.cjs +1 -1
- package/dist/adapters/mcp-tools.js +18 -20
- package/dist/adapters/mcp-transport-BpG44Fvn.js +730 -0
- package/dist/adapters/mcp-transport-CDxZXpc-.cjs +42 -0
- package/dist/adapters/mcp-transport.d.ts +13 -2
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +5 -2
- package/dist/adapters/nextjs/index.js +32 -32
- package/dist/adapters/{openai-Crp3X_zg.js → openai-BZ48ioYp.js} +1 -1
- package/dist/adapters/{openai-CmdN7Sj1.cjs → openai-Bw1j-OiP.cjs} +1 -1
- package/dist/adapters/{openai-Dwt9bxOE.cjs → openai-CLjyL5_J.cjs} +2 -2
- package/dist/adapters/{openai-CGJM6Qun.js → openai-CYYjUG_3.js} +4 -4
- package/dist/adapters/{utils-DboNUT3A.js → utils-BagURNRb.js} +1963 -1135
- package/dist/adapters/utils-BiKIg2tk.cjs +128 -0
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.d.ts +19 -5
- package/dist/adapters/utils.js +1 -1
- package/dist/cjs/adapters/core/http-port.d.ts +34 -7
- package/dist/cjs/adapters/core/index.d.ts +1 -0
- package/dist/cjs/adapters/core/rest-handlers.d.ts +1 -1
- package/dist/cjs/adapters/express/index.d.ts +11 -2
- package/dist/cjs/adapters/fastify/index.d.ts +11 -2
- package/dist/cjs/adapters/mcp-tools-handlers.d.ts +10 -3
- package/dist/cjs/adapters/mcp-transport.d.ts +13 -2
- package/dist/cjs/adapters/nextjs/index.d.ts +5 -2
- package/dist/cjs/adapters/utils.d.ts +19 -5
- package/dist/cjs/client/charts/chartConfigRegistry.d.ts +7 -0
- package/dist/cjs/client/charts/chartConfigs.d.ts +17 -1
- package/dist/cjs/client/client/CubeClient.d.ts +11 -1
- package/dist/cjs/client/components/AnalysisBuilder/AnalysisDisplayConfigPanel.d.ts +4 -2
- package/dist/cjs/client/components/AnalysisBuilder/ColumnFormatsEditor.d.ts +10 -0
- package/dist/cjs/client/components/AnalysisBuilder/DisplayOptionControl.d.ts +3 -2
- package/dist/cjs/client/components/AnalysisBuilder/utils/queryUtils.d.ts +7 -1
- package/dist/cjs/client/components/analyticsPortlet/PortletChart.d.ts +2 -1
- package/dist/cjs/client/components/analyticsPortlet/PortletChartView.d.ts +4 -1
- package/dist/cjs/client/components/analyticsPortlet/usePortletDeadMembers.d.ts +24 -0
- package/dist/cjs/client/components/analyticsPortlet/usePortletPagination.d.ts +21 -0
- package/dist/cjs/client/components/charts/RecordsTable.config.d.ts +10 -0
- package/dist/cjs/client/components/charts/RecordsTable.d.ts +4 -0
- package/dist/cjs/client/components/charts/recordsTableHooks.d.ts +68 -0
- package/dist/cjs/client/icons/types.d.ts +1 -0
- package/dist/cjs/client/index.d.ts +2 -2
- package/dist/cjs/client/types.d.ts +92 -1
- package/dist/cjs/client/utils/recordsTableUtils.d.ts +71 -0
- package/dist/cjs/client/utils/rowLinkUtils.d.ts +35 -0
- package/dist/cjs/server/adapters/base-adapter.d.ts +46 -0
- package/dist/cjs/server/adapters/databend-adapter.d.ts +5 -0
- package/dist/cjs/server/adapters/duckdb-adapter.d.ts +5 -0
- package/dist/cjs/server/adapters/mysql-adapter.d.ts +14 -0
- package/dist/cjs/server/adapters/postgres-adapter.d.ts +15 -0
- package/dist/cjs/server/adapters/snowflake-adapter.d.ts +6 -0
- package/dist/cjs/server/adapters/sqlite-adapter.d.ts +21 -0
- package/dist/cjs/server/agent/chart-validation.d.ts +1 -1
- package/dist/cjs/server/ai/chart-schema.d.ts +117 -0
- package/dist/cjs/server/ai/discovery-helpers.d.ts +14 -0
- package/dist/cjs/server/ai/discovery.d.ts +6 -0
- package/dist/cjs/server/ai/query-schema.d.ts +1 -1
- package/dist/cjs/server/attribute-dimensions.d.ts +102 -0
- package/dist/cjs/server/builders/group-by-builder.d.ts +15 -0
- package/dist/cjs/server/cache-utils.d.ts +5 -1
- package/dist/cjs/server/compiler-metadata.d.ts +24 -3
- package/dist/cjs/server/compiler.d.ts +159 -13
- package/dist/cjs/server/execution/query-result-cache.d.ts +1 -1
- package/dist/cjs/server/executor.d.ts +15 -0
- package/dist/cjs/server/index.d.ts +13 -3
- package/dist/cjs/server/query-handlers.d.ts +2 -1
- package/dist/cjs/server/query-validator.d.ts +36 -4
- package/dist/cjs/server/types/core.d.ts +13 -0
- package/dist/cjs/server/types/cube.d.ts +39 -2
- package/dist/cjs/server/types/query.d.ts +8 -0
- package/dist/cli/index.cjs +130 -52
- package/dist/client/charts/chartConfigRegistry.d.ts +7 -0
- package/dist/client/charts/chartConfigs.d.ts +17 -1
- package/dist/client/charts.js +13 -13
- package/dist/client/chunks/{DashboardEditModal-BOfLdTgV.js → DashboardEditModal-_ZDMwaGX.js} +1653 -1188
- package/dist/client/chunks/DashboardEditModal-_ZDMwaGX.js.map +1 -0
- package/dist/client/chunks/{ProportionBarChart-DwoXU5VP.js → ProportionBarChart-qfpAWhIg.js} +3 -3
- package/dist/client/chunks/{ProportionBarChart-DwoXU5VP.js.map → ProportionBarChart-qfpAWhIg.js.map} +1 -1
- package/dist/client/chunks/RecordsTable-KmJy94xN.js +556 -0
- package/dist/client/chunks/RecordsTable-KmJy94xN.js.map +1 -0
- package/dist/client/chunks/{RetentionCombinedChart-BqlSV7yF.js → RetentionCombinedChart-C7X6aj97.js} +3 -3
- package/dist/client/chunks/{RetentionCombinedChart-BqlSV7yF.js.map → RetentionCombinedChart-C7X6aj97.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-VdVkBg8Q.js → RetentionHeatmap-PpRpiqR_.js} +2 -2
- package/dist/client/chunks/{RetentionHeatmap-VdVkBg8Q.js.map → RetentionHeatmap-PpRpiqR_.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-DXw60SEs.js → analysis-builder-DaqyOjLX.js} +169 -168
- package/dist/client/chunks/{analysis-builder-DXw60SEs.js.map → analysis-builder-DaqyOjLX.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-CEvHIlmk.js → analysis-builder-shared-ow9KAHDP.js} +965 -954
- package/dist/client/chunks/analysis-builder-shared-ow9KAHDP.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-4jfS8khG.js → chart-activity-grid-DO82rrbW.js} +140 -84
- package/dist/client/chunks/chart-activity-grid-DO82rrbW.js.map +1 -0
- package/dist/client/chunks/{chart-area-Dol6s9no.js → chart-area-9SBeG0GM.js} +21 -21
- package/dist/client/chunks/{chart-area-Dol6s9no.js.map → chart-area-9SBeG0GM.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-5_niozi2.js → chart-bar-tfgmLK2D.js} +5 -5
- package/dist/client/chunks/{chart-bar-5_niozi2.js.map → chart-bar-tfgmLK2D.js.map} +1 -1
- package/dist/client/chunks/{chart-box-plot-Dhp-VwhD.js → chart-box-plot-BuYW6j6g.js} +2 -2
- package/dist/client/chunks/{chart-box-plot-Dhp-VwhD.js.map → chart-box-plot-BuYW6j6g.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BM2BAMSo.js → chart-bubble-BNmonWqW.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BM2BAMSo.js.map → chart-bubble-BNmonWqW.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-BNwLIBfm.js → chart-candlestick-BYeWNkKl.js} +2 -2
- package/dist/client/chunks/{chart-candlestick-BNwLIBfm.js.map → chart-candlestick-BYeWNkKl.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-DoDHQRe7.js → chart-data-table-C_oHiK6N.js} +1094 -1029
- package/dist/client/chunks/chart-data-table-C_oHiK6N.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-Cd7da_sa.js → chart-funnel-B_CWC3cL.js} +2 -2
- package/dist/client/chunks/{chart-funnel-Cd7da_sa.js.map → chart-funnel-B_CWC3cL.js.map} +1 -1
- package/dist/client/chunks/{chart-gauge-DOpul-Oz.js → chart-gauge-D7VxwPnx.js} +3 -3
- package/dist/client/chunks/{chart-gauge-DOpul-Oz.js.map → chart-gauge-D7VxwPnx.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-CeKbK655.js → chart-heat-map-q7Vf_dog.js} +3 -3
- package/dist/client/chunks/{chart-heat-map-CeKbK655.js.map → chart-heat-map-q7Vf_dog.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-Dq8qUOOT.js → chart-kpi-delta-PEuA3iGs.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-Dq8qUOOT.js.map → chart-kpi-delta-PEuA3iGs.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-DgiqTi9g.js → chart-kpi-number-DlxrO6Pq.js} +5 -5
- package/dist/client/chunks/{chart-kpi-number-DgiqTi9g.js.map → chart-kpi-number-DlxrO6Pq.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-CsZMVEnM.js → chart-kpi-text-Cx6cJu2s.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-CsZMVEnM.js.map → chart-kpi-text-Cx6cJu2s.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DlwOB7C7.js → chart-line-pDe25JzB.js} +3 -3
- package/dist/client/chunks/{chart-line-DlwOB7C7.js.map → chart-line-pDe25JzB.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-DPE34SjC.js → chart-markdown-CRY15yp0.js} +2 -2
- package/dist/client/chunks/{chart-markdown-DPE34SjC.js.map → chart-markdown-CRY15yp0.js.map} +1 -1
- package/dist/client/chunks/{chart-measure-profile-BpTz1fce.js → chart-measure-profile-DyQ-vvuC.js} +3 -3
- package/dist/client/chunks/{chart-measure-profile-BpTz1fce.js.map → chart-measure-profile-DyQ-vvuC.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-FGw66XAH.js → chart-pie-ZrnBycy1.js} +15 -15
- package/dist/client/chunks/{chart-pie-FGw66XAH.js.map → chart-pie-ZrnBycy1.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-D-eRDoiA.js → chart-radar-BXbnYMUJ.js} +13 -13
- package/dist/client/chunks/{chart-radar-D-eRDoiA.js.map → chart-radar-BXbnYMUJ.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DgtkNTs3.js → chart-radial-bar-CYxH3ryh.js} +3 -3
- package/dist/client/chunks/{chart-radial-bar-DgtkNTs3.js.map → chart-radial-bar-CYxH3ryh.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-D0hhb_EQ.js → chart-sankey-C9R_TDDh.js} +2 -2
- package/dist/client/chunks/{chart-sankey-D0hhb_EQ.js.map → chart-sankey-C9R_TDDh.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-D9EcAiMQ.js → chart-scatter-DrwRkzzl.js} +3 -3
- package/dist/client/chunks/{chart-scatter-D9EcAiMQ.js.map → chart-scatter-DrwRkzzl.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-DCYmJ5DU.js → chart-sunburst-Bs1yqIPp.js} +3 -3
- package/dist/client/chunks/{chart-sunburst-DCYmJ5DU.js.map → chart-sunburst-Bs1yqIPp.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-D_ACSSiB.js → chart-tree-map-BNjHhhVq.js} +3 -3
- package/dist/client/chunks/{chart-tree-map-D_ACSSiB.js.map → chart-tree-map-BNjHhhVq.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-CVUVNa1R.js → chart-waterfall-CyoC0uLT.js} +3 -3
- package/dist/client/chunks/{chart-waterfall-CVUVNa1R.js.map → chart-waterfall-CyoC0uLT.js.map} +1 -1
- package/dist/client/chunks/charts-core-DCQ7od_L.js +190 -0
- package/dist/client/chunks/charts-core-DCQ7od_L.js.map +1 -0
- package/dist/client/chunks/charts-loader-Bya_zDIA.js +86 -0
- package/dist/client/chunks/charts-loader-Bya_zDIA.js.map +1 -0
- package/dist/client/chunks/{en-US-BE6VoG0o.js → en-US-HP6FHuNy.js} +3 -1
- package/dist/client/chunks/{en-US-BE6VoG0o.js.map → en-US-HP6FHuNy.js.map} +1 -1
- package/dist/client/chunks/{exceljs.min-DWC_b8G9.js → exceljs.min-CiByP8VQ.js} +2 -3
- package/dist/client/chunks/{exceljs.min-DWC_b8G9.js.map → exceljs.min-CiByP8VQ.js.map} +1 -1
- package/dist/client/chunks/{nl-NL-DFLVORiD.js → nl-NL-CEdoCz6Q.js} +54 -1
- package/dist/client/chunks/nl-NL-CEdoCz6Q.js.map +1 -0
- package/dist/client/chunks/{schema-visualization-C6g_LCiA.js → schema-visualization-DfXxFBIY.js} +3 -3
- package/dist/client/chunks/{schema-visualization-C6g_LCiA.js.map → schema-visualization-DfXxFBIY.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-ZfChDEd3.js → useDirtyStateTracking-BFJHiiVK.js} +15 -15
- package/dist/client/chunks/{useDirtyStateTracking-ZfChDEd3.js.map → useDirtyStateTracking-BFJHiiVK.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-im9e1rVb.js → useExplainAI-_C4WQE5I.js} +16 -16
- package/dist/client/chunks/{useExplainAI-im9e1rVb.js.map → useExplainAI-_C4WQE5I.js.map} +1 -1
- package/dist/client/chunks/{vendor-Qa1s8oSX.js → vendor-Gb3lH0cc.js} +49 -49
- package/dist/client/chunks/vendor-Gb3lH0cc.js.map +1 -0
- package/dist/client/client/CubeClient.d.ts +11 -1
- package/dist/client/components/AnalysisBuilder/AnalysisDisplayConfigPanel.d.ts +4 -2
- package/dist/client/components/AnalysisBuilder/ColumnFormatsEditor.d.ts +10 -0
- package/dist/client/components/AnalysisBuilder/DisplayOptionControl.d.ts +3 -2
- package/dist/client/components/AnalysisBuilder/utils/queryUtils.d.ts +7 -1
- package/dist/client/components/analyticsPortlet/PortletChart.d.ts +2 -1
- package/dist/client/components/analyticsPortlet/PortletChartView.d.ts +4 -1
- package/dist/client/components/analyticsPortlet/usePortletDeadMembers.d.ts +24 -0
- package/dist/client/components/analyticsPortlet/usePortletPagination.d.ts +21 -0
- package/dist/client/components/charts/RecordsTable.config.d.ts +10 -0
- package/dist/client/components/charts/RecordsTable.d.ts +4 -0
- package/dist/client/components/charts/recordsTableHooks.d.ts +68 -0
- package/dist/client/components.js +1 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +213 -213
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/styles.css +1 -1
- package/dist/client/types.d.ts +92 -1
- package/dist/client/utils/recordsTableUtils.d.ts +71 -0
- package/dist/client/utils/rowLinkUtils.d.ts +35 -0
- package/dist/client/utils.js +14 -14
- package/dist/client-bundle-stats.html +1 -1
- package/dist/mcp-app/mcp-app.html +109 -109
- package/dist/server/adapters/base-adapter.d.ts +46 -0
- package/dist/server/adapters/databend-adapter.d.ts +5 -0
- package/dist/server/adapters/duckdb-adapter.d.ts +5 -0
- package/dist/server/adapters/mysql-adapter.d.ts +14 -0
- package/dist/server/adapters/postgres-adapter.d.ts +15 -0
- package/dist/server/adapters/snowflake-adapter.d.ts +6 -0
- package/dist/server/adapters/sqlite-adapter.d.ts +21 -0
- package/dist/server/agent/chart-validation.d.ts +1 -1
- package/dist/server/ai/chart-schema.d.ts +117 -0
- package/dist/server/ai/discovery-helpers.d.ts +14 -0
- package/dist/server/ai/discovery.d.ts +6 -0
- package/dist/server/ai/query-schema.d.ts +1 -1
- package/dist/server/attribute-dimensions.d.ts +102 -0
- package/dist/server/builders/group-by-builder.d.ts +15 -0
- package/dist/server/cache-utils.d.ts +5 -1
- package/dist/server/compiler-metadata.d.ts +24 -3
- package/dist/server/compiler.d.ts +159 -13
- package/dist/server/execution/query-result-cache.d.ts +1 -1
- package/dist/server/executor.d.ts +15 -0
- package/dist/{adapters/google-eKAc20al.js → server/google-DRY7jnOh.js} +46 -28
- package/dist/server/{google-BhvizbFR.cjs → google-PsZzwedr.cjs} +2 -2
- package/dist/server/index.cjs +42 -38
- package/dist/server/index.d.ts +13 -3
- package/dist/server/index.js +2079 -1573
- package/dist/server/{openai-Czk1BdHa.js → openai-6uUf7h-5.js} +1 -1
- package/dist/server/{openai-DBwI1OSu.cjs → openai-BBe1XbZd.cjs} +1 -1
- package/dist/server/{openai-Cu4TXXjl.cjs → openai-BmADmD1e.cjs} +1 -1
- package/dist/server/{openai-CUf4vc3Q.js → openai-C1gLuR-0.js} +1 -1
- package/dist/server/query-handlers.d.ts +2 -1
- package/dist/server/query-validator.d.ts +36 -4
- package/dist/server/types/core.d.ts +13 -0
- package/dist/server/types/cube.d.ts +39 -2
- package/dist/server/types/query.d.ts +8 -0
- package/package.json +2 -2
- package/dist/adapters/ActivityGridChart.config-D6hhj345.cjs +0 -1
- package/dist/adapters/ActivityGridChart.config-QZKs_NYg.js +0 -2
- package/dist/adapters/AreaChart.config-B5XM6G22.js +0 -2
- package/dist/adapters/AreaChart.config-NP34BH5y.cjs +0 -1
- package/dist/adapters/BarChart.config-Bqlmr81N.js +0 -2
- package/dist/adapters/BarChart.config-C3bw-cAP.cjs +0 -1
- package/dist/adapters/BoxPlotChart.config-BOAvoj6x.cjs +0 -1
- package/dist/adapters/BoxPlotChart.config-CTXiycYY.js +0 -2
- package/dist/adapters/BubbleChart.config-CGFIkl4H.cjs +0 -1
- package/dist/adapters/BubbleChart.config-Njxx4Eq1.js +0 -2
- package/dist/adapters/CandlestickChart.config-BZ_yWaSo.cjs +0 -1
- package/dist/adapters/CandlestickChart.config-D4Svhmef.js +0 -2
- package/dist/adapters/DataTable.config-B-bT9puT.js +0 -2
- package/dist/adapters/DataTable.config-BHtt1cPM.cjs +0 -1
- package/dist/adapters/FunnelChart.config-C1e07O7B.cjs +0 -1
- package/dist/adapters/FunnelChart.config-CVEy0tV9.js +0 -2
- package/dist/adapters/GaugeChart.config-5PLNlQlu.js +0 -2
- package/dist/adapters/GaugeChart.config-Cdv6knjZ.cjs +0 -1
- package/dist/adapters/HeatMapChart.config-MGTfYpWJ.js +0 -2
- package/dist/adapters/HeatMapChart.config-jfBEi1ZI.cjs +0 -1
- package/dist/adapters/KpiDelta.config-D2IUsEYz.cjs +0 -1
- package/dist/adapters/KpiDelta.config-DT_MmAHw.js +0 -2
- package/dist/adapters/KpiNumber.config-ChgbKmx8.cjs +0 -1
- package/dist/adapters/KpiNumber.config-CvZ_FhyL.js +0 -2
- package/dist/adapters/KpiText.config-Bgkw8gr2.js +0 -2
- package/dist/adapters/KpiText.config-Bz9orqt6.cjs +0 -1
- package/dist/adapters/LineChart.config-BVew35dI.cjs +0 -1
- package/dist/adapters/LineChart.config-DSCCKXNg.js +0 -2
- package/dist/adapters/MarkdownChart.config-Bu6XUuhI.js +0 -2
- package/dist/adapters/MarkdownChart.config-E4aSVTf3.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-BF249hc_.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-lERVe38G.js +0 -2
- package/dist/adapters/PieChart.config-7Ujwp8R5.cjs +0 -1
- package/dist/adapters/PieChart.config-jQl2HIcA.js +0 -2
- package/dist/adapters/ProportionBarChart.config-o0w_Pnlt.js +0 -2
- package/dist/adapters/ProportionBarChart.config-phNohhhY.cjs +0 -1
- package/dist/adapters/RadarChart.config-BmrYBd9x.js +0 -2
- package/dist/adapters/RadarChart.config-Dlt3UflG.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-CeEm8xRb.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-Dishh6bC.js +0 -2
- package/dist/adapters/RetentionCombinedChart.config-BaD4ev85.cjs +0 -1
- package/dist/adapters/RetentionCombinedChart.config-m2FjBUi9.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-DiMplGdk.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-Dp6oYwQZ.cjs +0 -1
- package/dist/adapters/SankeyChart.config-C4Y6qzCS.cjs +0 -1
- package/dist/adapters/SankeyChart.config-CJHqgjQ1.js +0 -2
- package/dist/adapters/ScatterChart.config-C0QqvDrN.cjs +0 -1
- package/dist/adapters/ScatterChart.config-DywOsWPW.js +0 -2
- package/dist/adapters/SunburstChart.config-DE8RxpDR.cjs +0 -1
- package/dist/adapters/SunburstChart.config-DohowrO3.js +0 -2
- package/dist/adapters/TreeMapChart.config-D2gXz-zC.cjs +0 -1
- package/dist/adapters/TreeMapChart.config-HMlI29GG.js +0 -2
- package/dist/adapters/WaterfallChart.config-BO2WV2VB.js +0 -2
- package/dist/adapters/WaterfallChart.config-CzwGiheB.cjs +0 -1
- package/dist/adapters/compiler-BNjqYdmc.cjs +0 -166
- package/dist/adapters/core-CzFfrJzu.cjs +0 -1
- package/dist/adapters/handler-m6WgA9xu.cjs +0 -25
- package/dist/adapters/mcp-transport-B0b27YUB.cjs +0 -40
- package/dist/adapters/mcp-transport-BXyA4dTk.js +0 -603
- package/dist/adapters/utils-BoOeig94.cjs +0 -128
- package/dist/client/chunks/DashboardEditModal-BOfLdTgV.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-CEvHIlmk.js.map +0 -1
- package/dist/client/chunks/chart-activity-grid-4jfS8khG.js.map +0 -1
- package/dist/client/chunks/chart-data-table-DoDHQRe7.js.map +0 -1
- package/dist/client/chunks/charts-core-BPD_hLaL.js +0 -215
- package/dist/client/chunks/charts-core-BPD_hLaL.js.map +0 -1
- package/dist/client/chunks/charts-loader-CwMcOfwT.js +0 -85
- package/dist/client/chunks/charts-loader-CwMcOfwT.js.map +0 -1
- package/dist/client/chunks/nl-NL-DFLVORiD.js.map +0 -1
- package/dist/client/chunks/vendor-Qa1s8oSX.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
-
import {
|
|
2
|
+
import { F as t, s as n } from "./chart-activity-grid-DO82rrbW.js";
|
|
3
3
|
import r, { useMemo as i } from "react";
|
|
4
4
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
5
|
import { Cell as s, Funnel as c, FunnelChart as l, LabelList as u, ResponsiveContainer as d, Tooltip as f } from "recharts";
|
|
@@ -406,4 +406,4 @@ var P = /* @__PURE__ */ e({ default: () => F }), F = r.memo(function({ data: e,
|
|
|
406
406
|
//#endregion
|
|
407
407
|
export { C as a, g as c, _ as i, S as l, P as n, p as o, h as r, m as s, F as t };
|
|
408
408
|
|
|
409
|
-
//# sourceMappingURL=chart-funnel-
|
|
409
|
+
//# sourceMappingURL=chart-funnel-B_CWC3cL.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-funnel-Cd7da_sa.js","names":[],"sources":["../../../src/client/utils/funnelExecution.ts","../../../src/client/components/charts/FunnelChart.helpers.ts","../../../src/client/components/charts/FunnelViews.tsx","../../../src/client/components/charts/FunnelChart.tsx"],"sourcesContent":["/**\n * Funnel Query Execution Utilities\n *\n * Handles sequential execution of funnel queries where each step\n * filters based on binding key values from the previous step.\n */\n\nimport type { CubeQuery, SimpleFilter } from '../types.js'\n\n/**\n * Default maximum number of binding key values to pass between funnel steps.\n * Limits the size of the IN clause to prevent performance issues.\n */\nexport const DEFAULT_BINDING_KEY_LIMIT = 500\nimport type {\n FunnelBindingKey,\n FunnelBindingKeyMapping,\n FunnelConfig,\n FunnelStep,\n FunnelStepResult,\n FunnelExecutionResult,\n FunnelChartData,\n} from '../types/funnel.js'\n\n/**\n * Extract the binding key field name for a specific query/cube.\n *\n * For simple binding keys (string), returns the dimension directly.\n * For cross-cube mappings, finds the mapping for the cube used in the query.\n *\n * @param bindingKey - The funnel binding key configuration\n * @param query - The cube query (used to determine which cube is being queried)\n * @returns The binding key field name (e.g., \"Users.userId\")\n */\nexport function getBindingKeyField(\n bindingKey: FunnelBindingKey,\n query: CubeQuery\n): string {\n // Simple case: single dimension name\n if (typeof bindingKey.dimension === 'string') {\n return bindingKey.dimension\n }\n\n // Cross-cube case: find the mapping for this query's cube\n const mappings = bindingKey.dimension as FunnelBindingKeyMapping[]\n\n // Extract cube name from query fields\n const cubeName = getCubeNameFromQuery(query)\n if (!cubeName) {\n // If we can't determine the cube, use the first mapping\n return mappings[0]?.dimension || ''\n }\n\n // Find matching mapping\n const mapping = mappings.find(m => m.cube === cubeName)\n if (mapping) {\n return mapping.dimension\n }\n\n // Fallback to first mapping if no match found\n return mappings[0]?.dimension || ''\n}\n\n/**\n * Extract the cube name from a query by looking at measures/dimensions\n */\nexport function getCubeNameFromQuery(query: CubeQuery): string | null {\n // Check measures first\n if (query.measures && query.measures.length > 0) {\n const parts = query.measures[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check dimensions\n if (query.dimensions && query.dimensions.length > 0) {\n const parts = query.dimensions[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check time dimensions\n if (query.timeDimensions && query.timeDimensions.length > 0) {\n const parts = query.timeDimensions[0].dimension.split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n return null\n}\n\n/**\n * Result from extracting binding key values\n */\nexport interface ExtractedBindingKeyValues {\n /** Binding key values (limited to max if specified) */\n values: (string | number)[]\n /** Total count of unique values before limiting */\n totalCount: number\n /** Whether values were truncated due to limit */\n wasTruncated: boolean\n}\n\n/**\n * Extract unique values for the binding key from query result data\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution is now the default approach.\n *\n * @param data - Raw data from query result\n * @param bindingKeyField - The field name to extract values from\n * @param limit - Maximum number of values to return (default: DEFAULT_BINDING_KEY_LIMIT)\n * @returns Object with values array, total count, and truncation flag\n */\nexport function extractBindingKeyValues(\n data: unknown[],\n bindingKeyField: string,\n limit: number = DEFAULT_BINDING_KEY_LIMIT\n): ExtractedBindingKeyValues {\n const values = new Set<string | number>()\n\n for (const row of data) {\n if (typeof row === 'object' && row !== null) {\n const value = (row as Record<string, unknown>)[bindingKeyField]\n if (value !== null && value !== undefined) {\n // Convert to string or number\n if (typeof value === 'number') {\n values.add(value)\n } else {\n values.add(String(value))\n }\n }\n }\n }\n\n const allValues = Array.from(values)\n const totalCount = allValues.length\n\n // Sort values for consistent ordering (enables query cache hits)\n // Numbers sort numerically, strings sort alphabetically\n allValues.sort((a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n return String(a).localeCompare(String(b))\n })\n\n const limitedValues = limit > 0 ? allValues.slice(0, limit) : allValues\n\n return {\n values: limitedValues,\n totalCount,\n wasTruncated: limitedValues.length < totalCount,\n }\n}\n\n/**\n * Build a step query with binding key filter applied.\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution is now the default approach.\n *\n * For the first step (no previous values), returns the original query\n * with the binding key dimension ensured.\n *\n * For subsequent steps, adds an IN filter for the previous step's\n * binding key values.\n *\n * @param step - The funnel step configuration\n * @param bindingKey - The funnel binding key configuration\n * @param previousBindingKeyValues - Binding key values from previous step (null for first step)\n * @returns Modified CubeQuery with binding key filter\n */\nexport function buildStepQuery(\n step: FunnelStep,\n bindingKey: FunnelBindingKey,\n previousBindingKeyValues: (string | number)[] | null\n): CubeQuery {\n const query: CubeQuery = { ...step.query }\n\n // Get binding key field for this query\n const bindingKeyField = getBindingKeyField(bindingKey, query)\n\n // Ensure binding key dimension is in the query (needed to extract values for next step)\n if (!query.dimensions?.includes(bindingKeyField)) {\n query.dimensions = [...(query.dimensions || []), bindingKeyField]\n }\n\n // Add IN filter for previous step's binding key values (except for first step)\n if (previousBindingKeyValues && previousBindingKeyValues.length > 0) {\n const inFilter: SimpleFilter = {\n member: bindingKeyField,\n operator: 'in',\n values: previousBindingKeyValues,\n }\n query.filters = [...(query.filters || []), inFilter]\n }\n\n return query\n}\n\n/**\n * Calculate conversion metrics for a step\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now calculates metrics directly.\n */\nexport function calculateStepMetrics(\n currentCount: number,\n previousCount: number | null,\n firstStepCount: number\n): {\n conversionRate: number | null\n cumulativeConversionRate: number\n} {\n const conversionRate =\n previousCount !== null && previousCount > 0\n ? currentCount / previousCount\n : null\n\n const cumulativeConversionRate =\n firstStepCount > 0 ? currentCount / firstStepCount : 1.0\n\n return { conversionRate, cumulativeConversionRate }\n}\n\n/**\n * Build a funnel step result from query execution\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now returns results directly.\n */\nexport function buildStepResult(\n step: FunnelStep,\n stepIndex: number,\n data: unknown[],\n bindingKeyField: string,\n countUnique: boolean,\n previousCount: number | null,\n firstStepCount: number,\n executionTime: number,\n error: Error | null = null,\n bindingKeyLimit: number = DEFAULT_BINDING_KEY_LIMIT\n): FunnelStepResult {\n // Extract binding key values (with limit applied)\n const extracted = error\n ? { values: [], totalCount: 0, wasTruncated: false }\n : extractBindingKeyValues(data, bindingKeyField, bindingKeyLimit)\n\n // Calculate count based on total unique values (before truncation)\n const count = error\n ? 0\n : countUnique\n ? extracted.totalCount\n : data.length\n\n // Calculate conversion metrics\n const { conversionRate, cumulativeConversionRate } = calculateStepMetrics(\n count,\n previousCount,\n firstStepCount || count // Use current count as first step count if this is step 0\n )\n\n return {\n stepIndex,\n stepName: step.name,\n stepId: step.id,\n data,\n bindingKeyValues: extracted.values,\n bindingKeyTotalCount: extracted.totalCount,\n count,\n conversionRate,\n cumulativeConversionRate,\n executionTime,\n error,\n }\n}\n\n/**\n * Convert step results to chart-ready data format\n *\n * @deprecated Use transformServerFunnelResult() instead.\n * Server-side funnel execution returns data in a compatible format.\n */\nexport function buildFunnelChartData(\n stepResults: FunnelStepResult[]\n): FunnelChartData[] {\n if (stepResults.length === 0) return []\n\n const firstStepCount = stepResults[0]?.count || 0\n\n return stepResults.map((result, index) => ({\n name: result.stepName,\n value: result.count,\n percentage: firstStepCount > 0 ? (result.count / firstStepCount) * 100 : 0,\n conversionRate: result.conversionRate,\n stepIndex: index,\n }))\n}\n\n/**\n * Build the complete funnel execution result\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now builds results directly.\n */\nexport function buildFunnelResult(\n config: FunnelConfig,\n stepResults: FunnelStepResult[],\n status: FunnelExecutionResult['status'],\n error: Error | null = null,\n currentStepIndex: number | null = null\n): FunnelExecutionResult {\n const firstStepCount = stepResults[0]?.count || 0\n const lastStepCount = stepResults[stepResults.length - 1]?.count || 0\n const totalExecutionTime = stepResults.reduce((sum, r) => sum + r.executionTime, 0)\n\n return {\n config,\n steps: stepResults,\n summary: {\n totalEntries: firstStepCount,\n totalCompletions: lastStepCount,\n overallConversionRate: firstStepCount > 0 ? lastStepCount / firstStepCount : 0,\n totalExecutionTime,\n },\n chartData: buildFunnelChartData(stepResults),\n status,\n error,\n currentStepIndex,\n }\n}\n\n/**\n * Create an empty/initial funnel result\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution manages state differently.\n */\nexport function createEmptyFunnelResult(\n config: FunnelConfig\n): FunnelExecutionResult {\n return {\n config,\n steps: [],\n summary: {\n totalEntries: 0,\n totalCompletions: 0,\n overallConversionRate: 0,\n totalExecutionTime: 0,\n },\n chartData: [],\n status: 'idle',\n error: null,\n currentStepIndex: null,\n }\n}\n\n/**\n * Build a FunnelConfig from multi-query config state.\n * Used to convert AnalysisBuilder state to funnel configuration.\n *\n * @deprecated Use the dedicated funnel mode (analysisType === 'funnel') instead.\n * This function supports backward compatibility with legacy multi-query funnel mode\n * (mergeStrategy === 'funnel'). For new implementations, use the dedicated funnel\n * state in the store which provides better UX with step-based configuration.\n *\n * @param queries - Array of CubeQuery objects (one per step)\n * @param bindingKey - The binding key configuration\n * @param stepLabels - Optional labels for each step\n * @param stepTimeToConvert - Optional time window for each step\n * @returns FunnelConfig ready for execution\n */\nexport function buildFunnelConfigFromQueries(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey,\n stepLabels?: string[],\n stepTimeToConvert?: (string | null)[]\n): FunnelConfig {\n const steps: FunnelStep[] = queries.map((query, index) => ({\n id: `step-${index}`,\n name: stepLabels?.[index] || `Step ${index + 1}`,\n query,\n timeToConvert: stepTimeToConvert?.[index] || undefined,\n }))\n\n return {\n id: `funnel-${Date.now()}`,\n name: 'Funnel Analysis',\n bindingKey,\n steps,\n countUnique: true,\n }\n}\n\n/**\n * Check if funnel execution should stop early\n * (e.g., when no binding key values remain)\n */\nexport function shouldStopFunnelExecution(\n stepResult: FunnelStepResult\n): boolean {\n return stepResult.bindingKeyValues.length === 0 || stepResult.error !== null\n}\n\n/**\n * Metadata fields injected into funnel result data\n * (for compatibility with existing chart/table components)\n */\nexport interface FunnelMetadata {\n __stepIndex: number\n __stepName: string\n __stepId: string\n __conversionRate: number | null\n __cumulativeRate: number\n}\n\n/**\n * Check if data contains funnel metadata\n */\nexport function isFunnelData(data: unknown[]): boolean {\n return (\n data.length > 0 &&\n typeof data[0] === 'object' &&\n data[0] !== null &&\n '__stepIndex' in data[0]\n )\n}\n\n// =============================================================================\n// Server-Side Funnel Support\n// =============================================================================\n\n/**\n * Server-side funnel step definition (for FunnelQueryConfig)\n */\nexport interface ServerFunnelStep {\n name: string\n filter?: SimpleFilter | SimpleFilter[]\n timeToConvert?: string\n}\n\n/**\n * Server-side funnel query configuration\n */\nexport interface ServerFunnelQueryConfig {\n bindingKey: string | FunnelBindingKeyMapping[]\n timeDimension: string | Array<{ cube: string; dimension: string }>\n steps: ServerFunnelStep[]\n includeTimeMetrics?: boolean\n globalTimeWindow?: string\n}\n\n/**\n * Server-side funnel result row\n */\nexport interface ServerFunnelResultRow {\n step: string\n stepIndex: number\n count: number\n conversionRate: number | null\n cumulativeConversionRate: number\n avgSecondsToConvert?: number | null\n medianSecondsToConvert?: number | null\n p90SecondsToConvert?: number | null\n minSecondsToConvert?: number | null\n maxSecondsToConvert?: number | null\n}\n\n/**\n * Query shape for server-side funnel execution\n */\nexport interface ServerFunnelQuery {\n funnel: ServerFunnelQueryConfig\n}\n\n/**\n * Build a server-side funnel query from client state.\n *\n * Transforms the client-side FunnelConfig format into a SemanticQuery\n * with `funnel` property that the server can execute.\n *\n * @param queries - Array of CubeQuery objects (one per step)\n * @param bindingKey - The binding key configuration\n * @param stepLabels - Optional labels for each step\n * @param stepTimeToConvert - Optional time window for each step (ISO 8601 duration)\n * @param includeTimeMetrics - Whether to include time-to-convert metrics\n * @returns Query object with funnel configuration for server execution\n */\nexport function buildServerFunnelQuery(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey,\n stepLabels?: string[],\n stepTimeToConvert?: (string | null)[],\n includeTimeMetrics: boolean = true\n): ServerFunnelQuery {\n // 1. Unwrap binding key from client format (client wraps in { dimension: ... })\n const serverBindingKey = bindingKey.dimension\n\n // 2. Extract time dimension from queries\n const timeDimension = extractTimeDimensionFromQueries(queries, bindingKey)\n\n // 3. Convert each CubeQuery to a server FunnelStep\n const steps: ServerFunnelStep[] = queries.map((query, index) => {\n const step: ServerFunnelStep = {\n name: stepLabels?.[index] || `Step ${index + 1}`,\n }\n\n // Extract filters from query\n const filter = extractFiltersFromQuery(query)\n if (filter) {\n step.filter = filter\n }\n\n // Add time-to-convert constraint if specified\n const timeConstraint = stepTimeToConvert?.[index]\n if (timeConstraint) {\n step.timeToConvert = timeConstraint\n }\n\n return step\n })\n\n return {\n funnel: {\n bindingKey: serverBindingKey,\n timeDimension,\n steps,\n includeTimeMetrics,\n },\n }\n}\n\n/**\n * Extract time dimension from queries.\n *\n * For single-cube funnels, returns the first time dimension found.\n * For cross-cube funnels (with binding key mappings), builds a mapping array.\n *\n * @param queries - Array of CubeQuery objects\n * @param bindingKey - The binding key configuration (to detect cross-cube)\n * @returns Time dimension string or mapping array\n */\nfunction extractTimeDimensionFromQueries(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey\n): string | Array<{ cube: string; dimension: string }> {\n // Check if this is a cross-cube funnel\n if (Array.isArray(bindingKey.dimension)) {\n return extractCrossCubeTimeDimensions(queries, bindingKey.dimension as FunnelBindingKeyMapping[])\n }\n return extractSingleCubeTimeDimension(queries)\n}\n\n/**\n * Single-cube: return the first explicit time dimension, falling back to the\n * common `<cube>.createdAt` convention.\n */\nfunction extractSingleCubeTimeDimension(queries: CubeQuery[]): string {\n for (const query of queries) {\n if (query.timeDimensions?.length) {\n return query.timeDimensions[0].dimension\n }\n }\n // Fallback: try to infer from measures/dimensions\n const cubeName = getCubeNameFromQuery(queries[0])\n if (cubeName) {\n return `${cubeName}.createdAt` // Common convention\n }\n throw new Error('Funnel requires at least one time dimension in step queries')\n}\n\n/**\n * Cross-cube: build a time-dimension mapping per cube, falling back to the\n * common `<cube>.createdAt` convention when none is present.\n */\nfunction extractCrossCubeTimeDimensions(\n queries: CubeQuery[],\n bindingMappings: FunnelBindingKeyMapping[]\n): Array<{ cube: string; dimension: string }> {\n return bindingMappings.map(mapping => {\n const cubeQuery = queries.find(q => getCubeNameFromQuery(q) === mapping.cube)\n const dimension = cubeQuery?.timeDimensions?.length\n ? cubeQuery.timeDimensions[0].dimension\n : `${mapping.cube}.createdAt` // Fallback to common convention\n return { cube: mapping.cube, dimension }\n })\n}\n\n/**\n * Extract filters from a CubeQuery for server funnel step.\n *\n * @param query - The CubeQuery\n * @returns Filter or array of filters, or undefined if no filters\n */\nfunction extractFiltersFromQuery(query: CubeQuery): SimpleFilter | SimpleFilter[] | undefined {\n if (!query.filters?.length) {\n return undefined\n }\n\n // Filter out any binding key filters (server handles those)\n const filters = query.filters.filter(f => {\n // Keep only SimpleFilter with member (not grouped filters for now)\n if ('member' in f) {\n return true\n }\n return false\n }) as SimpleFilter[]\n\n if (filters.length === 0) {\n return undefined\n }\n\n if (filters.length === 1) {\n return filters[0]\n }\n\n return filters\n}\n\n/**\n * Transform server funnel result rows to client FunnelChartData format.\n *\n * Maps the server's FunnelResultRow[] to the client's FunnelChartData[]\n * format expected by FunnelChart component.\n *\n * @param serverResult - Raw data from server (FunnelResultRow[])\n * @param stepNames - Optional step names to override server names\n * @returns FunnelChartData[] ready for FunnelChart component\n */\nexport function transformServerFunnelResult(\n serverResult: unknown[],\n stepNames?: string[]\n): FunnelChartData[] {\n if (!serverResult?.length) {\n return []\n }\n\n const rows = serverResult as ServerFunnelResultRow[]\n\n return rows.map((row, index) => ({\n // Map server fields to client format\n name: stepNames?.[index] || row.step,\n value: row.count,\n // Convert cumulative rate to percentage\n percentage: row.cumulativeConversionRate * 100,\n // Convert step-to-step rate to percentage (null for first step)\n conversionRate: row.conversionRate !== null ? row.conversionRate * 100 : null,\n stepIndex: row.stepIndex,\n // Include time metrics for optional display\n avgSecondsToConvert: row.avgSecondsToConvert,\n medianSecondsToConvert: row.medianSecondsToConvert,\n p90SecondsToConvert: row.p90SecondsToConvert,\n }))\n}\n\n/**\n * Format a duration in seconds to a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @returns Formatted string (e.g., \"45s\", \"2.5m\", \"1.3h\", \"3.2d\")\n */\nexport function formatDuration(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined) {\n return '-'\n }\n\n if (seconds < 60) {\n return `${Math.round(seconds)}s`\n }\n\n if (seconds < 3600) {\n const minutes = seconds / 60\n return minutes < 10 ? `${minutes.toFixed(1)}m` : `${Math.round(minutes)}m`\n }\n\n if (seconds < 86400) {\n const hours = seconds / 3600\n return hours < 10 ? `${hours.toFixed(1)}h` : `${Math.round(hours)}h`\n }\n\n const days = seconds / 86400\n return days < 10 ? `${days.toFixed(1)}d` : `${Math.round(days)}d`\n}\n","/**\n * Co-located helpers for FunnelChart.\n *\n * Pure data-shaping + display-option resolution extracted from the component.\n * No behaviour change — mirrors the original inline logic exactly.\n */\nimport type { ChartDisplayConfig } from '../../types.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { formatDuration } from '../../utils/funnelExecution.js'\n\n/** Check if data is already in funnel data format. */\nexport function isFunnelData(data: unknown[]): data is FunnelChartData[] {\n if (!data || data.length === 0) return false\n const first = data[0]\n return (\n typeof first === 'object' &&\n first !== null &&\n 'name' in first &&\n 'value' in first &&\n 'percentage' in first\n )\n}\n\n/**\n * Render time metrics based on config options - returns array of lines for\n * vertical stacking.\n */\nexport function getTimeMetricsLines(\n step: FunnelChartData,\n showAvg: boolean,\n showMedian: boolean,\n showP90: boolean\n): string[] {\n const lines: string[] = []\n if (showAvg && step.avgSecondsToConvert != null) {\n lines.push(`Avg: ${formatDuration(step.avgSecondsToConvert)}`)\n }\n if (showMedian && step.medianSecondsToConvert != null) {\n lines.push(`Med: ${formatDuration(step.medianSecondsToConvert)}`)\n }\n if (showP90 && step.p90SecondsToConvert != null) {\n lines.push(`P90: ${formatDuration(step.p90SecondsToConvert)}`)\n }\n return lines\n}\n\n/** Coerce arbitrary query rows into FunnelChartData by probing field names. */\nexport function toFunnelData(data: unknown[]): FunnelChartData[] {\n if (!data || data.length === 0) return []\n if (isFunnelData(data)) return data\n\n return data.map((row, index) => {\n const record = row as Record<string, unknown>\n\n const nameField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('step') || k.toLowerCase().includes('name') || k === '__stepName'\n )\n const name = nameField ? String(record[nameField]) : `Step ${index + 1}`\n\n const valueField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('count') || k.toLowerCase().includes('value') || k === '__count'\n )\n const value = valueField ? Number(record[valueField]) || 0 : 0\n\n const percentField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('percent') || k === '__percentage'\n )\n const percentage = percentField ? Number(record[percentField]) || 0 : 0\n\n const convRateField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('conversion') || k === '__conversionRate'\n )\n const conversionRate = convRateField ? Number(record[convRateField]) || null : null\n\n return { name, value, percentage, conversionRate, stepIndex: index }\n })\n}\n\nexport interface FunnelDisplayOptions {\n customStepLabels?: string[]\n isVertical: boolean\n funnelStyle: NonNullable<ChartDisplayConfig['funnelStyle']>\n showConversion: boolean\n showAvgTime: boolean\n showMedianTime: boolean\n showP90Time: boolean\n hideSummaryFooter: boolean\n}\n\n/** Resolve every funnel display option (with backward-compat for time metrics). */\nexport function resolveFunnelDisplayOptions(\n displayConfig: ChartDisplayConfig | undefined\n): FunnelDisplayOptions {\n return {\n customStepLabels: displayConfig?.funnelStepLabels,\n isVertical: (displayConfig?.funnelOrientation || 'horizontal') === 'vertical',\n funnelStyle: displayConfig?.funnelStyle ?? 'bars',\n showConversion: displayConfig?.showFunnelConversion ?? true,\n // Time metrics - individual toggles with backward compat for showFunnelTimeMetrics\n showAvgTime: displayConfig?.showFunnelAvgTime ?? (displayConfig?.showFunnelTimeMetrics ?? false),\n showMedianTime: displayConfig?.showFunnelMedianTime ?? false,\n showP90Time: displayConfig?.showFunnelP90Time ?? false,\n hideSummaryFooter: displayConfig?.hideSummaryFooter ?? false\n }\n}\n\n/** Color for a funnel step (cyclic over the palette or the default funnel gradient). */\nexport function getStepColor(index: number, colorPalette: string[]): string {\n return colorPalette[index % colorPalette.length]\n}\n","import { FunnelChart as RechartsFunnelChart, Funnel, LabelList, Tooltip, Cell, ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { getStepColor, getTimeMetricsLines, type FunnelDisplayOptions } from './FunnelChart.helpers.js'\n\ninterface FunnelViewProps {\n funnelData: FunnelChartData[]\n firstStepValue: number\n paletteColors: string[]\n options: FunnelDisplayOptions\n height: string | number\n}\n\n/** Shared summary footer (steps count, overall conversion, completed ratio). */\nfunction FunnelSummaryFooter({\n funnelData,\n firstStepValue\n}: {\n funnelData: FunnelChartData[]\n firstStepValue: number\n}) {\n const { t } = useTranslation()\n const lastValue = funnelData[funnelData.length - 1]?.value || 0\n return (\n <div className=\"dc:flex-shrink-0 dc:px-4 dc:py-2 dc:border-t border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:text-sm\">\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{funnelData.length}</span> steps\n </div>\n <div className=\"text-dc-text\">\n <span className=\"text-dc-text-muted\">{t('chart.runtime.funnel.overall')}</span>{' '}\n <span className=\"dc:font-medium\">\n {firstStepValue > 0 ? `${(lastValue / firstStepValue * 100).toFixed(1)}%` : '0%'}\n </span>\n </div>\n <div className=\"text-dc-text-muted\">\n {lastValue.toLocaleString() || 0} / {firstStepValue.toLocaleString()} completed\n </div>\n </div>\n </div>\n )\n}\n\n/** Per-step conversion + time-metrics block (shared by vertical/horizontal views). */\nfunction StepMetrics({\n stepConversionRate,\n arrow,\n showConversion,\n timeMetricsLines\n}: {\n stepConversionRate: number | null\n arrow: string\n showConversion: boolean\n timeMetricsLines: string[]\n}) {\n if (stepConversionRate === null) {\n return <div className=\"dc:text-xs text-dc-text-muted\">—</div>\n }\n return (\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {showConversion && <span>{arrow} {stepConversionRate.toFixed(1)}%</span>}\n {timeMetricsLines.length > 0 && (\n <div className=\"text-dc-text-muted dc:mt-0.5 dc:space-y-0.5\">\n {timeMetricsLines.map((line, i) => (\n <div key={i}>⏱ {line}</div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n/** Recharts trapezoid funnel style. */\nexport function FunnelShapeView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n // Recharts FunnelChart layout: 'horizontal' = funnel flows left-to-right,\n // 'vertical' = top-to-bottom (default). Our 'vertical' orientation maps to\n // a left-to-right Recharts funnel.\n const rechartsLayout: 'horizontal' | 'vertical' = options.isVertical ? 'horizontal' : 'vertical'\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsFunnelChart layout={rechartsLayout} accessibilityLayer={false}>\n <Tooltip\n formatter={(value) => typeof value === 'number' ? value.toLocaleString() : String(value)}\n contentStyle={{\n backgroundColor: 'var(--dc-surface)',\n border: '1px solid var(--dc-border)',\n borderRadius: '4px',\n }}\n />\n <Funnel dataKey=\"value\" nameKey=\"name\" data={funnelData} isAnimationActive>\n {funnelData.map((_, index) => (\n <Cell key={`cell-${index}`} fill={getStepColor(index, paletteColors)} />\n ))}\n <LabelList position=\"right\" dataKey=\"name\" fill=\"var(--dc-text)\" style={{ fontSize: '12px' }} />\n <LabelList\n position=\"center\"\n dataKey=\"percentage\"\n formatter={(v) => typeof v === 'number' ? `${v.toFixed(1)}%` : String(v)}\n fill=\"#fff\"\n style={{ fontSize: '11px', fontWeight: 500 }}\n />\n </Funnel>\n </RechartsFunnelChart>\n </ResponsiveContainer>\n </div>\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n\n/** Vertical bars (steps laid out horizontally, bars grow bottom-to-top). */\nexport function FunnelVerticalView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1 dc:flex dc:items-end dc:justify-center dc:gap-4 dc:px-4 dc:py-3 dc:overflow-hidden\">\n {funnelData.map((step, index) => {\n const heightPercent = firstStepValue > 0 ? (step.value / firstStepValue) * 100 : 0\n const prevStep = index > 0 ? funnelData[index - 1] : null\n const stepConversionRate = prevStep && prevStep.value > 0 ? (step.value / prevStep.value) * 100 : null\n const displayName = options.customStepLabels?.[index] || step.name\n const timeMetricsLines = getTimeMetricsLines(step, options.showAvgTime, options.showMedianTime, options.showP90Time)\n const metricsCount = timeMetricsLines.length\n\n return (\n <div key={step.name} className=\"dc:flex dc:flex-col dc:items-center dc:gap-2 dc:flex-1 dc:max-w-32 dc:h-full\">\n <div className={`${metricsCount > 0 ? (metricsCount > 1 ? 'dc:min-h-16' : 'dc:min-h-10') : 'dc:h-5'} dc:flex-shrink-0 dc:text-center`}>\n <StepMetrics\n stepConversionRate={stepConversionRate}\n arrow=\"→\"\n showConversion={options.showConversion}\n timeMetricsLines={timeMetricsLines}\n />\n </div>\n\n <div className=\"dc:flex-1 dc:w-full dc:relative dc:min-h-12\">\n <div className=\"dc:absolute dc:inset-0 bg-dc-surface-secondary dc:rounded-sm\" />\n <div\n className=\"dc:absolute dc:bottom-0 dc:left-0 dc:right-0 dc:rounded-sm dc:transition-all dc:duration-300\"\n style={{ height: `${Math.max(heightPercent, 5)}%`, backgroundColor: getStepColor(index, paletteColors) }}\n />\n <div\n className=\"dc:absolute dc:bottom-0 dc:left-0 dc:right-0 dc:flex dc:items-end dc:justify-center dc:pb-1 dc:pointer-events-none\"\n style={{ height: `${Math.max(heightPercent, 20)}%` }}\n >\n <span className=\"dc:text-xs dc:font-medium text-white dc:drop-shadow-sm\">\n {step.percentage?.toFixed(1) ?? heightPercent.toFixed(1)}%\n </span>\n </div>\n </div>\n\n <div className=\"dc:flex-shrink-0 dc:text-center\">\n <div className=\"dc:text-sm dc:font-medium text-dc-text dc:truncate\" title={displayName}>\n {displayName}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted\">\n {step.value.toLocaleString()}\n </div>\n </div>\n </div>\n )\n })}\n </div>\n\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n\n/** Horizontal bars (default - steps stacked vertically, bars grow left-to-right). */\nexport function FunnelHorizontalView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1 dc:flex dc:flex-col dc:justify-center dc:gap-2 dc:px-4 dc:py-3 dc:overflow-hidden\">\n {funnelData.map((step, index) => {\n const widthPercent = firstStepValue > 0 ? (step.value / firstStepValue) * 100 : 0\n const prevStep = index > 0 ? funnelData[index - 1] : null\n const stepConversionRate = prevStep && prevStep.value > 0 ? (step.value / prevStep.value) * 100 : null\n const displayName = options.customStepLabels?.[index] || step.name\n const timeMetricsLines = getTimeMetricsLines(step, options.showAvgTime, options.showMedianTime, options.showP90Time)\n const metricsCount = timeMetricsLines.length\n\n return (\n <div key={step.name} className=\"dc:flex dc:items-center dc:gap-3\">\n <div className=\"dc:w-24 dc:flex-shrink-0 dc:text-right\">\n <div className=\"dc:text-sm dc:font-medium text-dc-text dc:truncate\" title={displayName}>\n {displayName}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted\">\n {step.value.toLocaleString()}\n </div>\n </div>\n\n <div className=\"dc:flex-1 dc:relative\">\n <div className=\"dc:w-full dc:h-8 bg-dc-surface-secondary dc:rounded-sm\" />\n <div\n className=\"dc:absolute dc:top-0 dc:left-0 dc:h-8 dc:rounded-sm dc:transition-all dc:duration-300\"\n style={{ width: `${Math.max(widthPercent, 2)}%`, backgroundColor: getStepColor(index, paletteColors) }}\n />\n <div\n className=\"dc:absolute dc:top-0 dc:left-0 dc:h-8 dc:flex dc:items-center dc:px-2 dc:pointer-events-none\"\n style={{ width: `${Math.max(widthPercent, 20)}%` }}\n >\n <span className=\"dc:text-xs dc:font-medium text-white dc:drop-shadow-sm\">\n {step.percentage?.toFixed(1) ?? widthPercent.toFixed(1)}%\n </span>\n </div>\n </div>\n\n <div className={`${metricsCount > 0 ? (metricsCount > 1 ? 'dc:w-36' : 'dc:w-28') : 'dc:w-16'} dc:flex-shrink-0 dc:text-left`}>\n <StepMetrics\n stepConversionRate={stepConversionRate}\n arrow=\"↓\"\n showConversion={options.showConversion}\n timeMetricsLines={timeMetricsLines}\n />\n </div>\n </div>\n )\n })}\n </div>\n\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n","/**\n * FunnelChart Component\n *\n * Visualizes funnel data showing conversion rates between steps.\n * Uses horizontal bars with percentage widths to represent the funnel shape.\n * Works with data from useFunnelQuery hook which provides FunnelChartData.\n *\n * When displayConfig.showFunnelTimeMetrics is enabled, displays time-to-convert\n * metrics from server-side funnel execution (avg, median, P90 seconds).\n */\n\nimport React, { useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { CHART_COLORS } from '../../utils/chartConstants.js'\nimport type { ChartProps } from '../../types.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { toFunnelData, resolveFunnelDisplayOptions } from './FunnelChart.helpers.js'\nimport { FunnelShapeView, FunnelVerticalView, FunnelHorizontalView } from './FunnelViews.js'\n\n/**\n * FunnelChart Component\n *\n * Renders a funnel visualization from FunnelChartData array.\n * Shows each step as a horizontal bar with width proportional to count.\n * Displays conversion rates between steps.\n */\nconst FunnelChart = React.memo(function FunnelChart({\n data,\n height = '100%',\n colorPalette,\n displayConfig,\n}: ChartProps) {\n const { t } = useTranslation()\n const options = resolveFunnelDisplayOptions(displayConfig)\n\n // Transform data if needed\n const funnelData = useMemo<FunnelChartData[]>(() => toFunnelData(data), [data])\n\n // Calculate first step value for percentage calculations\n const firstStepValue = funnelData[0]?.value || 0\n\n // Handle no data\n if (!data || data.length === 0 || funnelData.length === 0) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.funnel.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.funnel')}\n </div>\n </div>\n </div>\n )\n }\n\n const paletteColors = colorPalette?.colors || CHART_COLORS\n const viewProps = { funnelData, firstStepValue, paletteColors, options, height }\n\n if (options.funnelStyle === 'funnel') {\n return <FunnelShapeView {...viewProps} />\n }\n\n if (options.isVertical) {\n return <FunnelVerticalView {...viewProps} />\n }\n\n return <FunnelHorizontalView {...viewProps} />\n})\n\nexport default FunnelChart\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-funnel-B_CWC3cL.js","names":[],"sources":["../../../src/client/utils/funnelExecution.ts","../../../src/client/components/charts/FunnelChart.helpers.ts","../../../src/client/components/charts/FunnelViews.tsx","../../../src/client/components/charts/FunnelChart.tsx"],"sourcesContent":["/**\n * Funnel Query Execution Utilities\n *\n * Handles sequential execution of funnel queries where each step\n * filters based on binding key values from the previous step.\n */\n\nimport type { CubeQuery, SimpleFilter } from '../types.js'\n\n/**\n * Default maximum number of binding key values to pass between funnel steps.\n * Limits the size of the IN clause to prevent performance issues.\n */\nexport const DEFAULT_BINDING_KEY_LIMIT = 500\nimport type {\n FunnelBindingKey,\n FunnelBindingKeyMapping,\n FunnelConfig,\n FunnelStep,\n FunnelStepResult,\n FunnelExecutionResult,\n FunnelChartData,\n} from '../types/funnel.js'\n\n/**\n * Extract the binding key field name for a specific query/cube.\n *\n * For simple binding keys (string), returns the dimension directly.\n * For cross-cube mappings, finds the mapping for the cube used in the query.\n *\n * @param bindingKey - The funnel binding key configuration\n * @param query - The cube query (used to determine which cube is being queried)\n * @returns The binding key field name (e.g., \"Users.userId\")\n */\nexport function getBindingKeyField(\n bindingKey: FunnelBindingKey,\n query: CubeQuery\n): string {\n // Simple case: single dimension name\n if (typeof bindingKey.dimension === 'string') {\n return bindingKey.dimension\n }\n\n // Cross-cube case: find the mapping for this query's cube\n const mappings = bindingKey.dimension as FunnelBindingKeyMapping[]\n\n // Extract cube name from query fields\n const cubeName = getCubeNameFromQuery(query)\n if (!cubeName) {\n // If we can't determine the cube, use the first mapping\n return mappings[0]?.dimension || ''\n }\n\n // Find matching mapping\n const mapping = mappings.find(m => m.cube === cubeName)\n if (mapping) {\n return mapping.dimension\n }\n\n // Fallback to first mapping if no match found\n return mappings[0]?.dimension || ''\n}\n\n/**\n * Extract the cube name from a query by looking at measures/dimensions\n */\nexport function getCubeNameFromQuery(query: CubeQuery): string | null {\n // Check measures first\n if (query.measures && query.measures.length > 0) {\n const parts = query.measures[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check dimensions\n if (query.dimensions && query.dimensions.length > 0) {\n const parts = query.dimensions[0].split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n // Then check time dimensions\n if (query.timeDimensions && query.timeDimensions.length > 0) {\n const parts = query.timeDimensions[0].dimension.split('.')\n if (parts.length >= 2) {\n return parts[0]\n }\n }\n\n return null\n}\n\n/**\n * Result from extracting binding key values\n */\nexport interface ExtractedBindingKeyValues {\n /** Binding key values (limited to max if specified) */\n values: (string | number)[]\n /** Total count of unique values before limiting */\n totalCount: number\n /** Whether values were truncated due to limit */\n wasTruncated: boolean\n}\n\n/**\n * Extract unique values for the binding key from query result data\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution is now the default approach.\n *\n * @param data - Raw data from query result\n * @param bindingKeyField - The field name to extract values from\n * @param limit - Maximum number of values to return (default: DEFAULT_BINDING_KEY_LIMIT)\n * @returns Object with values array, total count, and truncation flag\n */\nexport function extractBindingKeyValues(\n data: unknown[],\n bindingKeyField: string,\n limit: number = DEFAULT_BINDING_KEY_LIMIT\n): ExtractedBindingKeyValues {\n const values = new Set<string | number>()\n\n for (const row of data) {\n if (typeof row === 'object' && row !== null) {\n const value = (row as Record<string, unknown>)[bindingKeyField]\n if (value !== null && value !== undefined) {\n // Convert to string or number\n if (typeof value === 'number') {\n values.add(value)\n } else {\n values.add(String(value))\n }\n }\n }\n }\n\n const allValues = Array.from(values)\n const totalCount = allValues.length\n\n // Sort values for consistent ordering (enables query cache hits)\n // Numbers sort numerically, strings sort alphabetically\n allValues.sort((a, b) => {\n if (typeof a === 'number' && typeof b === 'number') {\n return a - b\n }\n return String(a).localeCompare(String(b))\n })\n\n const limitedValues = limit > 0 ? allValues.slice(0, limit) : allValues\n\n return {\n values: limitedValues,\n totalCount,\n wasTruncated: limitedValues.length < totalCount,\n }\n}\n\n/**\n * Build a step query with binding key filter applied.\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution is now the default approach.\n *\n * For the first step (no previous values), returns the original query\n * with the binding key dimension ensured.\n *\n * For subsequent steps, adds an IN filter for the previous step's\n * binding key values.\n *\n * @param step - The funnel step configuration\n * @param bindingKey - The funnel binding key configuration\n * @param previousBindingKeyValues - Binding key values from previous step (null for first step)\n * @returns Modified CubeQuery with binding key filter\n */\nexport function buildStepQuery(\n step: FunnelStep,\n bindingKey: FunnelBindingKey,\n previousBindingKeyValues: (string | number)[] | null\n): CubeQuery {\n const query: CubeQuery = { ...step.query }\n\n // Get binding key field for this query\n const bindingKeyField = getBindingKeyField(bindingKey, query)\n\n // Ensure binding key dimension is in the query (needed to extract values for next step)\n if (!query.dimensions?.includes(bindingKeyField)) {\n query.dimensions = [...(query.dimensions || []), bindingKeyField]\n }\n\n // Add IN filter for previous step's binding key values (except for first step)\n if (previousBindingKeyValues && previousBindingKeyValues.length > 0) {\n const inFilter: SimpleFilter = {\n member: bindingKeyField,\n operator: 'in',\n values: previousBindingKeyValues,\n }\n query.filters = [...(query.filters || []), inFilter]\n }\n\n return query\n}\n\n/**\n * Calculate conversion metrics for a step\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now calculates metrics directly.\n */\nexport function calculateStepMetrics(\n currentCount: number,\n previousCount: number | null,\n firstStepCount: number\n): {\n conversionRate: number | null\n cumulativeConversionRate: number\n} {\n const conversionRate =\n previousCount !== null && previousCount > 0\n ? currentCount / previousCount\n : null\n\n const cumulativeConversionRate =\n firstStepCount > 0 ? currentCount / firstStepCount : 1.0\n\n return { conversionRate, cumulativeConversionRate }\n}\n\n/**\n * Build a funnel step result from query execution\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now returns results directly.\n */\nexport function buildStepResult(\n step: FunnelStep,\n stepIndex: number,\n data: unknown[],\n bindingKeyField: string,\n countUnique: boolean,\n previousCount: number | null,\n firstStepCount: number,\n executionTime: number,\n error: Error | null = null,\n bindingKeyLimit: number = DEFAULT_BINDING_KEY_LIMIT\n): FunnelStepResult {\n // Extract binding key values (with limit applied)\n const extracted = error\n ? { values: [], totalCount: 0, wasTruncated: false }\n : extractBindingKeyValues(data, bindingKeyField, bindingKeyLimit)\n\n // Calculate count based on total unique values (before truncation)\n const count = error\n ? 0\n : countUnique\n ? extracted.totalCount\n : data.length\n\n // Calculate conversion metrics\n const { conversionRate, cumulativeConversionRate } = calculateStepMetrics(\n count,\n previousCount,\n firstStepCount || count // Use current count as first step count if this is step 0\n )\n\n return {\n stepIndex,\n stepName: step.name,\n stepId: step.id,\n data,\n bindingKeyValues: extracted.values,\n bindingKeyTotalCount: extracted.totalCount,\n count,\n conversionRate,\n cumulativeConversionRate,\n executionTime,\n error,\n }\n}\n\n/**\n * Convert step results to chart-ready data format\n *\n * @deprecated Use transformServerFunnelResult() instead.\n * Server-side funnel execution returns data in a compatible format.\n */\nexport function buildFunnelChartData(\n stepResults: FunnelStepResult[]\n): FunnelChartData[] {\n if (stepResults.length === 0) return []\n\n const firstStepCount = stepResults[0]?.count || 0\n\n return stepResults.map((result, index) => ({\n name: result.stepName,\n value: result.count,\n percentage: firstStepCount > 0 ? (result.count / firstStepCount) * 100 : 0,\n conversionRate: result.conversionRate,\n stepIndex: index,\n }))\n}\n\n/**\n * Build the complete funnel execution result\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution now builds results directly.\n */\nexport function buildFunnelResult(\n config: FunnelConfig,\n stepResults: FunnelStepResult[],\n status: FunnelExecutionResult['status'],\n error: Error | null = null,\n currentStepIndex: number | null = null\n): FunnelExecutionResult {\n const firstStepCount = stepResults[0]?.count || 0\n const lastStepCount = stepResults[stepResults.length - 1]?.count || 0\n const totalExecutionTime = stepResults.reduce((sum, r) => sum + r.executionTime, 0)\n\n return {\n config,\n steps: stepResults,\n summary: {\n totalEntries: firstStepCount,\n totalCompletions: lastStepCount,\n overallConversionRate: firstStepCount > 0 ? lastStepCount / firstStepCount : 0,\n totalExecutionTime,\n },\n chartData: buildFunnelChartData(stepResults),\n status,\n error,\n currentStepIndex,\n }\n}\n\n/**\n * Create an empty/initial funnel result\n *\n * @deprecated This function was used for client-side funnel execution.\n * Server-side funnel execution manages state differently.\n */\nexport function createEmptyFunnelResult(\n config: FunnelConfig\n): FunnelExecutionResult {\n return {\n config,\n steps: [],\n summary: {\n totalEntries: 0,\n totalCompletions: 0,\n overallConversionRate: 0,\n totalExecutionTime: 0,\n },\n chartData: [],\n status: 'idle',\n error: null,\n currentStepIndex: null,\n }\n}\n\n/**\n * Build a FunnelConfig from multi-query config state.\n * Used to convert AnalysisBuilder state to funnel configuration.\n *\n * @deprecated Use the dedicated funnel mode (analysisType === 'funnel') instead.\n * This function supports backward compatibility with legacy multi-query funnel mode\n * (mergeStrategy === 'funnel'). For new implementations, use the dedicated funnel\n * state in the store which provides better UX with step-based configuration.\n *\n * @param queries - Array of CubeQuery objects (one per step)\n * @param bindingKey - The binding key configuration\n * @param stepLabels - Optional labels for each step\n * @param stepTimeToConvert - Optional time window for each step\n * @returns FunnelConfig ready for execution\n */\nexport function buildFunnelConfigFromQueries(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey,\n stepLabels?: string[],\n stepTimeToConvert?: (string | null)[]\n): FunnelConfig {\n const steps: FunnelStep[] = queries.map((query, index) => ({\n id: `step-${index}`,\n name: stepLabels?.[index] || `Step ${index + 1}`,\n query,\n timeToConvert: stepTimeToConvert?.[index] || undefined,\n }))\n\n return {\n id: `funnel-${Date.now()}`,\n name: 'Funnel Analysis',\n bindingKey,\n steps,\n countUnique: true,\n }\n}\n\n/**\n * Check if funnel execution should stop early\n * (e.g., when no binding key values remain)\n */\nexport function shouldStopFunnelExecution(\n stepResult: FunnelStepResult\n): boolean {\n return stepResult.bindingKeyValues.length === 0 || stepResult.error !== null\n}\n\n/**\n * Metadata fields injected into funnel result data\n * (for compatibility with existing chart/table components)\n */\nexport interface FunnelMetadata {\n __stepIndex: number\n __stepName: string\n __stepId: string\n __conversionRate: number | null\n __cumulativeRate: number\n}\n\n/**\n * Check if data contains funnel metadata\n */\nexport function isFunnelData(data: unknown[]): boolean {\n return (\n data.length > 0 &&\n typeof data[0] === 'object' &&\n data[0] !== null &&\n '__stepIndex' in data[0]\n )\n}\n\n// =============================================================================\n// Server-Side Funnel Support\n// =============================================================================\n\n/**\n * Server-side funnel step definition (for FunnelQueryConfig)\n */\nexport interface ServerFunnelStep {\n name: string\n filter?: SimpleFilter | SimpleFilter[]\n timeToConvert?: string\n}\n\n/**\n * Server-side funnel query configuration\n */\nexport interface ServerFunnelQueryConfig {\n bindingKey: string | FunnelBindingKeyMapping[]\n timeDimension: string | Array<{ cube: string; dimension: string }>\n steps: ServerFunnelStep[]\n includeTimeMetrics?: boolean\n globalTimeWindow?: string\n}\n\n/**\n * Server-side funnel result row\n */\nexport interface ServerFunnelResultRow {\n step: string\n stepIndex: number\n count: number\n conversionRate: number | null\n cumulativeConversionRate: number\n avgSecondsToConvert?: number | null\n medianSecondsToConvert?: number | null\n p90SecondsToConvert?: number | null\n minSecondsToConvert?: number | null\n maxSecondsToConvert?: number | null\n}\n\n/**\n * Query shape for server-side funnel execution\n */\nexport interface ServerFunnelQuery {\n funnel: ServerFunnelQueryConfig\n}\n\n/**\n * Build a server-side funnel query from client state.\n *\n * Transforms the client-side FunnelConfig format into a SemanticQuery\n * with `funnel` property that the server can execute.\n *\n * @param queries - Array of CubeQuery objects (one per step)\n * @param bindingKey - The binding key configuration\n * @param stepLabels - Optional labels for each step\n * @param stepTimeToConvert - Optional time window for each step (ISO 8601 duration)\n * @param includeTimeMetrics - Whether to include time-to-convert metrics\n * @returns Query object with funnel configuration for server execution\n */\nexport function buildServerFunnelQuery(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey,\n stepLabels?: string[],\n stepTimeToConvert?: (string | null)[],\n includeTimeMetrics: boolean = true\n): ServerFunnelQuery {\n // 1. Unwrap binding key from client format (client wraps in { dimension: ... })\n const serverBindingKey = bindingKey.dimension\n\n // 2. Extract time dimension from queries\n const timeDimension = extractTimeDimensionFromQueries(queries, bindingKey)\n\n // 3. Convert each CubeQuery to a server FunnelStep\n const steps: ServerFunnelStep[] = queries.map((query, index) => {\n const step: ServerFunnelStep = {\n name: stepLabels?.[index] || `Step ${index + 1}`,\n }\n\n // Extract filters from query\n const filter = extractFiltersFromQuery(query)\n if (filter) {\n step.filter = filter\n }\n\n // Add time-to-convert constraint if specified\n const timeConstraint = stepTimeToConvert?.[index]\n if (timeConstraint) {\n step.timeToConvert = timeConstraint\n }\n\n return step\n })\n\n return {\n funnel: {\n bindingKey: serverBindingKey,\n timeDimension,\n steps,\n includeTimeMetrics,\n },\n }\n}\n\n/**\n * Extract time dimension from queries.\n *\n * For single-cube funnels, returns the first time dimension found.\n * For cross-cube funnels (with binding key mappings), builds a mapping array.\n *\n * @param queries - Array of CubeQuery objects\n * @param bindingKey - The binding key configuration (to detect cross-cube)\n * @returns Time dimension string or mapping array\n */\nfunction extractTimeDimensionFromQueries(\n queries: CubeQuery[],\n bindingKey: FunnelBindingKey\n): string | Array<{ cube: string; dimension: string }> {\n // Check if this is a cross-cube funnel\n if (Array.isArray(bindingKey.dimension)) {\n return extractCrossCubeTimeDimensions(queries, bindingKey.dimension as FunnelBindingKeyMapping[])\n }\n return extractSingleCubeTimeDimension(queries)\n}\n\n/**\n * Single-cube: return the first explicit time dimension, falling back to the\n * common `<cube>.createdAt` convention.\n */\nfunction extractSingleCubeTimeDimension(queries: CubeQuery[]): string {\n for (const query of queries) {\n if (query.timeDimensions?.length) {\n return query.timeDimensions[0].dimension\n }\n }\n // Fallback: try to infer from measures/dimensions\n const cubeName = getCubeNameFromQuery(queries[0])\n if (cubeName) {\n return `${cubeName}.createdAt` // Common convention\n }\n throw new Error('Funnel requires at least one time dimension in step queries')\n}\n\n/**\n * Cross-cube: build a time-dimension mapping per cube, falling back to the\n * common `<cube>.createdAt` convention when none is present.\n */\nfunction extractCrossCubeTimeDimensions(\n queries: CubeQuery[],\n bindingMappings: FunnelBindingKeyMapping[]\n): Array<{ cube: string; dimension: string }> {\n return bindingMappings.map(mapping => {\n const cubeQuery = queries.find(q => getCubeNameFromQuery(q) === mapping.cube)\n const dimension = cubeQuery?.timeDimensions?.length\n ? cubeQuery.timeDimensions[0].dimension\n : `${mapping.cube}.createdAt` // Fallback to common convention\n return { cube: mapping.cube, dimension }\n })\n}\n\n/**\n * Extract filters from a CubeQuery for server funnel step.\n *\n * @param query - The CubeQuery\n * @returns Filter or array of filters, or undefined if no filters\n */\nfunction extractFiltersFromQuery(query: CubeQuery): SimpleFilter | SimpleFilter[] | undefined {\n if (!query.filters?.length) {\n return undefined\n }\n\n // Filter out any binding key filters (server handles those)\n const filters = query.filters.filter(f => {\n // Keep only SimpleFilter with member (not grouped filters for now)\n if ('member' in f) {\n return true\n }\n return false\n }) as SimpleFilter[]\n\n if (filters.length === 0) {\n return undefined\n }\n\n if (filters.length === 1) {\n return filters[0]\n }\n\n return filters\n}\n\n/**\n * Transform server funnel result rows to client FunnelChartData format.\n *\n * Maps the server's FunnelResultRow[] to the client's FunnelChartData[]\n * format expected by FunnelChart component.\n *\n * @param serverResult - Raw data from server (FunnelResultRow[])\n * @param stepNames - Optional step names to override server names\n * @returns FunnelChartData[] ready for FunnelChart component\n */\nexport function transformServerFunnelResult(\n serverResult: unknown[],\n stepNames?: string[]\n): FunnelChartData[] {\n if (!serverResult?.length) {\n return []\n }\n\n const rows = serverResult as ServerFunnelResultRow[]\n\n return rows.map((row, index) => ({\n // Map server fields to client format\n name: stepNames?.[index] || row.step,\n value: row.count,\n // Convert cumulative rate to percentage\n percentage: row.cumulativeConversionRate * 100,\n // Convert step-to-step rate to percentage (null for first step)\n conversionRate: row.conversionRate !== null ? row.conversionRate * 100 : null,\n stepIndex: row.stepIndex,\n // Include time metrics for optional display\n avgSecondsToConvert: row.avgSecondsToConvert,\n medianSecondsToConvert: row.medianSecondsToConvert,\n p90SecondsToConvert: row.p90SecondsToConvert,\n }))\n}\n\n/**\n * Format a duration in seconds to a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @returns Formatted string (e.g., \"45s\", \"2.5m\", \"1.3h\", \"3.2d\")\n */\nexport function formatDuration(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined) {\n return '-'\n }\n\n if (seconds < 60) {\n return `${Math.round(seconds)}s`\n }\n\n if (seconds < 3600) {\n const minutes = seconds / 60\n return minutes < 10 ? `${minutes.toFixed(1)}m` : `${Math.round(minutes)}m`\n }\n\n if (seconds < 86400) {\n const hours = seconds / 3600\n return hours < 10 ? `${hours.toFixed(1)}h` : `${Math.round(hours)}h`\n }\n\n const days = seconds / 86400\n return days < 10 ? `${days.toFixed(1)}d` : `${Math.round(days)}d`\n}\n","/**\n * Co-located helpers for FunnelChart.\n *\n * Pure data-shaping + display-option resolution extracted from the component.\n * No behaviour change — mirrors the original inline logic exactly.\n */\nimport type { ChartDisplayConfig } from '../../types.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { formatDuration } from '../../utils/funnelExecution.js'\n\n/** Check if data is already in funnel data format. */\nexport function isFunnelData(data: unknown[]): data is FunnelChartData[] {\n if (!data || data.length === 0) return false\n const first = data[0]\n return (\n typeof first === 'object' &&\n first !== null &&\n 'name' in first &&\n 'value' in first &&\n 'percentage' in first\n )\n}\n\n/**\n * Render time metrics based on config options - returns array of lines for\n * vertical stacking.\n */\nexport function getTimeMetricsLines(\n step: FunnelChartData,\n showAvg: boolean,\n showMedian: boolean,\n showP90: boolean\n): string[] {\n const lines: string[] = []\n if (showAvg && step.avgSecondsToConvert != null) {\n lines.push(`Avg: ${formatDuration(step.avgSecondsToConvert)}`)\n }\n if (showMedian && step.medianSecondsToConvert != null) {\n lines.push(`Med: ${formatDuration(step.medianSecondsToConvert)}`)\n }\n if (showP90 && step.p90SecondsToConvert != null) {\n lines.push(`P90: ${formatDuration(step.p90SecondsToConvert)}`)\n }\n return lines\n}\n\n/** Coerce arbitrary query rows into FunnelChartData by probing field names. */\nexport function toFunnelData(data: unknown[]): FunnelChartData[] {\n if (!data || data.length === 0) return []\n if (isFunnelData(data)) return data\n\n return data.map((row, index) => {\n const record = row as Record<string, unknown>\n\n const nameField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('step') || k.toLowerCase().includes('name') || k === '__stepName'\n )\n const name = nameField ? String(record[nameField]) : `Step ${index + 1}`\n\n const valueField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('count') || k.toLowerCase().includes('value') || k === '__count'\n )\n const value = valueField ? Number(record[valueField]) || 0 : 0\n\n const percentField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('percent') || k === '__percentage'\n )\n const percentage = percentField ? Number(record[percentField]) || 0 : 0\n\n const convRateField = Object.keys(record).find(\n (k) => k.toLowerCase().includes('conversion') || k === '__conversionRate'\n )\n const conversionRate = convRateField ? Number(record[convRateField]) || null : null\n\n return { name, value, percentage, conversionRate, stepIndex: index }\n })\n}\n\nexport interface FunnelDisplayOptions {\n customStepLabels?: string[]\n isVertical: boolean\n funnelStyle: NonNullable<ChartDisplayConfig['funnelStyle']>\n showConversion: boolean\n showAvgTime: boolean\n showMedianTime: boolean\n showP90Time: boolean\n hideSummaryFooter: boolean\n}\n\n/** Resolve every funnel display option (with backward-compat for time metrics). */\nexport function resolveFunnelDisplayOptions(\n displayConfig: ChartDisplayConfig | undefined\n): FunnelDisplayOptions {\n return {\n customStepLabels: displayConfig?.funnelStepLabels,\n isVertical: (displayConfig?.funnelOrientation || 'horizontal') === 'vertical',\n funnelStyle: displayConfig?.funnelStyle ?? 'bars',\n showConversion: displayConfig?.showFunnelConversion ?? true,\n // Time metrics - individual toggles with backward compat for showFunnelTimeMetrics\n showAvgTime: displayConfig?.showFunnelAvgTime ?? (displayConfig?.showFunnelTimeMetrics ?? false),\n showMedianTime: displayConfig?.showFunnelMedianTime ?? false,\n showP90Time: displayConfig?.showFunnelP90Time ?? false,\n hideSummaryFooter: displayConfig?.hideSummaryFooter ?? false\n }\n}\n\n/** Color for a funnel step (cyclic over the palette or the default funnel gradient). */\nexport function getStepColor(index: number, colorPalette: string[]): string {\n return colorPalette[index % colorPalette.length]\n}\n","import { FunnelChart as RechartsFunnelChart, Funnel, LabelList, Tooltip, Cell, ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { getStepColor, getTimeMetricsLines, type FunnelDisplayOptions } from './FunnelChart.helpers.js'\n\ninterface FunnelViewProps {\n funnelData: FunnelChartData[]\n firstStepValue: number\n paletteColors: string[]\n options: FunnelDisplayOptions\n height: string | number\n}\n\n/** Shared summary footer (steps count, overall conversion, completed ratio). */\nfunction FunnelSummaryFooter({\n funnelData,\n firstStepValue\n}: {\n funnelData: FunnelChartData[]\n firstStepValue: number\n}) {\n const { t } = useTranslation()\n const lastValue = funnelData[funnelData.length - 1]?.value || 0\n return (\n <div className=\"dc:flex-shrink-0 dc:px-4 dc:py-2 dc:border-t border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:text-sm\">\n <div className=\"text-dc-text-muted\">\n <span className=\"dc:font-medium\">{funnelData.length}</span> steps\n </div>\n <div className=\"text-dc-text\">\n <span className=\"text-dc-text-muted\">{t('chart.runtime.funnel.overall')}</span>{' '}\n <span className=\"dc:font-medium\">\n {firstStepValue > 0 ? `${(lastValue / firstStepValue * 100).toFixed(1)}%` : '0%'}\n </span>\n </div>\n <div className=\"text-dc-text-muted\">\n {lastValue.toLocaleString() || 0} / {firstStepValue.toLocaleString()} completed\n </div>\n </div>\n </div>\n )\n}\n\n/** Per-step conversion + time-metrics block (shared by vertical/horizontal views). */\nfunction StepMetrics({\n stepConversionRate,\n arrow,\n showConversion,\n timeMetricsLines\n}: {\n stepConversionRate: number | null\n arrow: string\n showConversion: boolean\n timeMetricsLines: string[]\n}) {\n if (stepConversionRate === null) {\n return <div className=\"dc:text-xs text-dc-text-muted\">—</div>\n }\n return (\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {showConversion && <span>{arrow} {stepConversionRate.toFixed(1)}%</span>}\n {timeMetricsLines.length > 0 && (\n <div className=\"text-dc-text-muted dc:mt-0.5 dc:space-y-0.5\">\n {timeMetricsLines.map((line, i) => (\n <div key={i}>⏱ {line}</div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n/** Recharts trapezoid funnel style. */\nexport function FunnelShapeView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n // Recharts FunnelChart layout: 'horizontal' = funnel flows left-to-right,\n // 'vertical' = top-to-bottom (default). Our 'vertical' orientation maps to\n // a left-to-right Recharts funnel.\n const rechartsLayout: 'horizontal' | 'vertical' = options.isVertical ? 'horizontal' : 'vertical'\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RechartsFunnelChart layout={rechartsLayout} accessibilityLayer={false}>\n <Tooltip\n formatter={(value) => typeof value === 'number' ? value.toLocaleString() : String(value)}\n contentStyle={{\n backgroundColor: 'var(--dc-surface)',\n border: '1px solid var(--dc-border)',\n borderRadius: '4px',\n }}\n />\n <Funnel dataKey=\"value\" nameKey=\"name\" data={funnelData} isAnimationActive>\n {funnelData.map((_, index) => (\n <Cell key={`cell-${index}`} fill={getStepColor(index, paletteColors)} />\n ))}\n <LabelList position=\"right\" dataKey=\"name\" fill=\"var(--dc-text)\" style={{ fontSize: '12px' }} />\n <LabelList\n position=\"center\"\n dataKey=\"percentage\"\n formatter={(v) => typeof v === 'number' ? `${v.toFixed(1)}%` : String(v)}\n fill=\"#fff\"\n style={{ fontSize: '11px', fontWeight: 500 }}\n />\n </Funnel>\n </RechartsFunnelChart>\n </ResponsiveContainer>\n </div>\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n\n/** Vertical bars (steps laid out horizontally, bars grow bottom-to-top). */\nexport function FunnelVerticalView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1 dc:flex dc:items-end dc:justify-center dc:gap-4 dc:px-4 dc:py-3 dc:overflow-hidden\">\n {funnelData.map((step, index) => {\n const heightPercent = firstStepValue > 0 ? (step.value / firstStepValue) * 100 : 0\n const prevStep = index > 0 ? funnelData[index - 1] : null\n const stepConversionRate = prevStep && prevStep.value > 0 ? (step.value / prevStep.value) * 100 : null\n const displayName = options.customStepLabels?.[index] || step.name\n const timeMetricsLines = getTimeMetricsLines(step, options.showAvgTime, options.showMedianTime, options.showP90Time)\n const metricsCount = timeMetricsLines.length\n\n return (\n <div key={step.name} className=\"dc:flex dc:flex-col dc:items-center dc:gap-2 dc:flex-1 dc:max-w-32 dc:h-full\">\n <div className={`${metricsCount > 0 ? (metricsCount > 1 ? 'dc:min-h-16' : 'dc:min-h-10') : 'dc:h-5'} dc:flex-shrink-0 dc:text-center`}>\n <StepMetrics\n stepConversionRate={stepConversionRate}\n arrow=\"→\"\n showConversion={options.showConversion}\n timeMetricsLines={timeMetricsLines}\n />\n </div>\n\n <div className=\"dc:flex-1 dc:w-full dc:relative dc:min-h-12\">\n <div className=\"dc:absolute dc:inset-0 bg-dc-surface-secondary dc:rounded-sm\" />\n <div\n className=\"dc:absolute dc:bottom-0 dc:left-0 dc:right-0 dc:rounded-sm dc:transition-all dc:duration-300\"\n style={{ height: `${Math.max(heightPercent, 5)}%`, backgroundColor: getStepColor(index, paletteColors) }}\n />\n <div\n className=\"dc:absolute dc:bottom-0 dc:left-0 dc:right-0 dc:flex dc:items-end dc:justify-center dc:pb-1 dc:pointer-events-none\"\n style={{ height: `${Math.max(heightPercent, 20)}%` }}\n >\n <span className=\"dc:text-xs dc:font-medium text-white dc:drop-shadow-sm\">\n {step.percentage?.toFixed(1) ?? heightPercent.toFixed(1)}%\n </span>\n </div>\n </div>\n\n <div className=\"dc:flex-shrink-0 dc:text-center\">\n <div className=\"dc:text-sm dc:font-medium text-dc-text dc:truncate\" title={displayName}>\n {displayName}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted\">\n {step.value.toLocaleString()}\n </div>\n </div>\n </div>\n )\n })}\n </div>\n\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n\n/** Horizontal bars (default - steps stacked vertically, bars grow left-to-right). */\nexport function FunnelHorizontalView({ funnelData, firstStepValue, paletteColors, options, height }: FunnelViewProps) {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:flex dc:flex-col\" style={{ height }}>\n <div className=\"dc:flex-1 dc:flex dc:flex-col dc:justify-center dc:gap-2 dc:px-4 dc:py-3 dc:overflow-hidden\">\n {funnelData.map((step, index) => {\n const widthPercent = firstStepValue > 0 ? (step.value / firstStepValue) * 100 : 0\n const prevStep = index > 0 ? funnelData[index - 1] : null\n const stepConversionRate = prevStep && prevStep.value > 0 ? (step.value / prevStep.value) * 100 : null\n const displayName = options.customStepLabels?.[index] || step.name\n const timeMetricsLines = getTimeMetricsLines(step, options.showAvgTime, options.showMedianTime, options.showP90Time)\n const metricsCount = timeMetricsLines.length\n\n return (\n <div key={step.name} className=\"dc:flex dc:items-center dc:gap-3\">\n <div className=\"dc:w-24 dc:flex-shrink-0 dc:text-right\">\n <div className=\"dc:text-sm dc:font-medium text-dc-text dc:truncate\" title={displayName}>\n {displayName}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted\">\n {step.value.toLocaleString()}\n </div>\n </div>\n\n <div className=\"dc:flex-1 dc:relative\">\n <div className=\"dc:w-full dc:h-8 bg-dc-surface-secondary dc:rounded-sm\" />\n <div\n className=\"dc:absolute dc:top-0 dc:left-0 dc:h-8 dc:rounded-sm dc:transition-all dc:duration-300\"\n style={{ width: `${Math.max(widthPercent, 2)}%`, backgroundColor: getStepColor(index, paletteColors) }}\n />\n <div\n className=\"dc:absolute dc:top-0 dc:left-0 dc:h-8 dc:flex dc:items-center dc:px-2 dc:pointer-events-none\"\n style={{ width: `${Math.max(widthPercent, 20)}%` }}\n >\n <span className=\"dc:text-xs dc:font-medium text-white dc:drop-shadow-sm\">\n {step.percentage?.toFixed(1) ?? widthPercent.toFixed(1)}%\n </span>\n </div>\n </div>\n\n <div className={`${metricsCount > 0 ? (metricsCount > 1 ? 'dc:w-36' : 'dc:w-28') : 'dc:w-16'} dc:flex-shrink-0 dc:text-left`}>\n <StepMetrics\n stepConversionRate={stepConversionRate}\n arrow=\"↓\"\n showConversion={options.showConversion}\n timeMetricsLines={timeMetricsLines}\n />\n </div>\n </div>\n )\n })}\n </div>\n\n {!options.hideSummaryFooter && (\n <FunnelSummaryFooter funnelData={funnelData} firstStepValue={firstStepValue} />\n )}\n </div>\n )\n}\n","/**\n * FunnelChart Component\n *\n * Visualizes funnel data showing conversion rates between steps.\n * Uses horizontal bars with percentage widths to represent the funnel shape.\n * Works with data from useFunnelQuery hook which provides FunnelChartData.\n *\n * When displayConfig.showFunnelTimeMetrics is enabled, displays time-to-convert\n * metrics from server-side funnel execution (avg, median, P90 seconds).\n */\n\nimport React, { useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { CHART_COLORS } from '../../utils/chartConstants.js'\nimport type { ChartProps } from '../../types.js'\nimport type { FunnelChartData } from '../../types/funnel.js'\nimport { toFunnelData, resolveFunnelDisplayOptions } from './FunnelChart.helpers.js'\nimport { FunnelShapeView, FunnelVerticalView, FunnelHorizontalView } from './FunnelViews.js'\n\n/**\n * FunnelChart Component\n *\n * Renders a funnel visualization from FunnelChartData array.\n * Shows each step as a horizontal bar with width proportional to count.\n * Displays conversion rates between steps.\n */\nconst FunnelChart = React.memo(function FunnelChart({\n data,\n height = '100%',\n colorPalette,\n displayConfig,\n}: ChartProps) {\n const { t } = useTranslation()\n const options = resolveFunnelDisplayOptions(displayConfig)\n\n // Transform data if needed\n const funnelData = useMemo<FunnelChartData[]>(() => toFunnelData(data), [data])\n\n // Calculate first step value for percentage calculations\n const firstStepValue = funnelData[0]?.value || 0\n\n // Handle no data\n if (!data || data.length === 0 || funnelData.length === 0) {\n return (\n <div\n className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\"\n style={{ height }}\n >\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.funnel.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.funnel')}\n </div>\n </div>\n </div>\n )\n }\n\n const paletteColors = colorPalette?.colors || CHART_COLORS\n const viewProps = { funnelData, firstStepValue, paletteColors, options, height }\n\n if (options.funnelStyle === 'funnel') {\n return <FunnelShapeView {...viewProps} />\n }\n\n if (options.isVertical) {\n return <FunnelVerticalView {...viewProps} />\n }\n\n return <FunnelHorizontalView {...viewProps} />\n})\n\nexport default FunnelChart\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
-
import {
|
|
3
|
-
import { D as i, O as a, k as o } from "./chart-area-
|
|
2
|
+
import { F as t, S as n, w as r } from "./chart-activity-grid-DO82rrbW.js";
|
|
3
|
+
import { D as i, O as a, k as o } from "./chart-area-9SBeG0GM.js";
|
|
4
4
|
import s, { useLayoutEffect as c, useMemo as l, useRef as u, useState as d } from "react";
|
|
5
5
|
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
6
6
|
//#region node_modules/d3-shape/src/constant.js
|
|
@@ -453,4 +453,4 @@ var he = /* @__PURE__ */ e({ default: () => ge }), ge = s.memo(function({ data:
|
|
|
453
453
|
//#endregion
|
|
454
454
|
export { oe as n, he as t };
|
|
455
455
|
|
|
456
|
-
//# sourceMappingURL=chart-gauge-
|
|
456
|
+
//# sourceMappingURL=chart-gauge-D7VxwPnx.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-gauge-DOpul-Oz.js","names":["epsilon","pi","tau","constant","tau","pi"],"sources":["../../../node_modules/d3-shape/src/constant.js","../../../node_modules/d3-shape/src/math.js","../../../node_modules/d3-path/src/path.js","../../../node_modules/d3-shape/src/path.js","../../../node_modules/d3-shape/src/arc.js","../../../src/client/components/charts/gaugeChartHelpers.ts","../../../src/client/components/charts/GaugeChart.tsx"],"sourcesContent":["export default function(x) {\n return function constant() {\n return x;\n };\n}\n","export const abs = Math.abs;\nexport const atan2 = Math.atan2;\nexport const cos = Math.cos;\nexport const max = Math.max;\nexport const min = Math.min;\nexport const sin = Math.sin;\nexport const sqrt = Math.sqrt;\n\nexport const epsilon = 1e-12;\nexport const pi = Math.PI;\nexport const halfPi = pi / 2;\nexport const tau = 2 * pi;\n\nexport function acos(x) {\n return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);\n}\n\nexport function asin(x) {\n return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x);\n}\n","const pi = Math.PI,\n tau = 2 * pi,\n epsilon = 1e-6,\n tauEpsilon = tau - epsilon;\n\nfunction append(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\n\nfunction appendRound(digits) {\n let d = Math.floor(digits);\n if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);\n if (d > 15) return append;\n const k = 10 ** d;\n return function(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += Math.round(arguments[i] * k) / k + strings[i];\n }\n };\n}\n\nexport class Path {\n constructor(digits) {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null; // end of current subpath\n this._ = \"\";\n this._append = digits == null ? append : appendRound(digits);\n }\n moveTo(x, y) {\n this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._append`Z`;\n }\n }\n lineTo(x, y) {\n this._append`L${this._x1 = +x},${this._y1 = +y}`;\n }\n quadraticCurveTo(x1, y1, x, y) {\n this._append`Q${+x1},${+y1},${this._x1 = +x},${this._y1 = +y}`;\n }\n bezierCurveTo(x1, y1, x2, y2, x, y) {\n this._append`C${+x1},${+y1},${+x2},${+y2},${this._x1 = +x},${this._y1 = +y}`;\n }\n arcTo(x1, y1, x2, y2, r) {\n x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;\n\n // Is the radius negative? Error.\n if (r < 0) throw new Error(`negative radius: ${r}`);\n\n let x0 = this._x1,\n y0 = this._y1,\n x21 = x2 - x1,\n y21 = y2 - y1,\n x01 = x0 - x1,\n y01 = y0 - y1,\n l01_2 = x01 * x01 + y01 * y01;\n\n // Is this path empty? Move to (x1,y1).\n if (this._x1 === null) {\n this._append`M${this._x1 = x1},${this._y1 = y1}`;\n }\n\n // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.\n else if (!(l01_2 > epsilon));\n\n // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?\n // Equivalently, is (x1,y1) coincident with (x2,y2)?\n // Or, is the radius zero? Line to (x1,y1).\n else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {\n this._append`L${this._x1 = x1},${this._y1 = y1}`;\n }\n\n // Otherwise, draw an arc!\n else {\n let x20 = x2 - x0,\n y20 = y2 - y0,\n l21_2 = x21 * x21 + y21 * y21,\n l20_2 = x20 * x20 + y20 * y20,\n l21 = Math.sqrt(l21_2),\n l01 = Math.sqrt(l01_2),\n l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),\n t01 = l / l01,\n t21 = l / l21;\n\n // If the start tangent is not coincident with (x0,y0), line to.\n if (Math.abs(t01 - 1) > epsilon) {\n this._append`L${x1 + t01 * x01},${y1 + t01 * y01}`;\n }\n\n this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x1 + t21 * x21},${this._y1 = y1 + t21 * y21}`;\n }\n }\n arc(x, y, r, a0, a1, ccw) {\n x = +x, y = +y, r = +r, ccw = !!ccw;\n\n // Is the radius negative? Error.\n if (r < 0) throw new Error(`negative radius: ${r}`);\n\n let dx = r * Math.cos(a0),\n dy = r * Math.sin(a0),\n x0 = x + dx,\n y0 = y + dy,\n cw = 1 ^ ccw,\n da = ccw ? a0 - a1 : a1 - a0;\n\n // Is this path empty? Move to (x0,y0).\n if (this._x1 === null) {\n this._append`M${x0},${y0}`;\n }\n\n // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).\n else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {\n this._append`L${x0},${y0}`;\n }\n\n // Is this arc empty? We’re done.\n if (!r) return;\n\n // Does the angle go the wrong way? Flip the direction.\n if (da < 0) da = da % tau + tau;\n\n // Is this a complete circle? Draw two arcs to complete the circle.\n if (da > tauEpsilon) {\n this._append`A${r},${r},0,1,${cw},${x - dx},${y - dy}A${r},${r},0,1,${cw},${this._x1 = x0},${this._y1 = y0}`;\n }\n\n // Is this arc non-empty? Draw an arc!\n else if (da > epsilon) {\n this._append`A${r},${r},0,${+(da >= pi)},${cw},${this._x1 = x + r * Math.cos(a1)},${this._y1 = y + r * Math.sin(a1)}`;\n }\n }\n rect(x, y, w, h) {\n this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}h${w = +w}v${+h}h${-w}Z`;\n }\n toString() {\n return this._;\n }\n}\n\nexport function path() {\n return new Path;\n}\n\n// Allow instanceof d3.path\npath.prototype = Path.prototype;\n\nexport function pathRound(digits = 3) {\n return new Path(+digits);\n}\n","import {Path} from \"d3-path\";\n\nexport function withPath(shape) {\n let digits = 3;\n\n shape.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) {\n digits = null;\n } else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n return shape;\n };\n\n return () => new Path(digits);\n}\n","import constant from \"./constant.js\";\nimport {abs, acos, asin, atan2, cos, epsilon, halfPi, max, min, pi, sin, sqrt, tau} from \"./math.js\";\nimport {withPath} from \"./path.js\";\n\nfunction arcInnerRadius(d) {\n return d.innerRadius;\n}\n\nfunction arcOuterRadius(d) {\n return d.outerRadius;\n}\n\nfunction arcStartAngle(d) {\n return d.startAngle;\n}\n\nfunction arcEndAngle(d) {\n return d.endAngle;\n}\n\nfunction arcPadAngle(d) {\n return d && d.padAngle; // Note: optional!\n}\n\nfunction intersect(x0, y0, x1, y1, x2, y2, x3, y3) {\n var x10 = x1 - x0, y10 = y1 - y0,\n x32 = x3 - x2, y32 = y3 - y2,\n t = y32 * x10 - x32 * y10;\n if (t * t < epsilon) return;\n t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;\n return [x0 + t * x10, y0 + t * y10];\n}\n\n// Compute perpendicular offset line of length rc.\n// http://mathworld.wolfram.com/Circle-LineIntersection.html\nfunction cornerTangents(x0, y0, x1, y1, r1, rc, cw) {\n var x01 = x0 - x1,\n y01 = y0 - y1,\n lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01),\n ox = lo * y01,\n oy = -lo * x01,\n x11 = x0 + ox,\n y11 = y0 + oy,\n x10 = x1 + ox,\n y10 = y1 + oy,\n x00 = (x11 + x10) / 2,\n y00 = (y11 + y10) / 2,\n dx = x10 - x11,\n dy = y10 - y11,\n d2 = dx * dx + dy * dy,\n r = r1 - rc,\n D = x11 * y10 - x10 * y11,\n d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)),\n cx0 = (D * dy - dx * d) / d2,\n cy0 = (-D * dx - dy * d) / d2,\n cx1 = (D * dy + dx * d) / d2,\n cy1 = (-D * dx + dy * d) / d2,\n dx0 = cx0 - x00,\n dy0 = cy0 - y00,\n dx1 = cx1 - x00,\n dy1 = cy1 - y00;\n\n // Pick the closer of the two intersection points.\n // TODO Is there a faster way to determine which intersection to use?\n if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;\n\n return {\n cx: cx0,\n cy: cy0,\n x01: -ox,\n y01: -oy,\n x11: cx0 * (r1 / r - 1),\n y11: cy0 * (r1 / r - 1)\n };\n}\n\nexport default function() {\n var innerRadius = arcInnerRadius,\n outerRadius = arcOuterRadius,\n cornerRadius = constant(0),\n padRadius = null,\n startAngle = arcStartAngle,\n endAngle = arcEndAngle,\n padAngle = arcPadAngle,\n context = null,\n path = withPath(arc);\n\n function arc() {\n var buffer,\n r,\n r0 = +innerRadius.apply(this, arguments),\n r1 = +outerRadius.apply(this, arguments),\n a0 = startAngle.apply(this, arguments) - halfPi,\n a1 = endAngle.apply(this, arguments) - halfPi,\n da = abs(a1 - a0),\n cw = a1 > a0;\n\n if (!context) context = buffer = path();\n\n // Ensure that the outer radius is always larger than the inner radius.\n if (r1 < r0) r = r1, r1 = r0, r0 = r;\n\n // Is it a point?\n if (!(r1 > epsilon)) context.moveTo(0, 0);\n\n // Or is it a circle or annulus?\n else if (da > tau - epsilon) {\n context.moveTo(r1 * cos(a0), r1 * sin(a0));\n context.arc(0, 0, r1, a0, a1, !cw);\n if (r0 > epsilon) {\n context.moveTo(r0 * cos(a1), r0 * sin(a1));\n context.arc(0, 0, r0, a1, a0, cw);\n }\n }\n\n // Or is it a circular or annular sector?\n else {\n var a01 = a0,\n a11 = a1,\n a00 = a0,\n a10 = a1,\n da0 = da,\n da1 = da,\n ap = padAngle.apply(this, arguments) / 2,\n rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)),\n rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),\n rc0 = rc,\n rc1 = rc,\n t0,\n t1;\n\n // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.\n if (rp > epsilon) {\n var p0 = asin(rp / r0 * sin(ap)),\n p1 = asin(rp / r1 * sin(ap));\n if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;\n else da0 = 0, a00 = a10 = (a0 + a1) / 2;\n if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;\n else da1 = 0, a01 = a11 = (a0 + a1) / 2;\n }\n\n var x01 = r1 * cos(a01),\n y01 = r1 * sin(a01),\n x10 = r0 * cos(a10),\n y10 = r0 * sin(a10);\n\n // Apply rounded corners?\n if (rc > epsilon) {\n var x11 = r1 * cos(a11),\n y11 = r1 * sin(a11),\n x00 = r0 * cos(a00),\n y00 = r0 * sin(a00),\n oc;\n\n // Restrict the corner radius according to the sector angle. If this\n // intersection fails, it’s probably because the arc is too small, so\n // disable the corner radius entirely.\n if (da < pi) {\n if (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10)) {\n var ax = x01 - oc[0],\n ay = y01 - oc[1],\n bx = x11 - oc[0],\n by = y11 - oc[1],\n kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2),\n lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]);\n rc0 = min(rc, (r0 - lc) / (kc - 1));\n rc1 = min(rc, (r1 - lc) / (kc + 1));\n } else {\n rc0 = rc1 = 0;\n }\n }\n }\n\n // Is the sector collapsed to a line?\n if (!(da1 > epsilon)) context.moveTo(x01, y01);\n\n // Does the sector’s outer ring have rounded corners?\n else if (rc1 > epsilon) {\n t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);\n t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);\n\n context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);\n\n // Have the corners merged?\n if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);\n\n // Otherwise, draw the two corners and the ring.\n else {\n context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);\n context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);\n context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);\n }\n }\n\n // Or is the outer ring just a circular arc?\n else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);\n\n // Is there no inner ring, and it’s a circular sector?\n // Or perhaps it’s an annular sector collapsed due to padding?\n if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10);\n\n // Does the sector’s inner ring (or point) have rounded corners?\n else if (rc0 > epsilon) {\n t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);\n t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);\n\n context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);\n\n // Have the corners merged?\n if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);\n\n // Otherwise, draw the two corners and the ring.\n else {\n context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);\n context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);\n context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);\n }\n }\n\n // Or is the inner ring just a circular arc?\n else context.arc(0, 0, r0, a10, a00, cw);\n }\n\n context.closePath();\n\n if (buffer) return context = null, buffer + \"\" || null;\n }\n\n arc.centroid = function() {\n var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,\n a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2;\n return [cos(a) * r, sin(a) * r];\n };\n\n arc.innerRadius = function(_) {\n return arguments.length ? (innerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : innerRadius;\n };\n\n arc.outerRadius = function(_) {\n return arguments.length ? (outerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : outerRadius;\n };\n\n arc.cornerRadius = function(_) {\n return arguments.length ? (cornerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : cornerRadius;\n };\n\n arc.padRadius = function(_) {\n return arguments.length ? (padRadius = _ == null ? null : typeof _ === \"function\" ? _ : constant(+_), arc) : padRadius;\n };\n\n arc.startAngle = function(_) {\n return arguments.length ? (startAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : startAngle;\n };\n\n arc.endAngle = function(_) {\n return arguments.length ? (endAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : endAngle;\n };\n\n arc.padAngle = function(_) {\n return arguments.length ? (padAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : padAngle;\n };\n\n arc.context = function(_) {\n return arguments.length ? ((context = _ == null ? null : _), arc) : context;\n };\n\n return arc;\n}\n","import { arc } from 'd3-shape'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport type { AxisFormatConfig, ThresholdBand } from '../../types.js'\n\n/**\n * Co-located geometry/value maths for {@link GaugeChart}.\n *\n * Everything here is pure so the component stays declarative: it reads a\n * layout, a list of band segments, a list of scale ticks and a needle path,\n * then renders them.\n *\n * ## Angle convention\n * d3-shape's: `0` points at 12 o'clock and positive angles run clockwise. The\n * dial sweeps 270°, from `START_ANGLE` (-135°, lower-left) to `END_ANGLE`\n * (+135°, lower-right).\n *\n * ## Threshold semantics\n * A {@link ThresholdBand}'s `value` is the **lower bound** of its band, as a\n * 0–1 fraction of the min→max range. So `[{0, red}, {0.5, amber}, {0.7, green}]`\n * paints 0–50% red, 50–70% amber and 70–100% green. This matches\n * {@link resolveColor}, and the invariant\n * `bandContaining(f).color === resolveColor(f)` holds for every `f` in [0, 1).\n */\n\n/** Dial start: -135°, lower-left. */\nexport const START_ANGLE = -Math.PI * 0.75\n/** Dial end: +135°, lower-right. */\nexport const END_ANGLE = Math.PI * 0.75\n/** Total dial sweep in radians (270°). */\nexport const ANGLE_SPAN = END_ANGLE - START_ANGLE\n\n/** Neutral band colour for the region below every configured threshold. */\nexport const DEFAULT_FILL = 'var(--dc-accent)'\n/** Angular gap rendered between adjacent band segments (radians, ~2.3°). */\nexport const BAND_GAP_RADIANS = 0.04\n/** Band segments narrower than this (after the gap) are not drawn. */\nconst MIN_SEGMENT_ANGLE = 0.02\n/**\n * Minimum angular separation between two rendered scale ticks (~22°). Keeps\n * labels from colliding on a dial configured with many thresholds.\n */\nconst MIN_TICK_SEPARATION = 0.38\n/** Fractions closer together than this are treated as the same boundary. */\nconst FRACTION_EPSILON = 1e-6\n\n/**\n * Height of the 270° arc's bounding box as a multiple of its radius.\n * The arc spans y from `-r` (top) to `+r·cos45°` (the two lower tips).\n */\nexport const ARC_BBOX_HEIGHT_RATIO = 1 + Math.SQRT1_2\n/** Width of the 270° arc's bounding box as a multiple of its radius. */\nexport const ARC_BBOX_WIDTH_RATIO = 2\n/** Fraction of the available box the dial occupies, leaving a little breathing room. */\nconst DIAL_MARGIN = 0.94\n\nexport function parseNum(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nexport function clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v))\n}\n\n/** A finite `value`, or `fallback` when it is undefined / NaN / infinite. */\nexport function finiteOr(value: number | undefined | null, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\n}\n\n/** Map a 0–1 fraction of the range onto its dial angle. */\nexport function fractionToAngle(fraction: number): number {\n return START_ANGLE + clamp(fraction, 0, 1) * ANGLE_SPAN\n}\n\nexport function valueToAngle(value: number, min: number, max: number): number {\n const span = max === min ? 1 : max - min\n return fractionToAngle((value - min) / span)\n}\n\n/** Cartesian point at `angle`/`radius` in the d3 angle convention. */\nexport function polarPoint(angle: number, radius: number): { x: number; y: number } {\n return { x: Math.sin(angle) * radius, y: -Math.cos(angle) * radius }\n}\n\nexport function resolveColor(fraction: number, thresholds: ThresholdBand[]): string {\n const sorted = normalizeThresholds(thresholds)\n let color = DEFAULT_FILL\n for (const t of sorted) {\n if (fraction >= t.value) color = t.color\n }\n return color\n}\n\nexport function buildArcPath(\n innerRadius: number,\n outerRadius: number,\n startAngle: number,\n endAngle: number,\n cornerRadius = 0\n): string {\n const pathFn = arc().cornerRadius(cornerRadius)\n return pathFn({ innerRadius, outerRadius, startAngle, endAngle }) ?? ''\n}\n\nfunction isThresholdBand(entry: unknown): entry is ThresholdBand {\n return (\n entry !== null &&\n typeof entry === 'object' &&\n typeof (entry as ThresholdBand).value === 'number' &&\n Number.isFinite((entry as ThresholdBand).value) &&\n typeof (entry as ThresholdBand).color === 'string' &&\n (entry as ThresholdBand).color.trim() !== ''\n )\n}\n\n/** Parse the displayConfig.thresholds value (array or JSON string) into bands. */\nexport function parseThresholds(raw: unknown): ThresholdBand[] {\n let arr: unknown[] | null = null\n if (Array.isArray(raw)) {\n arr = raw\n } else if (typeof raw === 'string' && raw.trim()) {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (Array.isArray(parsed)) arr = parsed\n } catch (e) {\n console.warn('GaugeChart: invalid threshold JSON', e)\n return []\n }\n }\n if (!arr) return []\n return arr.filter(isThresholdBand)\n}\n\n/** Clamp threshold fractions into [0, 1] and sort them ascending. */\nexport function normalizeThresholds(thresholds: ThresholdBand[]): ThresholdBand[] {\n return thresholds\n .map((t) => ({ color: t.color, value: clamp(t.value, 0, 1) }))\n .sort((a, b) => a.value - b.value)\n}\n\nexport interface ThresholdArcBand {\n color: string\n /** Lower bound of the band, as a 0–1 fraction of the min→max range. */\n startFraction: number\n /** Upper bound of the band, as a 0–1 fraction of the min→max range. */\n endFraction: number\n /** Dial angle of {@link startFraction}. */\n startAngle: number\n /** Dial angle of {@link endFraction}. */\n endAngle: number\n}\n\n/**\n * Split the dial into coloured bands. The bands tile the whole 0–1 range with\n * no holes: a leading neutral band covers anything below the first threshold,\n * and the last threshold's band runs to 1. Zero-width bands (duplicate\n * thresholds, or one pinned at 1) are dropped.\n *\n * With no thresholds configured the dial is a single neutral band, so the\n * gauge still renders a full arc.\n */\nexport function buildThresholdBands(thresholds: ThresholdBand[]): ThresholdArcBand[] {\n const sorted = normalizeThresholds(thresholds)\n const spans: { color: string; startFraction: number; endFraction: number }[] = []\n\n if (sorted.length === 0) {\n spans.push({ color: DEFAULT_FILL, startFraction: 0, endFraction: 1 })\n } else {\n if (sorted[0].value > FRACTION_EPSILON) {\n spans.push({ color: DEFAULT_FILL, startFraction: 0, endFraction: sorted[0].value })\n }\n sorted.forEach((t, i) => {\n spans.push({\n color: t.color,\n startFraction: t.value,\n endFraction: i < sorted.length - 1 ? sorted[i + 1].value : 1\n })\n })\n }\n\n return spans\n .filter((s) => s.endFraction - s.startFraction > FRACTION_EPSILON)\n .map((s) => ({\n ...s,\n startAngle: fractionToAngle(s.startFraction),\n endAngle: fractionToAngle(s.endFraction)\n }))\n}\n\nexport interface GaugeBandSegment {\n color: string\n startAngle: number\n endAngle: number\n}\n\n/**\n * Turn logical bands into drawable segments by inserting a gap at every\n * *internal* boundary (the dial's outer ends keep the full 270° sweep).\n * Segments too narrow to render cleanly with rounded caps are dropped.\n */\nexport function buildBandSegments(\n bands: ThresholdArcBand[],\n gap = BAND_GAP_RADIANS\n): GaugeBandSegment[] {\n const half = Math.max(gap, 0) / 2\n return bands\n .map((band, i) => ({\n color: band.color,\n startAngle: band.startAngle + (i === 0 ? 0 : half),\n endAngle: band.endAngle + (i === bands.length - 1 ? 0 : -half)\n }))\n .filter((s) => s.endAngle - s.startAngle >= MIN_SEGMENT_ANGLE)\n}\n\nexport interface GaugeScaleTick {\n fraction: number\n value: number\n angle: number\n}\n\n/**\n * Numeric scale ticks at the band boundaries (plus the dial's start and end).\n * Ticks are thinned back-to-front so the max is always kept and no two labels\n * collide.\n */\nexport function buildScaleTicks(\n bands: ThresholdArcBand[],\n minValue: number,\n maxValue: number\n): GaugeScaleTick[] {\n const fractions: number[] = [0]\n for (const band of bands) fractions.push(band.startFraction, band.endFraction)\n fractions.push(1)\n\n const unique = [...fractions]\n .sort((a, b) => a - b)\n .filter((f, i, all) => i === 0 || f - all[i - 1] > FRACTION_EPSILON)\n\n const kept: number[] = []\n for (let i = unique.length - 1; i >= 0; i--) {\n const angle = fractionToAngle(unique[i])\n const last = kept.length > 0 ? fractionToAngle(kept[kept.length - 1]) : null\n if (last === null || last - angle >= MIN_TICK_SEPARATION) kept.push(unique[i])\n }\n\n return kept\n .reverse()\n .map((fraction) => ({\n fraction,\n value: minValue + fraction * (maxValue - minValue),\n angle: fractionToAngle(fraction)\n }))\n}\n\n/** Triangular needle: wide at the hub, tapering to a point at `length`. */\nexport function buildNeedlePath(angle: number, length: number, halfWidth: number): string {\n const tip = polarPoint(angle, length)\n const perpX = Math.cos(angle)\n const perpY = Math.sin(angle)\n const round = (n: number) => Number(n.toFixed(3))\n return [\n `M${round(tip.x)},${round(tip.y)}`,\n `L${round(perpX * halfWidth)},${round(perpY * halfWidth)}`,\n `L${round(-perpX * halfWidth)},${round(-perpY * halfWidth)}`,\n 'Z'\n ].join('')\n}\n\nexport interface GaugeLayout {\n /** Dial centre in SVG coordinates. */\n cx: number\n cy: number\n radius: number\n outerRadius: number\n innerRadius: number\n /** Corner radius that fully rounds a band segment's ends. */\n bandCornerRadius: number\n /** Radius at which scale tick labels are centred (just inside the band). */\n tickRadius: number\n needleLength: number\n needleHalfWidth: number\n hubRadius: number\n tickFontSize: number\n labelFontSize: number\n labelY: number\n valueFontSize: number\n valueY: number\n}\n\n/**\n * Size and position the dial so its 270° bounding box is centred in, and fits\n * inside, a `width` x `height` box. Everything else is expressed as a ratio of\n * the resulting radius so the gauge scales smoothly.\n */\nexport function computeGaugeLayout(width: number, height: number): GaugeLayout {\n const w = Math.max(finiteOr(width, 0), 1)\n const h = Math.max(finiteOr(height, 0), 1)\n const radius = Math.max(\n 1,\n Math.min(w / ARC_BBOX_WIDTH_RATIO, h / ARC_BBOX_HEIGHT_RATIO) * DIAL_MARGIN\n )\n const outerRadius = radius\n const innerRadius = radius * 0.8\n\n return {\n cx: w / 2,\n // Shift down so the bbox (which extends further above the centre than\n // below it) is vertically centred.\n cy: h / 2 + radius * (1 - ARC_BBOX_HEIGHT_RATIO / 2),\n radius,\n outerRadius,\n innerRadius,\n bandCornerRadius: (outerRadius - innerRadius) / 2,\n tickRadius: radius * 0.7,\n needleLength: radius * 0.56,\n needleHalfWidth: radius * 0.055,\n hubRadius: radius * 0.075,\n tickFontSize: radius * 0.095,\n labelFontSize: radius * 0.1,\n labelY: radius * 0.28,\n valueFontSize: radius * 0.165,\n valueY: radius * 0.52\n }\n}\n\nexport interface GaugeGeometry {\n effectiveMax: number\n clampedValue: number\n fraction: number\n fillColor: string\n needleAngle: number\n}\n\n/** Compute the gauge's clamped value, fraction, indicated colour and angle. */\nexport function computeGaugeGeometry(\n rawValue: number,\n minValue: number,\n maxValue: number,\n thresholds: ThresholdBand[]\n): GaugeGeometry {\n const min = finiteOr(minValue, 0)\n const max = finiteOr(maxValue, min + 1)\n const effectiveMax = max <= min ? min + 1 : max\n const clampedValue = clamp(finiteOr(rawValue, min), min, effectiveMax)\n const fraction = clamp((clampedValue - min) / (effectiveMax - min), 0, 1)\n return {\n effectiveMax,\n clampedValue,\n fraction,\n fillColor: resolveColor(fraction, thresholds),\n needleAngle: fractionToAngle(fraction)\n }\n}\n\n/**\n * Format a gauge value. With a configured axis format this honours its unit,\n * decimals and abbreviation (so a percent format renders `66.9%`); without one\n * it falls back to the shared default numeric formatting (`66.94`).\n */\nexport function formatGaugeValue(value: number, yAxisFormat?: AxisFormatConfig): string {\n return formatAxisValue(value, yAxisFormat)\n}\n","import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { ChartEmptyState, ChartConfigError, ChartRenderError } from './ChartStates.js'\nimport {\n parseNum,\n finiteOr,\n buildArcPath,\n buildNeedlePath,\n parseThresholds,\n buildThresholdBands,\n buildBandSegments,\n buildScaleTicks,\n computeGaugeLayout,\n computeGaugeGeometry,\n formatGaugeValue,\n polarPoint\n} from './gaugeChartHelpers.js'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel.js'\nimport type { ChartProps, ThresholdBand } from '../../types.js'\n\n/**\n * Gauge chart: a 270° dial whose arc *is* the threshold banding — one thick,\n * rounded segment per threshold with a small gap between them — read by a\n * tapered needle, with numeric scale labels at the band boundaries and the\n * measure label + value stacked below the centre.\n *\n * All geometry lives in `gaugeChartHelpers.ts`; this component only renders it.\n */\nconst GaugeChart = React.memo(function GaugeChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n}: ChartProps) {\n const { t } = useTranslation()\n const getFieldLabel = useCubeFieldLabel()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const { valueField, maxField, configError } = useMemo(() => {\n const yAxis: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n const valueField = yAxis[0] ?? ''\n const maxField = yAxis[1] ?? ''\n\n if (!valueField) {\n return { valueField, maxField, configError: 'Gauge requires at least 1 measure in Y-Axis (current value)' }\n }\n return { valueField, maxField, configError: null }\n }, [chartConfig])\n\n const thresholds: ThresholdBand[] = useMemo(\n () => parseThresholds(displayConfig?.thresholds),\n [displayConfig?.thresholds]\n )\n\n const bands = useMemo(() => buildThresholdBands(thresholds), [thresholds])\n const segments = useMemo(() => buildBandSegments(bands), [bands])\n\n try {\n if (!data || data.length === 0) {\n return <ChartEmptyState height={height} hint={t('chart.runtime.noDataHint.gauge')} />\n }\n\n if (configError) {\n return <ChartConfigError height={height} hint={configError} />\n }\n\n const row = (data as Record<string, unknown>[])[0]\n const rawValue = parseNum(row[valueField])\n if (rawValue === null || !Number.isFinite(rawValue)) {\n return (\n <ChartEmptyState\n height={height}\n titleKey=\"chart.runtime.noValidData\"\n hint={t('chart.runtime.noValidDataHint.gauge')}\n />\n )\n }\n\n const minValue = finiteOr(displayConfig?.minValue, 0)\n const maxFieldValue = maxField ? parseNum(row[maxField]) : null\n const maxValue = finiteOr(displayConfig?.maxValue ?? maxFieldValue, 100)\n\n const { effectiveMax, fraction, fillColor, needleAngle } =\n computeGaugeGeometry(rawValue, minValue, maxValue, thresholds)\n\n const showCenterLabel = displayConfig?.showCenterLabel ?? true\n const showPercentage = displayConfig?.showPercentage ?? false\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const containerW = dimensions.width || 300\n const containerH = typeof height === 'number' ? height : (dimensions.height || 200)\n\n const layout = computeGaugeLayout(containerW, containerH)\n const ticks = buildScaleTicks(bands, minValue, effectiveMax)\n\n const valueLabel = showPercentage\n ? `${(fraction * 100).toFixed(1)}%`\n : formatGaugeValue(rawValue, yAxisFormat)\n\n const fieldLabel = getFieldLabel(valueField)\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height=\"100%\"\n viewBox={`0 0 ${containerW} ${containerH}`}\n preserveAspectRatio=\"xMidYMid meet\"\n data-testid=\"gauge-svg\"\n >\n <g transform={`translate(${layout.cx}, ${layout.cy})`}>\n {segments.map((segment, i) => (\n <path\n key={i}\n d={buildArcPath(\n layout.innerRadius,\n layout.outerRadius,\n segment.startAngle,\n segment.endAngle,\n layout.bandCornerRadius\n )}\n fill={segment.color}\n data-testid={`gauge-band-${i}`}\n />\n ))}\n\n {ticks.map((tick, i) => {\n const point = polarPoint(tick.angle, layout.tickRadius)\n return (\n <text\n key={i}\n x={point.x}\n y={point.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontSize={layout.tickFontSize}\n fill=\"currentColor\"\n className=\"text-dc-text-muted\"\n data-testid={`gauge-tick-${i}`}\n >\n {formatGaugeValue(tick.value, yAxisFormat)}\n </text>\n )\n })}\n\n <path\n d={buildNeedlePath(needleAngle, layout.needleLength, layout.needleHalfWidth)}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-needle\"\n data-fraction={fraction.toFixed(4)}\n data-color={fillColor}\n />\n <circle\n r={layout.hubRadius}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-hub\"\n />\n\n {showCenterLabel && (\n <g data-testid=\"gauge-label\">\n <text\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n y={layout.labelY}\n fontSize={layout.labelFontSize}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-field-text\"\n >\n {fieldLabel}\n </text>\n <text\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n y={layout.valueY}\n fontSize={layout.valueFontSize}\n fontWeight=\"600\"\n fill=\"currentColor\"\n className=\"text-dc-text\"\n data-testid=\"gauge-value-text\"\n >\n {valueLabel}\n </text>\n </g>\n )}\n </g>\n </svg>\n </div>\n )\n } catch (error) {\n return <ChartRenderError height={height} chartType=\"Gauge Chart\" error={error} />\n }\n})\n\nexport default GaugeChart\n"],"x_google_ignoreList":[0,1,2,3,4],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-gauge-D7VxwPnx.js","names":["epsilon","pi","tau","constant","tau","pi"],"sources":["../../../node_modules/d3-shape/src/constant.js","../../../node_modules/d3-shape/src/math.js","../../../node_modules/d3-path/src/path.js","../../../node_modules/d3-shape/src/path.js","../../../node_modules/d3-shape/src/arc.js","../../../src/client/components/charts/gaugeChartHelpers.ts","../../../src/client/components/charts/GaugeChart.tsx"],"sourcesContent":["export default function(x) {\n return function constant() {\n return x;\n };\n}\n","export const abs = Math.abs;\nexport const atan2 = Math.atan2;\nexport const cos = Math.cos;\nexport const max = Math.max;\nexport const min = Math.min;\nexport const sin = Math.sin;\nexport const sqrt = Math.sqrt;\n\nexport const epsilon = 1e-12;\nexport const pi = Math.PI;\nexport const halfPi = pi / 2;\nexport const tau = 2 * pi;\n\nexport function acos(x) {\n return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);\n}\n\nexport function asin(x) {\n return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x);\n}\n","const pi = Math.PI,\n tau = 2 * pi,\n epsilon = 1e-6,\n tauEpsilon = tau - epsilon;\n\nfunction append(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\n\nfunction appendRound(digits) {\n let d = Math.floor(digits);\n if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);\n if (d > 15) return append;\n const k = 10 ** d;\n return function(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += Math.round(arguments[i] * k) / k + strings[i];\n }\n };\n}\n\nexport class Path {\n constructor(digits) {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null; // end of current subpath\n this._ = \"\";\n this._append = digits == null ? append : appendRound(digits);\n }\n moveTo(x, y) {\n this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._append`Z`;\n }\n }\n lineTo(x, y) {\n this._append`L${this._x1 = +x},${this._y1 = +y}`;\n }\n quadraticCurveTo(x1, y1, x, y) {\n this._append`Q${+x1},${+y1},${this._x1 = +x},${this._y1 = +y}`;\n }\n bezierCurveTo(x1, y1, x2, y2, x, y) {\n this._append`C${+x1},${+y1},${+x2},${+y2},${this._x1 = +x},${this._y1 = +y}`;\n }\n arcTo(x1, y1, x2, y2, r) {\n x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;\n\n // Is the radius negative? Error.\n if (r < 0) throw new Error(`negative radius: ${r}`);\n\n let x0 = this._x1,\n y0 = this._y1,\n x21 = x2 - x1,\n y21 = y2 - y1,\n x01 = x0 - x1,\n y01 = y0 - y1,\n l01_2 = x01 * x01 + y01 * y01;\n\n // Is this path empty? Move to (x1,y1).\n if (this._x1 === null) {\n this._append`M${this._x1 = x1},${this._y1 = y1}`;\n }\n\n // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.\n else if (!(l01_2 > epsilon));\n\n // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?\n // Equivalently, is (x1,y1) coincident with (x2,y2)?\n // Or, is the radius zero? Line to (x1,y1).\n else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {\n this._append`L${this._x1 = x1},${this._y1 = y1}`;\n }\n\n // Otherwise, draw an arc!\n else {\n let x20 = x2 - x0,\n y20 = y2 - y0,\n l21_2 = x21 * x21 + y21 * y21,\n l20_2 = x20 * x20 + y20 * y20,\n l21 = Math.sqrt(l21_2),\n l01 = Math.sqrt(l01_2),\n l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),\n t01 = l / l01,\n t21 = l / l21;\n\n // If the start tangent is not coincident with (x0,y0), line to.\n if (Math.abs(t01 - 1) > epsilon) {\n this._append`L${x1 + t01 * x01},${y1 + t01 * y01}`;\n }\n\n this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x1 + t21 * x21},${this._y1 = y1 + t21 * y21}`;\n }\n }\n arc(x, y, r, a0, a1, ccw) {\n x = +x, y = +y, r = +r, ccw = !!ccw;\n\n // Is the radius negative? Error.\n if (r < 0) throw new Error(`negative radius: ${r}`);\n\n let dx = r * Math.cos(a0),\n dy = r * Math.sin(a0),\n x0 = x + dx,\n y0 = y + dy,\n cw = 1 ^ ccw,\n da = ccw ? a0 - a1 : a1 - a0;\n\n // Is this path empty? Move to (x0,y0).\n if (this._x1 === null) {\n this._append`M${x0},${y0}`;\n }\n\n // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).\n else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {\n this._append`L${x0},${y0}`;\n }\n\n // Is this arc empty? We’re done.\n if (!r) return;\n\n // Does the angle go the wrong way? Flip the direction.\n if (da < 0) da = da % tau + tau;\n\n // Is this a complete circle? Draw two arcs to complete the circle.\n if (da > tauEpsilon) {\n this._append`A${r},${r},0,1,${cw},${x - dx},${y - dy}A${r},${r},0,1,${cw},${this._x1 = x0},${this._y1 = y0}`;\n }\n\n // Is this arc non-empty? Draw an arc!\n else if (da > epsilon) {\n this._append`A${r},${r},0,${+(da >= pi)},${cw},${this._x1 = x + r * Math.cos(a1)},${this._y1 = y + r * Math.sin(a1)}`;\n }\n }\n rect(x, y, w, h) {\n this._append`M${this._x0 = this._x1 = +x},${this._y0 = this._y1 = +y}h${w = +w}v${+h}h${-w}Z`;\n }\n toString() {\n return this._;\n }\n}\n\nexport function path() {\n return new Path;\n}\n\n// Allow instanceof d3.path\npath.prototype = Path.prototype;\n\nexport function pathRound(digits = 3) {\n return new Path(+digits);\n}\n","import {Path} from \"d3-path\";\n\nexport function withPath(shape) {\n let digits = 3;\n\n shape.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) {\n digits = null;\n } else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n return shape;\n };\n\n return () => new Path(digits);\n}\n","import constant from \"./constant.js\";\nimport {abs, acos, asin, atan2, cos, epsilon, halfPi, max, min, pi, sin, sqrt, tau} from \"./math.js\";\nimport {withPath} from \"./path.js\";\n\nfunction arcInnerRadius(d) {\n return d.innerRadius;\n}\n\nfunction arcOuterRadius(d) {\n return d.outerRadius;\n}\n\nfunction arcStartAngle(d) {\n return d.startAngle;\n}\n\nfunction arcEndAngle(d) {\n return d.endAngle;\n}\n\nfunction arcPadAngle(d) {\n return d && d.padAngle; // Note: optional!\n}\n\nfunction intersect(x0, y0, x1, y1, x2, y2, x3, y3) {\n var x10 = x1 - x0, y10 = y1 - y0,\n x32 = x3 - x2, y32 = y3 - y2,\n t = y32 * x10 - x32 * y10;\n if (t * t < epsilon) return;\n t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;\n return [x0 + t * x10, y0 + t * y10];\n}\n\n// Compute perpendicular offset line of length rc.\n// http://mathworld.wolfram.com/Circle-LineIntersection.html\nfunction cornerTangents(x0, y0, x1, y1, r1, rc, cw) {\n var x01 = x0 - x1,\n y01 = y0 - y1,\n lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01),\n ox = lo * y01,\n oy = -lo * x01,\n x11 = x0 + ox,\n y11 = y0 + oy,\n x10 = x1 + ox,\n y10 = y1 + oy,\n x00 = (x11 + x10) / 2,\n y00 = (y11 + y10) / 2,\n dx = x10 - x11,\n dy = y10 - y11,\n d2 = dx * dx + dy * dy,\n r = r1 - rc,\n D = x11 * y10 - x10 * y11,\n d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)),\n cx0 = (D * dy - dx * d) / d2,\n cy0 = (-D * dx - dy * d) / d2,\n cx1 = (D * dy + dx * d) / d2,\n cy1 = (-D * dx + dy * d) / d2,\n dx0 = cx0 - x00,\n dy0 = cy0 - y00,\n dx1 = cx1 - x00,\n dy1 = cy1 - y00;\n\n // Pick the closer of the two intersection points.\n // TODO Is there a faster way to determine which intersection to use?\n if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;\n\n return {\n cx: cx0,\n cy: cy0,\n x01: -ox,\n y01: -oy,\n x11: cx0 * (r1 / r - 1),\n y11: cy0 * (r1 / r - 1)\n };\n}\n\nexport default function() {\n var innerRadius = arcInnerRadius,\n outerRadius = arcOuterRadius,\n cornerRadius = constant(0),\n padRadius = null,\n startAngle = arcStartAngle,\n endAngle = arcEndAngle,\n padAngle = arcPadAngle,\n context = null,\n path = withPath(arc);\n\n function arc() {\n var buffer,\n r,\n r0 = +innerRadius.apply(this, arguments),\n r1 = +outerRadius.apply(this, arguments),\n a0 = startAngle.apply(this, arguments) - halfPi,\n a1 = endAngle.apply(this, arguments) - halfPi,\n da = abs(a1 - a0),\n cw = a1 > a0;\n\n if (!context) context = buffer = path();\n\n // Ensure that the outer radius is always larger than the inner radius.\n if (r1 < r0) r = r1, r1 = r0, r0 = r;\n\n // Is it a point?\n if (!(r1 > epsilon)) context.moveTo(0, 0);\n\n // Or is it a circle or annulus?\n else if (da > tau - epsilon) {\n context.moveTo(r1 * cos(a0), r1 * sin(a0));\n context.arc(0, 0, r1, a0, a1, !cw);\n if (r0 > epsilon) {\n context.moveTo(r0 * cos(a1), r0 * sin(a1));\n context.arc(0, 0, r0, a1, a0, cw);\n }\n }\n\n // Or is it a circular or annular sector?\n else {\n var a01 = a0,\n a11 = a1,\n a00 = a0,\n a10 = a1,\n da0 = da,\n da1 = da,\n ap = padAngle.apply(this, arguments) / 2,\n rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)),\n rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),\n rc0 = rc,\n rc1 = rc,\n t0,\n t1;\n\n // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.\n if (rp > epsilon) {\n var p0 = asin(rp / r0 * sin(ap)),\n p1 = asin(rp / r1 * sin(ap));\n if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;\n else da0 = 0, a00 = a10 = (a0 + a1) / 2;\n if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;\n else da1 = 0, a01 = a11 = (a0 + a1) / 2;\n }\n\n var x01 = r1 * cos(a01),\n y01 = r1 * sin(a01),\n x10 = r0 * cos(a10),\n y10 = r0 * sin(a10);\n\n // Apply rounded corners?\n if (rc > epsilon) {\n var x11 = r1 * cos(a11),\n y11 = r1 * sin(a11),\n x00 = r0 * cos(a00),\n y00 = r0 * sin(a00),\n oc;\n\n // Restrict the corner radius according to the sector angle. If this\n // intersection fails, it’s probably because the arc is too small, so\n // disable the corner radius entirely.\n if (da < pi) {\n if (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10)) {\n var ax = x01 - oc[0],\n ay = y01 - oc[1],\n bx = x11 - oc[0],\n by = y11 - oc[1],\n kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2),\n lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]);\n rc0 = min(rc, (r0 - lc) / (kc - 1));\n rc1 = min(rc, (r1 - lc) / (kc + 1));\n } else {\n rc0 = rc1 = 0;\n }\n }\n }\n\n // Is the sector collapsed to a line?\n if (!(da1 > epsilon)) context.moveTo(x01, y01);\n\n // Does the sector’s outer ring have rounded corners?\n else if (rc1 > epsilon) {\n t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);\n t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);\n\n context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);\n\n // Have the corners merged?\n if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);\n\n // Otherwise, draw the two corners and the ring.\n else {\n context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);\n context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);\n context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);\n }\n }\n\n // Or is the outer ring just a circular arc?\n else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);\n\n // Is there no inner ring, and it’s a circular sector?\n // Or perhaps it’s an annular sector collapsed due to padding?\n if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10);\n\n // Does the sector’s inner ring (or point) have rounded corners?\n else if (rc0 > epsilon) {\n t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);\n t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);\n\n context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);\n\n // Have the corners merged?\n if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);\n\n // Otherwise, draw the two corners and the ring.\n else {\n context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);\n context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);\n context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);\n }\n }\n\n // Or is the inner ring just a circular arc?\n else context.arc(0, 0, r0, a10, a00, cw);\n }\n\n context.closePath();\n\n if (buffer) return context = null, buffer + \"\" || null;\n }\n\n arc.centroid = function() {\n var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,\n a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2;\n return [cos(a) * r, sin(a) * r];\n };\n\n arc.innerRadius = function(_) {\n return arguments.length ? (innerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : innerRadius;\n };\n\n arc.outerRadius = function(_) {\n return arguments.length ? (outerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : outerRadius;\n };\n\n arc.cornerRadius = function(_) {\n return arguments.length ? (cornerRadius = typeof _ === \"function\" ? _ : constant(+_), arc) : cornerRadius;\n };\n\n arc.padRadius = function(_) {\n return arguments.length ? (padRadius = _ == null ? null : typeof _ === \"function\" ? _ : constant(+_), arc) : padRadius;\n };\n\n arc.startAngle = function(_) {\n return arguments.length ? (startAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : startAngle;\n };\n\n arc.endAngle = function(_) {\n return arguments.length ? (endAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : endAngle;\n };\n\n arc.padAngle = function(_) {\n return arguments.length ? (padAngle = typeof _ === \"function\" ? _ : constant(+_), arc) : padAngle;\n };\n\n arc.context = function(_) {\n return arguments.length ? ((context = _ == null ? null : _), arc) : context;\n };\n\n return arc;\n}\n","import { arc } from 'd3-shape'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport type { AxisFormatConfig, ThresholdBand } from '../../types.js'\n\n/**\n * Co-located geometry/value maths for {@link GaugeChart}.\n *\n * Everything here is pure so the component stays declarative: it reads a\n * layout, a list of band segments, a list of scale ticks and a needle path,\n * then renders them.\n *\n * ## Angle convention\n * d3-shape's: `0` points at 12 o'clock and positive angles run clockwise. The\n * dial sweeps 270°, from `START_ANGLE` (-135°, lower-left) to `END_ANGLE`\n * (+135°, lower-right).\n *\n * ## Threshold semantics\n * A {@link ThresholdBand}'s `value` is the **lower bound** of its band, as a\n * 0–1 fraction of the min→max range. So `[{0, red}, {0.5, amber}, {0.7, green}]`\n * paints 0–50% red, 50–70% amber and 70–100% green. This matches\n * {@link resolveColor}, and the invariant\n * `bandContaining(f).color === resolveColor(f)` holds for every `f` in [0, 1).\n */\n\n/** Dial start: -135°, lower-left. */\nexport const START_ANGLE = -Math.PI * 0.75\n/** Dial end: +135°, lower-right. */\nexport const END_ANGLE = Math.PI * 0.75\n/** Total dial sweep in radians (270°). */\nexport const ANGLE_SPAN = END_ANGLE - START_ANGLE\n\n/** Neutral band colour for the region below every configured threshold. */\nexport const DEFAULT_FILL = 'var(--dc-accent)'\n/** Angular gap rendered between adjacent band segments (radians, ~2.3°). */\nexport const BAND_GAP_RADIANS = 0.04\n/** Band segments narrower than this (after the gap) are not drawn. */\nconst MIN_SEGMENT_ANGLE = 0.02\n/**\n * Minimum angular separation between two rendered scale ticks (~22°). Keeps\n * labels from colliding on a dial configured with many thresholds.\n */\nconst MIN_TICK_SEPARATION = 0.38\n/** Fractions closer together than this are treated as the same boundary. */\nconst FRACTION_EPSILON = 1e-6\n\n/**\n * Height of the 270° arc's bounding box as a multiple of its radius.\n * The arc spans y from `-r` (top) to `+r·cos45°` (the two lower tips).\n */\nexport const ARC_BBOX_HEIGHT_RATIO = 1 + Math.SQRT1_2\n/** Width of the 270° arc's bounding box as a multiple of its radius. */\nexport const ARC_BBOX_WIDTH_RATIO = 2\n/** Fraction of the available box the dial occupies, leaving a little breathing room. */\nconst DIAL_MARGIN = 0.94\n\nexport function parseNum(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nexport function clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v))\n}\n\n/** A finite `value`, or `fallback` when it is undefined / NaN / infinite. */\nexport function finiteOr(value: number | undefined | null, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\n}\n\n/** Map a 0–1 fraction of the range onto its dial angle. */\nexport function fractionToAngle(fraction: number): number {\n return START_ANGLE + clamp(fraction, 0, 1) * ANGLE_SPAN\n}\n\nexport function valueToAngle(value: number, min: number, max: number): number {\n const span = max === min ? 1 : max - min\n return fractionToAngle((value - min) / span)\n}\n\n/** Cartesian point at `angle`/`radius` in the d3 angle convention. */\nexport function polarPoint(angle: number, radius: number): { x: number; y: number } {\n return { x: Math.sin(angle) * radius, y: -Math.cos(angle) * radius }\n}\n\nexport function resolveColor(fraction: number, thresholds: ThresholdBand[]): string {\n const sorted = normalizeThresholds(thresholds)\n let color = DEFAULT_FILL\n for (const t of sorted) {\n if (fraction >= t.value) color = t.color\n }\n return color\n}\n\nexport function buildArcPath(\n innerRadius: number,\n outerRadius: number,\n startAngle: number,\n endAngle: number,\n cornerRadius = 0\n): string {\n const pathFn = arc().cornerRadius(cornerRadius)\n return pathFn({ innerRadius, outerRadius, startAngle, endAngle }) ?? ''\n}\n\nfunction isThresholdBand(entry: unknown): entry is ThresholdBand {\n return (\n entry !== null &&\n typeof entry === 'object' &&\n typeof (entry as ThresholdBand).value === 'number' &&\n Number.isFinite((entry as ThresholdBand).value) &&\n typeof (entry as ThresholdBand).color === 'string' &&\n (entry as ThresholdBand).color.trim() !== ''\n )\n}\n\n/** Parse the displayConfig.thresholds value (array or JSON string) into bands. */\nexport function parseThresholds(raw: unknown): ThresholdBand[] {\n let arr: unknown[] | null = null\n if (Array.isArray(raw)) {\n arr = raw\n } else if (typeof raw === 'string' && raw.trim()) {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (Array.isArray(parsed)) arr = parsed\n } catch (e) {\n console.warn('GaugeChart: invalid threshold JSON', e)\n return []\n }\n }\n if (!arr) return []\n return arr.filter(isThresholdBand)\n}\n\n/** Clamp threshold fractions into [0, 1] and sort them ascending. */\nexport function normalizeThresholds(thresholds: ThresholdBand[]): ThresholdBand[] {\n return thresholds\n .map((t) => ({ color: t.color, value: clamp(t.value, 0, 1) }))\n .sort((a, b) => a.value - b.value)\n}\n\nexport interface ThresholdArcBand {\n color: string\n /** Lower bound of the band, as a 0–1 fraction of the min→max range. */\n startFraction: number\n /** Upper bound of the band, as a 0–1 fraction of the min→max range. */\n endFraction: number\n /** Dial angle of {@link startFraction}. */\n startAngle: number\n /** Dial angle of {@link endFraction}. */\n endAngle: number\n}\n\n/**\n * Split the dial into coloured bands. The bands tile the whole 0–1 range with\n * no holes: a leading neutral band covers anything below the first threshold,\n * and the last threshold's band runs to 1. Zero-width bands (duplicate\n * thresholds, or one pinned at 1) are dropped.\n *\n * With no thresholds configured the dial is a single neutral band, so the\n * gauge still renders a full arc.\n */\nexport function buildThresholdBands(thresholds: ThresholdBand[]): ThresholdArcBand[] {\n const sorted = normalizeThresholds(thresholds)\n const spans: { color: string; startFraction: number; endFraction: number }[] = []\n\n if (sorted.length === 0) {\n spans.push({ color: DEFAULT_FILL, startFraction: 0, endFraction: 1 })\n } else {\n if (sorted[0].value > FRACTION_EPSILON) {\n spans.push({ color: DEFAULT_FILL, startFraction: 0, endFraction: sorted[0].value })\n }\n sorted.forEach((t, i) => {\n spans.push({\n color: t.color,\n startFraction: t.value,\n endFraction: i < sorted.length - 1 ? sorted[i + 1].value : 1\n })\n })\n }\n\n return spans\n .filter((s) => s.endFraction - s.startFraction > FRACTION_EPSILON)\n .map((s) => ({\n ...s,\n startAngle: fractionToAngle(s.startFraction),\n endAngle: fractionToAngle(s.endFraction)\n }))\n}\n\nexport interface GaugeBandSegment {\n color: string\n startAngle: number\n endAngle: number\n}\n\n/**\n * Turn logical bands into drawable segments by inserting a gap at every\n * *internal* boundary (the dial's outer ends keep the full 270° sweep).\n * Segments too narrow to render cleanly with rounded caps are dropped.\n */\nexport function buildBandSegments(\n bands: ThresholdArcBand[],\n gap = BAND_GAP_RADIANS\n): GaugeBandSegment[] {\n const half = Math.max(gap, 0) / 2\n return bands\n .map((band, i) => ({\n color: band.color,\n startAngle: band.startAngle + (i === 0 ? 0 : half),\n endAngle: band.endAngle + (i === bands.length - 1 ? 0 : -half)\n }))\n .filter((s) => s.endAngle - s.startAngle >= MIN_SEGMENT_ANGLE)\n}\n\nexport interface GaugeScaleTick {\n fraction: number\n value: number\n angle: number\n}\n\n/**\n * Numeric scale ticks at the band boundaries (plus the dial's start and end).\n * Ticks are thinned back-to-front so the max is always kept and no two labels\n * collide.\n */\nexport function buildScaleTicks(\n bands: ThresholdArcBand[],\n minValue: number,\n maxValue: number\n): GaugeScaleTick[] {\n const fractions: number[] = [0]\n for (const band of bands) fractions.push(band.startFraction, band.endFraction)\n fractions.push(1)\n\n const unique = [...fractions]\n .sort((a, b) => a - b)\n .filter((f, i, all) => i === 0 || f - all[i - 1] > FRACTION_EPSILON)\n\n const kept: number[] = []\n for (let i = unique.length - 1; i >= 0; i--) {\n const angle = fractionToAngle(unique[i])\n const last = kept.length > 0 ? fractionToAngle(kept[kept.length - 1]) : null\n if (last === null || last - angle >= MIN_TICK_SEPARATION) kept.push(unique[i])\n }\n\n return kept\n .reverse()\n .map((fraction) => ({\n fraction,\n value: minValue + fraction * (maxValue - minValue),\n angle: fractionToAngle(fraction)\n }))\n}\n\n/** Triangular needle: wide at the hub, tapering to a point at `length`. */\nexport function buildNeedlePath(angle: number, length: number, halfWidth: number): string {\n const tip = polarPoint(angle, length)\n const perpX = Math.cos(angle)\n const perpY = Math.sin(angle)\n const round = (n: number) => Number(n.toFixed(3))\n return [\n `M${round(tip.x)},${round(tip.y)}`,\n `L${round(perpX * halfWidth)},${round(perpY * halfWidth)}`,\n `L${round(-perpX * halfWidth)},${round(-perpY * halfWidth)}`,\n 'Z'\n ].join('')\n}\n\nexport interface GaugeLayout {\n /** Dial centre in SVG coordinates. */\n cx: number\n cy: number\n radius: number\n outerRadius: number\n innerRadius: number\n /** Corner radius that fully rounds a band segment's ends. */\n bandCornerRadius: number\n /** Radius at which scale tick labels are centred (just inside the band). */\n tickRadius: number\n needleLength: number\n needleHalfWidth: number\n hubRadius: number\n tickFontSize: number\n labelFontSize: number\n labelY: number\n valueFontSize: number\n valueY: number\n}\n\n/**\n * Size and position the dial so its 270° bounding box is centred in, and fits\n * inside, a `width` x `height` box. Everything else is expressed as a ratio of\n * the resulting radius so the gauge scales smoothly.\n */\nexport function computeGaugeLayout(width: number, height: number): GaugeLayout {\n const w = Math.max(finiteOr(width, 0), 1)\n const h = Math.max(finiteOr(height, 0), 1)\n const radius = Math.max(\n 1,\n Math.min(w / ARC_BBOX_WIDTH_RATIO, h / ARC_BBOX_HEIGHT_RATIO) * DIAL_MARGIN\n )\n const outerRadius = radius\n const innerRadius = radius * 0.8\n\n return {\n cx: w / 2,\n // Shift down so the bbox (which extends further above the centre than\n // below it) is vertically centred.\n cy: h / 2 + radius * (1 - ARC_BBOX_HEIGHT_RATIO / 2),\n radius,\n outerRadius,\n innerRadius,\n bandCornerRadius: (outerRadius - innerRadius) / 2,\n tickRadius: radius * 0.7,\n needleLength: radius * 0.56,\n needleHalfWidth: radius * 0.055,\n hubRadius: radius * 0.075,\n tickFontSize: radius * 0.095,\n labelFontSize: radius * 0.1,\n labelY: radius * 0.28,\n valueFontSize: radius * 0.165,\n valueY: radius * 0.52\n }\n}\n\nexport interface GaugeGeometry {\n effectiveMax: number\n clampedValue: number\n fraction: number\n fillColor: string\n needleAngle: number\n}\n\n/** Compute the gauge's clamped value, fraction, indicated colour and angle. */\nexport function computeGaugeGeometry(\n rawValue: number,\n minValue: number,\n maxValue: number,\n thresholds: ThresholdBand[]\n): GaugeGeometry {\n const min = finiteOr(minValue, 0)\n const max = finiteOr(maxValue, min + 1)\n const effectiveMax = max <= min ? min + 1 : max\n const clampedValue = clamp(finiteOr(rawValue, min), min, effectiveMax)\n const fraction = clamp((clampedValue - min) / (effectiveMax - min), 0, 1)\n return {\n effectiveMax,\n clampedValue,\n fraction,\n fillColor: resolveColor(fraction, thresholds),\n needleAngle: fractionToAngle(fraction)\n }\n}\n\n/**\n * Format a gauge value. With a configured axis format this honours its unit,\n * decimals and abbreviation (so a percent format renders `66.9%`); without one\n * it falls back to the shared default numeric formatting (`66.94`).\n */\nexport function formatGaugeValue(value: number, yAxisFormat?: AxisFormatConfig): string {\n return formatAxisValue(value, yAxisFormat)\n}\n","import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { ChartEmptyState, ChartConfigError, ChartRenderError } from './ChartStates.js'\nimport {\n parseNum,\n finiteOr,\n buildArcPath,\n buildNeedlePath,\n parseThresholds,\n buildThresholdBands,\n buildBandSegments,\n buildScaleTicks,\n computeGaugeLayout,\n computeGaugeGeometry,\n formatGaugeValue,\n polarPoint\n} from './gaugeChartHelpers.js'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel.js'\nimport type { ChartProps, ThresholdBand } from '../../types.js'\n\n/**\n * Gauge chart: a 270° dial whose arc *is* the threshold banding — one thick,\n * rounded segment per threshold with a small gap between them — read by a\n * tapered needle, with numeric scale labels at the band boundaries and the\n * measure label + value stacked below the centre.\n *\n * All geometry lives in `gaugeChartHelpers.ts`; this component only renders it.\n */\nconst GaugeChart = React.memo(function GaugeChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n}: ChartProps) {\n const { t } = useTranslation()\n const getFieldLabel = useCubeFieldLabel()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const { valueField, maxField, configError } = useMemo(() => {\n const yAxis: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n const valueField = yAxis[0] ?? ''\n const maxField = yAxis[1] ?? ''\n\n if (!valueField) {\n return { valueField, maxField, configError: 'Gauge requires at least 1 measure in Y-Axis (current value)' }\n }\n return { valueField, maxField, configError: null }\n }, [chartConfig])\n\n const thresholds: ThresholdBand[] = useMemo(\n () => parseThresholds(displayConfig?.thresholds),\n [displayConfig?.thresholds]\n )\n\n const bands = useMemo(() => buildThresholdBands(thresholds), [thresholds])\n const segments = useMemo(() => buildBandSegments(bands), [bands])\n\n try {\n if (!data || data.length === 0) {\n return <ChartEmptyState height={height} hint={t('chart.runtime.noDataHint.gauge')} />\n }\n\n if (configError) {\n return <ChartConfigError height={height} hint={configError} />\n }\n\n const row = (data as Record<string, unknown>[])[0]\n const rawValue = parseNum(row[valueField])\n if (rawValue === null || !Number.isFinite(rawValue)) {\n return (\n <ChartEmptyState\n height={height}\n titleKey=\"chart.runtime.noValidData\"\n hint={t('chart.runtime.noValidDataHint.gauge')}\n />\n )\n }\n\n const minValue = finiteOr(displayConfig?.minValue, 0)\n const maxFieldValue = maxField ? parseNum(row[maxField]) : null\n const maxValue = finiteOr(displayConfig?.maxValue ?? maxFieldValue, 100)\n\n const { effectiveMax, fraction, fillColor, needleAngle } =\n computeGaugeGeometry(rawValue, minValue, maxValue, thresholds)\n\n const showCenterLabel = displayConfig?.showCenterLabel ?? true\n const showPercentage = displayConfig?.showPercentage ?? false\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const containerW = dimensions.width || 300\n const containerH = typeof height === 'number' ? height : (dimensions.height || 200)\n\n const layout = computeGaugeLayout(containerW, containerH)\n const ticks = buildScaleTicks(bands, minValue, effectiveMax)\n\n const valueLabel = showPercentage\n ? `${(fraction * 100).toFixed(1)}%`\n : formatGaugeValue(rawValue, yAxisFormat)\n\n const fieldLabel = getFieldLabel(valueField)\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height=\"100%\"\n viewBox={`0 0 ${containerW} ${containerH}`}\n preserveAspectRatio=\"xMidYMid meet\"\n data-testid=\"gauge-svg\"\n >\n <g transform={`translate(${layout.cx}, ${layout.cy})`}>\n {segments.map((segment, i) => (\n <path\n key={i}\n d={buildArcPath(\n layout.innerRadius,\n layout.outerRadius,\n segment.startAngle,\n segment.endAngle,\n layout.bandCornerRadius\n )}\n fill={segment.color}\n data-testid={`gauge-band-${i}`}\n />\n ))}\n\n {ticks.map((tick, i) => {\n const point = polarPoint(tick.angle, layout.tickRadius)\n return (\n <text\n key={i}\n x={point.x}\n y={point.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontSize={layout.tickFontSize}\n fill=\"currentColor\"\n className=\"text-dc-text-muted\"\n data-testid={`gauge-tick-${i}`}\n >\n {formatGaugeValue(tick.value, yAxisFormat)}\n </text>\n )\n })}\n\n <path\n d={buildNeedlePath(needleAngle, layout.needleLength, layout.needleHalfWidth)}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-needle\"\n data-fraction={fraction.toFixed(4)}\n data-color={fillColor}\n />\n <circle\n r={layout.hubRadius}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-hub\"\n />\n\n {showCenterLabel && (\n <g data-testid=\"gauge-label\">\n <text\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n y={layout.labelY}\n fontSize={layout.labelFontSize}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid=\"gauge-field-text\"\n >\n {fieldLabel}\n </text>\n <text\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n y={layout.valueY}\n fontSize={layout.valueFontSize}\n fontWeight=\"600\"\n fill=\"currentColor\"\n className=\"text-dc-text\"\n data-testid=\"gauge-value-text\"\n >\n {valueLabel}\n </text>\n </g>\n )}\n </g>\n </svg>\n </div>\n )\n } catch (error) {\n return <ChartRenderError height={height} chartType=\"Gauge Chart\" error={error} />\n }\n})\n\nexport default GaugeChart\n"],"x_google_ignoreList":[0,1,2,3,4],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
-
import { D as t, E as n,
|
|
3
|
-
import { O as a } from "./chart-area-
|
|
2
|
+
import { D as t, E as n, F as r, w as i } from "./chart-activity-grid-DO82rrbW.js";
|
|
3
|
+
import { O as a } from "./chart-area-9SBeG0GM.js";
|
|
4
4
|
import o, { useMemo as s } from "react";
|
|
5
5
|
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
6
6
|
import { ResponsiveHeatMap as d } from "@nivo/heatmap";
|
|
@@ -233,4 +233,4 @@ var w = /* @__PURE__ */ e({ default: () => T }), T = o.memo(function({ data: e,
|
|
|
233
233
|
//#endregion
|
|
234
234
|
export { w as t };
|
|
235
235
|
|
|
236
|
-
//# sourceMappingURL=chart-heat-map-
|
|
236
|
+
//# sourceMappingURL=chart-heat-map-q7Vf_dog.js.map
|