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.
Files changed (275) hide show
  1. package/README.md +3 -2
  2. package/dist/adapters/ActivityGridChart.config-BGndyZtr.cjs +1 -0
  3. package/dist/adapters/ActivityGridChart.config-ZdvHJAHq.js +2 -0
  4. package/dist/adapters/AreaChart.config-Cybigwcb.js +2 -0
  5. package/dist/adapters/AreaChart.config-DWGesxUg.cjs +1 -0
  6. package/dist/adapters/BarChart.config-Cc04tVQF.js +2 -0
  7. package/dist/adapters/BarChart.config-DBCu0t_-.cjs +1 -0
  8. package/dist/adapters/BoxPlotChart.config-C0WK_ipa.cjs +1 -0
  9. package/dist/adapters/BoxPlotChart.config-DapOUN_R.js +2 -0
  10. package/dist/adapters/BubbleChart.config-DPmf7sI5.cjs +1 -0
  11. package/dist/adapters/BubbleChart.config-DROSTwxW.js +2 -0
  12. package/dist/adapters/CandlestickChart.config-BHoEJ2nY.js +2 -0
  13. package/dist/adapters/CandlestickChart.config-Cm0PKObO.cjs +1 -0
  14. package/dist/adapters/DataTable.config-DLvfXXSH.cjs +1 -0
  15. package/dist/adapters/DataTable.config-DbVrWZIw.js +2 -0
  16. package/dist/adapters/DotStripChart.config-CKPw82HE.js +2 -0
  17. package/dist/adapters/DotStripChart.config-DPIrTLb6.cjs +1 -0
  18. package/dist/adapters/FunnelChart.config-DpiDbOTn.cjs +1 -0
  19. package/dist/adapters/FunnelChart.config-DtBHVpLB.js +2 -0
  20. package/dist/adapters/GaugeChart.config-CmuXGRNV.js +2 -0
  21. package/dist/adapters/GaugeChart.config-DLj1YNsp.cjs +1 -0
  22. package/dist/adapters/HeatMapChart.config-BvFK2bny.cjs +1 -0
  23. package/dist/adapters/HeatMapChart.config-DK18zZV8.js +2 -0
  24. package/dist/adapters/KpiDelta.config-BsaVN5-T.js +2 -0
  25. package/dist/adapters/KpiDelta.config-DHsMgIdk.cjs +1 -0
  26. package/dist/adapters/KpiNumber.config-D82-j-8T.js +2 -0
  27. package/dist/adapters/KpiNumber.config-pFRomJRE.cjs +1 -0
  28. package/dist/adapters/KpiText.config-CCqeKuFB.js +2 -0
  29. package/dist/adapters/KpiText.config-CSeCoBuO.cjs +1 -0
  30. package/dist/adapters/LineChart.config-C2acjFv4.js +2 -0
  31. package/dist/adapters/LineChart.config-Dr9wmiK0.cjs +1 -0
  32. package/dist/adapters/MarkdownChart.config-C-tYLLan.js +2 -0
  33. package/dist/adapters/MarkdownChart.config-Dvyfo0CB.cjs +1 -0
  34. package/dist/adapters/MeasureProfileChart.config-C5CjPw48.js +2 -0
  35. package/dist/adapters/MeasureProfileChart.config-Dj-7HqkS.cjs +1 -0
  36. package/dist/adapters/PieChart.config-CY7nFFQn.cjs +1 -0
  37. package/dist/adapters/PieChart.config-DQLQMHc_.js +2 -0
  38. package/dist/adapters/ProportionBarChart.config-BVqtS7wi.cjs +1 -0
  39. package/dist/adapters/ProportionBarChart.config-BaSgs976.js +2 -0
  40. package/dist/adapters/RadarChart.config-DxJ5k8L9.cjs +1 -0
  41. package/dist/adapters/RadarChart.config-DzL7zQUc.js +2 -0
  42. package/dist/adapters/RadialBarChart.config-Dzl1HiGz.js +2 -0
  43. package/dist/adapters/RadialBarChart.config-XlGTd9gV.cjs +1 -0
  44. package/dist/adapters/RecordsTable.config-CS5oIMvv.js +2 -0
  45. package/dist/adapters/RecordsTable.config-DRQdHghk.cjs +1 -0
  46. package/dist/adapters/RetentionCombinedChart.config-C0iiKOdf.js +2 -0
  47. package/dist/adapters/RetentionCombinedChart.config-Dl20GZnb.cjs +1 -0
  48. package/dist/adapters/RetentionHeatmap.config-Bt42ip_c.js +2 -0
  49. package/dist/adapters/RetentionHeatmap.config-DyggEvyy.cjs +1 -0
  50. package/dist/adapters/SankeyChart.config-DYz1nUx9.js +2 -0
  51. package/dist/adapters/SankeyChart.config-dlNLJMf9.cjs +1 -0
  52. package/dist/adapters/ScatterChart.config-D72zRviD.js +2 -0
  53. package/dist/adapters/ScatterChart.config-DRtyuQvV.cjs +1 -0
  54. package/dist/adapters/SunburstChart.config-C5nHXLcu.cjs +1 -0
  55. package/dist/adapters/SunburstChart.config-j5ioABeT.js +2 -0
  56. package/dist/adapters/TreeMapChart.config-CXKcX5CH.js +2 -0
  57. package/dist/adapters/TreeMapChart.config-DuYbme03.cjs +1 -0
  58. package/dist/adapters/WaterfallChart.config-BCn4tsBV.cjs +1 -0
  59. package/dist/adapters/WaterfallChart.config-BPqhdzTP.js +2 -0
  60. package/dist/adapters/{compiler-CpvetSCm.js → compiler-BKg3j2mm.js} +1260 -2446
  61. package/dist/adapters/compiler-BX6Ug_Uq.cjs +166 -0
  62. package/dist/adapters/core/index.cjs +1 -1
  63. package/dist/adapters/core/index.js +1 -1
  64. package/dist/adapters/{core-BH_56XtM.js → core-Bmb7XMBz.js} +2 -2
  65. package/dist/adapters/{core-CydD6oFu.cjs → core-JgUTMhxl.cjs} +1 -1
  66. package/dist/adapters/express/index.cjs +1 -1
  67. package/dist/adapters/express/index.js +5 -5
  68. package/dist/adapters/fastify/index.cjs +1 -1
  69. package/dist/adapters/fastify/index.js +23 -23
  70. package/dist/adapters/{handler-CtcALGcY.js → handler-CknKLUQW.js} +213 -209
  71. package/dist/adapters/{handler-Dp8fpSpk.cjs → handler-DLWgxPOk.cjs} +8 -8
  72. package/dist/adapters/hono/index.cjs +1 -1
  73. package/dist/adapters/hono/index.js +4 -4
  74. package/dist/adapters/mcp-app-html-Bu4j3yZM.cjs +1 -0
  75. package/dist/adapters/{mcp-app-html-C8vG9epH.js → mcp-app-html-D3GsxPcx.js} +1 -1
  76. package/dist/adapters/mcp-app-html.cjs +1 -1
  77. package/dist/adapters/mcp-app-html.js +1 -1
  78. package/dist/adapters/mcp-tools.cjs +1 -1
  79. package/dist/adapters/mcp-tools.js +3 -3
  80. package/dist/adapters/{mcp-transport-DDxjqyuK.js → mcp-transport-BTmAXLo8.js} +8 -3
  81. package/dist/adapters/{mcp-transport-QGYYYSgR.cjs → mcp-transport-DzxluRyH.cjs} +2 -2
  82. package/dist/adapters/nextjs/index.cjs +1 -1
  83. package/dist/adapters/nextjs/index.js +5 -5
  84. package/dist/adapters/openai-CDH_AU_Z.cjs +19 -0
  85. package/dist/adapters/{openai-pCkHdDh4.js → openai-CYTlIdxS.js} +1 -1
  86. package/dist/adapters/{openai-Cm4JcLuF.cjs → openai-KbobaAQj.cjs} +1 -1
  87. package/dist/adapters/{openai-DH5InEPj.js → openai-enh3Hkzr.js} +510 -439
  88. package/dist/adapters/utils-Du_UZbn5.cjs +139 -0
  89. package/dist/adapters/{utils-C_Mc0qsk.js → utils-i2h5cwI3.js} +2587 -1254
  90. package/dist/adapters/utils.cjs +1 -1
  91. package/dist/adapters/utils.js +1 -1
  92. package/dist/cjs/client/components/shared/dateRangeUtils.d.ts +7 -3
  93. package/dist/cjs/server/adapters/base-adapter.d.ts +3 -3
  94. package/dist/cjs/server/ai/query-schema.d.ts +3 -3
  95. package/dist/cjs/server/builders/date-time-builder.d.ts +1 -2
  96. package/dist/cjs/server/builders/date-time-helpers.d.ts +19 -6
  97. package/dist/cjs/server/builders/filter-operators.d.ts +10 -1
  98. package/dist/cjs/server/execution/query-normalizer.d.ts +9 -0
  99. package/dist/cjs/server/physical-plan/drizzle-sql-builder.d.ts +25 -0
  100. package/dist/cjs/server/physical-plan/semi-join.d.ts +21 -0
  101. package/dist/cjs/server/prompts/single-step-prompt.d.ts +1 -1
  102. package/dist/client/charts.js +12 -12
  103. package/dist/client/chunks/{DashboardEditModal-USQFytJw.js → DashboardEditModal-CiN77tQN.js} +662 -540
  104. package/dist/client/chunks/DashboardEditModal-CiN77tQN.js.map +1 -0
  105. package/dist/client/chunks/{DotStripChart-CjSsunHE.js → DotStripChart-in6QHc0b.js} +3 -3
  106. package/dist/client/chunks/{DotStripChart-CjSsunHE.js.map → DotStripChart-in6QHc0b.js.map} +1 -1
  107. package/dist/client/chunks/{ProportionBarChart-B8UyZBO_.js → ProportionBarChart-CjuOm7NT.js} +3 -3
  108. package/dist/client/chunks/{ProportionBarChart-B8UyZBO_.js.map → ProportionBarChart-CjuOm7NT.js.map} +1 -1
  109. package/dist/client/chunks/{RecordsTable-BSmkwdgd.js → RecordsTable-CXXsiaV1.js} +4 -4
  110. package/dist/client/chunks/{RecordsTable-BSmkwdgd.js.map → RecordsTable-CXXsiaV1.js.map} +1 -1
  111. package/dist/client/chunks/{RetentionCombinedChart-rOdIhUGH.js → RetentionCombinedChart-DFCeEFkx.js} +3 -3
  112. package/dist/client/chunks/{RetentionCombinedChart-rOdIhUGH.js.map → RetentionCombinedChart-DFCeEFkx.js.map} +1 -1
  113. package/dist/client/chunks/{RetentionHeatmap-DVm_7rph.js → RetentionHeatmap-jpshJ2Af.js} +2 -2
  114. package/dist/client/chunks/{RetentionHeatmap-DVm_7rph.js.map → RetentionHeatmap-jpshJ2Af.js.map} +1 -1
  115. package/dist/client/chunks/{analysis-builder-D_tw9BvU.js → analysis-builder-DIOnKxJu.js} +41 -41
  116. package/dist/client/chunks/{analysis-builder-D_tw9BvU.js.map → analysis-builder-DIOnKxJu.js.map} +1 -1
  117. package/dist/client/chunks/{analysis-builder-shared-BSINKFr2.js → analysis-builder-shared-CoX_nmo0.js} +640 -778
  118. package/dist/client/chunks/analysis-builder-shared-CoX_nmo0.js.map +1 -0
  119. package/dist/client/chunks/{chart-activity-grid-CSIsJ12e.js → chart-activity-grid-DGazwi4C.js} +9 -2
  120. package/dist/client/chunks/chart-activity-grid-DGazwi4C.js.map +1 -0
  121. package/dist/client/chunks/{chart-area-BpvSKH5I.js → chart-area-zyLGD-ym.js} +2 -2
  122. package/dist/client/chunks/{chart-area-BpvSKH5I.js.map → chart-area-zyLGD-ym.js.map} +1 -1
  123. package/dist/client/chunks/{chart-bar-Cjzv-LvG.js → chart-bar-DMCBq8qJ.js} +3 -3
  124. package/dist/client/chunks/{chart-bar-Cjzv-LvG.js.map → chart-bar-DMCBq8qJ.js.map} +1 -1
  125. package/dist/client/chunks/{chart-box-plot-DHsHfMt6.js → chart-box-plot-5Z55A-it.js} +2 -2
  126. package/dist/client/chunks/{chart-box-plot-DHsHfMt6.js.map → chart-box-plot-5Z55A-it.js.map} +1 -1
  127. package/dist/client/chunks/{chart-bubble-BtWm6x7L.js → chart-bubble-YD28dX8w.js} +2 -2
  128. package/dist/client/chunks/{chart-bubble-BtWm6x7L.js.map → chart-bubble-YD28dX8w.js.map} +1 -1
  129. package/dist/client/chunks/{chart-candlestick-Bz0_fLuq.js → chart-candlestick-BUMpBI08.js} +2 -2
  130. package/dist/client/chunks/{chart-candlestick-Bz0_fLuq.js.map → chart-candlestick-BUMpBI08.js.map} +1 -1
  131. package/dist/client/chunks/{chart-data-table-BH1A-1RN.js → chart-data-table-BdMo3zVh.js} +2 -2
  132. package/dist/client/chunks/chart-data-table-BdMo3zVh.js.map +1 -0
  133. package/dist/client/chunks/{chart-funnel-C_-K4RLj.js → chart-funnel-BRyZS6ie.js} +2 -2
  134. package/dist/client/chunks/{chart-funnel-C_-K4RLj.js.map → chart-funnel-BRyZS6ie.js.map} +1 -1
  135. package/dist/client/chunks/{chart-gauge-F-vdq2BX.js → chart-gauge-DxgHlZKp.js} +3 -3
  136. package/dist/client/chunks/{chart-gauge-F-vdq2BX.js.map → chart-gauge-DxgHlZKp.js.map} +1 -1
  137. package/dist/client/chunks/{chart-heat-map-D_8TluGo.js → chart-heat-map-5jHm3f-V.js} +3 -3
  138. package/dist/client/chunks/{chart-heat-map-D_8TluGo.js.map → chart-heat-map-5jHm3f-V.js.map} +1 -1
  139. package/dist/client/chunks/{chart-kpi-delta-DGvQ0BHZ.js → chart-kpi-delta-C84P-mwu.js} +3 -3
  140. package/dist/client/chunks/{chart-kpi-delta-DGvQ0BHZ.js.map → chart-kpi-delta-C84P-mwu.js.map} +1 -1
  141. package/dist/client/chunks/{chart-kpi-number-DP6zCh-c.js → chart-kpi-number-D9GqtBWw.js} +5 -5
  142. package/dist/client/chunks/{chart-kpi-number-DP6zCh-c.js.map → chart-kpi-number-D9GqtBWw.js.map} +1 -1
  143. package/dist/client/chunks/{chart-kpi-text-DDbWfMwK.js → chart-kpi-text-D3HqxXzU.js} +3 -3
  144. package/dist/client/chunks/{chart-kpi-text-DDbWfMwK.js.map → chart-kpi-text-D3HqxXzU.js.map} +1 -1
  145. package/dist/client/chunks/{chart-line-DlhmQQ-X.js → chart-line-IEgiF8Nv.js} +3 -3
  146. package/dist/client/chunks/{chart-line-DlhmQQ-X.js.map → chart-line-IEgiF8Nv.js.map} +1 -1
  147. package/dist/client/chunks/{chart-markdown-C5ldCjSN.js → chart-markdown-B_2Ed7FJ.js} +2 -2
  148. package/dist/client/chunks/{chart-markdown-C5ldCjSN.js.map → chart-markdown-B_2Ed7FJ.js.map} +1 -1
  149. package/dist/client/chunks/{chart-measure-profile-CjErXQI4.js → chart-measure-profile-CWsPrQhH.js} +3 -3
  150. package/dist/client/chunks/{chart-measure-profile-CjErXQI4.js.map → chart-measure-profile-CWsPrQhH.js.map} +1 -1
  151. package/dist/client/chunks/{chart-pie-CmKhmUR-.js → chart-pie-BEB2sCXF.js} +3 -3
  152. package/dist/client/chunks/{chart-pie-CmKhmUR-.js.map → chart-pie-BEB2sCXF.js.map} +1 -1
  153. package/dist/client/chunks/{chart-radar-B2bYTyb0.js → chart-radar-BbSbXKbP.js} +3 -3
  154. package/dist/client/chunks/{chart-radar-B2bYTyb0.js.map → chart-radar-BbSbXKbP.js.map} +1 -1
  155. package/dist/client/chunks/{chart-radial-bar-DvQ-xZS-.js → chart-radial-bar-CNYD7tkM.js} +3 -3
  156. package/dist/client/chunks/{chart-radial-bar-DvQ-xZS-.js.map → chart-radial-bar-CNYD7tkM.js.map} +1 -1
  157. package/dist/client/chunks/{chart-sankey-DHIrjmhj.js → chart-sankey-DKnTIvSr.js} +2 -2
  158. package/dist/client/chunks/{chart-sankey-DHIrjmhj.js.map → chart-sankey-DKnTIvSr.js.map} +1 -1
  159. package/dist/client/chunks/{chart-scatter-JnoA3CD5.js → chart-scatter-CSWF6-lx.js} +3 -3
  160. package/dist/client/chunks/{chart-scatter-JnoA3CD5.js.map → chart-scatter-CSWF6-lx.js.map} +1 -1
  161. package/dist/client/chunks/{chart-sunburst-BtzRp5bg.js → chart-sunburst-CdGzCq7q.js} +3 -3
  162. package/dist/client/chunks/{chart-sunburst-BtzRp5bg.js.map → chart-sunburst-CdGzCq7q.js.map} +1 -1
  163. package/dist/client/chunks/{chart-tree-map-HQitd39D.js → chart-tree-map-BiXB7EiM.js} +3 -3
  164. package/dist/client/chunks/{chart-tree-map-HQitd39D.js.map → chart-tree-map-BiXB7EiM.js.map} +1 -1
  165. package/dist/client/chunks/{chart-waterfall-Dd3HMz3p.js → chart-waterfall-5rSDeLEZ.js} +3 -3
  166. package/dist/client/chunks/{chart-waterfall-Dd3HMz3p.js.map → chart-waterfall-5rSDeLEZ.js.map} +1 -1
  167. package/dist/client/chunks/{charts-core-CQFOTTPb.js → charts-core-CKpkoMCa.js} +2 -2
  168. package/dist/client/chunks/{charts-core-CQFOTTPb.js.map → charts-core-CKpkoMCa.js.map} +1 -1
  169. package/dist/client/chunks/charts-loader-BTI0UPK4.js +87 -0
  170. package/dist/client/chunks/{charts-loader-BlxEsp39.js.map → charts-loader-BTI0UPK4.js.map} +1 -1
  171. package/dist/client/chunks/{nl-NL-gaWTnOGQ.js → nl-NL-kRjxedTf.js} +8 -1
  172. package/dist/client/chunks/{nl-NL-gaWTnOGQ.js.map → nl-NL-kRjxedTf.js.map} +1 -1
  173. package/dist/client/chunks/{schema-visualization-BspQ-XB8.js → schema-visualization-BbvL74Sf.js} +3 -3
  174. package/dist/client/chunks/{schema-visualization-BspQ-XB8.js.map → schema-visualization-BbvL74Sf.js.map} +1 -1
  175. package/dist/client/chunks/{useDirtyStateTracking-DY5sjvb6.js → useDirtyStateTracking-BfG1lX_3.js} +4 -4
  176. package/dist/client/chunks/{useDirtyStateTracking-DY5sjvb6.js.map → useDirtyStateTracking-BfG1lX_3.js.map} +1 -1
  177. package/dist/client/chunks/{useExplainAI-BY0Ti3FZ.js → useExplainAI-CDFhgmpE.js} +4 -4
  178. package/dist/client/chunks/{useExplainAI-BY0Ti3FZ.js.map → useExplainAI-CDFhgmpE.js.map} +1 -1
  179. package/dist/client/chunks/{vendor-C4pD7rZf.js → vendor-DeckzF1j.js} +2 -2
  180. package/dist/client/chunks/{vendor-C4pD7rZf.js.map → vendor-DeckzF1j.js.map} +1 -1
  181. package/dist/client/components/shared/dateRangeUtils.d.ts +7 -3
  182. package/dist/client/components.js +2 -2
  183. package/dist/client/hooks.js +3 -3
  184. package/dist/client/icons.js +1 -1
  185. package/dist/client/index.js +18 -18
  186. package/dist/client/index.js.map +1 -1
  187. package/dist/client/providers.js +1 -1
  188. package/dist/client/schema.js +1 -1
  189. package/dist/client/utils.js +4 -4
  190. package/dist/client-bundle-stats.html +1 -1
  191. package/dist/mcp-app/mcp-app.html +2 -2
  192. package/dist/server/adapters/base-adapter.d.ts +3 -3
  193. package/dist/server/ai/query-schema.d.ts +3 -3
  194. package/dist/server/builders/date-time-builder.d.ts +1 -2
  195. package/dist/server/builders/date-time-helpers.d.ts +19 -6
  196. package/dist/server/builders/filter-operators.d.ts +10 -1
  197. package/dist/server/execution/query-normalizer.d.ts +9 -0
  198. package/dist/server/index.cjs +54 -47
  199. package/dist/server/index.js +2562 -2409
  200. package/dist/server/{openai-D346-vmt.cjs → openai-BIHkBS7X.cjs} +1 -1
  201. package/dist/server/{openai-SILGL2q_.js → openai-CPW5x6kl.js} +1 -1
  202. package/dist/server/{openai-D0vh48Oi.js → openai-DCC49vC6.js} +507 -436
  203. package/dist/server/openai-xQRpdAPa.cjs +19 -0
  204. package/dist/server/physical-plan/drizzle-sql-builder.d.ts +25 -0
  205. package/dist/server/physical-plan/semi-join.d.ts +21 -0
  206. package/dist/server/prompts/single-step-prompt.d.ts +1 -1
  207. package/package.json +3 -3
  208. package/dist/adapters/ActivityGridChart.config-BgAUfqKS.js +0 -2
  209. package/dist/adapters/ActivityGridChart.config-CGsjbfYL.cjs +0 -1
  210. package/dist/adapters/AreaChart.config-Bmj24k3G.cjs +0 -1
  211. package/dist/adapters/AreaChart.config-DqJvquc-.js +0 -2
  212. package/dist/adapters/BarChart.config-CzGxsUq-.js +0 -2
  213. package/dist/adapters/BarChart.config-D1uQGV6T.cjs +0 -1
  214. package/dist/adapters/BoxPlotChart.config-I0S4-aNF.js +0 -2
  215. package/dist/adapters/BoxPlotChart.config-wfS4FxGI.cjs +0 -1
  216. package/dist/adapters/BubbleChart.config-BDSknEkc.js +0 -2
  217. package/dist/adapters/BubbleChart.config-CByvW3Rq.cjs +0 -1
  218. package/dist/adapters/CandlestickChart.config-08gqS1xj.cjs +0 -1
  219. package/dist/adapters/CandlestickChart.config-Bkr9bdwM.js +0 -2
  220. package/dist/adapters/DataTable.config-BFP6xnMc.cjs +0 -1
  221. package/dist/adapters/DataTable.config-DHYD7PA8.js +0 -2
  222. package/dist/adapters/DotStripChart.config-DRQybZZu.cjs +0 -1
  223. package/dist/adapters/DotStripChart.config-Sp0fOxfM.js +0 -2
  224. package/dist/adapters/FunnelChart.config-ByARozX6.cjs +0 -1
  225. package/dist/adapters/FunnelChart.config-DhCqap3P.js +0 -2
  226. package/dist/adapters/GaugeChart.config-CfRicB1o.cjs +0 -1
  227. package/dist/adapters/GaugeChart.config-PTQ85WM5.js +0 -2
  228. package/dist/adapters/HeatMapChart.config-0tmGHwm2.cjs +0 -1
  229. package/dist/adapters/HeatMapChart.config-Devz5A5U.js +0 -2
  230. package/dist/adapters/KpiDelta.config-CGTdddOM.js +0 -2
  231. package/dist/adapters/KpiDelta.config-CjWmwXjk.cjs +0 -1
  232. package/dist/adapters/KpiNumber.config-Cd4jw22d.cjs +0 -1
  233. package/dist/adapters/KpiNumber.config-D3Et71Zn.js +0 -2
  234. package/dist/adapters/KpiText.config-B9VATPy2.js +0 -2
  235. package/dist/adapters/KpiText.config-B_dkrdHj.cjs +0 -1
  236. package/dist/adapters/LineChart.config-C3p-mc15.cjs +0 -1
  237. package/dist/adapters/LineChart.config-DXWLMWjn.js +0 -2
  238. package/dist/adapters/MarkdownChart.config-BQGmd6Iz.js +0 -2
  239. package/dist/adapters/MarkdownChart.config-CQFu4297.cjs +0 -1
  240. package/dist/adapters/MeasureProfileChart.config-CXLeprVS.js +0 -2
  241. package/dist/adapters/MeasureProfileChart.config-KpfD016N.cjs +0 -1
  242. package/dist/adapters/PieChart.config-j-syrhBx.js +0 -2
  243. package/dist/adapters/PieChart.config-zzBPh0tx.cjs +0 -1
  244. package/dist/adapters/ProportionBarChart.config-BD9bf-LZ.js +0 -2
  245. package/dist/adapters/ProportionBarChart.config-CBLcLV4Z.cjs +0 -1
  246. package/dist/adapters/RadarChart.config-CW9f_VxU.cjs +0 -1
  247. package/dist/adapters/RadarChart.config-yKvcZ49V.js +0 -2
  248. package/dist/adapters/RadialBarChart.config-DwQYejI6.cjs +0 -1
  249. package/dist/adapters/RadialBarChart.config-xK4AyoOF.js +0 -2
  250. package/dist/adapters/RecordsTable.config-CquV7Wi0.js +0 -2
  251. package/dist/adapters/RecordsTable.config-DzrQXBvh.cjs +0 -1
  252. package/dist/adapters/RetentionCombinedChart.config-BYAFkFb-.cjs +0 -1
  253. package/dist/adapters/RetentionCombinedChart.config-Ddmb-WwM.js +0 -2
  254. package/dist/adapters/RetentionHeatmap.config-CSHXD736.cjs +0 -1
  255. package/dist/adapters/RetentionHeatmap.config-DODcy3gK.js +0 -2
  256. package/dist/adapters/SankeyChart.config-B56o6GFu.js +0 -2
  257. package/dist/adapters/SankeyChart.config-DLnhr2k_.cjs +0 -1
  258. package/dist/adapters/ScatterChart.config-CrIFaC-s.js +0 -2
  259. package/dist/adapters/ScatterChart.config-Dfj1_af-.cjs +0 -1
  260. package/dist/adapters/SunburstChart.config-CuLsLj6v.cjs +0 -1
  261. package/dist/adapters/SunburstChart.config-CvuVUfkp.js +0 -2
  262. package/dist/adapters/TreeMapChart.config-CvbDr1Ic.js +0 -2
  263. package/dist/adapters/TreeMapChart.config-Dqjhe8Xk.cjs +0 -1
  264. package/dist/adapters/WaterfallChart.config-DXFeGg7P.cjs +0 -1
  265. package/dist/adapters/WaterfallChart.config-MLHPNE5q.js +0 -2
  266. package/dist/adapters/compiler-C5OSdfwn.cjs +0 -166
  267. package/dist/adapters/mcp-app-html-DRWnkcx4.cjs +0 -1
  268. package/dist/adapters/openai-CwKv0DD-.cjs +0 -19
  269. package/dist/adapters/utils-BFGzuSlF.cjs +0 -132
  270. package/dist/client/chunks/DashboardEditModal-USQFytJw.js.map +0 -1
  271. package/dist/client/chunks/analysis-builder-shared-BSINKFr2.js.map +0 -1
  272. package/dist/client/chunks/chart-activity-grid-CSIsJ12e.js.map +0 -1
  273. package/dist/client/chunks/chart-data-table-BH1A-1RN.js.map +0 -1
  274. package/dist/client/chunks/charts-loader-BlxEsp39.js +0 -87
  275. 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-CSIsJ12e.js";
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-DVm_7rph.js.map
193
+ //# sourceMappingURL=RetentionHeatmap-jpshJ2Af.js.map
@@ -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-BH1A-1RN.js";
2
- import { E as c, M as l, S as u, c as d, o as f, s as p, y as m } from "./DashboardEditModal-USQFytJw.js";
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-CSIsJ12e.js";
5
- import { r as S, t as C } from "./useExplainAI-BY0Ti3FZ.js";
6
- import { a as w, t as T } from "./charts-loader-BlxEsp39.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-BSINKFr2.js";
8
- import { n as P } from "./charts-core-CQFOTTPb.js";
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: l, onColorPaletteChange: u, currentPaletteName: d, 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;
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 && l && /* @__PURE__ */ K("button", {
461
- onClick: l,
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
- u && r && /* @__PURE__ */ G(c, {
470
- currentPalette: d || "default",
471
- onPaletteChange: u
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-BspQ-XB8.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: c = {}, 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 }) {
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: c,
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(l, {
963
- code: JSON.stringify(c, null, 2),
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(l, {
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(l, {
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(l, {
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(l, {
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(l, {
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(l, {
1157
- code: JSON.stringify(c, null, 2),
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(l, {
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(l, {
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(), [l, d] = U(!1), [f, p] = U(!1), [m, h] = U(e.name), g = H(null), _ = H(null);
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
- l && g.current && (g.current.focus(), g.current.select());
2344
- }, [l]), B(() => {
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 ? u(e.cube, t) : t;
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
- l ? /* @__PURE__ */ G("input", {
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: u, displayConfig: f, colorPalette: p, onDisplayConfigChange: m }) {
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 && u(r);
4275
+ }), t && d(r);
4276
4276
  }, [
4277
4277
  v,
4278
4278
  n,
4279
4279
  y.dropZones,
4280
- u,
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), u(a);
4334
+ _(null), d(a);
4335
4335
  }, j = (e, t) => {
4336
- u(Fn(n, e, t));
4336
+ d(Fn(n, e, t));
4337
4337
  }, M = (e, t, r) => {
4338
4338
  let i = In(n, e, t, r);
4339
- i && (_(null), u(i));
4339
+ i && (_(null), d(i));
4340
4340
  }, N = z((e, t) => {
4341
- u({
4341
+ d({
4342
4342
  ...n,
4343
4343
  yAxisAssignment: {
4344
4344
  ...n.yAxisAssignment,
4345
4345
  [e]: t
4346
4346
  }
4347
4347
  });
4348
- }, [n, u]);
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(d, {
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-D_tw9BvU.js.map
5427
+ //# sourceMappingURL=analysis-builder-DIOnKxJu.js.map