drizzle-cube 0.9.6 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/adapters/ActivityGridChart.config-BGndyZtr.cjs +1 -0
- package/dist/adapters/ActivityGridChart.config-ZdvHJAHq.js +2 -0
- package/dist/adapters/AreaChart.config-Cybigwcb.js +2 -0
- package/dist/adapters/AreaChart.config-DWGesxUg.cjs +1 -0
- package/dist/adapters/BarChart.config-Cc04tVQF.js +2 -0
- package/dist/adapters/BarChart.config-DBCu0t_-.cjs +1 -0
- package/dist/adapters/BoxPlotChart.config-C0WK_ipa.cjs +1 -0
- package/dist/adapters/BoxPlotChart.config-DapOUN_R.js +2 -0
- package/dist/adapters/BubbleChart.config-DPmf7sI5.cjs +1 -0
- package/dist/adapters/BubbleChart.config-DROSTwxW.js +2 -0
- package/dist/adapters/CandlestickChart.config-BHoEJ2nY.js +2 -0
- package/dist/adapters/CandlestickChart.config-Cm0PKObO.cjs +1 -0
- package/dist/adapters/DataTable.config-DLvfXXSH.cjs +1 -0
- package/dist/adapters/DataTable.config-DbVrWZIw.js +2 -0
- package/dist/adapters/DotStripChart.config-CKPw82HE.js +2 -0
- package/dist/adapters/DotStripChart.config-DPIrTLb6.cjs +1 -0
- package/dist/adapters/FunnelChart.config-DpiDbOTn.cjs +1 -0
- package/dist/adapters/FunnelChart.config-DtBHVpLB.js +2 -0
- package/dist/adapters/GaugeChart.config-CmuXGRNV.js +2 -0
- package/dist/adapters/GaugeChart.config-DLj1YNsp.cjs +1 -0
- package/dist/adapters/HeatMapChart.config-BvFK2bny.cjs +1 -0
- package/dist/adapters/HeatMapChart.config-DK18zZV8.js +2 -0
- package/dist/adapters/KpiDelta.config-BsaVN5-T.js +2 -0
- package/dist/adapters/KpiDelta.config-DHsMgIdk.cjs +1 -0
- package/dist/adapters/KpiNumber.config-D82-j-8T.js +2 -0
- package/dist/adapters/KpiNumber.config-pFRomJRE.cjs +1 -0
- package/dist/adapters/KpiText.config-CCqeKuFB.js +2 -0
- package/dist/adapters/KpiText.config-CSeCoBuO.cjs +1 -0
- package/dist/adapters/LineChart.config-C2acjFv4.js +2 -0
- package/dist/adapters/LineChart.config-Dr9wmiK0.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-C-tYLLan.js +2 -0
- package/dist/adapters/MarkdownChart.config-Dvyfo0CB.cjs +1 -0
- package/dist/adapters/MeasureProfileChart.config-C5CjPw48.js +2 -0
- package/dist/adapters/MeasureProfileChart.config-Dj-7HqkS.cjs +1 -0
- package/dist/adapters/PieChart.config-CY7nFFQn.cjs +1 -0
- package/dist/adapters/PieChart.config-DQLQMHc_.js +2 -0
- package/dist/adapters/ProportionBarChart.config-BVqtS7wi.cjs +1 -0
- package/dist/adapters/ProportionBarChart.config-BaSgs976.js +2 -0
- package/dist/adapters/RadarChart.config-DxJ5k8L9.cjs +1 -0
- package/dist/adapters/RadarChart.config-DzL7zQUc.js +2 -0
- package/dist/adapters/RadialBarChart.config-Dzl1HiGz.js +2 -0
- package/dist/adapters/RadialBarChart.config-XlGTd9gV.cjs +1 -0
- package/dist/adapters/RecordsTable.config-CS5oIMvv.js +2 -0
- package/dist/adapters/RecordsTable.config-DRQdHghk.cjs +1 -0
- package/dist/adapters/RetentionCombinedChart.config-C0iiKOdf.js +2 -0
- package/dist/adapters/RetentionCombinedChart.config-Dl20GZnb.cjs +1 -0
- package/dist/adapters/RetentionHeatmap.config-Bt42ip_c.js +2 -0
- package/dist/adapters/RetentionHeatmap.config-DyggEvyy.cjs +1 -0
- package/dist/adapters/SankeyChart.config-DYz1nUx9.js +2 -0
- package/dist/adapters/SankeyChart.config-dlNLJMf9.cjs +1 -0
- package/dist/adapters/ScatterChart.config-D72zRviD.js +2 -0
- package/dist/adapters/ScatterChart.config-DRtyuQvV.cjs +1 -0
- package/dist/adapters/SunburstChart.config-C5nHXLcu.cjs +1 -0
- package/dist/adapters/SunburstChart.config-j5ioABeT.js +2 -0
- package/dist/adapters/TreeMapChart.config-CXKcX5CH.js +2 -0
- package/dist/adapters/TreeMapChart.config-DuYbme03.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-BCn4tsBV.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-BPqhdzTP.js +2 -0
- package/dist/adapters/{compiler-CpvetSCm.js → compiler-BKg3j2mm.js} +1260 -2446
- package/dist/adapters/compiler-BX6Ug_Uq.cjs +166 -0
- package/dist/adapters/core/index.cjs +1 -1
- package/dist/adapters/core/index.js +1 -1
- package/dist/adapters/{core-BH_56XtM.js → core-Bmb7XMBz.js} +2 -2
- package/dist/adapters/{core-CydD6oFu.cjs → core-JgUTMhxl.cjs} +1 -1
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.js +5 -5
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.js +23 -23
- package/dist/adapters/{handler-CtcALGcY.js → handler-CknKLUQW.js} +213 -209
- package/dist/adapters/{handler-Dp8fpSpk.cjs → handler-DLWgxPOk.cjs} +8 -8
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +4 -4
- package/dist/adapters/mcp-app-html-Bu4j3yZM.cjs +1 -0
- package/dist/adapters/{mcp-app-html-C8vG9epH.js → mcp-app-html-D3GsxPcx.js} +1 -1
- package/dist/adapters/mcp-app-html.cjs +1 -1
- package/dist/adapters/mcp-app-html.js +1 -1
- package/dist/adapters/mcp-tools.cjs +1 -1
- package/dist/adapters/mcp-tools.js +3 -3
- package/dist/adapters/{mcp-transport-DDxjqyuK.js → mcp-transport-BTmAXLo8.js} +8 -3
- package/dist/adapters/{mcp-transport-QGYYYSgR.cjs → mcp-transport-DzxluRyH.cjs} +2 -2
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +5 -5
- package/dist/adapters/openai-CDH_AU_Z.cjs +19 -0
- package/dist/adapters/{openai-pCkHdDh4.js → openai-CYTlIdxS.js} +1 -1
- package/dist/adapters/{openai-Cm4JcLuF.cjs → openai-KbobaAQj.cjs} +1 -1
- package/dist/adapters/{openai-DH5InEPj.js → openai-enh3Hkzr.js} +510 -439
- package/dist/adapters/utils-Du_UZbn5.cjs +139 -0
- package/dist/adapters/{utils-C_Mc0qsk.js → utils-i2h5cwI3.js} +2587 -1254
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.js +1 -1
- package/dist/cjs/client/components/shared/dateRangeUtils.d.ts +7 -3
- package/dist/cjs/server/adapters/base-adapter.d.ts +3 -3
- package/dist/cjs/server/ai/query-schema.d.ts +3 -3
- package/dist/cjs/server/builders/date-time-builder.d.ts +1 -2
- package/dist/cjs/server/builders/date-time-helpers.d.ts +19 -6
- package/dist/cjs/server/builders/filter-operators.d.ts +10 -1
- package/dist/cjs/server/execution/query-normalizer.d.ts +9 -0
- package/dist/cjs/server/physical-plan/drizzle-sql-builder.d.ts +25 -0
- package/dist/cjs/server/physical-plan/semi-join.d.ts +21 -0
- package/dist/cjs/server/prompts/single-step-prompt.d.ts +1 -1
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/{DashboardEditModal-USQFytJw.js → DashboardEditModal-CiN77tQN.js} +662 -540
- package/dist/client/chunks/DashboardEditModal-CiN77tQN.js.map +1 -0
- package/dist/client/chunks/{DotStripChart-CjSsunHE.js → DotStripChart-in6QHc0b.js} +3 -3
- package/dist/client/chunks/{DotStripChart-CjSsunHE.js.map → DotStripChart-in6QHc0b.js.map} +1 -1
- package/dist/client/chunks/{ProportionBarChart-B8UyZBO_.js → ProportionBarChart-CjuOm7NT.js} +3 -3
- package/dist/client/chunks/{ProportionBarChart-B8UyZBO_.js.map → ProportionBarChart-CjuOm7NT.js.map} +1 -1
- package/dist/client/chunks/{RecordsTable-BSmkwdgd.js → RecordsTable-CXXsiaV1.js} +4 -4
- package/dist/client/chunks/{RecordsTable-BSmkwdgd.js.map → RecordsTable-CXXsiaV1.js.map} +1 -1
- package/dist/client/chunks/{RetentionCombinedChart-rOdIhUGH.js → RetentionCombinedChart-DFCeEFkx.js} +3 -3
- package/dist/client/chunks/{RetentionCombinedChart-rOdIhUGH.js.map → RetentionCombinedChart-DFCeEFkx.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-DVm_7rph.js → RetentionHeatmap-jpshJ2Af.js} +2 -2
- package/dist/client/chunks/{RetentionHeatmap-DVm_7rph.js.map → RetentionHeatmap-jpshJ2Af.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-D_tw9BvU.js → analysis-builder-DIOnKxJu.js} +41 -41
- package/dist/client/chunks/{analysis-builder-D_tw9BvU.js.map → analysis-builder-DIOnKxJu.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-BSINKFr2.js → analysis-builder-shared-CoX_nmo0.js} +640 -778
- package/dist/client/chunks/analysis-builder-shared-CoX_nmo0.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-CSIsJ12e.js → chart-activity-grid-DGazwi4C.js} +9 -2
- package/dist/client/chunks/chart-activity-grid-DGazwi4C.js.map +1 -0
- package/dist/client/chunks/{chart-area-BpvSKH5I.js → chart-area-zyLGD-ym.js} +2 -2
- package/dist/client/chunks/{chart-area-BpvSKH5I.js.map → chart-area-zyLGD-ym.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-Cjzv-LvG.js → chart-bar-DMCBq8qJ.js} +3 -3
- package/dist/client/chunks/{chart-bar-Cjzv-LvG.js.map → chart-bar-DMCBq8qJ.js.map} +1 -1
- package/dist/client/chunks/{chart-box-plot-DHsHfMt6.js → chart-box-plot-5Z55A-it.js} +2 -2
- package/dist/client/chunks/{chart-box-plot-DHsHfMt6.js.map → chart-box-plot-5Z55A-it.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BtWm6x7L.js → chart-bubble-YD28dX8w.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BtWm6x7L.js.map → chart-bubble-YD28dX8w.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-Bz0_fLuq.js → chart-candlestick-BUMpBI08.js} +2 -2
- package/dist/client/chunks/{chart-candlestick-Bz0_fLuq.js.map → chart-candlestick-BUMpBI08.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-BH1A-1RN.js → chart-data-table-BdMo3zVh.js} +2 -2
- package/dist/client/chunks/chart-data-table-BdMo3zVh.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-C_-K4RLj.js → chart-funnel-BRyZS6ie.js} +2 -2
- package/dist/client/chunks/{chart-funnel-C_-K4RLj.js.map → chart-funnel-BRyZS6ie.js.map} +1 -1
- package/dist/client/chunks/{chart-gauge-F-vdq2BX.js → chart-gauge-DxgHlZKp.js} +3 -3
- package/dist/client/chunks/{chart-gauge-F-vdq2BX.js.map → chart-gauge-DxgHlZKp.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-D_8TluGo.js → chart-heat-map-5jHm3f-V.js} +3 -3
- package/dist/client/chunks/{chart-heat-map-D_8TluGo.js.map → chart-heat-map-5jHm3f-V.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-DGvQ0BHZ.js → chart-kpi-delta-C84P-mwu.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-DGvQ0BHZ.js.map → chart-kpi-delta-C84P-mwu.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-DP6zCh-c.js → chart-kpi-number-D9GqtBWw.js} +5 -5
- package/dist/client/chunks/{chart-kpi-number-DP6zCh-c.js.map → chart-kpi-number-D9GqtBWw.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-DDbWfMwK.js → chart-kpi-text-D3HqxXzU.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-DDbWfMwK.js.map → chart-kpi-text-D3HqxXzU.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DlhmQQ-X.js → chart-line-IEgiF8Nv.js} +3 -3
- package/dist/client/chunks/{chart-line-DlhmQQ-X.js.map → chart-line-IEgiF8Nv.js.map} +1 -1
- package/dist/client/chunks/{chart-markdown-C5ldCjSN.js → chart-markdown-B_2Ed7FJ.js} +2 -2
- package/dist/client/chunks/{chart-markdown-C5ldCjSN.js.map → chart-markdown-B_2Ed7FJ.js.map} +1 -1
- package/dist/client/chunks/{chart-measure-profile-CjErXQI4.js → chart-measure-profile-CWsPrQhH.js} +3 -3
- package/dist/client/chunks/{chart-measure-profile-CjErXQI4.js.map → chart-measure-profile-CWsPrQhH.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-CmKhmUR-.js → chart-pie-BEB2sCXF.js} +3 -3
- package/dist/client/chunks/{chart-pie-CmKhmUR-.js.map → chart-pie-BEB2sCXF.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-B2bYTyb0.js → chart-radar-BbSbXKbP.js} +3 -3
- package/dist/client/chunks/{chart-radar-B2bYTyb0.js.map → chart-radar-BbSbXKbP.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DvQ-xZS-.js → chart-radial-bar-CNYD7tkM.js} +3 -3
- package/dist/client/chunks/{chart-radial-bar-DvQ-xZS-.js.map → chart-radial-bar-CNYD7tkM.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-DHIrjmhj.js → chart-sankey-DKnTIvSr.js} +2 -2
- package/dist/client/chunks/{chart-sankey-DHIrjmhj.js.map → chart-sankey-DKnTIvSr.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-JnoA3CD5.js → chart-scatter-CSWF6-lx.js} +3 -3
- package/dist/client/chunks/{chart-scatter-JnoA3CD5.js.map → chart-scatter-CSWF6-lx.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-BtzRp5bg.js → chart-sunburst-CdGzCq7q.js} +3 -3
- package/dist/client/chunks/{chart-sunburst-BtzRp5bg.js.map → chart-sunburst-CdGzCq7q.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-HQitd39D.js → chart-tree-map-BiXB7EiM.js} +3 -3
- package/dist/client/chunks/{chart-tree-map-HQitd39D.js.map → chart-tree-map-BiXB7EiM.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-Dd3HMz3p.js → chart-waterfall-5rSDeLEZ.js} +3 -3
- package/dist/client/chunks/{chart-waterfall-Dd3HMz3p.js.map → chart-waterfall-5rSDeLEZ.js.map} +1 -1
- package/dist/client/chunks/{charts-core-CQFOTTPb.js → charts-core-CKpkoMCa.js} +2 -2
- package/dist/client/chunks/{charts-core-CQFOTTPb.js.map → charts-core-CKpkoMCa.js.map} +1 -1
- package/dist/client/chunks/charts-loader-BTI0UPK4.js +87 -0
- package/dist/client/chunks/{charts-loader-BlxEsp39.js.map → charts-loader-BTI0UPK4.js.map} +1 -1
- package/dist/client/chunks/{nl-NL-gaWTnOGQ.js → nl-NL-kRjxedTf.js} +8 -1
- package/dist/client/chunks/{nl-NL-gaWTnOGQ.js.map → nl-NL-kRjxedTf.js.map} +1 -1
- package/dist/client/chunks/{schema-visualization-BspQ-XB8.js → schema-visualization-BbvL74Sf.js} +3 -3
- package/dist/client/chunks/{schema-visualization-BspQ-XB8.js.map → schema-visualization-BbvL74Sf.js.map} +1 -1
- package/dist/client/chunks/{useDirtyStateTracking-DY5sjvb6.js → useDirtyStateTracking-BfG1lX_3.js} +4 -4
- package/dist/client/chunks/{useDirtyStateTracking-DY5sjvb6.js.map → useDirtyStateTracking-BfG1lX_3.js.map} +1 -1
- package/dist/client/chunks/{useExplainAI-BY0Ti3FZ.js → useExplainAI-CDFhgmpE.js} +4 -4
- package/dist/client/chunks/{useExplainAI-BY0Ti3FZ.js.map → useExplainAI-CDFhgmpE.js.map} +1 -1
- package/dist/client/chunks/{vendor-C4pD7rZf.js → vendor-DeckzF1j.js} +2 -2
- package/dist/client/chunks/{vendor-C4pD7rZf.js.map → vendor-DeckzF1j.js.map} +1 -1
- package/dist/client/components/shared/dateRangeUtils.d.ts +7 -3
- package/dist/client/components.js +2 -2
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +18 -18
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/utils.js +4 -4
- package/dist/client-bundle-stats.html +1 -1
- package/dist/mcp-app/mcp-app.html +2 -2
- package/dist/server/adapters/base-adapter.d.ts +3 -3
- package/dist/server/ai/query-schema.d.ts +3 -3
- package/dist/server/builders/date-time-builder.d.ts +1 -2
- package/dist/server/builders/date-time-helpers.d.ts +19 -6
- package/dist/server/builders/filter-operators.d.ts +10 -1
- package/dist/server/execution/query-normalizer.d.ts +9 -0
- package/dist/server/index.cjs +54 -47
- package/dist/server/index.js +2562 -2409
- package/dist/server/{openai-D346-vmt.cjs → openai-BIHkBS7X.cjs} +1 -1
- package/dist/server/{openai-SILGL2q_.js → openai-CPW5x6kl.js} +1 -1
- package/dist/server/{openai-D0vh48Oi.js → openai-DCC49vC6.js} +507 -436
- package/dist/server/openai-xQRpdAPa.cjs +19 -0
- package/dist/server/physical-plan/drizzle-sql-builder.d.ts +25 -0
- package/dist/server/physical-plan/semi-join.d.ts +21 -0
- package/dist/server/prompts/single-step-prompt.d.ts +1 -1
- package/package.json +3 -3
- package/dist/adapters/ActivityGridChart.config-BgAUfqKS.js +0 -2
- package/dist/adapters/ActivityGridChart.config-CGsjbfYL.cjs +0 -1
- package/dist/adapters/AreaChart.config-Bmj24k3G.cjs +0 -1
- package/dist/adapters/AreaChart.config-DqJvquc-.js +0 -2
- package/dist/adapters/BarChart.config-CzGxsUq-.js +0 -2
- package/dist/adapters/BarChart.config-D1uQGV6T.cjs +0 -1
- package/dist/adapters/BoxPlotChart.config-I0S4-aNF.js +0 -2
- package/dist/adapters/BoxPlotChart.config-wfS4FxGI.cjs +0 -1
- package/dist/adapters/BubbleChart.config-BDSknEkc.js +0 -2
- package/dist/adapters/BubbleChart.config-CByvW3Rq.cjs +0 -1
- package/dist/adapters/CandlestickChart.config-08gqS1xj.cjs +0 -1
- package/dist/adapters/CandlestickChart.config-Bkr9bdwM.js +0 -2
- package/dist/adapters/DataTable.config-BFP6xnMc.cjs +0 -1
- package/dist/adapters/DataTable.config-DHYD7PA8.js +0 -2
- package/dist/adapters/DotStripChart.config-DRQybZZu.cjs +0 -1
- package/dist/adapters/DotStripChart.config-Sp0fOxfM.js +0 -2
- package/dist/adapters/FunnelChart.config-ByARozX6.cjs +0 -1
- package/dist/adapters/FunnelChart.config-DhCqap3P.js +0 -2
- package/dist/adapters/GaugeChart.config-CfRicB1o.cjs +0 -1
- package/dist/adapters/GaugeChart.config-PTQ85WM5.js +0 -2
- package/dist/adapters/HeatMapChart.config-0tmGHwm2.cjs +0 -1
- package/dist/adapters/HeatMapChart.config-Devz5A5U.js +0 -2
- package/dist/adapters/KpiDelta.config-CGTdddOM.js +0 -2
- package/dist/adapters/KpiDelta.config-CjWmwXjk.cjs +0 -1
- package/dist/adapters/KpiNumber.config-Cd4jw22d.cjs +0 -1
- package/dist/adapters/KpiNumber.config-D3Et71Zn.js +0 -2
- package/dist/adapters/KpiText.config-B9VATPy2.js +0 -2
- package/dist/adapters/KpiText.config-B_dkrdHj.cjs +0 -1
- package/dist/adapters/LineChart.config-C3p-mc15.cjs +0 -1
- package/dist/adapters/LineChart.config-DXWLMWjn.js +0 -2
- package/dist/adapters/MarkdownChart.config-BQGmd6Iz.js +0 -2
- package/dist/adapters/MarkdownChart.config-CQFu4297.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-CXLeprVS.js +0 -2
- package/dist/adapters/MeasureProfileChart.config-KpfD016N.cjs +0 -1
- package/dist/adapters/PieChart.config-j-syrhBx.js +0 -2
- package/dist/adapters/PieChart.config-zzBPh0tx.cjs +0 -1
- package/dist/adapters/ProportionBarChart.config-BD9bf-LZ.js +0 -2
- package/dist/adapters/ProportionBarChart.config-CBLcLV4Z.cjs +0 -1
- package/dist/adapters/RadarChart.config-CW9f_VxU.cjs +0 -1
- package/dist/adapters/RadarChart.config-yKvcZ49V.js +0 -2
- package/dist/adapters/RadialBarChart.config-DwQYejI6.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-xK4AyoOF.js +0 -2
- package/dist/adapters/RecordsTable.config-CquV7Wi0.js +0 -2
- package/dist/adapters/RecordsTable.config-DzrQXBvh.cjs +0 -1
- package/dist/adapters/RetentionCombinedChart.config-BYAFkFb-.cjs +0 -1
- package/dist/adapters/RetentionCombinedChart.config-Ddmb-WwM.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-CSHXD736.cjs +0 -1
- package/dist/adapters/RetentionHeatmap.config-DODcy3gK.js +0 -2
- package/dist/adapters/SankeyChart.config-B56o6GFu.js +0 -2
- package/dist/adapters/SankeyChart.config-DLnhr2k_.cjs +0 -1
- package/dist/adapters/ScatterChart.config-CrIFaC-s.js +0 -2
- package/dist/adapters/ScatterChart.config-Dfj1_af-.cjs +0 -1
- package/dist/adapters/SunburstChart.config-CuLsLj6v.cjs +0 -1
- package/dist/adapters/SunburstChart.config-CvuVUfkp.js +0 -2
- package/dist/adapters/TreeMapChart.config-CvbDr1Ic.js +0 -2
- package/dist/adapters/TreeMapChart.config-Dqjhe8Xk.cjs +0 -1
- package/dist/adapters/WaterfallChart.config-DXFeGg7P.cjs +0 -1
- package/dist/adapters/WaterfallChart.config-MLHPNE5q.js +0 -2
- package/dist/adapters/compiler-C5OSdfwn.cjs +0 -166
- package/dist/adapters/mcp-app-html-DRWnkcx4.cjs +0 -1
- package/dist/adapters/openai-CwKv0DD-.cjs +0 -19
- package/dist/adapters/utils-BFGzuSlF.cjs +0 -132
- package/dist/client/chunks/DashboardEditModal-USQFytJw.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-BSINKFr2.js.map +0 -1
- package/dist/client/chunks/chart-activity-grid-CSIsJ12e.js.map +0 -1
- package/dist/client/chunks/chart-data-table-BH1A-1RN.js.map +0 -1
- package/dist/client/chunks/charts-loader-BlxEsp39.js +0 -87
- package/dist/server/openai-C6tdx3yN.cjs +0 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RetentionCombinedChart-rOdIhUGH.js","names":[],"sources":["../../../src/client/components/charts/RetentionCombinedChart.tsx"],"sourcesContent":["/**\n * RetentionCombinedChart Component\n *\n * Combined visualization for retention analysis data.\n * Supports multiple display modes: heatmap, line chart, or combined view.\n *\n * Features:\n * - X-axis: Period numbers (P0, P1, P2...)\n * - Y-axis: Retention % (0-100%)\n * - Lines: One per breakdown value (or single if no breakdown)\n * - Display modes: 'heatmap' | 'line' | 'combined'\n * - Heatmap shows color-coded retention matrix\n * - Line chart shows retention curves over periods\n */\n\nimport React, { useMemo, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport {\n ComposedChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Legend,\n} from 'recharts'\nimport ChartContainer from './ChartContainer.js'\nimport ChartTooltip from './ChartTooltip.js'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants.js'\nimport type { ChartProps } from '../../types.js'\nimport type { RetentionChartData, RetentionResultRow, RetentionGranularity } from '../../types/retention.js'\nimport { isRetentionData } from '../../types/retention.js'\n\n/**\n * Retention display mode\n * - 'heatmap': Show retention as color-coded bars\n * - 'line': Show retention as line curves\n * - 'combined': Show both heatmap background and line overlay\n */\nexport type RetentionDisplayMode = 'heatmap' | 'line' | 'combined'\n\n/**\n * Get color with opacity based on retention rate for heatmap cells\n * Uses a green gradient: higher retention = more saturated green\n */\nfunction getRetentionColor(rate: number): string {\n const clampedRate = Math.max(0, Math.min(1, rate))\n const alpha = 0.1 + clampedRate * 0.7\n return `rgba(34, 197, 94, ${alpha})`\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(rate: number): string {\n return `${Math.round(rate * 100)}%`\n}\n\n/**\n * Format period label based on granularity\n * Period 0 shows \"< 1 Day\" / \"< 1 Week\" etc. to indicate the initial cohort\n * e.g., Period 0 with 'week' granularity → \"< 1 Week\", Period 1 → \"Week 1\"\n */\nfunction formatPeriodLabel(period: number, granularity?: RetentionGranularity): string {\n const prefix = granularity === 'day' ? 'Day'\n : granularity === 'week' ? 'Week'\n : granularity === 'month' ? 'Month'\n : 'P' // Fallback to P0, P1, etc.\n\n // Period 0 is special - shows \"< 1 Day\" / \"< 1 Week\" etc.\n if (period === 0) {\n return granularity ? `< 1 ${prefix}` : 'P0'\n }\n\n return granularity ? `${prefix} ${period}` : `P${period}`\n}\n\n/**\n * Get display label for the cohort total column\n * Shows \"Total\" regardless of binding key - it's the cohort size count\n */\nfunction getCohortLabel(_bindingKeyLabel?: string): string {\n return 'Total'\n}\n\n/**\n * Get default series name based on binding key\n * e.g., \"userId\" → \"userId Retention\", null → \"Retention\"\n */\nfunction getDefaultSeriesName(bindingKeyLabel?: string): string {\n if (!bindingKeyLabel) return 'Retention'\n return `${bindingKeyLabel} Retention`\n}\n\n/**\n * Transform retention data for chart display\n * Groups data by period with breakdown values as series\n */\nfunction transformRetentionData(\n rows: RetentionResultRow[],\n periods: number[],\n breakdownValues?: string[],\n granularity?: RetentionGranularity,\n bindingKeyLabel?: string\n): { chartData: any[]; seriesKeys: string[]; defaultSeriesName: string } {\n const defaultSeriesName = getDefaultSeriesName(bindingKeyLabel)\n\n // If no breakdown, single series\n if (!breakdownValues || breakdownValues.length === 0) {\n const chartData = periods.map((period) => {\n const row = rows.find((r) => r.period === period && !r.breakdownValue)\n return {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n [defaultSeriesName]: row ? row.retentionRate : null,\n cohortSize: row?.cohortSize ?? 0,\n retainedUsers: row?.retainedUsers ?? 0,\n }\n })\n return { chartData, seriesKeys: [defaultSeriesName], defaultSeriesName }\n }\n\n // With breakdown, create series per breakdown value\n const chartData = periods.map((period) => {\n const dataPoint: any = {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n }\n\n breakdownValues.forEach((bv) => {\n const row = rows.find((r) => r.period === period && r.breakdownValue === bv)\n dataPoint[bv] = row ? row.retentionRate : null\n dataPoint[`${bv}_cohortSize`] = row?.cohortSize ?? 0\n dataPoint[`${bv}_retainedUsers`] = row?.retainedUsers ?? 0\n })\n\n return dataPoint\n })\n\n return { chartData, seriesKeys: breakdownValues, defaultSeriesName }\n}\n\ninterface TooltipData {\n period: number\n breakdownValue?: string | null\n cohortSize: number\n retainedUsers: number\n retentionRate: number\n x: number\n y: number\n}\n\n/**\n * RetentionCombinedChart Component\n */\nconst RetentionCombinedChart = React.memo(function RetentionCombinedChart({\n data,\n height = '100%',\n displayConfig,\n colorPalette,\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n const [heatmapTooltip, setHeatmapTooltip] = useState<TooltipData | null>(null)\n\n // Parse retention data\n const retentionData = useMemo<RetentionChartData | null>(() => {\n if (!data) return null\n\n // Check if data is already in RetentionChartData format\n if (isRetentionData(data)) {\n return data\n }\n\n // If data is an array of RetentionResultRow, convert it\n if (Array.isArray(data) && data.length > 0) {\n const rows = data as RetentionResultRow[]\n const periods = [...new Set(rows.map((r) => r.period))].sort((a, b) => a - b)\n const breakdownValues = [\n ...new Set(rows.filter((r) => r.breakdownValue).map((r) => r.breakdownValue!)),\n ]\n\n return {\n rows,\n periods,\n breakdownValues: breakdownValues.length > 0 ? breakdownValues : undefined,\n }\n }\n\n return null\n }, [data])\n\n // Transform data for chart\n const { chartData, seriesKeys, defaultSeriesName } = useMemo(() => {\n if (!retentionData) {\n return { chartData: [], seriesKeys: [], defaultSeriesName: 'Retention' }\n }\n return transformRetentionData(\n retentionData.rows,\n retentionData.periods,\n retentionData.breakdownValues,\n retentionData.granularity,\n retentionData.bindingKeyLabel\n )\n }, [retentionData])\n\n // Get cohort label for heatmap column header\n const cohortLabel = getCohortLabel(retentionData?.bindingKeyLabel)\n\n // Display mode from config\n const displayMode: RetentionDisplayMode =\n (displayConfig as any)?.retentionDisplayMode || 'line'\n\n const showLegend = displayConfig?.showLegend ?? true\n const showGrid = displayConfig?.showGrid ?? true\n const showTooltip = displayConfig?.showTooltip ?? true\n\n // Handle empty/loading states\n if (!data || (Array.isArray(data) && data.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.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.retention')}\n </div>\n </div>\n </div>\n )\n }\n\n if (!chartData || chartData.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.unableToRender')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.dataFormatIncorrect')}</div>\n </div>\n </div>\n )\n }\n\n // Render line chart component (reused in line and combined modes)\n const renderLineChart = (chartHeight: string | number) => {\n const chartMargins = {\n ...CHART_MARGINS,\n left: 50,\n right: 20,\n }\n\n return (\n <ChartContainer height={chartHeight}>\n <ComposedChart data={chartData} margin={chartMargins} accessibilityLayer={false}>\n {showGrid && <CartesianGrid strokeDasharray=\"3 3\" />}\n <XAxis\n dataKey=\"periodLabel\"\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n />\n <YAxis\n domain={[0, 1]}\n tickFormatter={(value) => formatPercentage(value)}\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n label={{\n value: 'Retention %',\n angle: -90,\n position: 'insideLeft',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-secondary)' },\n }}\n />\n {showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: string) => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatPercentage(value), name]\n }}\n labelFormatter={(label: string) => label}\n />\n )}\n {showLegend && (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"line\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n\n {/* Render lines */}\n {seriesKeys.map((seriesKey, index) => (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n stroke={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n strokeWidth={2}\n dot={{ r: 4, strokeWidth: 2 }}\n activeDot={{ r: 6 }}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={false}\n />\n ))}\n </ComposedChart>\n </ChartContainer>\n )\n }\n\n // Render heatmap table component (reused in heatmap and combined modes)\n const renderHeatmapTable = () => (\n <table className=\"dc:w-full dc:border-collapse dc:text-sm\">\n <thead className=\"dc:sticky dc:top-0 bg-dc-bg dc:z-10\">\n <tr>\n <th className=\"dc:text-left dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[100px] dc:whitespace-nowrap\">\n {retentionData?.breakdownValues?.length ? 'Segment' : 'Cohort'}\n </th>\n <th className=\"dc:text-right dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[60px] dc:whitespace-nowrap\">\n {cohortLabel}\n </th>\n {retentionData?.periods.map((period) => (\n <th\n key={period}\n className=\"dc:text-center dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[70px] dc:whitespace-nowrap\"\n >\n {formatPeriodLabel(period, retentionData?.granularity)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {seriesKeys.map((seriesKey, rowIndex) => {\n const period0Data = chartData.find((d) => d.period === 0)\n const isDefaultSeries = seriesKey === defaultSeriesName\n const cohortSize = isDefaultSeries\n ? period0Data?.cohortSize ?? 0\n : period0Data?.[`${seriesKey}_cohortSize`] ?? 0\n\n return (\n <tr\n key={seriesKey}\n className={rowIndex % 2 === 0 ? 'bg-dc-bg' : 'bg-dc-surface-secondary'}\n >\n <td className=\"dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:whitespace-nowrap\">\n {seriesKey}\n </td>\n <td className=\"dc:p-2 dc:text-right text-dc-text-secondary dc:border-b border-dc-border\">\n {cohortSize.toLocaleString()}\n </td>\n {retentionData?.periods.map((period) => {\n const dataPoint = chartData.find((d) => d.period === period)\n const rate = dataPoint?.[seriesKey] ?? 0\n const bgColor = rate > 0 ? getRetentionColor(rate) : 'transparent'\n const textColor = rate > 0.5 ? '#ffffff' : 'var(--dc-text)'\n\n return (\n <td\n key={period}\n className=\"dc:p-2 dc:text-center dc:border-b border-dc-border dc:cursor-default dc:transition-opacity dc:hover:opacity-80\"\n style={{ backgroundColor: bgColor, color: textColor }}\n onMouseEnter={(e) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const retainedUsers = isDefaultSeries\n ? dataPoint?.retainedUsers ?? 0\n : dataPoint?.[`${seriesKey}_retainedUsers`] ?? 0\n setHeatmapTooltip({\n period,\n breakdownValue: isDefaultSeries ? null : seriesKey,\n cohortSize,\n retainedUsers,\n retentionRate: rate,\n x: rect.left + rect.width / 2,\n y: rect.top,\n })\n }}\n onMouseLeave={() => setHeatmapTooltip(null)}\n >\n {rate > 0 ? formatPercentage(rate) : '-'}\n </td>\n )\n })}\n </tr>\n )\n })}\n </tbody>\n </table>\n )\n\n // Render heatmap tooltip (shared between heatmap and combined modes)\n const renderHeatmapTooltip = () =>\n heatmapTooltip && (\n <div\n className=\"dc:fixed dc:z-50 dc:px-3 dc:py-2 bg-dc-surface dc:border border-dc-border dc:rounded-sm dc:shadow-lg dc:text-sm dc:pointer-events-none\"\n style={{\n left: heatmapTooltip.x,\n top: heatmapTooltip.y - 10,\n transform: 'translate(-50%, -100%)',\n }}\n >\n <div className=\"dc:font-medium text-dc-text dc:mb-1\">\n {heatmapTooltip.breakdownValue\n ? `${heatmapTooltip.breakdownValue} - ${formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}`\n : formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}\n </div>\n <div className=\"text-dc-text-secondary dc:space-y-0.5\">\n <div>{t('chart.runtime.retention.cohortSize', { count: heatmapTooltip.cohortSize.toLocaleString() })}</div>\n <div>{t('chart.runtime.retention.retained', { count: heatmapTooltip.retainedUsers.toLocaleString() })}</div>\n <div className=\"dc:font-medium text-dc-text\">\n {t('chart.runtime.retention.rate', { rate: formatPercentage(heatmapTooltip.retentionRate) })}\n </div>\n </div>\n </div>\n )\n\n // Render heatmap mode (table-based only)\n if (displayMode === 'heatmap') {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:overflow-auto\" style={{ height }}>\n {renderHeatmapTable()}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Combined mode: line chart on top, heatmap table below\n if (displayMode === 'combined') {\n return (\n <div className=\"dc:flex dc:flex-col dc:w-full dc:h-full\" style={{ height }}>\n {/* Line chart - takes remaining space after heatmap */}\n <div className=\"dc:flex-1 dc:min-h-[200px]\">\n {renderLineChart('100%')}\n </div>\n {/* Heatmap table - auto-height based on content, scrolls if needed */}\n <div className=\"dc:flex-shrink-0 dc:max-h-[40%] dc:overflow-auto dc:border-t border-dc-border\">\n {renderHeatmapTable()}\n </div>\n {/* Shared heatmap tooltip */}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Line mode: just the line chart\n return renderLineChart(height)\n})\n\nexport default RetentionCombinedChart\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RetentionCombinedChart-DFCeEFkx.js","names":[],"sources":["../../../src/client/components/charts/RetentionCombinedChart.tsx"],"sourcesContent":["/**\n * RetentionCombinedChart Component\n *\n * Combined visualization for retention analysis data.\n * Supports multiple display modes: heatmap, line chart, or combined view.\n *\n * Features:\n * - X-axis: Period numbers (P0, P1, P2...)\n * - Y-axis: Retention % (0-100%)\n * - Lines: One per breakdown value (or single if no breakdown)\n * - Display modes: 'heatmap' | 'line' | 'combined'\n * - Heatmap shows color-coded retention matrix\n * - Line chart shows retention curves over periods\n */\n\nimport React, { useMemo, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport {\n ComposedChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Legend,\n} from 'recharts'\nimport ChartContainer from './ChartContainer.js'\nimport ChartTooltip from './ChartTooltip.js'\nimport { CHART_COLORS, CHART_MARGINS } from '../../utils/chartConstants.js'\nimport type { ChartProps } from '../../types.js'\nimport type { RetentionChartData, RetentionResultRow, RetentionGranularity } from '../../types/retention.js'\nimport { isRetentionData } from '../../types/retention.js'\n\n/**\n * Retention display mode\n * - 'heatmap': Show retention as color-coded bars\n * - 'line': Show retention as line curves\n * - 'combined': Show both heatmap background and line overlay\n */\nexport type RetentionDisplayMode = 'heatmap' | 'line' | 'combined'\n\n/**\n * Get color with opacity based on retention rate for heatmap cells\n * Uses a green gradient: higher retention = more saturated green\n */\nfunction getRetentionColor(rate: number): string {\n const clampedRate = Math.max(0, Math.min(1, rate))\n const alpha = 0.1 + clampedRate * 0.7\n return `rgba(34, 197, 94, ${alpha})`\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(rate: number): string {\n return `${Math.round(rate * 100)}%`\n}\n\n/**\n * Format period label based on granularity\n * Period 0 shows \"< 1 Day\" / \"< 1 Week\" etc. to indicate the initial cohort\n * e.g., Period 0 with 'week' granularity → \"< 1 Week\", Period 1 → \"Week 1\"\n */\nfunction formatPeriodLabel(period: number, granularity?: RetentionGranularity): string {\n const prefix = granularity === 'day' ? 'Day'\n : granularity === 'week' ? 'Week'\n : granularity === 'month' ? 'Month'\n : 'P' // Fallback to P0, P1, etc.\n\n // Period 0 is special - shows \"< 1 Day\" / \"< 1 Week\" etc.\n if (period === 0) {\n return granularity ? `< 1 ${prefix}` : 'P0'\n }\n\n return granularity ? `${prefix} ${period}` : `P${period}`\n}\n\n/**\n * Get display label for the cohort total column\n * Shows \"Total\" regardless of binding key - it's the cohort size count\n */\nfunction getCohortLabel(_bindingKeyLabel?: string): string {\n return 'Total'\n}\n\n/**\n * Get default series name based on binding key\n * e.g., \"userId\" → \"userId Retention\", null → \"Retention\"\n */\nfunction getDefaultSeriesName(bindingKeyLabel?: string): string {\n if (!bindingKeyLabel) return 'Retention'\n return `${bindingKeyLabel} Retention`\n}\n\n/**\n * Transform retention data for chart display\n * Groups data by period with breakdown values as series\n */\nfunction transformRetentionData(\n rows: RetentionResultRow[],\n periods: number[],\n breakdownValues?: string[],\n granularity?: RetentionGranularity,\n bindingKeyLabel?: string\n): { chartData: any[]; seriesKeys: string[]; defaultSeriesName: string } {\n const defaultSeriesName = getDefaultSeriesName(bindingKeyLabel)\n\n // If no breakdown, single series\n if (!breakdownValues || breakdownValues.length === 0) {\n const chartData = periods.map((period) => {\n const row = rows.find((r) => r.period === period && !r.breakdownValue)\n return {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n [defaultSeriesName]: row ? row.retentionRate : null,\n cohortSize: row?.cohortSize ?? 0,\n retainedUsers: row?.retainedUsers ?? 0,\n }\n })\n return { chartData, seriesKeys: [defaultSeriesName], defaultSeriesName }\n }\n\n // With breakdown, create series per breakdown value\n const chartData = periods.map((period) => {\n const dataPoint: any = {\n period,\n periodLabel: formatPeriodLabel(period, granularity),\n }\n\n breakdownValues.forEach((bv) => {\n const row = rows.find((r) => r.period === period && r.breakdownValue === bv)\n dataPoint[bv] = row ? row.retentionRate : null\n dataPoint[`${bv}_cohortSize`] = row?.cohortSize ?? 0\n dataPoint[`${bv}_retainedUsers`] = row?.retainedUsers ?? 0\n })\n\n return dataPoint\n })\n\n return { chartData, seriesKeys: breakdownValues, defaultSeriesName }\n}\n\ninterface TooltipData {\n period: number\n breakdownValue?: string | null\n cohortSize: number\n retainedUsers: number\n retentionRate: number\n x: number\n y: number\n}\n\n/**\n * RetentionCombinedChart Component\n */\nconst RetentionCombinedChart = React.memo(function RetentionCombinedChart({\n data,\n height = '100%',\n displayConfig,\n colorPalette,\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n const [heatmapTooltip, setHeatmapTooltip] = useState<TooltipData | null>(null)\n\n // Parse retention data\n const retentionData = useMemo<RetentionChartData | null>(() => {\n if (!data) return null\n\n // Check if data is already in RetentionChartData format\n if (isRetentionData(data)) {\n return data\n }\n\n // If data is an array of RetentionResultRow, convert it\n if (Array.isArray(data) && data.length > 0) {\n const rows = data as RetentionResultRow[]\n const periods = [...new Set(rows.map((r) => r.period))].sort((a, b) => a - b)\n const breakdownValues = [\n ...new Set(rows.filter((r) => r.breakdownValue).map((r) => r.breakdownValue!)),\n ]\n\n return {\n rows,\n periods,\n breakdownValues: breakdownValues.length > 0 ? breakdownValues : undefined,\n }\n }\n\n return null\n }, [data])\n\n // Transform data for chart\n const { chartData, seriesKeys, defaultSeriesName } = useMemo(() => {\n if (!retentionData) {\n return { chartData: [], seriesKeys: [], defaultSeriesName: 'Retention' }\n }\n return transformRetentionData(\n retentionData.rows,\n retentionData.periods,\n retentionData.breakdownValues,\n retentionData.granularity,\n retentionData.bindingKeyLabel\n )\n }, [retentionData])\n\n // Get cohort label for heatmap column header\n const cohortLabel = getCohortLabel(retentionData?.bindingKeyLabel)\n\n // Display mode from config\n const displayMode: RetentionDisplayMode =\n (displayConfig as any)?.retentionDisplayMode || 'line'\n\n const showLegend = displayConfig?.showLegend ?? true\n const showGrid = displayConfig?.showGrid ?? true\n const showTooltip = displayConfig?.showTooltip ?? true\n\n // Handle empty/loading states\n if (!data || (Array.isArray(data) && data.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.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.retention')}\n </div>\n </div>\n </div>\n )\n }\n\n if (!chartData || chartData.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.unableToRender')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.dataFormatIncorrect')}</div>\n </div>\n </div>\n )\n }\n\n // Render line chart component (reused in line and combined modes)\n const renderLineChart = (chartHeight: string | number) => {\n const chartMargins = {\n ...CHART_MARGINS,\n left: 50,\n right: 20,\n }\n\n return (\n <ChartContainer height={chartHeight}>\n <ComposedChart data={chartData} margin={chartMargins} accessibilityLayer={false}>\n {showGrid && <CartesianGrid strokeDasharray=\"3 3\" />}\n <XAxis\n dataKey=\"periodLabel\"\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n />\n <YAxis\n domain={[0, 1]}\n tickFormatter={(value) => formatPercentage(value)}\n tick={{ fontSize: 12 }}\n axisLine={{ stroke: 'var(--dc-border)' }}\n tickLine={{ stroke: 'var(--dc-border)' }}\n label={{\n value: 'Retention %',\n angle: -90,\n position: 'insideLeft',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-secondary)' },\n }}\n />\n {showTooltip && (\n <ChartTooltip\n formatter={(value: any, name: string) => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatPercentage(value), name]\n }}\n labelFormatter={(label: string) => label}\n />\n )}\n {showLegend && (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: '10px' }}\n iconType=\"line\"\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => setHoveredLegend(String(o.dataKey || ''))}\n onMouseLeave={() => setHoveredLegend(null)}\n />\n )}\n\n {/* Render lines */}\n {seriesKeys.map((seriesKey, index) => (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n stroke={\n (colorPalette?.colors && colorPalette.colors[index % colorPalette.colors.length]) ||\n CHART_COLORS[index % CHART_COLORS.length]\n }\n strokeWidth={2}\n dot={{ r: 4, strokeWidth: 2 }}\n activeDot={{ r: 6 }}\n strokeOpacity={hoveredLegend ? (hoveredLegend === seriesKey ? 1 : 0.3) : 1}\n connectNulls={false}\n />\n ))}\n </ComposedChart>\n </ChartContainer>\n )\n }\n\n // Render heatmap table component (reused in heatmap and combined modes)\n const renderHeatmapTable = () => (\n <table className=\"dc:w-full dc:border-collapse dc:text-sm\">\n <thead className=\"dc:sticky dc:top-0 bg-dc-bg dc:z-10\">\n <tr>\n <th className=\"dc:text-left dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[100px] dc:whitespace-nowrap\">\n {retentionData?.breakdownValues?.length ? 'Segment' : 'Cohort'}\n </th>\n <th className=\"dc:text-right dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[60px] dc:whitespace-nowrap\">\n {cohortLabel}\n </th>\n {retentionData?.periods.map((period) => (\n <th\n key={period}\n className=\"dc:text-center dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[70px] dc:whitespace-nowrap\"\n >\n {formatPeriodLabel(period, retentionData?.granularity)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {seriesKeys.map((seriesKey, rowIndex) => {\n const period0Data = chartData.find((d) => d.period === 0)\n const isDefaultSeries = seriesKey === defaultSeriesName\n const cohortSize = isDefaultSeries\n ? period0Data?.cohortSize ?? 0\n : period0Data?.[`${seriesKey}_cohortSize`] ?? 0\n\n return (\n <tr\n key={seriesKey}\n className={rowIndex % 2 === 0 ? 'bg-dc-bg' : 'bg-dc-surface-secondary'}\n >\n <td className=\"dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:whitespace-nowrap\">\n {seriesKey}\n </td>\n <td className=\"dc:p-2 dc:text-right text-dc-text-secondary dc:border-b border-dc-border\">\n {cohortSize.toLocaleString()}\n </td>\n {retentionData?.periods.map((period) => {\n const dataPoint = chartData.find((d) => d.period === period)\n const rate = dataPoint?.[seriesKey] ?? 0\n const bgColor = rate > 0 ? getRetentionColor(rate) : 'transparent'\n const textColor = rate > 0.5 ? '#ffffff' : 'var(--dc-text)'\n\n return (\n <td\n key={period}\n className=\"dc:p-2 dc:text-center dc:border-b border-dc-border dc:cursor-default dc:transition-opacity dc:hover:opacity-80\"\n style={{ backgroundColor: bgColor, color: textColor }}\n onMouseEnter={(e) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const retainedUsers = isDefaultSeries\n ? dataPoint?.retainedUsers ?? 0\n : dataPoint?.[`${seriesKey}_retainedUsers`] ?? 0\n setHeatmapTooltip({\n period,\n breakdownValue: isDefaultSeries ? null : seriesKey,\n cohortSize,\n retainedUsers,\n retentionRate: rate,\n x: rect.left + rect.width / 2,\n y: rect.top,\n })\n }}\n onMouseLeave={() => setHeatmapTooltip(null)}\n >\n {rate > 0 ? formatPercentage(rate) : '-'}\n </td>\n )\n })}\n </tr>\n )\n })}\n </tbody>\n </table>\n )\n\n // Render heatmap tooltip (shared between heatmap and combined modes)\n const renderHeatmapTooltip = () =>\n heatmapTooltip && (\n <div\n className=\"dc:fixed dc:z-50 dc:px-3 dc:py-2 bg-dc-surface dc:border border-dc-border dc:rounded-sm dc:shadow-lg dc:text-sm dc:pointer-events-none\"\n style={{\n left: heatmapTooltip.x,\n top: heatmapTooltip.y - 10,\n transform: 'translate(-50%, -100%)',\n }}\n >\n <div className=\"dc:font-medium text-dc-text dc:mb-1\">\n {heatmapTooltip.breakdownValue\n ? `${heatmapTooltip.breakdownValue} - ${formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}`\n : formatPeriodLabel(heatmapTooltip.period, retentionData?.granularity)}\n </div>\n <div className=\"text-dc-text-secondary dc:space-y-0.5\">\n <div>{t('chart.runtime.retention.cohortSize', { count: heatmapTooltip.cohortSize.toLocaleString() })}</div>\n <div>{t('chart.runtime.retention.retained', { count: heatmapTooltip.retainedUsers.toLocaleString() })}</div>\n <div className=\"dc:font-medium text-dc-text\">\n {t('chart.runtime.retention.rate', { rate: formatPercentage(heatmapTooltip.retentionRate) })}\n </div>\n </div>\n </div>\n )\n\n // Render heatmap mode (table-based only)\n if (displayMode === 'heatmap') {\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:overflow-auto\" style={{ height }}>\n {renderHeatmapTable()}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Combined mode: line chart on top, heatmap table below\n if (displayMode === 'combined') {\n return (\n <div className=\"dc:flex dc:flex-col dc:w-full dc:h-full\" style={{ height }}>\n {/* Line chart - takes remaining space after heatmap */}\n <div className=\"dc:flex-1 dc:min-h-[200px]\">\n {renderLineChart('100%')}\n </div>\n {/* Heatmap table - auto-height based on content, scrolls if needed */}\n <div className=\"dc:flex-shrink-0 dc:max-h-[40%] dc:overflow-auto dc:border-t border-dc-border\">\n {renderHeatmapTable()}\n </div>\n {/* Shared heatmap tooltip */}\n {renderHeatmapTooltip()}\n </div>\n )\n }\n\n // Line mode: just the line chart\n return renderLineChart(height)\n})\n\nexport default RetentionCombinedChart\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as e } from "./retention-ChW9jYdy.js";
|
|
2
|
-
import { F as t } from "./chart-activity-grid-
|
|
2
|
+
import { F as t } from "./chart-activity-grid-DGazwi4C.js";
|
|
3
3
|
import n, { useMemo as r, useState as i } from "react";
|
|
4
4
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
5
|
//#region src/client/components/charts/RetentionHeatmap.tsx
|
|
@@ -190,4 +190,4 @@ var d = n.memo(function({ data: n, height: d = "100%", displayConfig: f }) {
|
|
|
190
190
|
//#endregion
|
|
191
191
|
export { d as default };
|
|
192
192
|
|
|
193
|
-
//# sourceMappingURL=RetentionHeatmap-
|
|
193
|
+
//# sourceMappingURL=RetentionHeatmap-jpshJ2Af.js.map
|
package/dist/client/chunks/{RetentionHeatmap-DVm_7rph.js.map → RetentionHeatmap-jpshJ2Af.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RetentionHeatmap-DVm_7rph.js","names":[],"sources":["../../../src/client/components/charts/RetentionHeatmap.tsx"],"sourcesContent":["/**\n * RetentionHeatmap Component\n *\n * Visualizes retention analysis data as a cohort × period matrix.\n * Displays retention rates with color intensity based on percentage.\n *\n * Features:\n * - Cohort labels in first column (e.g., \"2024-01\", \"2024-02\")\n * - Cohort size in second column\n * - Period columns (P0, P1, P2, ... PN)\n * - Cell background color intensity based on retention rate\n * - Hover tooltip with detailed stats\n */\n\nimport React, { useMemo, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport type { ChartProps } from '../../types.js'\nimport type { RetentionChartData, RetentionResultRow } from '../../types/retention.js'\nimport { isRetentionData } from '../../types/retention.js'\n\n/**\n * Get color with opacity based on retention rate\n * Uses a green gradient: higher retention = more saturated green\n */\nfunction getRetentionColor(rate: number): string {\n // Clamp rate between 0 and 1\n const clampedRate = Math.max(0, Math.min(1, rate))\n\n // Use CSS variable for theming support\n // Fallback to a green color if CSS var not available\n const alpha = 0.1 + clampedRate * 0.7 // Range from 0.1 to 0.8 opacity\n\n // Green color (success color)\n return `rgba(34, 197, 94, ${alpha})`\n}\n\n/**\n * Get text color that contrasts with background\n */\nfunction getTextColor(rate: number): string {\n // Use dark text for lower rates, light text for higher rates\n return rate > 0.5 ? '#ffffff' : 'var(--dc-text)'\n}\n\n/**\n * Format cohort period for display\n * Converts date strings to readable format\n */\nfunction formatCohortPeriod(cohort: string): string {\n // If it's already in YYYY-MM format, return as-is\n if (/^\\d{4}-\\d{2}$/.test(cohort)) {\n return cohort\n }\n\n // Try to parse as date\n const date = new Date(cohort)\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short' })\n }\n\n return cohort\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(rate: number): string {\n return `${Math.round(rate * 100)}%`\n}\n\ninterface TooltipData {\n cohort: string\n period: number\n cohortSize: number\n retainedUsers: number\n retentionRate: number\n x: number\n y: number\n}\n\n/**\n * RetentionHeatmap Component\n */\nconst RetentionHeatmap = React.memo(function RetentionHeatmap({\n data,\n height = '100%',\n displayConfig,\n}: ChartProps) {\n const { t } = useTranslation()\n const [tooltip, setTooltip] = useState<TooltipData | null>(null)\n\n // Parse retention data\n const retentionData = useMemo<RetentionChartData | null>(() => {\n if (!data) return null\n\n // Check if data is already in RetentionChartData format\n if (isRetentionData(data)) {\n return data\n }\n\n // If data is an array of RetentionResultRow, convert it\n if (Array.isArray(data) && data.length > 0) {\n const rows = data as RetentionResultRow[]\n const breakdownValues = [...new Set(rows.map(r => r.breakdownValue || 'All Users'))].sort()\n const periods = [...new Set(rows.map(r => r.period))].sort((a, b) => a - b)\n\n return {\n rows,\n breakdownValues: breakdownValues.length > 1 || breakdownValues[0] !== 'All Users' ? breakdownValues : undefined,\n periods,\n }\n }\n\n return null\n }, [data])\n\n // Build matrix for display\n // In the new simplified format, rows are grouped by breakdownValue (or 'All Users' if no breakdown)\n const matrix = useMemo(() => {\n if (!retentionData) return null\n\n const { rows, breakdownValues, periods } = retentionData\n\n // Determine segments: use breakdownValues if available, otherwise single 'All Users' segment\n const segments = breakdownValues || ['All Users']\n\n // Create a lookup map for quick access: segment:period -> row\n const lookup = new Map<string, RetentionResultRow>()\n for (const row of rows) {\n const segment = row.breakdownValue || 'All Users'\n lookup.set(`${segment}:${row.period}`, row)\n }\n\n // Build matrix structure - one row per segment\n return segments.map((segment: string) => {\n const segmentRows = periods.map(period => {\n const row = lookup.get(`${segment}:${period}`)\n return row || null\n })\n\n // Get cohort size from period 0\n const period0 = segmentRows[0]\n const cohortSize = period0?.cohortSize ?? 0\n\n return {\n cohort: segment, // Keep 'cohort' key for compatibility with rendering\n cohortSize,\n periods: segmentRows,\n }\n })\n }, [retentionData])\n\n // Handle mouse enter on cell\n const handleMouseEnter = (\n event: React.MouseEvent,\n cohort: string,\n period: number,\n row: RetentionResultRow | null\n ) => {\n if (!row) return\n\n const rect = event.currentTarget.getBoundingClientRect()\n setTooltip({\n cohort,\n period,\n cohortSize: row.cohortSize,\n retainedUsers: row.retainedUsers,\n retentionRate: row.retentionRate,\n x: rect.left + rect.width / 2,\n y: rect.top,\n })\n }\n\n const handleMouseLeave = () => {\n setTooltip(null)\n }\n\n // Handle empty/loading states\n if (!data || (Array.isArray(data) && data.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.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.retention')}\n </div>\n </div>\n </div>\n )\n }\n\n if (!matrix || matrix.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.unableToRender')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.dataFormatIncorrect')}\n </div>\n </div>\n </div>\n )\n }\n\n const periods = retentionData?.periods ?? []\n const showLegend = displayConfig?.showLegend ?? true\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:overflow-auto\" style={{ height }}>\n {/* Retention Matrix Table */}\n <table className=\"dc:w-full dc:border-collapse dc:text-sm\">\n <thead className=\"dc:sticky dc:top-0 bg-dc-bg dc:z-10\">\n <tr>\n <th className=\"dc:text-left dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[100px]\">\n {t('chart.runtime.retention.cohort')}\n </th>\n <th className=\"dc:text-right dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[80px]\">\n {t('chart.runtime.retention.users')}\n </th>\n {periods.map(period => (\n <th\n key={period}\n className=\"dc:text-center dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[60px]\"\n >\n P{period}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {matrix.map((row, rowIndex) => (\n <tr key={row.cohort} className={rowIndex % 2 === 0 ? 'bg-dc-bg' : 'bg-dc-surface-secondary'}>\n <td className=\"dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:whitespace-nowrap\">\n {formatCohortPeriod(row.cohort)}\n </td>\n <td className=\"dc:p-2 dc:text-right text-dc-text-secondary dc:border-b border-dc-border\">\n {row.cohortSize.toLocaleString()}\n </td>\n {row.periods.map((cell, periodIndex) => {\n const period = periods[periodIndex]\n const rate = cell?.retentionRate ?? 0\n const bgColor = cell ? getRetentionColor(rate) : 'transparent'\n const textColor = cell ? getTextColor(rate) : 'var(--dc-text-muted)'\n\n return (\n <td\n key={period}\n className=\"dc:p-2 dc:text-center dc:border-b border-dc-border dc:cursor-default dc:transition-opacity dc:hover:opacity-80\"\n style={{ backgroundColor: bgColor, color: textColor }}\n onMouseEnter={(e) => handleMouseEnter(e, row.cohort, period, cell)}\n onMouseLeave={handleMouseLeave}\n >\n {cell ? formatPercentage(rate) : '-'}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n\n {/* Legend */}\n {showLegend && (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:mt-4 dc:gap-2 dc:text-xs text-dc-text-secondary\">\n <span>0%</span>\n <div className=\"dc:flex dc:h-4\">\n {[0, 0.2, 0.4, 0.6, 0.8, 1].map(rate => (\n <div\n key={rate}\n className=\"dc:w-6 dc:h-4\"\n style={{ backgroundColor: getRetentionColor(rate) }}\n />\n ))}\n </div>\n <span>100%</span>\n </div>\n )}\n\n {/* Tooltip */}\n {tooltip && (\n <div\n className=\"dc:fixed dc:z-50 dc:px-3 dc:py-2 bg-dc-surface dc:border border-dc-border dc:rounded-sm dc:shadow-lg dc:text-sm dc:pointer-events-none\"\n style={{\n left: tooltip.x,\n top: tooltip.y - 10,\n transform: 'translate(-50%, -100%)',\n }}\n >\n <div className=\"dc:font-medium text-dc-text dc:mb-1\">\n {t('chart.runtime.retention.periodLabel', {\n cohort: formatCohortPeriod(tooltip.cohort),\n period: tooltip.period\n })}\n </div>\n <div className=\"text-dc-text-secondary dc:space-y-0.5\">\n <div>{t('chart.runtime.retention.cohortSize', { count: tooltip.cohortSize.toLocaleString() })}</div>\n <div>{t('chart.runtime.retention.retained', { count: tooltip.retainedUsers.toLocaleString() })}</div>\n <div className=\"dc:font-medium text-dc-text\">\n {t('chart.runtime.retention.rate', { rate: formatPercentage(tooltip.retentionRate) })}\n </div>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nexport default RetentionHeatmap\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RetentionHeatmap-jpshJ2Af.js","names":[],"sources":["../../../src/client/components/charts/RetentionHeatmap.tsx"],"sourcesContent":["/**\n * RetentionHeatmap Component\n *\n * Visualizes retention analysis data as a cohort × period matrix.\n * Displays retention rates with color intensity based on percentage.\n *\n * Features:\n * - Cohort labels in first column (e.g., \"2024-01\", \"2024-02\")\n * - Cohort size in second column\n * - Period columns (P0, P1, P2, ... PN)\n * - Cell background color intensity based on retention rate\n * - Hover tooltip with detailed stats\n */\n\nimport React, { useMemo, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport type { ChartProps } from '../../types.js'\nimport type { RetentionChartData, RetentionResultRow } from '../../types/retention.js'\nimport { isRetentionData } from '../../types/retention.js'\n\n/**\n * Get color with opacity based on retention rate\n * Uses a green gradient: higher retention = more saturated green\n */\nfunction getRetentionColor(rate: number): string {\n // Clamp rate between 0 and 1\n const clampedRate = Math.max(0, Math.min(1, rate))\n\n // Use CSS variable for theming support\n // Fallback to a green color if CSS var not available\n const alpha = 0.1 + clampedRate * 0.7 // Range from 0.1 to 0.8 opacity\n\n // Green color (success color)\n return `rgba(34, 197, 94, ${alpha})`\n}\n\n/**\n * Get text color that contrasts with background\n */\nfunction getTextColor(rate: number): string {\n // Use dark text for lower rates, light text for higher rates\n return rate > 0.5 ? '#ffffff' : 'var(--dc-text)'\n}\n\n/**\n * Format cohort period for display\n * Converts date strings to readable format\n */\nfunction formatCohortPeriod(cohort: string): string {\n // If it's already in YYYY-MM format, return as-is\n if (/^\\d{4}-\\d{2}$/.test(cohort)) {\n return cohort\n }\n\n // Try to parse as date\n const date = new Date(cohort)\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short' })\n }\n\n return cohort\n}\n\n/**\n * Format percentage for display\n */\nfunction formatPercentage(rate: number): string {\n return `${Math.round(rate * 100)}%`\n}\n\ninterface TooltipData {\n cohort: string\n period: number\n cohortSize: number\n retainedUsers: number\n retentionRate: number\n x: number\n y: number\n}\n\n/**\n * RetentionHeatmap Component\n */\nconst RetentionHeatmap = React.memo(function RetentionHeatmap({\n data,\n height = '100%',\n displayConfig,\n}: ChartProps) {\n const { t } = useTranslation()\n const [tooltip, setTooltip] = useState<TooltipData | null>(null)\n\n // Parse retention data\n const retentionData = useMemo<RetentionChartData | null>(() => {\n if (!data) return null\n\n // Check if data is already in RetentionChartData format\n if (isRetentionData(data)) {\n return data\n }\n\n // If data is an array of RetentionResultRow, convert it\n if (Array.isArray(data) && data.length > 0) {\n const rows = data as RetentionResultRow[]\n const breakdownValues = [...new Set(rows.map(r => r.breakdownValue || 'All Users'))].sort()\n const periods = [...new Set(rows.map(r => r.period))].sort((a, b) => a - b)\n\n return {\n rows,\n breakdownValues: breakdownValues.length > 1 || breakdownValues[0] !== 'All Users' ? breakdownValues : undefined,\n periods,\n }\n }\n\n return null\n }, [data])\n\n // Build matrix for display\n // In the new simplified format, rows are grouped by breakdownValue (or 'All Users' if no breakdown)\n const matrix = useMemo(() => {\n if (!retentionData) return null\n\n const { rows, breakdownValues, periods } = retentionData\n\n // Determine segments: use breakdownValues if available, otherwise single 'All Users' segment\n const segments = breakdownValues || ['All Users']\n\n // Create a lookup map for quick access: segment:period -> row\n const lookup = new Map<string, RetentionResultRow>()\n for (const row of rows) {\n const segment = row.breakdownValue || 'All Users'\n lookup.set(`${segment}:${row.period}`, row)\n }\n\n // Build matrix structure - one row per segment\n return segments.map((segment: string) => {\n const segmentRows = periods.map(period => {\n const row = lookup.get(`${segment}:${period}`)\n return row || null\n })\n\n // Get cohort size from period 0\n const period0 = segmentRows[0]\n const cohortSize = period0?.cohortSize ?? 0\n\n return {\n cohort: segment, // Keep 'cohort' key for compatibility with rendering\n cohortSize,\n periods: segmentRows,\n }\n })\n }, [retentionData])\n\n // Handle mouse enter on cell\n const handleMouseEnter = (\n event: React.MouseEvent,\n cohort: string,\n period: number,\n row: RetentionResultRow | null\n ) => {\n if (!row) return\n\n const rect = event.currentTarget.getBoundingClientRect()\n setTooltip({\n cohort,\n period,\n cohortSize: row.cohortSize,\n retainedUsers: row.retainedUsers,\n retentionRate: row.retentionRate,\n x: rect.left + rect.width / 2,\n y: rect.top,\n })\n }\n\n const handleMouseLeave = () => {\n setTooltip(null)\n }\n\n // Handle empty/loading states\n if (!data || (Array.isArray(data) && data.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.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noDataHint.retention')}\n </div>\n </div>\n </div>\n )\n }\n\n if (!matrix || matrix.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.unableToRender')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.dataFormatIncorrect')}\n </div>\n </div>\n </div>\n )\n }\n\n const periods = retentionData?.periods ?? []\n const showLegend = displayConfig?.showLegend ?? true\n\n return (\n <div className=\"dc:relative dc:w-full dc:h-full dc:overflow-auto\" style={{ height }}>\n {/* Retention Matrix Table */}\n <table className=\"dc:w-full dc:border-collapse dc:text-sm\">\n <thead className=\"dc:sticky dc:top-0 bg-dc-bg dc:z-10\">\n <tr>\n <th className=\"dc:text-left dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[100px]\">\n {t('chart.runtime.retention.cohort')}\n </th>\n <th className=\"dc:text-right dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[80px]\">\n {t('chart.runtime.retention.users')}\n </th>\n {periods.map(period => (\n <th\n key={period}\n className=\"dc:text-center dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:min-w-[60px]\"\n >\n P{period}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {matrix.map((row, rowIndex) => (\n <tr key={row.cohort} className={rowIndex % 2 === 0 ? 'bg-dc-bg' : 'bg-dc-surface-secondary'}>\n <td className=\"dc:p-2 dc:font-medium text-dc-text dc:border-b border-dc-border dc:whitespace-nowrap\">\n {formatCohortPeriod(row.cohort)}\n </td>\n <td className=\"dc:p-2 dc:text-right text-dc-text-secondary dc:border-b border-dc-border\">\n {row.cohortSize.toLocaleString()}\n </td>\n {row.periods.map((cell, periodIndex) => {\n const period = periods[periodIndex]\n const rate = cell?.retentionRate ?? 0\n const bgColor = cell ? getRetentionColor(rate) : 'transparent'\n const textColor = cell ? getTextColor(rate) : 'var(--dc-text-muted)'\n\n return (\n <td\n key={period}\n className=\"dc:p-2 dc:text-center dc:border-b border-dc-border dc:cursor-default dc:transition-opacity dc:hover:opacity-80\"\n style={{ backgroundColor: bgColor, color: textColor }}\n onMouseEnter={(e) => handleMouseEnter(e, row.cohort, period, cell)}\n onMouseLeave={handleMouseLeave}\n >\n {cell ? formatPercentage(rate) : '-'}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n\n {/* Legend */}\n {showLegend && (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:mt-4 dc:gap-2 dc:text-xs text-dc-text-secondary\">\n <span>0%</span>\n <div className=\"dc:flex dc:h-4\">\n {[0, 0.2, 0.4, 0.6, 0.8, 1].map(rate => (\n <div\n key={rate}\n className=\"dc:w-6 dc:h-4\"\n style={{ backgroundColor: getRetentionColor(rate) }}\n />\n ))}\n </div>\n <span>100%</span>\n </div>\n )}\n\n {/* Tooltip */}\n {tooltip && (\n <div\n className=\"dc:fixed dc:z-50 dc:px-3 dc:py-2 bg-dc-surface dc:border border-dc-border dc:rounded-sm dc:shadow-lg dc:text-sm dc:pointer-events-none\"\n style={{\n left: tooltip.x,\n top: tooltip.y - 10,\n transform: 'translate(-50%, -100%)',\n }}\n >\n <div className=\"dc:font-medium text-dc-text dc:mb-1\">\n {t('chart.runtime.retention.periodLabel', {\n cohort: formatCohortPeriod(tooltip.cohort),\n period: tooltip.period\n })}\n </div>\n <div className=\"text-dc-text-secondary dc:space-y-0.5\">\n <div>{t('chart.runtime.retention.cohortSize', { count: tooltip.cohortSize.toLocaleString() })}</div>\n <div>{t('chart.runtime.retention.retained', { count: tooltip.retainedUsers.toLocaleString() })}</div>\n <div className=\"dc:font-medium text-dc-text\">\n {t('chart.runtime.retention.rate', { rate: formatPercentage(tooltip.retentionRate) })}\n </div>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nexport default RetentionHeatmap\n"],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { A as e, C as t, _ as n, _t as r, gt as i, l as a, u as o, y as s } from "./chart-data-table-
|
|
2
|
-
import {
|
|
1
|
+
import { A as e, C as t, _ as n, _t as r, gt as i, l as a, u as o, y as s } from "./chart-data-table-BdMo3zVh.js";
|
|
2
|
+
import { F as c, S as l, c as u, k as d, o as f, s as p, y as m } from "./DashboardEditModal-CiN77tQN.js";
|
|
3
3
|
import { i as h, n as g, o as _, r as v, s as y } from "./retention-ChW9jYdy.js";
|
|
4
|
-
import { B as b, F as x } from "./chart-activity-grid-
|
|
5
|
-
import { r as S, t as C } from "./useExplainAI-
|
|
6
|
-
import { a as w, t as T } from "./charts-loader-
|
|
7
|
-
import { F as E, M as D, N as O, S as k, c as A, n as ee, p as j, t as M, u as N } from "./analysis-builder-shared-
|
|
8
|
-
import { n as P } from "./charts-core-
|
|
4
|
+
import { B as b, F as x } from "./chart-activity-grid-DGazwi4C.js";
|
|
5
|
+
import { r as S, t as C } from "./useExplainAI-CDFhgmpE.js";
|
|
6
|
+
import { a as w, t as T } from "./charts-loader-BTI0UPK4.js";
|
|
7
|
+
import { F as E, M as D, N as O, S as k, c as A, n as ee, p as j, t as M, u as N } from "./analysis-builder-shared-CoX_nmo0.js";
|
|
8
|
+
import { n as P } from "./charts-core-CKpkoMCa.js";
|
|
9
9
|
import F, { Component as I, forwardRef as L, memo as R, useCallback as z, useEffect as B, useImperativeHandle as te, useMemo as V, useRef as H, useState as U, useSyncExternalStore as ne } from "react";
|
|
10
10
|
import { Fragment as W, jsx as G, jsxs as K } from "react/jsx-runtime";
|
|
11
11
|
//#region src/client/shared/components/QueryAnalysisPanel.sections.tsx
|
|
@@ -430,7 +430,7 @@ function Q({ onRefreshClick: e, canRefresh: t, isRefreshing: n, showCacheBustInd
|
|
|
430
430
|
});
|
|
431
431
|
}
|
|
432
432
|
function Te({ summary: e, toolbar: t, display: n, hasResults: r }) {
|
|
433
|
-
let { t: i } = x(), { displayLimit: a, onDisplayLimitChange: o, isAIOpen: s, onAIToggle:
|
|
433
|
+
let { t: i } = x(), { displayLimit: a, onDisplayLimitChange: o, isAIOpen: s, onAIToggle: c, onColorPaletteChange: l, currentPaletteName: u, onClearClick: f, canClear: p, setIsClearConfirmOpen: m, setShowDebug: h, setShowSchema: g } = t, { activeView: _, showDebug: v, showSchema: y, enableAI: b, isFunnelMode: S, showSchemaDiagram: C } = n, { executionError: w, debugDataPerQuery: T } = e;
|
|
434
434
|
return /* @__PURE__ */ K("div", {
|
|
435
435
|
className: "dc:flex dc:items-center dc:gap-2",
|
|
436
436
|
children: [
|
|
@@ -457,8 +457,8 @@ function Te({ summary: e, toolbar: t, display: n, hasResults: r }) {
|
|
|
457
457
|
})
|
|
458
458
|
]
|
|
459
459
|
}),
|
|
460
|
-
b &&
|
|
461
|
-
onClick:
|
|
460
|
+
b && c && /* @__PURE__ */ K("button", {
|
|
461
|
+
onClick: c,
|
|
462
462
|
className: `dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded-sm dc:transition-colors ${s ? "text-white bg-dc-accent dc:border border-dc-accent" : "text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg dc:border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg"}`,
|
|
463
463
|
title: s ? "Close AI assistant" : "Analyse with AI",
|
|
464
464
|
children: [/* @__PURE__ */ G(be, { className: "dc:w-3 dc:h-3" }), /* @__PURE__ */ G("span", {
|
|
@@ -466,9 +466,9 @@ function Te({ summary: e, toolbar: t, display: n, hasResults: r }) {
|
|
|
466
466
|
children: i("results.ai.button")
|
|
467
467
|
})]
|
|
468
468
|
}),
|
|
469
|
-
|
|
470
|
-
currentPalette:
|
|
471
|
-
onPaletteChange:
|
|
469
|
+
l && r && /* @__PURE__ */ G(d, {
|
|
470
|
+
currentPalette: u || "default",
|
|
471
|
+
onPaletteChange: l
|
|
472
472
|
}),
|
|
473
473
|
/* @__PURE__ */ G(we, {
|
|
474
474
|
onShareClick: t.onShareClick,
|
|
@@ -671,7 +671,7 @@ function Ke(e, t, n) {
|
|
|
671
671
|
}
|
|
672
672
|
//#endregion
|
|
673
673
|
//#region src/client/components/AnalysisBuilder/AnalysisResultsPanel.tsx
|
|
674
|
-
var qe = F.lazy(() => import("./schema-visualization-
|
|
674
|
+
var qe = F.lazy(() => import("./schema-visualization-BbvL74Sf.js").then((e) => e.n).then((e) => ({ default: e.SchemaVisualizationLazy }))), Je = R(function({ executionStatus: t, executionResults: n, executionError: r, totalRowCount: i, resultsStale: a = !1, chartType: o = "line", chartConfig: l = {}, displayConfig: u = {}, colorPalette: d, currentPaletteName: p, onColorPaletteChange: m, allQueries: h, funnelExecutedQueries: g, activeView: _ = "chart", onActiveViewChange: v, displayLimit: y = 100, onDisplayLimitChange: b, chartAvailability: E, debugDataPerQuery: D = [], onShareClick: k, canShare: A = !1, shareButtonState: ee = "idle", onRefreshClick: j, canRefresh: M = !1, isRefreshing: N = !1, needsRefresh: P = !1, onClearClick: I, canClear: L = !1, enableAI: R = !1, isAIOpen: te = !1, onAIToggle: ne, queryCount: re = 1, perQueryResults: ie, activeTableIndex: ae = 0, onActiveTableChange: oe, analysisType: se, isFunnelMode: ce = !1, funnelServerQuery: le, funnelDebugData: ue, flowServerQuery: de, flowDebugData: fe, retentionServerQuery: pe, retentionDebugData: me, retentionChartData: q, retentionValidation: he, warnings: _e, highlightedFields: ve, onSchemaFieldClick: ye }) {
|
|
675
675
|
let { t: J } = x(), Y = se === "funnel" || ce, X = se === "flow", Z = se === "retention", { features: be } = e(), [xe, Se] = U(!1), [Ce, we] = U(!1), [Q, Te] = U(0), [De, Oe] = U(!1), [ke, Ae] = U(!1), [je, Me] = U(!1), [Ne, Pe] = U("idle");
|
|
676
676
|
B(() => {
|
|
677
677
|
let e = (e) => {
|
|
@@ -922,7 +922,7 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
922
922
|
return w(e) ? /* @__PURE__ */ G(T, {
|
|
923
923
|
chartType: e,
|
|
924
924
|
data: Z && q ? q : n,
|
|
925
|
-
chartConfig:
|
|
925
|
+
chartConfig: l,
|
|
926
926
|
displayConfig: u,
|
|
927
927
|
colorPalette: d,
|
|
928
928
|
queryObject: jt,
|
|
@@ -959,18 +959,18 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
959
959
|
})]
|
|
960
960
|
}) : null, Jt = () => /* @__PURE__ */ K("div", {
|
|
961
961
|
className: "dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc:gap-4",
|
|
962
|
-
children: [/* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(
|
|
963
|
-
code: JSON.stringify(
|
|
962
|
+
children: [/* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(c, {
|
|
963
|
+
code: JSON.stringify(l, null, 2),
|
|
964
964
|
language: "json",
|
|
965
965
|
title: J("results.debug.chartConfig"),
|
|
966
966
|
height: "16rem"
|
|
967
|
-
}) }), /* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(
|
|
967
|
+
}) }), /* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(c, {
|
|
968
968
|
code: JSON.stringify(u, null, 2),
|
|
969
969
|
language: "json",
|
|
970
970
|
title: J("results.debug.displayConfig"),
|
|
971
971
|
height: "16rem"
|
|
972
972
|
}) })]
|
|
973
|
-
}), Yt = (e) => /* @__PURE__ */ G("div", { children: n ? /* @__PURE__ */ G(
|
|
973
|
+
}), Yt = (e) => /* @__PURE__ */ G("div", { children: n ? /* @__PURE__ */ G(c, {
|
|
974
974
|
code: JSON.stringify(n, null, 2),
|
|
975
975
|
language: "json",
|
|
976
976
|
title: e || `${J("results.debug.serverResponse")} (${n.length} ${J("results.header.rows")})`,
|
|
@@ -981,7 +981,7 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
981
981
|
}), /* @__PURE__ */ G("div", {
|
|
982
982
|
className: "bg-dc-surface-secondary dc:border border-dc-border dc:rounded-sm dc:p-3 text-dc-text-muted dc:text-sm",
|
|
983
983
|
children: J("results.debug.noResults")
|
|
984
|
-
})] }) }), Xt = () => /* @__PURE__ */ G("div", { children: q ? /* @__PURE__ */ G(
|
|
984
|
+
})] }) }), Xt = () => /* @__PURE__ */ G("div", { children: q ? /* @__PURE__ */ G(c, {
|
|
985
985
|
code: JSON.stringify(q, null, 2),
|
|
986
986
|
language: "json",
|
|
987
987
|
title: `Server Response (${q.rows.length} rows, ${q.periods.length} periods)`,
|
|
@@ -1009,7 +1009,7 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
1009
1009
|
]
|
|
1010
1010
|
}),
|
|
1011
1011
|
qt(),
|
|
1012
|
-
/* @__PURE__ */ G("div", { children: e.serverQuery ? /* @__PURE__ */ G(
|
|
1012
|
+
/* @__PURE__ */ G("div", { children: e.serverQuery ? /* @__PURE__ */ G(c, {
|
|
1013
1013
|
code: JSON.stringify(e.serverQuery, null, 2),
|
|
1014
1014
|
language: "json",
|
|
1015
1015
|
title: e.serverQueryTitle,
|
|
@@ -1109,7 +1109,7 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
1109
1109
|
className: "bg-dc-surface-secondary dc:border border-dc-border dc:rounded-sm dc:p-3 text-dc-text-muted dc:text-sm",
|
|
1110
1110
|
children: J(Ye ? "results.debug.analysisError" : "results.debug.analysisEmpty")
|
|
1111
1111
|
})] }),
|
|
1112
|
-
/* @__PURE__ */ G("div", { children: $ ? /* @__PURE__ */ K(W, { children: [/* @__PURE__ */ G(
|
|
1112
|
+
/* @__PURE__ */ G("div", { children: $ ? /* @__PURE__ */ K(W, { children: [/* @__PURE__ */ G(c, {
|
|
1113
1113
|
code: JSON.stringify($, null, 2),
|
|
1114
1114
|
language: "json",
|
|
1115
1115
|
title: J(Xe ? "results.debug.cubeQueryExecuted" : "results.debug.cubeQuery"),
|
|
@@ -1153,19 +1153,19 @@ var qe = F.lazy(() => import("./schema-visualization-BspQ-XB8.js").then((e) => e
|
|
|
1153
1153
|
}),
|
|
1154
1154
|
/* @__PURE__ */ K("div", {
|
|
1155
1155
|
className: "dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc:gap-4",
|
|
1156
|
-
children: [/* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(
|
|
1157
|
-
code: JSON.stringify(
|
|
1156
|
+
children: [/* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(c, {
|
|
1157
|
+
code: JSON.stringify(l, null, 2),
|
|
1158
1158
|
language: "json",
|
|
1159
1159
|
title: J("results.debug.chartConfig"),
|
|
1160
1160
|
height: "16rem"
|
|
1161
|
-
}) }), /* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(
|
|
1161
|
+
}) }), /* @__PURE__ */ G("div", { children: /* @__PURE__ */ G(c, {
|
|
1162
1162
|
code: JSON.stringify(u, null, 2),
|
|
1163
1163
|
language: "json",
|
|
1164
1164
|
title: J("results.debug.displayConfig"),
|
|
1165
1165
|
height: "16rem"
|
|
1166
1166
|
}) })]
|
|
1167
1167
|
}),
|
|
1168
|
-
/* @__PURE__ */ G("div", { children: n ? /* @__PURE__ */ G(
|
|
1168
|
+
/* @__PURE__ */ G("div", { children: n ? /* @__PURE__ */ G(c, {
|
|
1169
1169
|
code: JSON.stringify(n, null, 2),
|
|
1170
1170
|
language: "json",
|
|
1171
1171
|
title: `${J("results.debug.serverResponse")} (${n.length} ${J("results.header.rows")})`,
|
|
@@ -2336,12 +2336,12 @@ var vt = R(function({ value: e, label: t, placeholder: n, icon: r, options: i, o
|
|
|
2336
2336
|
label: "90 days"
|
|
2337
2337
|
}
|
|
2338
2338
|
], Et = R(function({ step: e, stepIndex: t, isActive: n, canRemove: r, schema: i, onSelect: a, onRemove: o, onUpdate: s }) {
|
|
2339
|
-
let { t: c } = x(), [
|
|
2339
|
+
let { t: c } = x(), [u, d] = U(!1), [f, p] = U(!1), [m, h] = U(e.name), g = H(null), _ = H(null);
|
|
2340
2340
|
B(() => {
|
|
2341
2341
|
h(e.name);
|
|
2342
2342
|
}, [e.name]), B(() => {
|
|
2343
|
-
|
|
2344
|
-
}, [
|
|
2343
|
+
u && g.current && (g.current.focus(), g.current.select());
|
|
2344
|
+
}, [u]), B(() => {
|
|
2345
2345
|
function e(e) {
|
|
2346
2346
|
_.current && !_.current.contains(e.target) && p(!1);
|
|
2347
2347
|
}
|
|
@@ -2369,7 +2369,7 @@ var vt = R(function({ value: e, label: t, placeholder: n, icon: r, options: i, o
|
|
|
2369
2369
|
...e,
|
|
2370
2370
|
description: e.description || ""
|
|
2371
2371
|
})) };
|
|
2372
|
-
return e.cube ?
|
|
2372
|
+
return e.cube ? l(e.cube, t) : t;
|
|
2373
2373
|
}, [i, e.cube]);
|
|
2374
2374
|
return /* @__PURE__ */ K("div", {
|
|
2375
2375
|
className: `
|
|
@@ -2389,7 +2389,7 @@ var vt = R(function({ value: e, label: t, placeholder: n, icon: r, options: i, o
|
|
|
2389
2389
|
className: "dc:flex-shrink-0 dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded-full bg-dc-primary/10 text-dc-primary dc:text-xs dc:font-medium",
|
|
2390
2390
|
children: t + 1
|
|
2391
2391
|
}),
|
|
2392
|
-
|
|
2392
|
+
u ? /* @__PURE__ */ G("input", {
|
|
2393
2393
|
ref: g,
|
|
2394
2394
|
type: "text",
|
|
2395
2395
|
value: m,
|
|
@@ -4253,7 +4253,7 @@ function In(e, t, n, r) {
|
|
|
4253
4253
|
//#endregion
|
|
4254
4254
|
//#region src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.tsx
|
|
4255
4255
|
var Ln = s("measure"), Rn = s("dimension"), zn = s("timeDimension");
|
|
4256
|
-
function Bn({ chartType: e, chartConfig: n, metrics: a, breakdowns: o, schema: s, chartAvailability: c, onChartTypeChange: l, onChartConfigChange:
|
|
4256
|
+
function Bn({ chartType: e, chartConfig: n, metrics: a, breakdowns: o, schema: s, chartAvailability: c, onChartTypeChange: l, onChartConfigChange: d, displayConfig: f, colorPalette: p, onDisplayConfigChange: m }) {
|
|
4257
4257
|
let { t: h } = x(), [g, _] = U(null), v = V(() => ({
|
|
4258
4258
|
measures: a.map((e) => e.field),
|
|
4259
4259
|
dimensions: o.filter((e) => !e.isTimeDimension).map((e) => e.field),
|
|
@@ -4272,12 +4272,12 @@ function Bn({ chartType: e, chartConfig: n, metrics: a, breakdowns: o, schema: s
|
|
|
4272
4272
|
y.dropZones.forEach((n) => {
|
|
4273
4273
|
let i = w(n.key), a = i.filter((t) => e.includes(t));
|
|
4274
4274
|
a.length !== i.length && (t = !0, a.length === 0 ? delete r[n.key] : n.maxItems === 1 ? r[n.key] = a[0] : r[n.key] = a);
|
|
4275
|
-
}), t &&
|
|
4275
|
+
}), t && d(r);
|
|
4276
4276
|
}, [
|
|
4277
4277
|
v,
|
|
4278
4278
|
n,
|
|
4279
4279
|
y.dropZones,
|
|
4280
|
-
|
|
4280
|
+
d,
|
|
4281
4281
|
w,
|
|
4282
4282
|
b
|
|
4283
4283
|
]);
|
|
@@ -4331,21 +4331,21 @@ function Bn({ chartType: e, chartConfig: n, metrics: a, breakdowns: o, schema: s
|
|
|
4331
4331
|
}, ee = (e, t) => {
|
|
4332
4332
|
e.preventDefault();
|
|
4333
4333
|
let { field: r, fromAxis: i } = JSON.parse(e.dataTransfer.getData("text/plain")), a = Pn(n, r, i, t, y.dropZones.find((e) => e.key === t));
|
|
4334
|
-
_(null),
|
|
4334
|
+
_(null), d(a);
|
|
4335
4335
|
}, j = (e, t) => {
|
|
4336
|
-
|
|
4336
|
+
d(Fn(n, e, t));
|
|
4337
4337
|
}, M = (e, t, r) => {
|
|
4338
4338
|
let i = In(n, e, t, r);
|
|
4339
|
-
i && (_(null),
|
|
4339
|
+
i && (_(null), d(i));
|
|
4340
4340
|
}, N = z((e, t) => {
|
|
4341
|
-
|
|
4341
|
+
d({
|
|
4342
4342
|
...n,
|
|
4343
4343
|
yAxisAssignment: {
|
|
4344
4344
|
...n.yAxisAssignment,
|
|
4345
4345
|
[e]: t
|
|
4346
4346
|
}
|
|
4347
4347
|
});
|
|
4348
|
-
}, [n,
|
|
4348
|
+
}, [n, d]);
|
|
4349
4349
|
if (!b) return /* @__PURE__ */ K("div", {
|
|
4350
4350
|
className: "dc:space-y-6",
|
|
4351
4351
|
children: [/* @__PURE__ */ K("div", { children: [/* @__PURE__ */ G(P, {
|
|
@@ -4399,7 +4399,7 @@ function Bn({ chartType: e, chartConfig: n, metrics: a, breakdowns: o, schema: s
|
|
|
4399
4399
|
})] }),
|
|
4400
4400
|
f && m && C.length > 0 && /* @__PURE__ */ G("div", {
|
|
4401
4401
|
className: "dc:space-y-2",
|
|
4402
|
-
children: C.map((e) => /* @__PURE__ */ G(
|
|
4402
|
+
children: C.map((e) => /* @__PURE__ */ G(u, {
|
|
4403
4403
|
option: e,
|
|
4404
4404
|
displayConfig: f,
|
|
4405
4405
|
colorPalette: p,
|
|
@@ -5424,4 +5424,4 @@ br.displayName = "AnalysisBuilder";
|
|
|
5424
5424
|
//#endregion
|
|
5425
5425
|
export { br as default };
|
|
5426
5426
|
|
|
5427
|
-
//# sourceMappingURL=analysis-builder-
|
|
5427
|
+
//# sourceMappingURL=analysis-builder-DIOnKxJu.js.map
|