drizzle-cube 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/dist/adapters/ActivityGridChart.config-D6hhj345.cjs +1 -0
  2. package/dist/adapters/ActivityGridChart.config-QZKs_NYg.js +2 -0
  3. package/dist/adapters/AreaChart.config-B5XM6G22.js +2 -0
  4. package/dist/adapters/AreaChart.config-NP34BH5y.cjs +1 -0
  5. package/dist/adapters/BarChart.config-Bqlmr81N.js +2 -0
  6. package/dist/adapters/BarChart.config-C3bw-cAP.cjs +1 -0
  7. package/dist/adapters/BoxPlotChart.config-BOAvoj6x.cjs +1 -0
  8. package/dist/adapters/BoxPlotChart.config-CTXiycYY.js +2 -0
  9. package/dist/adapters/BubbleChart.config-CGFIkl4H.cjs +1 -0
  10. package/dist/adapters/BubbleChart.config-Njxx4Eq1.js +2 -0
  11. package/dist/adapters/CandlestickChart.config-BZ_yWaSo.cjs +1 -0
  12. package/dist/adapters/CandlestickChart.config-D4Svhmef.js +2 -0
  13. package/dist/adapters/DataTable.config-B-bT9puT.js +2 -0
  14. package/dist/adapters/DataTable.config-BHtt1cPM.cjs +1 -0
  15. package/dist/adapters/FunnelChart.config-C1e07O7B.cjs +1 -0
  16. package/dist/adapters/FunnelChart.config-CVEy0tV9.js +2 -0
  17. package/dist/adapters/GaugeChart.config-5PLNlQlu.js +2 -0
  18. package/dist/adapters/GaugeChart.config-Cdv6knjZ.cjs +1 -0
  19. package/dist/adapters/HeatMapChart.config-MGTfYpWJ.js +2 -0
  20. package/dist/adapters/HeatMapChart.config-jfBEi1ZI.cjs +1 -0
  21. package/dist/adapters/KpiDelta.config-D2IUsEYz.cjs +1 -0
  22. package/dist/adapters/KpiDelta.config-DT_MmAHw.js +2 -0
  23. package/dist/adapters/KpiNumber.config-ChgbKmx8.cjs +1 -0
  24. package/dist/adapters/KpiNumber.config-CvZ_FhyL.js +2 -0
  25. package/dist/adapters/KpiText.config-Bgkw8gr2.js +2 -0
  26. package/dist/adapters/KpiText.config-Bz9orqt6.cjs +1 -0
  27. package/dist/adapters/LineChart.config-BVew35dI.cjs +1 -0
  28. package/dist/adapters/LineChart.config-DSCCKXNg.js +2 -0
  29. package/dist/adapters/MarkdownChart.config-Bu6XUuhI.js +2 -0
  30. package/dist/adapters/MarkdownChart.config-E4aSVTf3.cjs +1 -0
  31. package/dist/adapters/MeasureProfileChart.config-BF249hc_.cjs +1 -0
  32. package/dist/adapters/MeasureProfileChart.config-lERVe38G.js +2 -0
  33. package/dist/adapters/PieChart.config-7Ujwp8R5.cjs +1 -0
  34. package/dist/adapters/PieChart.config-jQl2HIcA.js +2 -0
  35. package/dist/adapters/ProportionBarChart.config-o0w_Pnlt.js +2 -0
  36. package/dist/adapters/ProportionBarChart.config-phNohhhY.cjs +1 -0
  37. package/dist/adapters/RadarChart.config-BmrYBd9x.js +2 -0
  38. package/dist/adapters/RadarChart.config-Dlt3UflG.cjs +1 -0
  39. package/dist/adapters/RadialBarChart.config-CeEm8xRb.cjs +1 -0
  40. package/dist/adapters/RadialBarChart.config-Dishh6bC.js +2 -0
  41. package/dist/adapters/RetentionCombinedChart.config-BaD4ev85.cjs +1 -0
  42. package/dist/adapters/RetentionCombinedChart.config-m2FjBUi9.js +2 -0
  43. package/dist/adapters/RetentionHeatmap.config-DiMplGdk.js +2 -0
  44. package/dist/adapters/RetentionHeatmap.config-Dp6oYwQZ.cjs +1 -0
  45. package/dist/adapters/SankeyChart.config-C4Y6qzCS.cjs +1 -0
  46. package/dist/adapters/SankeyChart.config-CJHqgjQ1.js +2 -0
  47. package/dist/adapters/ScatterChart.config-C0QqvDrN.cjs +1 -0
  48. package/dist/adapters/ScatterChart.config-DywOsWPW.js +2 -0
  49. package/dist/adapters/SunburstChart.config-DE8RxpDR.cjs +1 -0
  50. package/dist/adapters/SunburstChart.config-DohowrO3.js +2 -0
  51. package/dist/adapters/TreeMapChart.config-D2gXz-zC.cjs +1 -0
  52. package/dist/adapters/TreeMapChart.config-HMlI29GG.js +2 -0
  53. package/dist/adapters/WaterfallChart.config-BO2WV2VB.js +2 -0
  54. package/dist/adapters/WaterfallChart.config-CzwGiheB.cjs +1 -0
  55. package/dist/adapters/{compiler-DAyodAnH.cjs → compiler-BNjqYdmc.cjs} +1 -1
  56. package/dist/adapters/{compiler-Dq04wAjm.js → compiler-DiYxWAKg.js} +1 -1
  57. package/dist/adapters/core/index.cjs +1 -1
  58. package/dist/adapters/core/index.js +1 -1
  59. package/dist/adapters/{core-BjxfG6Uf.js → core-BOPRmxPc.js} +2 -2
  60. package/dist/adapters/{core-zV2w0hO2.cjs → core-CzFfrJzu.cjs} +1 -1
  61. package/dist/adapters/express/index.cjs +1 -1
  62. package/dist/adapters/express/index.js +5 -5
  63. package/dist/adapters/fastify/index.cjs +1 -1
  64. package/dist/adapters/fastify/index.js +5 -5
  65. package/dist/adapters/{handler-ox6qxLw5.js → handler-DGud-C-w.js} +31 -32
  66. package/dist/adapters/{handler-C6Hj6_Yk.cjs → handler-m6WgA9xu.cjs} +3 -3
  67. package/dist/adapters/hono/index.cjs +1 -1
  68. package/dist/adapters/hono/index.js +4 -4
  69. package/dist/adapters/mcp-tools.cjs +1 -1
  70. package/dist/adapters/mcp-tools.js +2 -2
  71. package/dist/adapters/mcp-transport-B0b27YUB.cjs +40 -0
  72. package/dist/adapters/mcp-transport-BXyA4dTk.js +603 -0
  73. package/dist/adapters/nextjs/index.cjs +1 -1
  74. package/dist/adapters/nextjs/index.js +5 -5
  75. package/dist/adapters/{openai-C9LNhHfK.js → openai-CGJM6Qun.js} +1 -1
  76. package/dist/adapters/{openai-BffpdO4n.cjs → openai-CmdN7Sj1.cjs} +1 -1
  77. package/dist/adapters/{openai-CmyXJWti.js → openai-Crp3X_zg.js} +1 -1
  78. package/dist/adapters/{openai-DlT-0VRC.cjs → openai-Dwt9bxOE.cjs} +1 -1
  79. package/dist/adapters/utils-BoOeig94.cjs +128 -0
  80. package/dist/adapters/{utils-tjiwXFnP.js → utils-DboNUT3A.js} +6 -2
  81. package/dist/adapters/utils.cjs +1 -1
  82. package/dist/adapters/utils.js +1 -1
  83. package/dist/cjs/client/charts/chartConfigs.d.ts +1 -1
  84. package/dist/cjs/client/components/charts/GaugeChart.d.ts +8 -0
  85. package/dist/cjs/client/components/charts/gaugeChartHelpers.d.ts +117 -12
  86. package/dist/client/charts/chartConfigs.d.ts +1 -1
  87. package/dist/client/charts.js +12 -12
  88. package/dist/client/chunks/{DashboardEditModal-ByXLlXZD.js → DashboardEditModal-BOfLdTgV.js} +1061 -992
  89. package/dist/client/chunks/{DashboardEditModal-ByXLlXZD.js.map → DashboardEditModal-BOfLdTgV.js.map} +1 -1
  90. package/dist/client/chunks/{ProportionBarChart-lOeVz8ZC.js → ProportionBarChart-DwoXU5VP.js} +3 -3
  91. package/dist/client/chunks/{ProportionBarChart-lOeVz8ZC.js.map → ProportionBarChart-DwoXU5VP.js.map} +1 -1
  92. package/dist/client/chunks/{RetentionCombinedChart-Mcm7zHFx.js → RetentionCombinedChart-BqlSV7yF.js} +3 -3
  93. package/dist/client/chunks/{RetentionCombinedChart-Mcm7zHFx.js.map → RetentionCombinedChart-BqlSV7yF.js.map} +1 -1
  94. package/dist/client/chunks/{RetentionHeatmap-4VJx5KDM.js → RetentionHeatmap-VdVkBg8Q.js} +2 -2
  95. package/dist/client/chunks/{RetentionHeatmap-4VJx5KDM.js.map → RetentionHeatmap-VdVkBg8Q.js.map} +1 -1
  96. package/dist/client/chunks/{af-ZA-BTaChuqI.js → af-ZA-C0dGb_53.js} +7 -3
  97. package/dist/client/chunks/af-ZA-C0dGb_53.js.map +1 -0
  98. package/dist/client/chunks/{analysis-builder-CWTJQQtL.js → analysis-builder-DXw60SEs.js} +9 -9
  99. package/dist/client/chunks/{analysis-builder-CWTJQQtL.js.map → analysis-builder-DXw60SEs.js.map} +1 -1
  100. package/dist/client/chunks/{analysis-builder-shared-l-4WKVS1.js → analysis-builder-shared-CEvHIlmk.js} +9 -9
  101. package/dist/client/chunks/{analysis-builder-shared-l-4WKVS1.js.map → analysis-builder-shared-CEvHIlmk.js.map} +1 -1
  102. package/dist/client/chunks/{chart-activity-grid-DVOhLgxv.js → chart-activity-grid-4jfS8khG.js} +9 -5
  103. package/dist/client/chunks/chart-activity-grid-4jfS8khG.js.map +1 -0
  104. package/dist/client/chunks/{chart-area-C-5ATxvi.js → chart-area-Dol6s9no.js} +2 -2
  105. package/dist/client/chunks/{chart-area-C-5ATxvi.js.map → chart-area-Dol6s9no.js.map} +1 -1
  106. package/dist/client/chunks/{chart-bar-CPiLaXHP.js → chart-bar-5_niozi2.js} +3 -3
  107. package/dist/client/chunks/{chart-bar-CPiLaXHP.js.map → chart-bar-5_niozi2.js.map} +1 -1
  108. package/dist/client/chunks/{chart-box-plot-Bae5O9xC.js → chart-box-plot-Dhp-VwhD.js} +2 -2
  109. package/dist/client/chunks/{chart-box-plot-Bae5O9xC.js.map → chart-box-plot-Dhp-VwhD.js.map} +1 -1
  110. package/dist/client/chunks/{chart-bubble-BFN5WIpf.js → chart-bubble-BM2BAMSo.js} +2 -2
  111. package/dist/client/chunks/{chart-bubble-BFN5WIpf.js.map → chart-bubble-BM2BAMSo.js.map} +1 -1
  112. package/dist/client/chunks/{chart-candlestick-PBQKp_z7.js → chart-candlestick-BNwLIBfm.js} +2 -2
  113. package/dist/client/chunks/{chart-candlestick-PBQKp_z7.js.map → chart-candlestick-BNwLIBfm.js.map} +1 -1
  114. package/dist/client/chunks/{chart-config-gauge-DNafFwfS.js → chart-config-gauge-CJktdjox.js} +3 -4
  115. package/dist/client/chunks/chart-config-gauge-CJktdjox.js.map +1 -0
  116. package/dist/client/chunks/{chart-data-table-SNSqZj9B.js → chart-data-table-DoDHQRe7.js} +4 -4
  117. package/dist/client/chunks/chart-data-table-DoDHQRe7.js.map +1 -0
  118. package/dist/client/chunks/{chart-funnel-CkHSXp6h.js → chart-funnel-Cd7da_sa.js} +2 -2
  119. package/dist/client/chunks/{chart-funnel-CkHSXp6h.js.map → chart-funnel-Cd7da_sa.js.map} +1 -1
  120. package/dist/client/chunks/{chart-gauge-DHIGq3TH.js → chart-gauge-DOpul-Oz.js} +169 -116
  121. package/dist/client/chunks/chart-gauge-DOpul-Oz.js.map +1 -0
  122. package/dist/client/chunks/{chart-heat-map-Bb8L1XQr.js → chart-heat-map-CeKbK655.js} +3 -3
  123. package/dist/client/chunks/{chart-heat-map-Bb8L1XQr.js.map → chart-heat-map-CeKbK655.js.map} +1 -1
  124. package/dist/client/chunks/{chart-kpi-delta-BJCOXE-F.js → chart-kpi-delta-Dq8qUOOT.js} +3 -3
  125. package/dist/client/chunks/{chart-kpi-delta-BJCOXE-F.js.map → chart-kpi-delta-Dq8qUOOT.js.map} +1 -1
  126. package/dist/client/chunks/{chart-kpi-number-Cdqgv20g.js → chart-kpi-number-DgiqTi9g.js} +5 -5
  127. package/dist/client/chunks/{chart-kpi-number-Cdqgv20g.js.map → chart-kpi-number-DgiqTi9g.js.map} +1 -1
  128. package/dist/client/chunks/{chart-kpi-text-B10ZHCsI.js → chart-kpi-text-CsZMVEnM.js} +3 -3
  129. package/dist/client/chunks/{chart-kpi-text-B10ZHCsI.js.map → chart-kpi-text-CsZMVEnM.js.map} +1 -1
  130. package/dist/client/chunks/{chart-line-CzvVL3Be.js → chart-line-DlwOB7C7.js} +3 -3
  131. package/dist/client/chunks/{chart-line-CzvVL3Be.js.map → chart-line-DlwOB7C7.js.map} +1 -1
  132. package/dist/client/chunks/{chart-markdown-C0xxBW81.js → chart-markdown-DPE34SjC.js} +2 -2
  133. package/dist/client/chunks/{chart-markdown-C0xxBW81.js.map → chart-markdown-DPE34SjC.js.map} +1 -1
  134. package/dist/client/chunks/{chart-measure-profile-BSUPFZCR.js → chart-measure-profile-BpTz1fce.js} +3 -3
  135. package/dist/client/chunks/{chart-measure-profile-BSUPFZCR.js.map → chart-measure-profile-BpTz1fce.js.map} +1 -1
  136. package/dist/client/chunks/{chart-pie-CwRfwWWZ.js → chart-pie-FGw66XAH.js} +3 -3
  137. package/dist/client/chunks/{chart-pie-CwRfwWWZ.js.map → chart-pie-FGw66XAH.js.map} +1 -1
  138. package/dist/client/chunks/{chart-radar-Dfql2E7i.js → chart-radar-D-eRDoiA.js} +3 -3
  139. package/dist/client/chunks/{chart-radar-Dfql2E7i.js.map → chart-radar-D-eRDoiA.js.map} +1 -1
  140. package/dist/client/chunks/{chart-radial-bar-oE9OZ1IX.js → chart-radial-bar-DgtkNTs3.js} +3 -3
  141. package/dist/client/chunks/{chart-radial-bar-oE9OZ1IX.js.map → chart-radial-bar-DgtkNTs3.js.map} +1 -1
  142. package/dist/client/chunks/{chart-sankey-tK7Oz1bC.js → chart-sankey-D0hhb_EQ.js} +2 -2
  143. package/dist/client/chunks/{chart-sankey-tK7Oz1bC.js.map → chart-sankey-D0hhb_EQ.js.map} +1 -1
  144. package/dist/client/chunks/{chart-scatter-BtLfAsZb.js → chart-scatter-D9EcAiMQ.js} +3 -3
  145. package/dist/client/chunks/{chart-scatter-BtLfAsZb.js.map → chart-scatter-D9EcAiMQ.js.map} +1 -1
  146. package/dist/client/chunks/{chart-sunburst-B7ryWwQ1.js → chart-sunburst-DCYmJ5DU.js} +3 -3
  147. package/dist/client/chunks/{chart-sunburst-B7ryWwQ1.js.map → chart-sunburst-DCYmJ5DU.js.map} +1 -1
  148. package/dist/client/chunks/{chart-tree-map-DU5M3-qe.js → chart-tree-map-D_ACSSiB.js} +3 -3
  149. package/dist/client/chunks/{chart-tree-map-DU5M3-qe.js.map → chart-tree-map-D_ACSSiB.js.map} +1 -1
  150. package/dist/client/chunks/{chart-waterfall-CAwutpzd.js → chart-waterfall-CVUVNa1R.js} +3 -3
  151. package/dist/client/chunks/{chart-waterfall-CAwutpzd.js.map → chart-waterfall-CVUVNa1R.js.map} +1 -1
  152. package/dist/client/chunks/{charts-core-BxBB2zBE.js → charts-core-BPD_hLaL.js} +2 -2
  153. package/dist/client/chunks/{charts-core-BxBB2zBE.js.map → charts-core-BPD_hLaL.js.map} +1 -1
  154. package/dist/client/chunks/charts-loader-CwMcOfwT.js +85 -0
  155. package/dist/client/chunks/{charts-loader-0avVzeDd.js.map → charts-loader-CwMcOfwT.js.map} +1 -1
  156. package/dist/client/chunks/{nl-NL-BSMhprPr.js → nl-NL-DFLVORiD.js} +7 -3
  157. package/dist/client/chunks/nl-NL-DFLVORiD.js.map +1 -0
  158. package/dist/client/chunks/{schema-visualization-CGbnbzj_.js → schema-visualization-C6g_LCiA.js} +3 -3
  159. package/dist/client/chunks/{schema-visualization-CGbnbzj_.js.map → schema-visualization-C6g_LCiA.js.map} +1 -1
  160. package/dist/client/chunks/{useDirtyStateTracking-Dc-Si4db.js → useDirtyStateTracking-ZfChDEd3.js} +4 -4
  161. package/dist/client/chunks/{useDirtyStateTracking-Dc-Si4db.js.map → useDirtyStateTracking-ZfChDEd3.js.map} +1 -1
  162. package/dist/client/chunks/{useExplainAI-DJbc7Lu4.js → useExplainAI-im9e1rVb.js} +4 -4
  163. package/dist/client/chunks/{useExplainAI-DJbc7Lu4.js.map → useExplainAI-im9e1rVb.js.map} +1 -1
  164. package/dist/client/chunks/{vendor-cTfe9Kho.js → vendor-Qa1s8oSX.js} +2 -2
  165. package/dist/client/chunks/{vendor-cTfe9Kho.js.map → vendor-Qa1s8oSX.js.map} +1 -1
  166. package/dist/client/components/charts/GaugeChart.d.ts +8 -0
  167. package/dist/client/components/charts/gaugeChartHelpers.d.ts +117 -12
  168. package/dist/client/components.js +1 -1
  169. package/dist/client/hooks.js +3 -3
  170. package/dist/client/icons.js +1 -1
  171. package/dist/client/index.js +13 -13
  172. package/dist/client/providers.js +1 -1
  173. package/dist/client/schema.js +1 -1
  174. package/dist/client/utils.js +4 -4
  175. package/dist/client-bundle-stats.html +1 -1
  176. package/dist/mcp-app/mcp-app.html +86 -86
  177. package/dist/server/index.cjs +3 -3
  178. package/dist/server/index.js +8 -5
  179. package/package.json +1 -1
  180. package/dist/adapters/ActivityGridChart.config-DaYILvFZ.cjs +0 -1
  181. package/dist/adapters/ActivityGridChart.config-_SyTBEyR.js +0 -2
  182. package/dist/adapters/AreaChart.config-BKh6fY1_.cjs +0 -1
  183. package/dist/adapters/AreaChart.config-CJoxLP3Y.js +0 -2
  184. package/dist/adapters/BarChart.config-Bm1bfRbI.cjs +0 -1
  185. package/dist/adapters/BarChart.config-CGu2Bqrx.js +0 -2
  186. package/dist/adapters/BoxPlotChart.config-B7M9CQaE.js +0 -2
  187. package/dist/adapters/BoxPlotChart.config-CXQel8Hk.cjs +0 -1
  188. package/dist/adapters/BubbleChart.config-BJ36IuVS.cjs +0 -1
  189. package/dist/adapters/BubbleChart.config-CWoXeLdm.js +0 -2
  190. package/dist/adapters/CandlestickChart.config-CGMLZVIy.cjs +0 -1
  191. package/dist/adapters/CandlestickChart.config-CzOcfF1e.js +0 -2
  192. package/dist/adapters/DataTable.config-CdAzueTs.cjs +0 -1
  193. package/dist/adapters/DataTable.config-D_KmPyxV.js +0 -2
  194. package/dist/adapters/FunnelChart.config-D1QAUuYl.cjs +0 -1
  195. package/dist/adapters/FunnelChart.config-DCRHQoFc.js +0 -2
  196. package/dist/adapters/GaugeChart.config-DAybRXP3.js +0 -2
  197. package/dist/adapters/GaugeChart.config-WUPfyLP-.cjs +0 -1
  198. package/dist/adapters/HeatMapChart.config-CziltPnC.cjs +0 -1
  199. package/dist/adapters/HeatMapChart.config-DHpXNONW.js +0 -2
  200. package/dist/adapters/KpiDelta.config-Bw5o0ocY.js +0 -2
  201. package/dist/adapters/KpiDelta.config-CdAmE1pw.cjs +0 -1
  202. package/dist/adapters/KpiNumber.config-CQ_wq2gx.js +0 -2
  203. package/dist/adapters/KpiNumber.config-wxN8x4DC.cjs +0 -1
  204. package/dist/adapters/KpiText.config-DIRIC97F.cjs +0 -1
  205. package/dist/adapters/KpiText.config-eODcP6Hn.js +0 -2
  206. package/dist/adapters/LineChart.config-32-9zA2V.js +0 -2
  207. package/dist/adapters/LineChart.config-BukeFp6z.cjs +0 -1
  208. package/dist/adapters/MarkdownChart.config-BVsR5LDy.js +0 -2
  209. package/dist/adapters/MarkdownChart.config-j4veYjcZ.cjs +0 -1
  210. package/dist/adapters/MeasureProfileChart.config-BRDYx1hw.js +0 -2
  211. package/dist/adapters/MeasureProfileChart.config-CIosBxco.cjs +0 -1
  212. package/dist/adapters/PieChart.config-Bj8KiA0n.cjs +0 -1
  213. package/dist/adapters/PieChart.config-DgAj3y-I.js +0 -2
  214. package/dist/adapters/ProportionBarChart.config-BfFOppHY.js +0 -2
  215. package/dist/adapters/ProportionBarChart.config-c8GGE1aK.cjs +0 -1
  216. package/dist/adapters/RadarChart.config-D7iHY1v9.js +0 -2
  217. package/dist/adapters/RadarChart.config-ghlANG2-.cjs +0 -1
  218. package/dist/adapters/RadialBarChart.config-CsXIz-0v.js +0 -2
  219. package/dist/adapters/RadialBarChart.config-Dsvu2CPV.cjs +0 -1
  220. package/dist/adapters/RetentionCombinedChart.config-CdT1kXC7.js +0 -2
  221. package/dist/adapters/RetentionCombinedChart.config-sDjFKH9K.cjs +0 -1
  222. package/dist/adapters/RetentionHeatmap.config-CvKBvQmu.cjs +0 -1
  223. package/dist/adapters/RetentionHeatmap.config-DbM3ICwc.js +0 -2
  224. package/dist/adapters/SankeyChart.config-BNBcIHaD.js +0 -2
  225. package/dist/adapters/SankeyChart.config-DZscz3kh.cjs +0 -1
  226. package/dist/adapters/ScatterChart.config-BNYIddyM.cjs +0 -1
  227. package/dist/adapters/ScatterChart.config-CEhtoLWc.js +0 -2
  228. package/dist/adapters/SunburstChart.config-ClseCzji.cjs +0 -1
  229. package/dist/adapters/SunburstChart.config-nnphNoVO.js +0 -2
  230. package/dist/adapters/TreeMapChart.config-C8-75muA.js +0 -2
  231. package/dist/adapters/TreeMapChart.config-DoXeUg9Y.cjs +0 -1
  232. package/dist/adapters/WaterfallChart.config-BOF1qxY3.cjs +0 -1
  233. package/dist/adapters/WaterfallChart.config-uW5YyOji.js +0 -2
  234. package/dist/adapters/mcp-transport-C_t_p0wU.cjs +0 -40
  235. package/dist/adapters/mcp-transport-DFH9e6de.js +0 -603
  236. package/dist/adapters/utils-C5FLHK04.cjs +0 -128
  237. package/dist/client/chunks/af-ZA-BTaChuqI.js.map +0 -1
  238. package/dist/client/chunks/chart-activity-grid-DVOhLgxv.js.map +0 -1
  239. package/dist/client/chunks/chart-config-gauge-DNafFwfS.js.map +0 -1
  240. package/dist/client/chunks/chart-data-table-SNSqZj9B.js.map +0 -1
  241. package/dist/client/chunks/chart-gauge-DHIGq3TH.js.map +0 -1
  242. package/dist/client/chunks/charts-loader-0avVzeDd.js +0 -85
  243. package/dist/client/chunks/nl-NL-BSMhprPr.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { n as e } from "./rolldown-runtime-DArdT4gl.js";
2
- import { D as t, E as n, M as r, P as i, S as a, T as o, l as s, s as c, w as l } from "./chart-activity-grid-DVOhLgxv.js";
2
+ import { D as t, E as n, M as r, P as i, S as a, T as o, l as s, s as c, w as l } from "./chart-activity-grid-4jfS8khG.js";
3
3
  import u, { Fragment as d, startTransition as f, useId as p, useLayoutEffect as m, useMemo as h, useRef as g, useState as _ } from "react";
4
4
  import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
5
5
  import { Area as x, CartesianGrid as S, ComposedChart as ee, Legend as C, Line as w, ResponsiveContainer as T, Tooltip as E, XAxis as te, YAxis as D } from "recharts";
@@ -960,4 +960,4 @@ var Me = u.memo(function({ summaries: e, getSeriesLabel: t, valueFormat: n, righ
960
960
  //#endregion
961
961
  export { V as A, I as B, ue as C, U as D, G as E, M as F, k as H, j as I, R as L, z as M, se as N, H as O, N as P, A as R, Z as S, K as T, ne as V, he as _, je as a, ge as b, Oe as c, ve as d, Se as f, J as g, X as h, xe as i, B as j, W as k, ke as l, q as m, Ne as n, Ae as o, we as p, Me as r, $ as s, Pe as t, ye as u, me as v, de as w, Y as x, pe as y, L as z };
962
962
 
963
- //# sourceMappingURL=chart-area-C-5ATxvi.js.map
963
+ //# sourceMappingURL=chart-area-Dol6s9no.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-area-C-5ATxvi.js","names":[],"sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/utils/comparisonUtils.ts","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/components/charts/AngledXAxisTick.tsx","../../../src/client/components/charts/ChartStates.tsx","../../../src/client/components/charts/chartAxisResolution.ts","../../../src/client/utils/targetUtils.ts","../../../src/client/components/charts/chartScaffolding.tsx","../../../src/client/components/charts/cartesianChartHelpers.tsx","../../../src/client/components/charts/ChartSummaryHeader.tsx","../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["/**\n * LoadingIndicator Component\n *\n * A centralized, theme-aware loading spinner that uses CSS variables\n * for consistent styling across all drizzle-cube components.\n *\n * Can be overridden at the Dashboard or Portlet level by passing a\n * custom loadingComponent prop.\n */\n\nexport interface LoadingIndicatorProps {\n /** Size variant: 'xs' (12px), 'sm' (24px), 'md' (32px), 'lg' (48px) */\n size?: 'xs' | 'sm' | 'md' | 'lg'\n /** Additional CSS classes */\n className?: string\n}\n\nconst sizeClasses = {\n xs: 'dc:h-3 dc:w-3',\n sm: 'dc:h-6 dc:w-6',\n md: 'dc:h-8 dc:w-8',\n lg: 'dc:h-12 dc:w-12'\n}\n\nexport default function LoadingIndicator({\n size = 'md',\n className = ''\n}: LoadingIndicatorProps) {\n return (\n <div\n className={`dc:animate-spin dc:rounded-full dc:border-b-2 ${sizeClasses[size]} ${className}`}\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n role=\"status\"\n aria-label=\"Loading\"\n />\n )\n}\n","/**\n * Comparison Data Utilities\n * Handles period-over-period comparison data transformation for charts\n *\n * These utilities detect comparison query results (with __periodIndex metadata)\n * and transform them for visualization in either 'separate' or 'overlay' mode.\n */\n\n/**\n * Check if data contains comparison period metadata\n */\nexport function isComparisonData(data: any[]): boolean {\n return data.length > 0 && '__periodIndex' in data[0]\n}\n\n/**\n * Get unique period labels from comparison data\n */\nexport function getPeriodLabels(data: any[]): string[] {\n if (!isComparisonData(data)) return []\n\n const labels = new Set<string>()\n for (const row of data) {\n if (row.__period) {\n labels.add(row.__period)\n }\n }\n return Array.from(labels)\n}\n\n/**\n * Get period indices from comparison data\n */\nexport function getPeriodIndices(data: any[]): number[] {\n if (!isComparisonData(data)) return []\n\n const indices = new Set<number>()\n for (const row of data) {\n if (typeof row.__periodIndex === 'number') {\n indices.add(row.__periodIndex)\n }\n }\n return Array.from(indices).sort((a, b) => a - b)\n}\n\n/**\n * Generate a short label for a period (used in legends)\n * Uses simple \"Current\" / \"Prior\" labels for clarity\n */\nexport function generatePeriodShortLabel(_periodLabel: string, index: number): string {\n return index === 0 ? 'Current' : 'Prior'\n}\n\n/**\n * Transform comparison data for 'separate' mode\n * Returns data with each row having its original measure values\n * Series are created per period (e.g., \"totalLinesOfCode (Current)\", \"totalLinesOfCode (Prior)\")\n */\nexport function transformForSeparateMode(\n data: any[],\n measures: string[],\n _timeDimensionKey: string\n): { data: any[], seriesKeys: string[] } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures }\n }\n\n const periodLabels = getPeriodLabels(data)\n const seriesKeys: string[] = []\n\n // Create series key for each measure + period combination\n for (const measure of measures) {\n for (let i = 0; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n const key = `${measure} (${shortLabel})`\n seriesKeys.push(key)\n }\n }\n\n // Data already has period info, just return as-is for separate mode\n // The chart will group by time dimension and show multiple lines\n return { data, seriesKeys }\n}\n\n/**\n * Detect dimension fields in comparison data\n * Returns fields that are not measures, time dimension, or metadata fields\n */\nfunction detectDimensionFields(\n data: any[],\n measures: string[],\n timeDimensionKey: string\n): string[] {\n if (data.length === 0) return []\n\n const metadataFields = ['__period', '__periodIndex', '__periodDayIndex']\n const firstRow = data[0]\n const dimensions: string[] = []\n\n for (const key of Object.keys(firstRow)) {\n if (\n !measures.includes(key) &&\n key !== timeDimensionKey &&\n !metadataFields.includes(key)\n ) {\n dimensions.push(key)\n }\n }\n\n return dimensions\n}\n\n/**\n * Get unique dimension values from data for a set of dimension fields\n */\nfunction getUniqueDimensionValues(\n data: any[],\n dimensionFields: string[]\n): Map<string, Set<any>> {\n const values = new Map<string, Set<any>>()\n\n for (const field of dimensionFields) {\n values.set(field, new Set())\n }\n\n for (const row of data) {\n for (const field of dimensionFields) {\n if (row[field] !== undefined && row[field] !== null) {\n values.get(field)!.add(row[field])\n }\n }\n }\n\n return values\n}\n\n/**\n * Transform comparison data for 'overlay' mode\n * Pivots data so each row represents a day-of-period index,\n * with separate columns for each period's values.\n *\n * When dimensions are present, creates series keys that include\n * dimension values: \"Engineering - Total Lines of Code (Current)\"\n *\n * Input (without dimensions):\n * [\n * { date: '2024-01-01', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-02', value: 110, __periodIndex: 0, __periodDayIndex: 1 },\n * { date: '2023-01-01', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-02', value: 85, __periodIndex: 1, __periodDayIndex: 1 },\n * ]\n *\n * Output (without dimensions):\n * [\n * { __periodDayIndex: 0, 'value (Current)': 100, 'value (Prior)': 80 },\n * { __periodDayIndex: 1, 'value (Current)': 110, 'value (Prior)': 85 },\n * ]\n *\n * Input (with dimensions):\n * [\n * { date: '2024-01-01', 'Dept.name': 'Engineering', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-01', 'Dept.name': 'Sales', value: 50, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Engineering', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Sales', value: 40, __periodIndex: 1, __periodDayIndex: 0 },\n * ]\n *\n * Output (with dimensions):\n * [\n * {\n * __periodDayIndex: 0,\n * 'Engineering - value (Current)': 100,\n * 'Engineering - value (Prior)': 80,\n * 'Sales - value (Current)': 50,\n * 'Sales - value (Prior)': 40,\n * },\n * ]\n */\nexport function transformForOverlayMode(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n getFieldLabel?: (fieldName: string) => string\n): { data: any[], seriesKeys: string[], xAxisKey: string } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures, xAxisKey: timeDimensionKey }\n }\n\n const periodLabels = getPeriodLabels(data)\n const periodIndices = getPeriodIndices(data)\n\n // Detect dimension fields in the data\n const dimensionFields = detectDimensionFields(data, measures, timeDimensionKey)\n const hasDimensions = dimensionFields.length > 0\n\n // Get unique dimension values for generating series keys\n const uniqueDimensionValues = hasDimensions\n ? getUniqueDimensionValues(data, dimensionFields)\n : null\n\n const transformedData = pivotByDayIndex(data, measures, timeDimensionKey, {\n dimensionFields,\n hasDimensions,\n periodLabels,\n getFieldLabel\n })\n\n const seriesKeys = buildOverlaySeriesKeys(measures, periodLabels, periodIndices, {\n dimensionFields,\n uniqueDimensionValues,\n getFieldLabel\n })\n\n return {\n data: transformedData,\n seriesKeys,\n xAxisKey: '__periodDayIndex'\n }\n}\n\n/**\n * Build the `dimensionValue / dimensionValue` prefix for a comparison row,\n * applying field labels when available. Empty when no dimensions are present.\n */\nfunction buildDimensionPrefix(\n row: any,\n dimensionFields: string[],\n getFieldLabel?: (fieldName: string) => string\n): string {\n if (dimensionFields.length === 0) return ''\n const dimensionValues = dimensionFields.map(field => {\n const value = row[field]\n return getFieldLabel ? getFieldLabel(String(value)) : String(value)\n })\n return dimensionValues.join(' / ')\n}\n\n/**\n * Pivot comparison rows so each output row is one `__periodDayIndex`, with a\n * column per measure/dimension/period combination.\n */\nfunction pivotByDayIndex(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n opts: {\n dimensionFields: string[]\n hasDimensions: boolean\n periodLabels: string[]\n getFieldLabel?: (fieldName: string) => string\n }\n): any[] {\n const { dimensionFields, hasDimensions, periodLabels, getFieldLabel } = opts\n const groupedByDayIndex = new Map<number, Record<string, any>>()\n\n for (const row of data) {\n const dayIndex = row.__periodDayIndex\n const periodIndex = row.__periodIndex\n\n if (!groupedByDayIndex.has(dayIndex)) {\n groupedByDayIndex.set(dayIndex, {\n __periodDayIndex: dayIndex,\n // Store the date from the first period (index 0) for reference\n __displayDate: periodIndex === 0 ? row[timeDimensionKey] : undefined\n })\n }\n\n const groupedRow = groupedByDayIndex.get(dayIndex)!\n\n // If this is the first period and we don't have a display date yet, add it\n if (!groupedRow.__displayDate && row[timeDimensionKey]) {\n groupedRow.__displayDate = row[timeDimensionKey]\n }\n\n // Build dimension prefix if dimensions are present\n const dimensionPrefix = hasDimensions\n ? buildDimensionPrefix(row, dimensionFields, getFieldLabel)\n : ''\n\n // Add measure values with optional dimension prefix and period suffix\n const shortLabel = generatePeriodShortLabel(periodLabels[periodIndex] || '', periodIndex)\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n const key = dimensionPrefix\n ? `${dimensionPrefix} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n groupedRow[key] = row[measure]\n }\n }\n\n // Convert to array and sort by day index\n return Array.from(groupedByDayIndex.values())\n .sort((a, b) => a.__periodDayIndex - b.__periodDayIndex)\n}\n\n/**\n * Generate the overlay-mode series keys (matching the data column names) for\n * each measure/dimension-combination/period.\n */\nfunction buildOverlaySeriesKeys(\n measures: string[],\n periodLabels: string[],\n periodIndices: number[],\n opts: {\n dimensionFields: string[]\n uniqueDimensionValues: Map<string, Set<any>> | null\n getFieldLabel?: (fieldName: string) => string\n }\n): string[] {\n const { dimensionFields, uniqueDimensionValues, getFieldLabel } = opts\n const seriesKeys: string[] = []\n\n // When dimensions are present, prefix each series key with the combination;\n // otherwise use a single empty prefix to share the measure/period loop.\n const dimensionCombinations = uniqueDimensionValues\n ? generateDimensionCombinations(dimensionFields, uniqueDimensionValues, getFieldLabel)\n : ['']\n\n for (const dimCombo of dimensionCombinations) {\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(\n dimCombo\n ? `${dimCombo} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n )\n }\n }\n }\n\n return seriesKeys\n}\n\n/**\n * Generate all combinations of dimension values as formatted strings\n */\nfunction generateDimensionCombinations(\n dimensionFields: string[],\n uniqueValues: Map<string, Set<any>>,\n getFieldLabel?: (fieldName: string) => string\n): string[] {\n if (dimensionFields.length === 0) return []\n\n // For single dimension, just return the values\n if (dimensionFields.length === 1) {\n const field = dimensionFields[0]\n const values = Array.from(uniqueValues.get(field) || [])\n return values.map(v => getFieldLabel ? getFieldLabel(String(v)) : String(v))\n }\n\n // For multiple dimensions, generate cartesian product\n const result: string[] = []\n const fieldValues = dimensionFields.map(field =>\n Array.from(uniqueValues.get(field) || [])\n )\n\n function generateCombos(index: number, current: string[]): void {\n if (index === fieldValues.length) {\n const formatted = current.map(v =>\n getFieldLabel ? getFieldLabel(String(v)) : String(v)\n )\n result.push(formatted.join(' / '))\n return\n }\n\n for (const value of fieldValues[index]) {\n generateCombos(index + 1, [...current, value])\n }\n }\n\n generateCombos(0, [])\n return result\n}\n\n/**\n * Format the period day index for display on X-axis\n * Can show as \"Day 1\", \"Day 2\", etc., or as the original date\n */\nexport function formatPeriodDayIndex(\n dayIndex: number,\n displayDate?: string | Date,\n options?: {\n showDayNumber?: boolean\n dateFormat?: 'short' | 'long'\n }\n): string {\n if (options?.showDayNumber) {\n return `Day ${dayIndex + 1}`\n }\n\n if (displayDate) {\n const date = typeof displayDate === 'string' ? new Date(displayDate) : displayDate\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', {\n month: options?.dateFormat === 'long' ? 'long' : 'short',\n day: 'numeric'\n })\n }\n }\n\n return `${dayIndex + 1}`\n}\n\n/**\n * Check if a series key represents a prior period (not the first period)\n * Used for applying different styling to prior period lines\n */\nexport function isPriorPeriodSeries(seriesKey: string, periodLabels: string[]): boolean {\n if (periodLabels.length < 2) return false\n\n // Check if the series key contains any label other than the first period's\n for (let i = 1; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n if (seriesKey.includes(`(${shortLabel})`)) {\n return true\n }\n }\n\n // Also check for \"(Prior\" pattern\n return seriesKey.includes('(Prior')\n}\n\n/**\n * Get the stroke dash array for prior period styling\n */\nexport function getPriorPeriodStrokeDashArray(\n style: 'solid' | 'dashed' | 'dotted' = 'dashed'\n): string | undefined {\n switch (style) {\n case 'solid':\n return undefined\n case 'dashed':\n return '5 5'\n case 'dotted':\n return '2 2'\n default:\n return '5 5'\n }\n}\n","import { ReactElement, useState, useRef, useLayoutEffect, startTransition } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport LoadingIndicator from '../LoadingIndicator.js'\n\ninterface ChartContainerProps {\n children: ReactElement\n height?: string | number\n /**\n * Override the default minimum height. Charts that share their portlet with\n * another element - a wrapped summary header, say - need the plot to shrink\n * rather than push past the card.\n */\n minHeight?: string | number\n}\n\nexport default function ChartContainer({\n children,\n height = \"100%\",\n minHeight\n}: ChartContainerProps) {\n // The default floor keeps a lone chart from collapsing, but it also stops the\n // plot shrinking when something else shares the portlet (e.g. a summary\n // header that has wrapped). Callers in that position pass a smaller floor.\n const effectiveMinHeight = minHeight ?? undefined\n const { t } = useTranslation()\n // Track if container is ready to render ResponsiveContainer\n // We need to wait for the container to be in the DOM with valid dimensions\n const containerRef = useRef<HTMLDivElement>(null)\n const [isReady, setIsReady] = useState(false)\n const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })\n const sizeRef = useRef({ width: 0, height: 0 })\n const readyRef = useRef(false)\n const pendingSizeRef = useRef<{ width: number; height: number } | null>(null)\n const frameRef = useRef<number | null>(null)\n\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\n\n const flushPendingSize = () => {\n frameRef.current = null\n if (!mounted) return\n const pending = pendingSizeRef.current\n pendingSizeRef.current = null\n if (!pending) return\n\n const nextWidth = Math.round(pending.width)\n const nextHeight = Math.round(pending.height)\n if (nextWidth <= 0 || nextHeight <= 0) return\n\n const sizeChanged =\n sizeRef.current.width !== nextWidth || sizeRef.current.height !== nextHeight\n const shouldBecomeReady = !readyRef.current\n\n if (!sizeChanged && !shouldBecomeReady) return\n\n sizeRef.current = { width: nextWidth, height: nextHeight }\n readyRef.current = true\n\n // Resize-driven chart updates can come in bursts (one per portlet).\n // Transitioning these avoids blocking urgent input and coalesces visual work.\n startTransition(() => {\n if (sizeChanged) {\n setContainerSize({ width: nextWidth, height: nextHeight })\n }\n if (shouldBecomeReady) {\n setIsReady(true)\n }\n })\n }\n\n const scheduleSizeUpdate = (width: number, height: number) => {\n pendingSizeRef.current = { width, height }\n if (frameRef.current === null) {\n frameRef.current = requestAnimationFrame(flushPendingSize)\n }\n }\n\n const measureAndSetReady = () => {\n if (!mounted || !containerRef.current) return\n\n const rect = containerRef.current.getBoundingClientRect()\n // Check both clientWidth/Height AND getBoundingClientRect for robustness\n const width = Math.max(containerRef.current.clientWidth, rect.width)\n const measuredHeight = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && measuredHeight > 0) {\n scheduleSizeUpdate(width, measuredHeight)\n }\n }\n\n // Set up ResizeObserver to detect when container gets valid dimensions\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: entryHeight } = entry.contentRect\n if (width > 0 && entryHeight > 0) {\n scheduleSizeUpdate(width, entryHeight)\n }\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n // Also try immediate measurement\n measureAndSetReady()\n }\n\n return () => {\n mounted = false\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n resizeObserver?.disconnect()\n }\n }, [])\n\n try {\n if (height === \"100%\") {\n // For 100% height, make the container fill the available flex space with proper sizing\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative\"\n style={{ minHeight: effectiveMinHeight ?? '250px', minWidth: '100px', overflow: 'hidden', userSelect: 'none' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n }\n\n // For specific heights, use them directly\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n const containerStyle = {\n height: typeof height === 'number' ? `${height}px` : height,\n width: '100%',\n minHeight: effectiveMinHeight ?? '200px',\n minWidth: '100px',\n userSelect: 'none' as const\n }\n\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:flex dc:flex-col dc:relative\"\n style={{ ...containerStyle, overflow: 'hidden' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n } catch (error) {\n // ChartContainer ResponsiveContainer error\n\n return (\n <div\n className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-4 dc:text-center dc:border dc:border-dashed dc:rounded-lg\"\n style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}\n >\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted\">{t('chart.runtime.unableToDisplay')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {error instanceof Error ? error.message : 'Failed to create responsive container'}\n </div>\n </div>\n )\n }\n}\n","import React from 'react'\nimport { Tooltip } from 'recharts'\nimport { formatNumericValue } from '../../utils/chartUtils.js'\n\ninterface ChartTooltipProps {\n formatter?: (value: any, name: any, props: any) => [React.ReactText, React.ReactText]\n labelFormatter?: (label: any, payload?: readonly any[]) => React.ReactText\n}\n\n// Default formatter that rounds numeric values to at most 2 decimal places\nconst defaultFormatter = (value: any, name: any): [React.ReactText, React.ReactText] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatNumericValue(value), name]\n}\n\nexport default function ChartTooltip({ formatter, labelFormatter }: ChartTooltipProps) {\n return (\n <Tooltip\n formatter={formatter || defaultFormatter}\n labelFormatter={labelFormatter}\n contentStyle={{\n backgroundColor: 'white',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n fontSize: '0.875rem',\n color: '#1f2937',\n boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n padding: '8px 12px'\n }}\n />\n )\n}","import React from 'react'\n\ninterface AngledXAxisTickProps {\n x?: number\n y?: number\n payload?: {\n value: string | number\n }\n tickFormatter?: (value: string | number, index: number) => string\n index?: number\n visibleTicksCount?: number\n // Allow any additional props recharts might pass\n [key: string]: unknown\n}\n\n/**\n * Longest label the angled axis reserves room for; see\n * MAX_ANGLED_AXIS_HEIGHT in chartScaffolding.\n */\nexport const MAX_TICK_LABEL_CHARS = 16\n\n/**\n * Custom XAxis tick component for properly aligned angled labels.\n * Fixes alignment issues in recharts 3.7+ where angled labels don't\n * center properly under data points.\n */\nconst AngledXAxisTick: React.FC<AngledXAxisTickProps> = ({\n x = 0,\n y = 0,\n payload,\n tickFormatter,\n index = 0\n}) => {\n if (!payload) return null\n\n const rawValue = tickFormatter\n ? tickFormatter(payload.value, index)\n : String(payload.value)\n\n // The axis reserves height for the longest label (resolveAngledAxisHeight),\n // capped so one very long value cannot squeeze the plot. Truncate past that\n // cap rather than let the label be clipped by the chart edge.\n const displayValue =\n rawValue.length > MAX_TICK_LABEL_CHARS\n ? `${rawValue.slice(0, MAX_TICK_LABEL_CHARS - 1)}\\u2026`\n : rawValue\n\n return (\n <g transform={`translate(${x},${y})`}>\n <text\n x={0}\n y={0}\n dy={16}\n textAnchor=\"end\"\n fill=\"var(--dc-text-muted)\"\n fontSize={12}\n transform=\"rotate(-45)\"\n >\n {displayValue}\n </text>\n </g>\n )\n}\n\nexport default AngledXAxisTick\n","import React from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\n\n/**\n * Shared guard/state components for chart rendering.\n *\n * Cartesian charts (bar, line, area, pie, …) all duplicated the same\n * centred flex blocks for their empty / config-error / render-error states,\n * differing only in the hint text. These components own the duplicated wrapper\n * JSX; each chart supplies its own already-resolved `hint` (a translation key\n * resolved via `t()`, or a literal string) so per-chart messaging is preserved.\n */\n\ninterface ChartStateProps {\n height?: string | number\n /** Already-resolved hint text (caller resolves its own i18n key) */\n hint?: React.ReactNode\n}\n\n/**\n * Empty / no-data state (muted styling). `titleKey` defaults to the generic\n * \"No data available\" heading but can be overridden (e.g. for the post-transform\n * \"No valid data\" state).\n */\nexport function ChartEmptyState({\n height,\n hint,\n titleKey = 'chart.runtime.noData'\n}: ChartStateProps & { titleKey?: string }) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t(titleKey)}</div>\n {hint != null && <div className=\"dc:text-xs text-dc-text-secondary\">{hint}</div>}\n </div>\n </div>\n )\n}\n\n/**\n * Invalid-configuration state (warning styling). Title is always\n * \"Configuration Error\"; the chart supplies a hint describing what is missing.\n */\nexport function ChartConfigError({ height, hint }: ChartStateProps) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n {hint != null && <div className=\"dc:text-xs\">{hint}</div>}\n </div>\n </div>\n )\n}\n\n/**\n * Render-error state (error styling), used in chart `catch` blocks.\n */\nexport function ChartRenderError({\n height,\n chartType,\n error\n}: {\n height?: string | number\n /** Display name used in the \"{chartType} Error\" heading */\n chartType: string\n error: unknown\n}) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n}\n","import type { ChartAxisConfig } from '../../types.js'\n\n/**\n * Discriminated error code returned by {@link resolveChartAxisFields} when the\n * chart configuration is invalid. Each chart maps these codes to its own i18n\n * hint key (e.g. pie charts surface a pie-specific message for `axisInvalid`).\n */\nexport type ChartAxisErrorCode = 'axisInvalid' | 'axisFields'\n\n/**\n * Result of resolving X/Y/series fields from a {@link ChartAxisConfig}.\n * When `errorCode` is non-null the field values are not usable and the chart\n * should render a configuration-error state instead.\n */\nexport interface ResolvedChartAxisFields {\n /** Resolved X-axis field (category), or undefined when the config is invalid */\n xAxisField?: string\n /** Resolved Y-axis (value/measure) fields */\n yAxisFields: string[]\n /** Optional series/grouping fields (only present in the new config format) */\n seriesFields: string[]\n /** Non-null when the configuration cannot produce a renderable axis setup */\n errorCode: ChartAxisErrorCode | null\n}\n\n/**\n * Pure resolver for the X/Y/series field extraction that Cartesian charts\n * (bar, line, area, pie) all duplicated inline.\n *\n * Supports both the new format (`xAxis` / `yAxis` / `series` arrays) and the\n * legacy format (`x` / `y`). Returns a discriminated `errorCode` rather than\n * JSX so each chart can map it to its own i18n hint key and render its own\n * guard component.\n */\nexport function resolveChartAxisFields(chartConfig?: ChartAxisConfig): ResolvedChartAxisFields {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let errorCode: ChartAxisErrorCode | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n errorCode = 'axisInvalid'\n }\n\n if (!errorCode && (!xAxisField || yAxisFields.length === 0)) {\n errorCode = 'axisFields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, errorCode }\n}\n","/**\n * Utility functions for handling target values in charts\n */\n\n/**\n * Parse target values from string format\n * @param targetString - String containing target values (e.g., \"100\" or \"50,75,100\")\n * @returns Array of numeric target values\n */\nexport function parseTargetValues(targetString: string): number[] {\n if (!targetString || typeof targetString !== 'string') {\n return []\n }\n\n const trimmed = targetString.trim()\n if (!trimmed) {\n return []\n }\n\n try {\n // Split by comma and parse each value\n const values = trimmed\n .split(',')\n .map(val => val.trim())\n .filter(val => val !== '')\n .map(val => {\n const num = parseFloat(val)\n if (isNaN(num)) {\n throw new Error(`Invalid numeric value: ${val}`)\n }\n return num\n })\n\n return values.length > 0 ? values : []\n } catch (error) {\n console.warn('Failed to parse target values:', error)\n return []\n }\n}\n\n/**\n * Spread target values across data points\n * @param targets - Array of target values\n * @param dataLength - Number of data points to spread across\n * @returns Array of target values for each data point\n */\nexport function spreadTargetValues(targets: number[], dataLength: number): number[] {\n if (targets.length === 0 || dataLength <= 0) {\n return []\n }\n\n // If only one target value, repeat for all data points\n if (targets.length === 1) {\n return new Array(dataLength).fill(targets[0])\n }\n\n // If we have multiple targets, spread them evenly across data points\n const result: number[] = []\n const baseGroupSize = Math.floor(dataLength / targets.length)\n const remainder = dataLength % targets.length\n\n let currentIndex = 0\n \n for (let i = 0; i < targets.length; i++) {\n // Calculate group size for this target\n // First 'remainder' groups get an extra item\n const groupSize = baseGroupSize + (i < remainder ? 1 : 0)\n \n // Fill this group with the current target value\n for (let j = 0; j < groupSize; j++) {\n result[currentIndex++] = targets[i]\n }\n }\n\n return result\n}\n\n/**\n * Calculate variance between actual and target values\n * @param actual - Actual value\n * @param target - Target value\n * @returns Variance as percentage\n */\nexport function calculateVariance(actual: number, target: number): number {\n if (target === 0) {\n return actual === 0 ? 0 : (actual > 0 ? 100 : -100)\n }\n return ((actual - target) / target) * 100\n}\n\n/**\n * Format variance as percentage string with appropriate sign and color indication\n * @param variance - Variance percentage\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted variance string (e.g., \"+12.5%\" or \"-8.3%\")\n */\nexport function formatVariance(variance: number, decimals: number = 1): string {\n const sign = variance >= 0 ? '+' : ''\n return `${sign}${variance.toFixed(decimals)}%`\n}\n\n/**\n * Get unique target values for reference lines\n * @param targets - Array of target values (may contain duplicates)\n * @returns Array of unique target values\n */\nexport function getUniqueTargets(targets: number[]): number[] {\n return [...new Set(targets)].sort((a, b) => a - b)\n}","import { Fragment } from 'react'\nimport { YAxis, Line, Legend } from 'recharts'\nimport { CHART_MARGINS } from '../../utils/chartConstants.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils.js'\nimport type { AxisFormatConfig } from '../../types.js'\n\n/**\n * Shared scaffolding for the Cartesian recharts charts (bar, line, area).\n *\n * These charts duplicated the same dual-Y-axis derivation, chart margins,\n * target-line overlay, and the left/right `<YAxis>` JSX. The pure helpers and\n * recharts render-helpers here own that shared setup. Render-helpers return\n * recharts elements (inside a fragment) and are embedded directly in the chart\n * children — recharts flattens fragments when discovering axes/series, exactly\n * as it already does for the inline target-line fragment.\n */\n\nexport interface DualAxisInfo {\n /** True when at least one measure is assigned to the right axis */\n hasRightAxis: boolean\n /** Measure fields rendered against the left axis */\n leftAxisFields: string[]\n /** Measure fields rendered against the right axis */\n rightAxisFields: string[]\n}\n\n/** Derive left/right axis membership from per-measure axis assignments. */\nexport function getDualAxisInfo(\n yAxisFields: string[],\n yAxisAssignment: Record<string, 'left' | 'right'>\n): DualAxisInfo {\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n return { hasRightAxis, leftAxisFields, rightAxisFields }\n}\n\n/** Chart margins with extra room for the Y-axis label(s). */\nexport function getYAxisChartMargins(hasRightAxis: boolean) {\n return {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n}\n\n/**\n * Vertical space an angled X-axis label needs.\n *\n * `AngledXAxisTick` rotates its text -45deg from an anchor offset dy=16, so the\n * space required below the axis is the label's own width projected onto the\n * vertical, plus that offset. A fixed height clipped longer labels: \"2026-08-24\"\n * is roughly 66px wide at 12px, which projects to ~47px and needs ~63px in\n * total against the 60px that used to be hardcoded.\n *\n * Capped, because a pathological label should cost the plot a bounded amount of\n * height rather than squeeze it away - past the cap the label is truncated\n * instead (see AngledXAxisTick).\n */\nexport const MIN_ANGLED_AXIS_HEIGHT = 60\nexport const MAX_ANGLED_AXIS_HEIGHT = 96\n/** Rough advance width of the tick font (12px sans) per character. */\nconst TICK_CHAR_WIDTH = 6.6\n\nexport function resolveAngledAxisHeight(values: Array<string | number | undefined>): number {\n let longest = 0\n for (const value of values) {\n if (value === null || value === undefined) continue\n const len = String(value).length\n if (len > longest) longest = len\n }\n if (longest === 0) return MIN_ANGLED_AXIS_HEIGHT\n\n const projected = longest * TICK_CHAR_WIDTH * Math.SQRT1_2\n const needed = Math.ceil(projected) + 20 // the tick's dy offset plus a little air\n return Math.max(MIN_ANGLED_AXIS_HEIGHT, Math.min(needed, MAX_ANGLED_AXIS_HEIGHT))\n}\n\n/**\n * Width reserved for the left `<YAxis>`. This is recharts' own default, stated\n * explicitly so anything needing to line up with the plot area can rely on it\n * rather than assume it.\n */\nexport const Y_AXIS_WIDTH = 60\n\n/**\n * Distance from the chart container's left edge to the left edge of the plot\n * area — the chart margin plus the Y-axis gutter. Used to indent content\n * rendered outside the chart (the summary header) so it lines up with the first\n * data point instead of floating against the card edge.\n */\nexport function getPlotLeftOffset(hasRightAxis: boolean): number {\n return getYAxisChartMargins(hasRightAxis).left + Y_AXIS_WIDTH\n}\n\n/**\n * Apply target values (single or comma-separated spread) onto chart data,\n * returning the spread targets plus data enhanced with a `__target` key.\n */\nexport function withTargetData<T extends Record<string, any>>(\n chartData: T[],\n target: string | undefined\n): { spreadTargets: number[]; enhancedChartData: T[] } {\n const targetValues = parseTargetValues(target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n const enhancedChartData = spreadTargets.length > 0\n ? chartData.map((dataPoint, index) => ({ ...dataPoint, __target: spreadTargets[index] || null }))\n : chartData\n return { spreadTargets, enhancedChartData }\n}\n\n/**\n * Render the left + optional right `<YAxis>`. Returns recharts elements in a\n * fragment for embedding directly in the chart children. Positional args keep\n * the (otherwise identical) call sites in each chart down to a single line.\n *\n * @param isPercentStack when true (area/bar percent stacking) the left axis shows 0–100%\n */\nexport function renderDualYAxes(\n { hasRightAxis, leftAxisFields, rightAxisFields }: DualAxisInfo,\n getFieldLabel: (field: string) => string,\n leftYAxisFormat?: AxisFormatConfig,\n rightYAxisFormat?: AxisFormatConfig,\n isPercentStack = false\n) {\n return (\n <Fragment>\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n width={Y_AXIS_WIDTH}\n tick={{ fontSize: 12 }}\n tickFormatter={\n isPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={isPercentStack ? [0, 1] : undefined}\n label={\n isPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-muted)' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-muted)' }\n }\n : undefined\n }\n />\n )}\n </Fragment>\n )\n}\n\n/**\n * Render the target overlay: a white backing line plus a purple dashed line\n * on top (shared by bar, line, area). Returns null when there are no targets.\n */\nexport function renderChartTargetLines(spreadTargets: number[]) {\n if (spreadTargets.length === 0) return null\n return (\n <Fragment>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </Fragment>\n )\n}\n\ninterface CartesianTooltipOptions {\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n yAxisAssignment: Record<string, 'left' | 'right'>\n /** Maps a series key (display label) back to its original measure field. */\n resolveField: (name: string) => string | undefined\n /** When true, values render as percentages (area/bar percent stacking). */\n isPercentStack?: boolean\n}\n\n/**\n * Build the value/name tooltip formatter shared by the Cartesian charts.\n * Handles null values, the target series, percent stacking, and per-series\n * left/right axis format selection.\n */\nexport function makeCartesianTooltipFormatter({\n leftYAxisFormat,\n rightYAxisFormat,\n yAxisAssignment,\n resolveField,\n isPercentStack = false\n}: CartesianTooltipOptions) {\n return (value: any, name: any): [any, any] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n if (isPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = resolveField(name)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }\n}\n\n/**\n * Render the hover-aware bottom legend shared by the Cartesian charts.\n * Returns null when the legend is hidden. `iconType` / `paddingTop` differ\n * per chart (rect+10 for area, rect+25 for bar, line+25 for line).\n */\nexport function renderHoverLegend({\n show,\n iconType,\n paddingTop,\n onHover,\n onLeave\n}: {\n show: boolean\n iconType: 'rect' | 'line' | 'circle'\n paddingTop: number\n onHover: (dataKey: string) => void\n onLeave: () => void\n}) {\n if (!show) return null\n return (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: `${paddingTop}px` }}\n iconType={iconType}\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => onHover(String(o.dataKey || ''))}\n onMouseLeave={onLeave}\n />\n )\n}\n","import React from 'react'\nimport { Line, Area } from 'recharts'\nimport { formatTimeValue, getFieldGranularity, transformChartDataWithSeries } from '../../utils/chartUtils.js'\nimport { CHART_COLORS } from '../../utils/chartConstants.js'\nimport {\n isComparisonData,\n getPeriodLabels,\n transformForOverlayMode,\n isPriorPeriodSeries,\n getPriorPeriodStrokeDashArray\n} from '../../utils/comparisonUtils.js'\nimport type { ColorPalette } from '../../types.js'\n\n/**\n * Co-located helpers shared by the Cartesian time-series charts (Line, Area).\n *\n * These extract the heavier inline logic that previously lived inside the chart\n * components — the clickable/drill dot renderer, the comparison-mode tick and\n * label formatters, and the series-key → measure-field resolution — so the\n * component bodies stay focused on chart composition. Pure extraction: no\n * behaviour change.\n */\n\nexport interface DataPointClickPayload {\n dataPoint: any\n clickedField: string\n xValue: any\n position: { x: number; y: number }\n nativeEvent: React.MouseEvent\n}\n\ninterface DrillDotOptions {\n /** Recharts dot props (cx, cy, payload, key). */\n props: any\n color: string\n drillEnabled?: boolean\n originalField?: string\n seriesKey: string\n onDataPointClick?: (payload: DataPointClickPayload) => void\n}\n\n/**\n * Render a single data-point dot. When drill is enabled and a click handler is\n * present, renders a larger clickable dot with a surface-coloured backing\n * circle to mask grid lines; otherwise a small plain dot. Returns null when the\n * point has no coordinates.\n *\n * `renderPlain` controls whether a small non-interactive dot is drawn when\n * drill is disabled (Line draws one; Area returns nothing).\n */\nexport function renderDrillDot({\n props,\n color,\n drillEnabled,\n originalField,\n seriesKey,\n onDataPointClick,\n renderPlain\n}: DrillDotOptions & { renderPlain: boolean }): React.ReactElement | null {\n const { cx, cy, payload, key } = props\n if (cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n if (drillEnabled && onDataPointClick) {\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle cx={cx} cy={cy} r={6} fill=\"var(--dc-surface)\" style={{ pointerEvents: 'none' }} />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={color}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }\n\n if (!renderPlain) return null\n\n return <circle key={key} cx={cx} cy={cy} r={3} fill={color} />\n}\n\n/**\n * Format a comparison-data X-axis value: shows the current period's date,\n * formatted to the query granularity, falling back to \"Period N\".\n */\nfunction formatComparisonDate(\n displayDate: unknown,\n queryObject: any,\n xAxisField: string,\n fallbackIndex: number\n): string {\n if (displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(displayDate as any, granularity)\n }\n return `Period ${fallbackIndex + 1}`\n}\n\n/**\n * Build the comparison-mode X-axis tick formatter for time-series charts.\n * Returns undefined when not in comparison mode (no custom formatting).\n */\nexport function makeComparisonTickFormatter(\n hasComparisonData: boolean,\n chartData: any[],\n queryObject: any,\n xAxisField: string\n): ((value: string | number, index: number) => string) | undefined {\n if (!hasComparisonData) return undefined\n return (value: string | number, index: number) => {\n const row = chartData[index]\n return formatComparisonDate(row?.__displayDate, queryObject, xAxisField, Number(value))\n }\n}\n\n/**\n * Build the comparison-mode tooltip label formatter for time-series charts.\n * Returns undefined when not in comparison mode (no custom formatting).\n */\nexport function makeComparisonLabelFormatter(\n hasComparisonData: boolean,\n queryObject: any,\n xAxisField: string\n): ((label: any, payload: any) => string) | undefined {\n if (!hasComparisonData) return undefined\n return (label: any, payload: any) => {\n const row = payload && payload.length > 0 ? payload[0]?.payload : undefined\n return formatComparisonDate(row?.__displayDate, queryObject, xAxisField, Number(label))\n }\n}\n\n/**\n * Resolve effective stacking for the Area chart from `stackType` (new) /\n * `stacked` (legacy), disabling stacking when a right axis is present (areas on\n * different axes can't be stacked).\n */\nexport function resolveAreaStacking(\n displayConfig: { stackType?: string; stacked?: boolean } | undefined,\n hasRightAxis: boolean\n): { effectiveShouldStack: boolean; effectiveIsPercentStack: boolean; stackOffset: 'expand' | undefined } {\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const effectiveShouldStack = stackType !== 'none' && !hasRightAxis\n const effectiveIsPercentStack = stackType === 'percent' && !hasRightAxis\n return {\n effectiveShouldStack,\n effectiveIsPercentStack,\n stackOffset: effectiveIsPercentStack ? 'expand' : undefined\n }\n}\n\n/** Build a map from series display label to original measure field name. */\nexport function buildSeriesKeyToFieldMap(\n yAxisFields: string[],\n getFieldLabel: (field: string) => string\n): Record<string, string> {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n mapping[getFieldLabel(field)] = field\n })\n return mapping\n}\n\n/**\n * Resolve a series key back to its original measure field, handling comparison\n * suffixes like \"(Current)\" / \"(Prior)\" and dimension prefixes (\"Dim - Label\").\n */\nexport function makeSeriesKeyResolver(\n seriesKeyToField: Record<string, string>\n): (seriesKey: string) => string | undefined {\n return (seriesKey: string): string | undefined => {\n if (seriesKeyToField[seriesKey]) return seriesKeyToField[seriesKey]\n // Guard against excessive input length to prevent ReDoS\n if (seriesKey.length > 1000) return undefined\n const withoutSuffix = seriesKey.replace(/\\s*\\((Current|Prior)\\)$/, '')\n const parts = withoutSuffix.split(' - ')\n const measureLabel = parts[parts.length - 1]\n return seriesKeyToField[measureLabel]\n }\n}\n\n/** Pick a series colour by index, preferring the palette then the defaults. */\nexport function getSeriesColor(colorPalette: ColorPalette | undefined, index: number): string {\n const colors = colorPalette?.colors\n return (colors && colors[index % colors.length]) || CHART_COLORS[index % CHART_COLORS.length]\n}\n\ninterface LineSeriesOptions {\n seriesKeys: string[]\n colorPalette?: ColorPalette\n resolveField: (seriesKey: string) => string | undefined\n yAxisAssignment: Record<string, 'left' | 'right'>\n hoveredLegend: string | null\n connectNulls: boolean\n /** Render a marker at every data point. Off is clearer on dense series. */\n showPoints?: boolean\n drillEnabled?: boolean\n onDataPointClick?: (payload: DataPointClickPayload) => void\n /** Comparison styling (omit/false → standard series). */\n hasComparisonData?: boolean\n periodLabels?: string[]\n priorPeriodStyle?: 'solid' | 'dashed' | 'dotted'\n priorPeriodOpacity?: number\n}\n\n/** Render the `<Line>` element for one resolved series (Line chart). */\nfunction renderOneLineSeries(seriesKey: string, index: number, opts: LineSeriesOptions): React.ReactElement {\n const {\n colorPalette, resolveField, yAxisAssignment, hoveredLegend, connectNulls,\n drillEnabled, onDataPointClick, hasComparisonData, periodLabels = [],\n priorPeriodStyle = 'dashed', priorPeriodOpacity = 0.5, showPoints = true\n } = opts\n\n const originalField = resolveField(seriesKey)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n\n const isPriorPeriod = Boolean(hasComparisonData) && isPriorPeriodSeries(seriesKey, periodLabels)\n const strokeDashArray = isPriorPeriod ? getPriorPeriodStrokeDashArray(priorPeriodStyle) : undefined\n const opacity = isPriorPeriod ? priorPeriodOpacity : 1\n const lineColor = getSeriesColor(colorPalette, index)\n\n let strokeOpacity = opacity\n if (hoveredLegend) strokeOpacity = hoveredLegend === seriesKey ? 1 : 0.3\n\n return (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stroke={lineColor}\n strokeWidth={isPriorPeriod ? 1.5 : 2}\n strokeDasharray={strokeDashArray}\n dot={isPriorPeriod || !showPoints ? false : (props: any) => renderDrillDot({\n props, color: lineColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n // With points hidden, surface one on hover instead — otherwise hiding\n // them would also remove the click target that drill-down relies on.\n activeDot={showPoints ? false : (props: any) => renderDrillDot({\n props, color: lineColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n strokeOpacity={strokeOpacity}\n connectNulls={connectNulls}\n />\n )\n}\n\n/** Render all line series for the Line chart. */\nexport function renderLineSeries(opts: LineSeriesOptions): React.ReactElement[] {\n return opts.seriesKeys.map((seriesKey, index) => renderOneLineSeries(seriesKey, index, opts))\n}\n\ninterface AreaSeriesOptions {\n seriesKeys: string[]\n colorPalette?: ColorPalette\n seriesKeyToField: Record<string, string>\n yAxisAssignment: Record<string, 'left' | 'right'>\n hoveredLegend: string | null\n connectNulls: boolean\n shouldStack: boolean\n /** Render a marker at every data point. Off is clearer on dense series. */\n showPoints?: boolean\n drillEnabled?: boolean\n onDataPointClick?: (payload: DataPointClickPayload) => void\n /**\n * Unique-per-chart-instance prefix for the `<defs>` gradient ids. When\n * omitted (or when stacking) the series fall back to a flat fill.\n */\n gradientIdPrefix?: string\n}\n\n/** Render the `<Area>` element for one series (Area chart). */\nfunction renderOneAreaSeries(seriesKey: string, index: number, opts: AreaSeriesOptions): React.ReactElement {\n const {\n colorPalette, seriesKeyToField, yAxisAssignment, hoveredLegend, connectNulls,\n shouldStack, drillEnabled, onDataPointClick, gradientIdPrefix, showPoints = true\n } = opts\n\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const areaColor = getSeriesColor(colorPalette, index)\n\n // Stacked areas read better solid — bands are bounded by their neighbours, so\n // a fade just muddies the boundaries.\n const fill = gradientIdPrefix && !shouldStack\n ? `url(#${gradientIdPrefix}-${index})`\n : areaColor\n\n let fillOpacity = 0.3\n let strokeOpacity = 1\n if (hoveredLegend) {\n const active = hoveredLegend === seriesKey\n fillOpacity = active ? 0.6 : 0.1\n strokeOpacity = active ? 1 : 0.3\n }\n\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={shouldStack ? 'stack' : undefined}\n stroke={areaColor}\n fill={fill}\n fillOpacity={fillOpacity}\n strokeWidth={2}\n strokeOpacity={strokeOpacity}\n connectNulls={connectNulls}\n // renderPlain follows the option: without it an area chart only ever drew\n // *drill* dots, so \"show data points\" did nothing wherever drill is off\n // (the analysis-builder preview, for one).\n dot={showPoints ? (props: any) => renderDrillDot({\n props, color: areaColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n }) : false}\n // See the line series: keep a hover target when points are hidden.\n activeDot={showPoints ? false : (props: any) => renderDrillDot({\n props, color: areaColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n />\n )\n}\n\n/**\n * Vertical fade gradients for the Area chart — one `<linearGradient>` per series.\n *\n * Recharts has no gradient primitive; the fade is plain SVG in `<defs>` that each\n * `<Area>` references by id. Both stops use the *same* hue (fading to white would\n * break the dark and neon themes) and the `<Area>`'s own `fillOpacity` stays the\n * master control, so the existing hover dim/highlight still works unchanged.\n */\nexport function renderAreaGradientDefs(\n seriesKeys: string[],\n colorPalette: ColorPalette | undefined,\n idPrefix: string\n): React.ReactElement {\n return (\n <defs>\n {seriesKeys.map((seriesKey, index) => {\n const color = getSeriesColor(colorPalette, index)\n return (\n <linearGradient\n key={seriesKey}\n id={`${idPrefix}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={color} stopOpacity={1} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0} />\n </linearGradient>\n )\n })}\n </defs>\n )\n}\n\n/** Render all area series for the Area chart. */\nexport function renderAreaSeries(opts: AreaSeriesOptions): React.ReactElement[] {\n return opts.seriesKeys.map((seriesKey, index) => renderOneAreaSeries(seriesKey, index, opts))\n}\n\n/**\n * Is the x-axis an ordered time series?\n *\n * The summary header's \"change since the start of the window\" only means\n * something when the x-axis is ordered. For a categorical axis (region,\n * product, status) the first and last categories are arbitrary, so the delta\n * would be noise.\n */\nexport function isTimeOrderedXAxis(queryObject: any, xAxisField: string | undefined): boolean {\n if (!xAxisField) return false\n const timeDimensions = queryObject?.timeDimensions\n if (!Array.isArray(timeDimensions)) return false\n return timeDimensions.some((td: any) => td?.dimension === xAxisField)\n}\n\n/**\n * Resolve which Y axis a series key is plotted against — the same rule the\n * `<Area>`/`<Line>` elements use, so summaries and series never disagree.\n */\nexport function makeAxisResolver(\n resolveField: (seriesKey: string) => string | undefined,\n yAxisAssignment: Record<string, 'left' | 'right'>\n): (seriesKey: string) => 'left' | 'right' {\n return (seriesKey: string) => {\n const field = resolveField(seriesKey)\n return field && yAxisAssignment[field] === 'right' ? 'right' : 'left'\n }\n}\n\nexport interface SeriesSummary {\n seriesKey: string\n color: string\n /**\n * Which Y axis this series is plotted against, so the summary can be\n * formatted with that axis' format rather than always the left one.\n */\n axis: 'left' | 'right'\n /** Latest non-null value in the window. */\n current: number | null\n /** First non-null value in the window — the baseline the delta is measured from. */\n baseline: number | null\n absoluteChange: number | null\n percentageChange: number | null\n /**\n * X-axis label of the point the delta is measured from, so the header can say\n * \"since Sep 2025\" rather than a generic \"since start of period\". Undefined\n * when the axis key is unknown or the baseline row carries no label.\n */\n baselineLabel?: string\n}\n\n/**\n * Per-series first/last/delta over the plotted window, for the summary header.\n *\n * Pure and DOM-free so it can be unit-tested directly. Nulls are skipped rather\n * than treated as zero — a gap in a series should not read as a crash to zero.\n * When a series has fewer than two non-null points there is nothing to compare,\n * so the deltas stay null and the header renders the value alone.\n */\nexport function computeSeriesSummaries(\n chartData: any[],\n seriesKeys: string[],\n colorPalette?: ColorPalette,\n resolveAxis?: (seriesKey: string) => 'left' | 'right',\n xAxisKey?: string\n): SeriesSummary[] {\n return seriesKeys.map((seriesKey, index) => {\n const axis = resolveAxis ? resolveAxis(seriesKey) : 'left'\n const numbers: number[] = []\n let baselineRow: any = undefined\n for (const row of chartData || []) {\n const raw = row?.[seriesKey]\n if (raw === null || raw === undefined) continue\n const num = typeof raw === 'number' ? raw : parseFloat(String(raw))\n if (!isNaN(num) && isFinite(num)) {\n if (numbers.length === 0) baselineRow = row\n numbers.push(num)\n }\n }\n\n const rawLabel = xAxisKey ? baselineRow?.[xAxisKey] : undefined\n const baselineLabel =\n rawLabel === null || rawLabel === undefined || rawLabel === '' ? undefined : String(rawLabel)\n\n const color = getSeriesColor(colorPalette, index)\n if (numbers.length === 0) {\n return { seriesKey, color, axis, current: null, baseline: null, absoluteChange: null, percentageChange: null }\n }\n\n const current = numbers[numbers.length - 1]\n const baseline = numbers[0]\n if (numbers.length < 2) {\n return { seriesKey, color, axis, current, baseline: null, absoluteChange: null, percentageChange: null }\n }\n\n const absoluteChange = current - baseline\n return {\n seriesKey,\n color,\n axis,\n current,\n baseline,\n absoluteChange,\n percentageChange: baseline !== 0 ? (absoluteChange / Math.abs(baseline)) * 100 : null,\n baselineLabel\n }\n })\n}\n\nexport interface TimeSeriesShape {\n chartData: any[]\n seriesKeys: string[]\n effectiveXAxisKey: string\n hasComparisonData: boolean\n periodLabels: string[]\n}\n\n/**\n * Shape raw rows for a Cartesian time-series chart. In comparison mode this\n * uses the overlay transform (aligned by period day index); otherwise the\n * standard series transform. Centralises the branch so the chart body stays\n * flat.\n */\nexport function buildTimeSeriesData(args: {\n data: any[]\n xAxisField: string\n yAxisFields: string[]\n seriesFields: string[]\n queryObject: any\n getFieldLabel: (field: string) => string\n}): TimeSeriesShape {\n const { data, xAxisField, yAxisFields, seriesFields, queryObject, getFieldLabel } = args\n const hasComparisonData = isComparisonData(data)\n\n if (hasComparisonData) {\n const overlay = transformForOverlayMode(data, yAxisFields, xAxisField, getFieldLabel)\n return {\n chartData: overlay.data,\n seriesKeys: overlay.seriesKeys,\n effectiveXAxisKey: '__periodDayIndex',\n hasComparisonData,\n periodLabels: getPeriodLabels(data)\n }\n }\n\n const standard = transformChartDataWithSeries(data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel)\n return {\n chartData: standard.data,\n seriesKeys: standard.seriesKeys,\n effectiveXAxisKey: 'name',\n hasComparisonData,\n periodLabels: []\n }\n}\n","import React from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport { POSITIVE_COLOR, NEGATIVE_COLOR } from '../../utils/chartConstants.js'\nimport type { SeriesSummary } from './cartesianChartHelpers.js'\nimport type { AxisFormatConfig } from '../../types.js'\n\ninterface ChartSummaryHeaderProps {\n summaries: SeriesSummary[]\n /** Resolves a series key to its display label. */\n getSeriesLabel: (seriesKey: string) => string\n /** Left-axis numeric format, so the header matches the axis it summarises. */\n valueFormat?: AxisFormatConfig\n /** Right-axis format, used for series assigned to the right axis. */\n rightValueFormat?: AxisFormatConfig\n /**\n * Whether a change vs. the start of the window is meaningful. False for a\n * categorical x-axis, where \"first\" and \"last\" are arbitrary categories.\n */\n showChange?: boolean\n /**\n * Distance from the container's left edge to the plot area, so the summary\n * lines up with the first data point rather than the card edge.\n */\n leftOffset?: number\n}\n\n/**\n * Summary band rendered above a time-series plot.\n *\n * Shows each series' latest value and how far it has moved since the start of\n * the window, so the chart is readable without hovering. All values are derived\n * from the already-fetched result set — this issues no queries of its own.\n */\nconst ChartSummaryHeader = React.memo(function ChartSummaryHeader({\n summaries,\n getSeriesLabel,\n valueFormat,\n rightValueFormat,\n showChange = true,\n leftOffset = 0\n}: ChartSummaryHeaderProps) {\n const { t } = useTranslation()\n\n if (summaries.length === 0) return null\n\n return (\n <div\n className=\"dc:flex dc:flex-wrap dc:items-start dc:gap-x-8 dc:gap-y-2 dc:flex-shrink-0 dc:pr-1 dc:pb-2\"\n style={{ paddingLeft: leftOffset }}\n data-testid=\"chart-summary-header\"\n >\n {summaries.map((summary) => {\n const hasChange = showChange && summary.absoluteChange !== null\n // A dual-axis chart formats each axis differently; match the series.\n const format = summary.axis === 'right' ? rightValueFormat : valueFormat\n const isPositive = (summary.absoluteChange ?? 0) >= 0\n return (\n <div key={summary.seriesKey} className=\"dc:flex dc:flex-col dc:gap-0.5 dc:min-w-0\">\n <div className=\"dc:flex dc:items-center dc:gap-1.5 dc:min-w-0\">\n <span\n className=\"dc:rounded-full dc:flex-shrink-0\"\n style={{ width: 8, height: 8, backgroundColor: summary.color }}\n />\n <span className=\"text-dc-text-secondary dc:truncate\" style={{ fontSize: '12px' }}>\n {getSeriesLabel(summary.seriesKey)}\n </span>\n </div>\n\n <div className=\"dc:font-semibold dc:leading-none text-dc-text\" style={{ fontSize: '24px' }}>\n {summary.current === null\n ? '—'\n : formatAxisValue(summary.current, format)}\n </div>\n\n {hasChange && (\n <>\n <div\n className=\"dc:font-semibold dc:truncate\"\n style={{ fontSize: '12px', color: isPositive ? POSITIVE_COLOR : NEGATIVE_COLOR }}\n >\n {isPositive ? '+' : ''}\n {formatAxisValue(summary.absoluteChange, format)}\n {summary.percentageChange !== null && (\n <> ({isPositive ? '+' : ''}{summary.percentageChange.toFixed(1)}%)</>\n )}\n </div>\n {/* On its own line, and naming the actual period start where we\n know it - \"since Sep 2025\" says more than \"since start of\n period\" and keeps the delta line short. */}\n <div className=\"text-dc-text-muted dc:truncate\" style={{ fontSize: '11px' }}>\n {summary.baselineLabel\n ? t('chart.runtime.summarySince', { period: summary.baselineLabel })\n : t('chart.runtime.summarySincePeriodStart')}\n </div>\n </>\n )}\n </div>\n )\n })}\n </div>\n )\n})\n\nexport default ChartSummaryHeader\n","import React, { useState, useMemo, useId } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { ComposedChart, XAxis, CartesianGrid } from 'recharts'\nimport ChartContainer from './ChartContainer.js'\nimport ChartTooltip from './ChartTooltip.js'\nimport AngledXAxisTick from './AngledXAxisTick.js'\nimport { ChartEmptyState, ChartConfigError, ChartRenderError } from './ChartStates.js'\nimport { resolveChartAxisFields } from './chartAxisResolution.js'\nimport {\n getDualAxisInfo,\n getYAxisChartMargins,\n resolveAngledAxisHeight,\n getPlotLeftOffset,\n withTargetData,\n renderDualYAxes,\n renderChartTargetLines,\n makeCartesianTooltipFormatter,\n renderHoverLegend\n} from './chartScaffolding.js'\nimport {\n buildSeriesKeyToFieldMap,\n computeSeriesSummaries,\n makeAxisResolver,\n isTimeOrderedXAxis,\n renderAreaGradientDefs,\n renderAreaSeries,\n resolveAreaStacking\n} from './cartesianChartHelpers.js'\nimport ChartSummaryHeader from './ChartSummaryHeader.js'\nimport { transformChartDataWithSeries } from '../../utils/chartUtils.js'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel.js'\nimport type { ChartProps } from '../../types.js'\n\nconst AreaChart = React.memo(function AreaChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Gradient ids must be unique per chart instance or two area portlets on one\n // dashboard steal each other's fills. useId() emits colons, which are not\n // reliable inside SVG url(#...) references — strip them.\n const gradientIdPrefix = `dc-area-${useId().replace(/:/g, '')}`\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Resolve + validate axis fields (hooks-first to satisfy React rules)\n const { xAxisField, yAxisFields, seriesFields, errorCode } = useMemo(\n () => resolveChartAxisFields(chartConfig),\n [chartConfig]\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Use shared function to transform data and handle series\n // (empty arrays when config is invalid — early returns happen after hooks)\n const { data: chartData, seriesKeys } = useMemo(() => {\n if (errorCode || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, errorCode])\n\n try {\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n const showAllXLabels = displayConfig?.showAllXLabels ?? false\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return <ChartEmptyState height={height} hint={t('chart.runtime.noDataHint.area')} />\n }\n\n if (errorCode) {\n return <ChartConfigError height={height} hint={t(`chart.runtime.configErrorHint.${errorCode}`)} />\n }\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField = buildSeriesKeyToFieldMap(yAxisFields, getFieldLabel)\n\n // Dual Y-axis derivation + margins (shared scaffolding)\n const axisInfo = getDualAxisInfo(yAxisFields, yAxisAssignment)\n const { hasRightAxis } = axisInfo\n\n // Resolve effective stacking (disabled when dual Y-axis present)\n const { effectiveShouldStack, effectiveIsPercentStack, stackOffset } =\n resolveAreaStacking(displayConfig, hasRightAxis)\n\n // Summary header: per-series current value + change since the start of the\n // window, derived from the data already fetched for the plot.\n const showSummary = displayConfig?.showSummary === true && seriesKeys.length > 0\n const summaries = showSummary\n ? computeSeriesSummaries(\n chartData,\n seriesKeys,\n colorPalette,\n makeAxisResolver((key: string) => seriesKeyToField[key], yAxisAssignment),\n 'name'\n )\n : []\n\n // The summary carries the colour dots, so the bottom legend becomes redundant.\n const showLegend = safeDisplayConfig.showLegend && !showSummary\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = getYAxisChartMargins(hasRightAxis)\n\n // Process target values and add to chart data\n const { spreadTargets, enhancedChartData } = withTargetData(chartData, displayConfig?.target)\n\n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <ChartEmptyState\n height={height}\n titleKey=\"chart.runtime.noValidData\"\n hint=\"No valid data points for area chart after transformation\"\n />\n )\n }\n\n return (\n <div className=\"dc:relative dc:w-full dc:flex dc:flex-col\" style={{ height }}>\n {showSummary && (\n <ChartSummaryHeader\n summaries={summaries}\n getSeriesLabel={(seriesKey) => seriesKey}\n valueFormat={leftYAxisFormat}\n rightValueFormat={rightYAxisFormat}\n showChange={isTimeOrderedXAxis(queryObject, xAxisField)}\n leftOffset={getPlotLeftOffset(hasRightAxis)}\n />\n )}\n {/* The header wraps, so its height is not knowable up front. Give the\n plot the remaining flex space rather than subtracting a constant\n that silently drifts out of sync once the header wraps. */}\n <div className={showSummary ? 'dc:flex-1 dc:min-h-0' : 'dc:contents'}>\n <ChartContainer height={showSummary ? '100%' : height} minHeight={showSummary ? 0 : undefined}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />}\n <XAxis\n dataKey=\"name\"\n type=\"category\"\n tick={<AngledXAxisTick />}\n height={resolveAngledAxisHeight(enhancedChartData.map((row: any) => row?.name))}\n interval={showAllXLabels ? 0 : undefined}\n />\n {renderDualYAxes(axisInfo, getFieldLabel, leftYAxisFormat, rightYAxisFormat, effectiveIsPercentStack)}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={makeCartesianTooltipFormatter({\n leftYAxisFormat,\n rightYAxisFormat,\n yAxisAssignment,\n resolveField: (name) => seriesKeyToField[name],\n isPercentStack: effectiveIsPercentStack\n })}\n />\n )}\n {renderHoverLegend({\n show: showLegend,\n iconType: 'rect',\n paddingTop: 10,\n onHover: setHoveredLegend,\n onLeave: () => setHoveredLegend(null)\n })}\n {!effectiveShouldStack && renderAreaGradientDefs(seriesKeys, colorPalette, gradientIdPrefix)}\n {renderAreaSeries({\n seriesKeys,\n colorPalette,\n seriesKeyToField,\n yAxisAssignment,\n hoveredLegend,\n connectNulls: safeDisplayConfig.connectNulls,\n shouldStack: effectiveShouldStack,\n // Default off: area charts have never drawn plain markers.\n showPoints: displayConfig?.showPoints ?? false,\n drillEnabled,\n onDataPointClick,\n gradientIdPrefix\n })}\n {renderChartTargetLines(spreadTargets)}\n </ComposedChart>\n </ChartContainer>\n </div>\n </div>\n )\n } catch (error) {\n return <ChartRenderError height={height} chartType=\"Area Chart\" error={error} />\n }\n})\n\nexport default AreaChart\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-area-Dol6s9no.js","names":[],"sources":["../../../src/client/components/LoadingIndicator.tsx","../../../src/client/utils/comparisonUtils.ts","../../../src/client/components/charts/ChartContainer.tsx","../../../src/client/components/charts/ChartTooltip.tsx","../../../src/client/components/charts/AngledXAxisTick.tsx","../../../src/client/components/charts/ChartStates.tsx","../../../src/client/components/charts/chartAxisResolution.ts","../../../src/client/utils/targetUtils.ts","../../../src/client/components/charts/chartScaffolding.tsx","../../../src/client/components/charts/cartesianChartHelpers.tsx","../../../src/client/components/charts/ChartSummaryHeader.tsx","../../../src/client/components/charts/AreaChart.tsx"],"sourcesContent":["/**\n * LoadingIndicator Component\n *\n * A centralized, theme-aware loading spinner that uses CSS variables\n * for consistent styling across all drizzle-cube components.\n *\n * Can be overridden at the Dashboard or Portlet level by passing a\n * custom loadingComponent prop.\n */\n\nexport interface LoadingIndicatorProps {\n /** Size variant: 'xs' (12px), 'sm' (24px), 'md' (32px), 'lg' (48px) */\n size?: 'xs' | 'sm' | 'md' | 'lg'\n /** Additional CSS classes */\n className?: string\n}\n\nconst sizeClasses = {\n xs: 'dc:h-3 dc:w-3',\n sm: 'dc:h-6 dc:w-6',\n md: 'dc:h-8 dc:w-8',\n lg: 'dc:h-12 dc:w-12'\n}\n\nexport default function LoadingIndicator({\n size = 'md',\n className = ''\n}: LoadingIndicatorProps) {\n return (\n <div\n className={`dc:animate-spin dc:rounded-full dc:border-b-2 ${sizeClasses[size]} ${className}`}\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n role=\"status\"\n aria-label=\"Loading\"\n />\n )\n}\n","/**\n * Comparison Data Utilities\n * Handles period-over-period comparison data transformation for charts\n *\n * These utilities detect comparison query results (with __periodIndex metadata)\n * and transform them for visualization in either 'separate' or 'overlay' mode.\n */\n\n/**\n * Check if data contains comparison period metadata\n */\nexport function isComparisonData(data: any[]): boolean {\n return data.length > 0 && '__periodIndex' in data[0]\n}\n\n/**\n * Get unique period labels from comparison data\n */\nexport function getPeriodLabels(data: any[]): string[] {\n if (!isComparisonData(data)) return []\n\n const labels = new Set<string>()\n for (const row of data) {\n if (row.__period) {\n labels.add(row.__period)\n }\n }\n return Array.from(labels)\n}\n\n/**\n * Get period indices from comparison data\n */\nexport function getPeriodIndices(data: any[]): number[] {\n if (!isComparisonData(data)) return []\n\n const indices = new Set<number>()\n for (const row of data) {\n if (typeof row.__periodIndex === 'number') {\n indices.add(row.__periodIndex)\n }\n }\n return Array.from(indices).sort((a, b) => a - b)\n}\n\n/**\n * Generate a short label for a period (used in legends)\n * Uses simple \"Current\" / \"Prior\" labels for clarity\n */\nexport function generatePeriodShortLabel(_periodLabel: string, index: number): string {\n return index === 0 ? 'Current' : 'Prior'\n}\n\n/**\n * Transform comparison data for 'separate' mode\n * Returns data with each row having its original measure values\n * Series are created per period (e.g., \"totalLinesOfCode (Current)\", \"totalLinesOfCode (Prior)\")\n */\nexport function transformForSeparateMode(\n data: any[],\n measures: string[],\n _timeDimensionKey: string\n): { data: any[], seriesKeys: string[] } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures }\n }\n\n const periodLabels = getPeriodLabels(data)\n const seriesKeys: string[] = []\n\n // Create series key for each measure + period combination\n for (const measure of measures) {\n for (let i = 0; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n const key = `${measure} (${shortLabel})`\n seriesKeys.push(key)\n }\n }\n\n // Data already has period info, just return as-is for separate mode\n // The chart will group by time dimension and show multiple lines\n return { data, seriesKeys }\n}\n\n/**\n * Detect dimension fields in comparison data\n * Returns fields that are not measures, time dimension, or metadata fields\n */\nfunction detectDimensionFields(\n data: any[],\n measures: string[],\n timeDimensionKey: string\n): string[] {\n if (data.length === 0) return []\n\n const metadataFields = ['__period', '__periodIndex', '__periodDayIndex']\n const firstRow = data[0]\n const dimensions: string[] = []\n\n for (const key of Object.keys(firstRow)) {\n if (\n !measures.includes(key) &&\n key !== timeDimensionKey &&\n !metadataFields.includes(key)\n ) {\n dimensions.push(key)\n }\n }\n\n return dimensions\n}\n\n/**\n * Get unique dimension values from data for a set of dimension fields\n */\nfunction getUniqueDimensionValues(\n data: any[],\n dimensionFields: string[]\n): Map<string, Set<any>> {\n const values = new Map<string, Set<any>>()\n\n for (const field of dimensionFields) {\n values.set(field, new Set())\n }\n\n for (const row of data) {\n for (const field of dimensionFields) {\n if (row[field] !== undefined && row[field] !== null) {\n values.get(field)!.add(row[field])\n }\n }\n }\n\n return values\n}\n\n/**\n * Transform comparison data for 'overlay' mode\n * Pivots data so each row represents a day-of-period index,\n * with separate columns for each period's values.\n *\n * When dimensions are present, creates series keys that include\n * dimension values: \"Engineering - Total Lines of Code (Current)\"\n *\n * Input (without dimensions):\n * [\n * { date: '2024-01-01', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-02', value: 110, __periodIndex: 0, __periodDayIndex: 1 },\n * { date: '2023-01-01', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-02', value: 85, __periodIndex: 1, __periodDayIndex: 1 },\n * ]\n *\n * Output (without dimensions):\n * [\n * { __periodDayIndex: 0, 'value (Current)': 100, 'value (Prior)': 80 },\n * { __periodDayIndex: 1, 'value (Current)': 110, 'value (Prior)': 85 },\n * ]\n *\n * Input (with dimensions):\n * [\n * { date: '2024-01-01', 'Dept.name': 'Engineering', value: 100, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2024-01-01', 'Dept.name': 'Sales', value: 50, __periodIndex: 0, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Engineering', value: 80, __periodIndex: 1, __periodDayIndex: 0 },\n * { date: '2023-01-01', 'Dept.name': 'Sales', value: 40, __periodIndex: 1, __periodDayIndex: 0 },\n * ]\n *\n * Output (with dimensions):\n * [\n * {\n * __periodDayIndex: 0,\n * 'Engineering - value (Current)': 100,\n * 'Engineering - value (Prior)': 80,\n * 'Sales - value (Current)': 50,\n * 'Sales - value (Prior)': 40,\n * },\n * ]\n */\nexport function transformForOverlayMode(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n getFieldLabel?: (fieldName: string) => string\n): { data: any[], seriesKeys: string[], xAxisKey: string } {\n if (!isComparisonData(data)) {\n return { data, seriesKeys: measures, xAxisKey: timeDimensionKey }\n }\n\n const periodLabels = getPeriodLabels(data)\n const periodIndices = getPeriodIndices(data)\n\n // Detect dimension fields in the data\n const dimensionFields = detectDimensionFields(data, measures, timeDimensionKey)\n const hasDimensions = dimensionFields.length > 0\n\n // Get unique dimension values for generating series keys\n const uniqueDimensionValues = hasDimensions\n ? getUniqueDimensionValues(data, dimensionFields)\n : null\n\n const transformedData = pivotByDayIndex(data, measures, timeDimensionKey, {\n dimensionFields,\n hasDimensions,\n periodLabels,\n getFieldLabel\n })\n\n const seriesKeys = buildOverlaySeriesKeys(measures, periodLabels, periodIndices, {\n dimensionFields,\n uniqueDimensionValues,\n getFieldLabel\n })\n\n return {\n data: transformedData,\n seriesKeys,\n xAxisKey: '__periodDayIndex'\n }\n}\n\n/**\n * Build the `dimensionValue / dimensionValue` prefix for a comparison row,\n * applying field labels when available. Empty when no dimensions are present.\n */\nfunction buildDimensionPrefix(\n row: any,\n dimensionFields: string[],\n getFieldLabel?: (fieldName: string) => string\n): string {\n if (dimensionFields.length === 0) return ''\n const dimensionValues = dimensionFields.map(field => {\n const value = row[field]\n return getFieldLabel ? getFieldLabel(String(value)) : String(value)\n })\n return dimensionValues.join(' / ')\n}\n\n/**\n * Pivot comparison rows so each output row is one `__periodDayIndex`, with a\n * column per measure/dimension/period combination.\n */\nfunction pivotByDayIndex(\n data: any[],\n measures: string[],\n timeDimensionKey: string,\n opts: {\n dimensionFields: string[]\n hasDimensions: boolean\n periodLabels: string[]\n getFieldLabel?: (fieldName: string) => string\n }\n): any[] {\n const { dimensionFields, hasDimensions, periodLabels, getFieldLabel } = opts\n const groupedByDayIndex = new Map<number, Record<string, any>>()\n\n for (const row of data) {\n const dayIndex = row.__periodDayIndex\n const periodIndex = row.__periodIndex\n\n if (!groupedByDayIndex.has(dayIndex)) {\n groupedByDayIndex.set(dayIndex, {\n __periodDayIndex: dayIndex,\n // Store the date from the first period (index 0) for reference\n __displayDate: periodIndex === 0 ? row[timeDimensionKey] : undefined\n })\n }\n\n const groupedRow = groupedByDayIndex.get(dayIndex)!\n\n // If this is the first period and we don't have a display date yet, add it\n if (!groupedRow.__displayDate && row[timeDimensionKey]) {\n groupedRow.__displayDate = row[timeDimensionKey]\n }\n\n // Build dimension prefix if dimensions are present\n const dimensionPrefix = hasDimensions\n ? buildDimensionPrefix(row, dimensionFields, getFieldLabel)\n : ''\n\n // Add measure values with optional dimension prefix and period suffix\n const shortLabel = generatePeriodShortLabel(periodLabels[periodIndex] || '', periodIndex)\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n const key = dimensionPrefix\n ? `${dimensionPrefix} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n groupedRow[key] = row[measure]\n }\n }\n\n // Convert to array and sort by day index\n return Array.from(groupedByDayIndex.values())\n .sort((a, b) => a.__periodDayIndex - b.__periodDayIndex)\n}\n\n/**\n * Generate the overlay-mode series keys (matching the data column names) for\n * each measure/dimension-combination/period.\n */\nfunction buildOverlaySeriesKeys(\n measures: string[],\n periodLabels: string[],\n periodIndices: number[],\n opts: {\n dimensionFields: string[]\n uniqueDimensionValues: Map<string, Set<any>> | null\n getFieldLabel?: (fieldName: string) => string\n }\n): string[] {\n const { dimensionFields, uniqueDimensionValues, getFieldLabel } = opts\n const seriesKeys: string[] = []\n\n // When dimensions are present, prefix each series key with the combination;\n // otherwise use a single empty prefix to share the measure/period loop.\n const dimensionCombinations = uniqueDimensionValues\n ? generateDimensionCombinations(dimensionFields, uniqueDimensionValues, getFieldLabel)\n : ['']\n\n for (const dimCombo of dimensionCombinations) {\n for (const measure of measures) {\n const displayName = getFieldLabel ? getFieldLabel(measure) : measure\n for (let i = 0; i < periodIndices.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i] || '', i)\n seriesKeys.push(\n dimCombo\n ? `${dimCombo} - ${displayName} (${shortLabel})`\n : `${displayName} (${shortLabel})`\n )\n }\n }\n }\n\n return seriesKeys\n}\n\n/**\n * Generate all combinations of dimension values as formatted strings\n */\nfunction generateDimensionCombinations(\n dimensionFields: string[],\n uniqueValues: Map<string, Set<any>>,\n getFieldLabel?: (fieldName: string) => string\n): string[] {\n if (dimensionFields.length === 0) return []\n\n // For single dimension, just return the values\n if (dimensionFields.length === 1) {\n const field = dimensionFields[0]\n const values = Array.from(uniqueValues.get(field) || [])\n return values.map(v => getFieldLabel ? getFieldLabel(String(v)) : String(v))\n }\n\n // For multiple dimensions, generate cartesian product\n const result: string[] = []\n const fieldValues = dimensionFields.map(field =>\n Array.from(uniqueValues.get(field) || [])\n )\n\n function generateCombos(index: number, current: string[]): void {\n if (index === fieldValues.length) {\n const formatted = current.map(v =>\n getFieldLabel ? getFieldLabel(String(v)) : String(v)\n )\n result.push(formatted.join(' / '))\n return\n }\n\n for (const value of fieldValues[index]) {\n generateCombos(index + 1, [...current, value])\n }\n }\n\n generateCombos(0, [])\n return result\n}\n\n/**\n * Format the period day index for display on X-axis\n * Can show as \"Day 1\", \"Day 2\", etc., or as the original date\n */\nexport function formatPeriodDayIndex(\n dayIndex: number,\n displayDate?: string | Date,\n options?: {\n showDayNumber?: boolean\n dateFormat?: 'short' | 'long'\n }\n): string {\n if (options?.showDayNumber) {\n return `Day ${dayIndex + 1}`\n }\n\n if (displayDate) {\n const date = typeof displayDate === 'string' ? new Date(displayDate) : displayDate\n if (!isNaN(date.getTime())) {\n return date.toLocaleDateString('en-US', {\n month: options?.dateFormat === 'long' ? 'long' : 'short',\n day: 'numeric'\n })\n }\n }\n\n return `${dayIndex + 1}`\n}\n\n/**\n * Check if a series key represents a prior period (not the first period)\n * Used for applying different styling to prior period lines\n */\nexport function isPriorPeriodSeries(seriesKey: string, periodLabels: string[]): boolean {\n if (periodLabels.length < 2) return false\n\n // Check if the series key contains any label other than the first period's\n for (let i = 1; i < periodLabels.length; i++) {\n const shortLabel = generatePeriodShortLabel(periodLabels[i], i)\n if (seriesKey.includes(`(${shortLabel})`)) {\n return true\n }\n }\n\n // Also check for \"(Prior\" pattern\n return seriesKey.includes('(Prior')\n}\n\n/**\n * Get the stroke dash array for prior period styling\n */\nexport function getPriorPeriodStrokeDashArray(\n style: 'solid' | 'dashed' | 'dotted' = 'dashed'\n): string | undefined {\n switch (style) {\n case 'solid':\n return undefined\n case 'dashed':\n return '5 5'\n case 'dotted':\n return '2 2'\n default:\n return '5 5'\n }\n}\n","import { ReactElement, useState, useRef, useLayoutEffect, startTransition } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport LoadingIndicator from '../LoadingIndicator.js'\n\ninterface ChartContainerProps {\n children: ReactElement\n height?: string | number\n /**\n * Override the default minimum height. Charts that share their portlet with\n * another element - a wrapped summary header, say - need the plot to shrink\n * rather than push past the card.\n */\n minHeight?: string | number\n}\n\nexport default function ChartContainer({\n children,\n height = \"100%\",\n minHeight\n}: ChartContainerProps) {\n // The default floor keeps a lone chart from collapsing, but it also stops the\n // plot shrinking when something else shares the portlet (e.g. a summary\n // header that has wrapped). Callers in that position pass a smaller floor.\n const effectiveMinHeight = minHeight ?? undefined\n const { t } = useTranslation()\n // Track if container is ready to render ResponsiveContainer\n // We need to wait for the container to be in the DOM with valid dimensions\n const containerRef = useRef<HTMLDivElement>(null)\n const [isReady, setIsReady] = useState(false)\n const [containerSize, setContainerSize] = useState({ width: 0, height: 0 })\n const sizeRef = useRef({ width: 0, height: 0 })\n const readyRef = useRef(false)\n const pendingSizeRef = useRef<{ width: number; height: number } | null>(null)\n const frameRef = useRef<number | null>(null)\n\n // Use useLayoutEffect to measure before paint\n useLayoutEffect(() => {\n let mounted = true\n let resizeObserver: ResizeObserver | null = null\n\n const flushPendingSize = () => {\n frameRef.current = null\n if (!mounted) return\n const pending = pendingSizeRef.current\n pendingSizeRef.current = null\n if (!pending) return\n\n const nextWidth = Math.round(pending.width)\n const nextHeight = Math.round(pending.height)\n if (nextWidth <= 0 || nextHeight <= 0) return\n\n const sizeChanged =\n sizeRef.current.width !== nextWidth || sizeRef.current.height !== nextHeight\n const shouldBecomeReady = !readyRef.current\n\n if (!sizeChanged && !shouldBecomeReady) return\n\n sizeRef.current = { width: nextWidth, height: nextHeight }\n readyRef.current = true\n\n // Resize-driven chart updates can come in bursts (one per portlet).\n // Transitioning these avoids blocking urgent input and coalesces visual work.\n startTransition(() => {\n if (sizeChanged) {\n setContainerSize({ width: nextWidth, height: nextHeight })\n }\n if (shouldBecomeReady) {\n setIsReady(true)\n }\n })\n }\n\n const scheduleSizeUpdate = (width: number, height: number) => {\n pendingSizeRef.current = { width, height }\n if (frameRef.current === null) {\n frameRef.current = requestAnimationFrame(flushPendingSize)\n }\n }\n\n const measureAndSetReady = () => {\n if (!mounted || !containerRef.current) return\n\n const rect = containerRef.current.getBoundingClientRect()\n // Check both clientWidth/Height AND getBoundingClientRect for robustness\n const width = Math.max(containerRef.current.clientWidth, rect.width)\n const measuredHeight = Math.max(containerRef.current.clientHeight, rect.height)\n\n if (width > 0 && measuredHeight > 0) {\n scheduleSizeUpdate(width, measuredHeight)\n }\n }\n\n // Set up ResizeObserver to detect when container gets valid dimensions\n resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: entryHeight } = entry.contentRect\n if (width > 0 && entryHeight > 0) {\n scheduleSizeUpdate(width, entryHeight)\n }\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n // Also try immediate measurement\n measureAndSetReady()\n }\n\n return () => {\n mounted = false\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n resizeObserver?.disconnect()\n }\n }, [])\n\n try {\n if (height === \"100%\") {\n // For 100% height, make the container fill the available flex space with proper sizing\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:h-full dc:flex-1 dc:flex dc:flex-col dc:relative\"\n style={{ minHeight: effectiveMinHeight ?? '250px', minWidth: '100px', overflow: 'hidden', userSelect: 'none' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n }\n\n // For specific heights, use them directly\n // user-select: none prevents browser selection box from appearing when clicking/dragging on charts\n const containerStyle = {\n height: typeof height === 'number' ? `${height}px` : height,\n width: '100%',\n minHeight: effectiveMinHeight ?? '200px',\n minWidth: '100px',\n userSelect: 'none' as const\n }\n\n return (\n <div\n ref={containerRef}\n className=\"dc:w-full dc:flex dc:flex-col dc:relative\"\n style={{ ...containerStyle, overflow: 'hidden' }}\n >\n {isReady && containerSize.width > 0 && containerSize.height > 0 ? (\n <ResponsiveContainer\n width={containerSize.width}\n height={containerSize.height - 16}\n debounce={100}\n style={{ marginTop: '16px' }}\n >\n {children}\n </ResponsiveContainer>\n ) : (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full dc:h-full\">\n <LoadingIndicator size=\"sm\" />\n </div>\n )}\n </div>\n )\n } catch (error) {\n // ChartContainer ResponsiveContainer error\n\n return (\n <div\n className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-4 dc:text-center dc:border dc:border-dashed dc:rounded-lg\"\n style={{ height, borderColor: 'var(--dc-border)', backgroundColor: 'var(--dc-surface)' }}\n >\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1 text-dc-text-muted\">{t('chart.runtime.unableToDisplay')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {error instanceof Error ? error.message : 'Failed to create responsive container'}\n </div>\n </div>\n )\n }\n}\n","import React from 'react'\nimport { Tooltip } from 'recharts'\nimport { formatNumericValue } from '../../utils/chartUtils.js'\n\ninterface ChartTooltipProps {\n formatter?: (value: any, name: any, props: any) => [React.ReactText, React.ReactText]\n labelFormatter?: (label: any, payload?: readonly any[]) => React.ReactText\n}\n\n// Default formatter that rounds numeric values to at most 2 decimal places\nconst defaultFormatter = (value: any, name: any): [React.ReactText, React.ReactText] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n return [formatNumericValue(value), name]\n}\n\nexport default function ChartTooltip({ formatter, labelFormatter }: ChartTooltipProps) {\n return (\n <Tooltip\n formatter={formatter || defaultFormatter}\n labelFormatter={labelFormatter}\n contentStyle={{\n backgroundColor: 'white',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n fontSize: '0.875rem',\n color: '#1f2937',\n boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',\n padding: '8px 12px'\n }}\n />\n )\n}","import React from 'react'\n\ninterface AngledXAxisTickProps {\n x?: number\n y?: number\n payload?: {\n value: string | number\n }\n tickFormatter?: (value: string | number, index: number) => string\n index?: number\n visibleTicksCount?: number\n // Allow any additional props recharts might pass\n [key: string]: unknown\n}\n\n/**\n * Longest label the angled axis reserves room for; see\n * MAX_ANGLED_AXIS_HEIGHT in chartScaffolding.\n */\nexport const MAX_TICK_LABEL_CHARS = 16\n\n/**\n * Custom XAxis tick component for properly aligned angled labels.\n * Fixes alignment issues in recharts 3.7+ where angled labels don't\n * center properly under data points.\n */\nconst AngledXAxisTick: React.FC<AngledXAxisTickProps> = ({\n x = 0,\n y = 0,\n payload,\n tickFormatter,\n index = 0\n}) => {\n if (!payload) return null\n\n const rawValue = tickFormatter\n ? tickFormatter(payload.value, index)\n : String(payload.value)\n\n // The axis reserves height for the longest label (resolveAngledAxisHeight),\n // capped so one very long value cannot squeeze the plot. Truncate past that\n // cap rather than let the label be clipped by the chart edge.\n const displayValue =\n rawValue.length > MAX_TICK_LABEL_CHARS\n ? `${rawValue.slice(0, MAX_TICK_LABEL_CHARS - 1)}\\u2026`\n : rawValue\n\n return (\n <g transform={`translate(${x},${y})`}>\n <text\n x={0}\n y={0}\n dy={16}\n textAnchor=\"end\"\n fill=\"var(--dc-text-muted)\"\n fontSize={12}\n transform=\"rotate(-45)\"\n >\n {displayValue}\n </text>\n </g>\n )\n}\n\nexport default AngledXAxisTick\n","import React from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\n\n/**\n * Shared guard/state components for chart rendering.\n *\n * Cartesian charts (bar, line, area, pie, …) all duplicated the same\n * centred flex blocks for their empty / config-error / render-error states,\n * differing only in the hint text. These components own the duplicated wrapper\n * JSX; each chart supplies its own already-resolved `hint` (a translation key\n * resolved via `t()`, or a literal string) so per-chart messaging is preserved.\n */\n\ninterface ChartStateProps {\n height?: string | number\n /** Already-resolved hint text (caller resolves its own i18n key) */\n hint?: React.ReactNode\n}\n\n/**\n * Empty / no-data state (muted styling). `titleKey` defaults to the generic\n * \"No data available\" heading but can be overridden (e.g. for the post-transform\n * \"No valid data\" state).\n */\nexport function ChartEmptyState({\n height,\n hint,\n titleKey = 'chart.runtime.noData'\n}: ChartStateProps & { titleKey?: string }) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-text-muted\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t(titleKey)}</div>\n {hint != null && <div className=\"dc:text-xs text-dc-text-secondary\">{hint}</div>}\n </div>\n </div>\n )\n}\n\n/**\n * Invalid-configuration state (warning styling). Title is always\n * \"Configuration Error\"; the chart supplies a hint describing what is missing.\n */\nexport function ChartConfigError({ height, hint }: ChartStateProps) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:w-full text-dc-warning\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.configError')}</div>\n {hint != null && <div className=\"dc:text-xs\">{hint}</div>}\n </div>\n </div>\n )\n}\n\n/**\n * Render-error state (error styling), used in chart `catch` blocks.\n */\nexport function ChartRenderError({\n height,\n chartType,\n error\n}: {\n height?: string | number\n /** Display name used in the \"{chartType} Error\" heading */\n chartType: string\n error: unknown\n}) {\n const { t } = useTranslation()\n return (\n <div className=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full text-dc-error dc:p-4\" style={{ height }}>\n <div className=\"dc:text-center\">\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">{t('chart.runtime.chartError', { chartType })}</div>\n <div className=\"dc:text-xs dc:mb-2\">{error instanceof Error ? error.message : t('chart.runtime.unknownError')}</div>\n <div className=\"dc:text-xs text-dc-text-muted\">{t('chart.runtime.checkConfig')}</div>\n </div>\n </div>\n )\n}\n","import type { ChartAxisConfig } from '../../types.js'\n\n/**\n * Discriminated error code returned by {@link resolveChartAxisFields} when the\n * chart configuration is invalid. Each chart maps these codes to its own i18n\n * hint key (e.g. pie charts surface a pie-specific message for `axisInvalid`).\n */\nexport type ChartAxisErrorCode = 'axisInvalid' | 'axisFields'\n\n/**\n * Result of resolving X/Y/series fields from a {@link ChartAxisConfig}.\n * When `errorCode` is non-null the field values are not usable and the chart\n * should render a configuration-error state instead.\n */\nexport interface ResolvedChartAxisFields {\n /** Resolved X-axis field (category), or undefined when the config is invalid */\n xAxisField?: string\n /** Resolved Y-axis (value/measure) fields */\n yAxisFields: string[]\n /** Optional series/grouping fields (only present in the new config format) */\n seriesFields: string[]\n /** Non-null when the configuration cannot produce a renderable axis setup */\n errorCode: ChartAxisErrorCode | null\n}\n\n/**\n * Pure resolver for the X/Y/series field extraction that Cartesian charts\n * (bar, line, area, pie) all duplicated inline.\n *\n * Supports both the new format (`xAxis` / `yAxis` / `series` arrays) and the\n * legacy format (`x` / `y`). Returns a discriminated `errorCode` rather than\n * JSX so each chart can map it to its own i18n hint key and render its own\n * guard component.\n */\nexport function resolveChartAxisFields(chartConfig?: ChartAxisConfig): ResolvedChartAxisFields {\n let xAxisField: string | undefined\n let yAxisFields: string[] = []\n let seriesFields: string[] = []\n let errorCode: ChartAxisErrorCode | null = null\n\n if (chartConfig?.xAxis && chartConfig?.yAxis) {\n // New format\n xAxisField = Array.isArray(chartConfig.xAxis) ? chartConfig.xAxis[0] : chartConfig.xAxis\n yAxisFields = Array.isArray(chartConfig.yAxis) ? chartConfig.yAxis : [chartConfig.yAxis]\n seriesFields = chartConfig.series || []\n } else if (chartConfig?.x && chartConfig?.y) {\n // Legacy format\n xAxisField = chartConfig.x\n yAxisFields = Array.isArray(chartConfig.y) ? chartConfig.y : [chartConfig.y]\n } else {\n errorCode = 'axisInvalid'\n }\n\n if (!errorCode && (!xAxisField || yAxisFields.length === 0)) {\n errorCode = 'axisFields'\n }\n\n return { xAxisField, yAxisFields, seriesFields, errorCode }\n}\n","/**\n * Utility functions for handling target values in charts\n */\n\n/**\n * Parse target values from string format\n * @param targetString - String containing target values (e.g., \"100\" or \"50,75,100\")\n * @returns Array of numeric target values\n */\nexport function parseTargetValues(targetString: string): number[] {\n if (!targetString || typeof targetString !== 'string') {\n return []\n }\n\n const trimmed = targetString.trim()\n if (!trimmed) {\n return []\n }\n\n try {\n // Split by comma and parse each value\n const values = trimmed\n .split(',')\n .map(val => val.trim())\n .filter(val => val !== '')\n .map(val => {\n const num = parseFloat(val)\n if (isNaN(num)) {\n throw new Error(`Invalid numeric value: ${val}`)\n }\n return num\n })\n\n return values.length > 0 ? values : []\n } catch (error) {\n console.warn('Failed to parse target values:', error)\n return []\n }\n}\n\n/**\n * Spread target values across data points\n * @param targets - Array of target values\n * @param dataLength - Number of data points to spread across\n * @returns Array of target values for each data point\n */\nexport function spreadTargetValues(targets: number[], dataLength: number): number[] {\n if (targets.length === 0 || dataLength <= 0) {\n return []\n }\n\n // If only one target value, repeat for all data points\n if (targets.length === 1) {\n return new Array(dataLength).fill(targets[0])\n }\n\n // If we have multiple targets, spread them evenly across data points\n const result: number[] = []\n const baseGroupSize = Math.floor(dataLength / targets.length)\n const remainder = dataLength % targets.length\n\n let currentIndex = 0\n \n for (let i = 0; i < targets.length; i++) {\n // Calculate group size for this target\n // First 'remainder' groups get an extra item\n const groupSize = baseGroupSize + (i < remainder ? 1 : 0)\n \n // Fill this group with the current target value\n for (let j = 0; j < groupSize; j++) {\n result[currentIndex++] = targets[i]\n }\n }\n\n return result\n}\n\n/**\n * Calculate variance between actual and target values\n * @param actual - Actual value\n * @param target - Target value\n * @returns Variance as percentage\n */\nexport function calculateVariance(actual: number, target: number): number {\n if (target === 0) {\n return actual === 0 ? 0 : (actual > 0 ? 100 : -100)\n }\n return ((actual - target) / target) * 100\n}\n\n/**\n * Format variance as percentage string with appropriate sign and color indication\n * @param variance - Variance percentage\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted variance string (e.g., \"+12.5%\" or \"-8.3%\")\n */\nexport function formatVariance(variance: number, decimals: number = 1): string {\n const sign = variance >= 0 ? '+' : ''\n return `${sign}${variance.toFixed(decimals)}%`\n}\n\n/**\n * Get unique target values for reference lines\n * @param targets - Array of target values (may contain duplicates)\n * @returns Array of unique target values\n */\nexport function getUniqueTargets(targets: number[]): number[] {\n return [...new Set(targets)].sort((a, b) => a - b)\n}","import { Fragment } from 'react'\nimport { YAxis, Line, Legend } from 'recharts'\nimport { CHART_MARGINS } from '../../utils/chartConstants.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport { parseTargetValues, spreadTargetValues } from '../../utils/targetUtils.js'\nimport type { AxisFormatConfig } from '../../types.js'\n\n/**\n * Shared scaffolding for the Cartesian recharts charts (bar, line, area).\n *\n * These charts duplicated the same dual-Y-axis derivation, chart margins,\n * target-line overlay, and the left/right `<YAxis>` JSX. The pure helpers and\n * recharts render-helpers here own that shared setup. Render-helpers return\n * recharts elements (inside a fragment) and are embedded directly in the chart\n * children — recharts flattens fragments when discovering axes/series, exactly\n * as it already does for the inline target-line fragment.\n */\n\nexport interface DualAxisInfo {\n /** True when at least one measure is assigned to the right axis */\n hasRightAxis: boolean\n /** Measure fields rendered against the left axis */\n leftAxisFields: string[]\n /** Measure fields rendered against the right axis */\n rightAxisFields: string[]\n}\n\n/** Derive left/right axis membership from per-measure axis assignments. */\nexport function getDualAxisInfo(\n yAxisFields: string[],\n yAxisAssignment: Record<string, 'left' | 'right'>\n): DualAxisInfo {\n const hasRightAxis = yAxisFields.some((field) => yAxisAssignment[field] === 'right')\n const leftAxisFields = yAxisFields.filter((f) => (yAxisAssignment[f] || 'left') === 'left')\n const rightAxisFields = yAxisFields.filter((f) => yAxisAssignment[f] === 'right')\n return { hasRightAxis, leftAxisFields, rightAxisFields }\n}\n\n/** Chart margins with extra room for the Y-axis label(s). */\nexport function getYAxisChartMargins(hasRightAxis: boolean) {\n return {\n ...CHART_MARGINS,\n left: 40, // Space for left Y-axis label\n right: hasRightAxis ? 40 : 20 // Extra space for right Y-axis label if needed\n }\n}\n\n/**\n * Vertical space an angled X-axis label needs.\n *\n * `AngledXAxisTick` rotates its text -45deg from an anchor offset dy=16, so the\n * space required below the axis is the label's own width projected onto the\n * vertical, plus that offset. A fixed height clipped longer labels: \"2026-08-24\"\n * is roughly 66px wide at 12px, which projects to ~47px and needs ~63px in\n * total against the 60px that used to be hardcoded.\n *\n * Capped, because a pathological label should cost the plot a bounded amount of\n * height rather than squeeze it away - past the cap the label is truncated\n * instead (see AngledXAxisTick).\n */\nexport const MIN_ANGLED_AXIS_HEIGHT = 60\nexport const MAX_ANGLED_AXIS_HEIGHT = 96\n/** Rough advance width of the tick font (12px sans) per character. */\nconst TICK_CHAR_WIDTH = 6.6\n\nexport function resolveAngledAxisHeight(values: Array<string | number | undefined>): number {\n let longest = 0\n for (const value of values) {\n if (value === null || value === undefined) continue\n const len = String(value).length\n if (len > longest) longest = len\n }\n if (longest === 0) return MIN_ANGLED_AXIS_HEIGHT\n\n const projected = longest * TICK_CHAR_WIDTH * Math.SQRT1_2\n const needed = Math.ceil(projected) + 20 // the tick's dy offset plus a little air\n return Math.max(MIN_ANGLED_AXIS_HEIGHT, Math.min(needed, MAX_ANGLED_AXIS_HEIGHT))\n}\n\n/**\n * Width reserved for the left `<YAxis>`. This is recharts' own default, stated\n * explicitly so anything needing to line up with the plot area can rely on it\n * rather than assume it.\n */\nexport const Y_AXIS_WIDTH = 60\n\n/**\n * Distance from the chart container's left edge to the left edge of the plot\n * area — the chart margin plus the Y-axis gutter. Used to indent content\n * rendered outside the chart (the summary header) so it lines up with the first\n * data point instead of floating against the card edge.\n */\nexport function getPlotLeftOffset(hasRightAxis: boolean): number {\n return getYAxisChartMargins(hasRightAxis).left + Y_AXIS_WIDTH\n}\n\n/**\n * Apply target values (single or comma-separated spread) onto chart data,\n * returning the spread targets plus data enhanced with a `__target` key.\n */\nexport function withTargetData<T extends Record<string, any>>(\n chartData: T[],\n target: string | undefined\n): { spreadTargets: number[]; enhancedChartData: T[] } {\n const targetValues = parseTargetValues(target || '')\n const spreadTargets = spreadTargetValues(targetValues, chartData.length)\n const enhancedChartData = spreadTargets.length > 0\n ? chartData.map((dataPoint, index) => ({ ...dataPoint, __target: spreadTargets[index] || null }))\n : chartData\n return { spreadTargets, enhancedChartData }\n}\n\n/**\n * Render the left + optional right `<YAxis>`. Returns recharts elements in a\n * fragment for embedding directly in the chart children. Positional args keep\n * the (otherwise identical) call sites in each chart down to a single line.\n *\n * @param isPercentStack when true (area/bar percent stacking) the left axis shows 0–100%\n */\nexport function renderDualYAxes(\n { hasRightAxis, leftAxisFields, rightAxisFields }: DualAxisInfo,\n getFieldLabel: (field: string) => string,\n leftYAxisFormat?: AxisFormatConfig,\n rightYAxisFormat?: AxisFormatConfig,\n isPercentStack = false\n) {\n return (\n <Fragment>\n <YAxis\n yAxisId=\"left\"\n orientation=\"left\"\n width={Y_AXIS_WIDTH}\n tick={{ fontSize: 12 }}\n tickFormatter={\n isPercentStack\n ? (v) => `${(v * 100).toFixed(0)}%`\n : leftYAxisFormat\n ? (value) => formatAxisValue(value, leftYAxisFormat)\n : undefined\n }\n domain={isPercentStack ? [0, 1] : undefined}\n label={\n isPercentStack\n ? undefined\n : leftAxisFields.length > 0\n ? {\n value: leftYAxisFormat?.label || getFieldLabel(leftAxisFields[0]),\n angle: -90,\n position: 'left',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-muted)' }\n }\n : undefined\n }\n />\n {hasRightAxis && (\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tick={{ fontSize: 12 }}\n tickFormatter={rightYAxisFormat ? (value) => formatAxisValue(value, rightYAxisFormat) : undefined}\n label={\n rightAxisFields.length > 0\n ? {\n value: rightYAxisFormat?.label || getFieldLabel(rightAxisFields[0]),\n angle: 90,\n position: 'right',\n style: { textAnchor: 'middle', fontSize: '12px', fill: 'var(--dc-text-muted)' }\n }\n : undefined\n }\n />\n )}\n </Fragment>\n )\n}\n\n/**\n * Render the target overlay: a white backing line plus a purple dashed line\n * on top (shared by bar, line, area). Returns null when there are no targets.\n */\nexport function renderChartTargetLines(spreadTargets: number[]) {\n if (spreadTargets.length === 0) return null\n return (\n <Fragment>\n {/* White background line */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n stroke=\"#ffffff\"\n strokeWidth={2}\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n {/* Grey dashed line on top */}\n <Line\n type=\"monotone\"\n dataKey=\"__target\"\n yAxisId=\"left\"\n name=\"Target\"\n stroke=\"#8B5CF6\"\n strokeWidth={2}\n strokeDasharray=\"2 3\"\n dot={false}\n activeDot={false}\n connectNulls={false}\n />\n </Fragment>\n )\n}\n\ninterface CartesianTooltipOptions {\n leftYAxisFormat?: AxisFormatConfig\n rightYAxisFormat?: AxisFormatConfig\n yAxisAssignment: Record<string, 'left' | 'right'>\n /** Maps a series key (display label) back to its original measure field. */\n resolveField: (name: string) => string | undefined\n /** When true, values render as percentages (area/bar percent stacking). */\n isPercentStack?: boolean\n}\n\n/**\n * Build the value/name tooltip formatter shared by the Cartesian charts.\n * Handles null values, the target series, percent stacking, and per-series\n * left/right axis format selection.\n */\nexport function makeCartesianTooltipFormatter({\n leftYAxisFormat,\n rightYAxisFormat,\n yAxisAssignment,\n resolveField,\n isPercentStack = false\n}: CartesianTooltipOptions) {\n return (value: any, name: any): [any, any] => {\n if (value === null || value === undefined) {\n return ['No data', name]\n }\n if (name === 'Target') {\n // Use left Y-axis format for target values\n return [formatAxisValue(value, leftYAxisFormat), 'Target Value']\n }\n if (isPercentStack && typeof value === 'number') {\n return [`${(value * 100).toFixed(1)}%`, name]\n }\n // Determine which axis format to use based on series name\n const originalField = resolveField(name)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const formatConfig = axisId === 'right' ? rightYAxisFormat : leftYAxisFormat\n return [formatAxisValue(value, formatConfig), name]\n }\n}\n\n/**\n * Render the hover-aware bottom legend shared by the Cartesian charts.\n * Returns null when the legend is hidden. `iconType` / `paddingTop` differ\n * per chart (rect+10 for area, rect+25 for bar, line+25 for line).\n */\nexport function renderHoverLegend({\n show,\n iconType,\n paddingTop,\n onHover,\n onLeave\n}: {\n show: boolean\n iconType: 'rect' | 'line' | 'circle'\n paddingTop: number\n onHover: (dataKey: string) => void\n onLeave: () => void\n}) {\n if (!show) return null\n return (\n <Legend\n wrapperStyle={{ fontSize: '12px', paddingTop: `${paddingTop}px` }}\n iconType={iconType}\n iconSize={8}\n layout=\"horizontal\"\n align=\"center\"\n verticalAlign=\"bottom\"\n onMouseEnter={(o) => onHover(String(o.dataKey || ''))}\n onMouseLeave={onLeave}\n />\n )\n}\n","import React from 'react'\nimport { Line, Area } from 'recharts'\nimport { formatTimeValue, getFieldGranularity, transformChartDataWithSeries } from '../../utils/chartUtils.js'\nimport { CHART_COLORS } from '../../utils/chartConstants.js'\nimport {\n isComparisonData,\n getPeriodLabels,\n transformForOverlayMode,\n isPriorPeriodSeries,\n getPriorPeriodStrokeDashArray\n} from '../../utils/comparisonUtils.js'\nimport type { ColorPalette } from '../../types.js'\n\n/**\n * Co-located helpers shared by the Cartesian time-series charts (Line, Area).\n *\n * These extract the heavier inline logic that previously lived inside the chart\n * components — the clickable/drill dot renderer, the comparison-mode tick and\n * label formatters, and the series-key → measure-field resolution — so the\n * component bodies stay focused on chart composition. Pure extraction: no\n * behaviour change.\n */\n\nexport interface DataPointClickPayload {\n dataPoint: any\n clickedField: string\n xValue: any\n position: { x: number; y: number }\n nativeEvent: React.MouseEvent\n}\n\ninterface DrillDotOptions {\n /** Recharts dot props (cx, cy, payload, key). */\n props: any\n color: string\n drillEnabled?: boolean\n originalField?: string\n seriesKey: string\n onDataPointClick?: (payload: DataPointClickPayload) => void\n}\n\n/**\n * Render a single data-point dot. When drill is enabled and a click handler is\n * present, renders a larger clickable dot with a surface-coloured backing\n * circle to mask grid lines; otherwise a small plain dot. Returns null when the\n * point has no coordinates.\n *\n * `renderPlain` controls whether a small non-interactive dot is drawn when\n * drill is disabled (Line draws one; Area returns nothing).\n */\nexport function renderDrillDot({\n props,\n color,\n drillEnabled,\n originalField,\n seriesKey,\n onDataPointClick,\n renderPlain\n}: DrillDotOptions & { renderPlain: boolean }): React.ReactElement | null {\n const { cx, cy, payload, key } = props\n if (cx === undefined || cy === undefined) return null\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation()\n event.preventDefault()\n if (onDataPointClick) {\n onDataPointClick({\n dataPoint: payload,\n clickedField: originalField || seriesKey,\n xValue: payload.name,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event\n })\n }\n }\n\n if (drillEnabled && onDataPointClick) {\n return (\n <g key={key}>\n {/* Background to mask grid lines - uses theme surface color */}\n <circle cx={cx} cy={cy} r={6} fill=\"var(--dc-surface)\" style={{ pointerEvents: 'none' }} />\n {/* Visible dot with click handler */}\n <circle\n cx={cx}\n cy={cy}\n r={4}\n fill=\"var(--dc-surface)\"\n stroke={color}\n strokeWidth={2}\n cursor=\"pointer\"\n onClick={(e: React.MouseEvent<SVGCircleElement>) => {\n handleClick(e as unknown as React.MouseEvent)\n }}\n />\n </g>\n )\n }\n\n if (!renderPlain) return null\n\n return <circle key={key} cx={cx} cy={cy} r={3} fill={color} />\n}\n\n/**\n * Format a comparison-data X-axis value: shows the current period's date,\n * formatted to the query granularity, falling back to \"Period N\".\n */\nfunction formatComparisonDate(\n displayDate: unknown,\n queryObject: any,\n xAxisField: string,\n fallbackIndex: number\n): string {\n if (displayDate) {\n const granularity = getFieldGranularity(queryObject, xAxisField)\n return formatTimeValue(displayDate as any, granularity)\n }\n return `Period ${fallbackIndex + 1}`\n}\n\n/**\n * Build the comparison-mode X-axis tick formatter for time-series charts.\n * Returns undefined when not in comparison mode (no custom formatting).\n */\nexport function makeComparisonTickFormatter(\n hasComparisonData: boolean,\n chartData: any[],\n queryObject: any,\n xAxisField: string\n): ((value: string | number, index: number) => string) | undefined {\n if (!hasComparisonData) return undefined\n return (value: string | number, index: number) => {\n const row = chartData[index]\n return formatComparisonDate(row?.__displayDate, queryObject, xAxisField, Number(value))\n }\n}\n\n/**\n * Build the comparison-mode tooltip label formatter for time-series charts.\n * Returns undefined when not in comparison mode (no custom formatting).\n */\nexport function makeComparisonLabelFormatter(\n hasComparisonData: boolean,\n queryObject: any,\n xAxisField: string\n): ((label: any, payload: any) => string) | undefined {\n if (!hasComparisonData) return undefined\n return (label: any, payload: any) => {\n const row = payload && payload.length > 0 ? payload[0]?.payload : undefined\n return formatComparisonDate(row?.__displayDate, queryObject, xAxisField, Number(label))\n }\n}\n\n/**\n * Resolve effective stacking for the Area chart from `stackType` (new) /\n * `stacked` (legacy), disabling stacking when a right axis is present (areas on\n * different axes can't be stacked).\n */\nexport function resolveAreaStacking(\n displayConfig: { stackType?: string; stacked?: boolean } | undefined,\n hasRightAxis: boolean\n): { effectiveShouldStack: boolean; effectiveIsPercentStack: boolean; stackOffset: 'expand' | undefined } {\n const stackType = displayConfig?.stackType ?? (displayConfig?.stacked ? 'normal' : 'none')\n const effectiveShouldStack = stackType !== 'none' && !hasRightAxis\n const effectiveIsPercentStack = stackType === 'percent' && !hasRightAxis\n return {\n effectiveShouldStack,\n effectiveIsPercentStack,\n stackOffset: effectiveIsPercentStack ? 'expand' : undefined\n }\n}\n\n/** Build a map from series display label to original measure field name. */\nexport function buildSeriesKeyToFieldMap(\n yAxisFields: string[],\n getFieldLabel: (field: string) => string\n): Record<string, string> {\n const mapping: Record<string, string> = {}\n yAxisFields.forEach((field) => {\n mapping[getFieldLabel(field)] = field\n })\n return mapping\n}\n\n/**\n * Resolve a series key back to its original measure field, handling comparison\n * suffixes like \"(Current)\" / \"(Prior)\" and dimension prefixes (\"Dim - Label\").\n */\nexport function makeSeriesKeyResolver(\n seriesKeyToField: Record<string, string>\n): (seriesKey: string) => string | undefined {\n return (seriesKey: string): string | undefined => {\n if (seriesKeyToField[seriesKey]) return seriesKeyToField[seriesKey]\n // Guard against excessive input length to prevent ReDoS\n if (seriesKey.length > 1000) return undefined\n const withoutSuffix = seriesKey.replace(/\\s*\\((Current|Prior)\\)$/, '')\n const parts = withoutSuffix.split(' - ')\n const measureLabel = parts[parts.length - 1]\n return seriesKeyToField[measureLabel]\n }\n}\n\n/** Pick a series colour by index, preferring the palette then the defaults. */\nexport function getSeriesColor(colorPalette: ColorPalette | undefined, index: number): string {\n const colors = colorPalette?.colors\n return (colors && colors[index % colors.length]) || CHART_COLORS[index % CHART_COLORS.length]\n}\n\ninterface LineSeriesOptions {\n seriesKeys: string[]\n colorPalette?: ColorPalette\n resolveField: (seriesKey: string) => string | undefined\n yAxisAssignment: Record<string, 'left' | 'right'>\n hoveredLegend: string | null\n connectNulls: boolean\n /** Render a marker at every data point. Off is clearer on dense series. */\n showPoints?: boolean\n drillEnabled?: boolean\n onDataPointClick?: (payload: DataPointClickPayload) => void\n /** Comparison styling (omit/false → standard series). */\n hasComparisonData?: boolean\n periodLabels?: string[]\n priorPeriodStyle?: 'solid' | 'dashed' | 'dotted'\n priorPeriodOpacity?: number\n}\n\n/** Render the `<Line>` element for one resolved series (Line chart). */\nfunction renderOneLineSeries(seriesKey: string, index: number, opts: LineSeriesOptions): React.ReactElement {\n const {\n colorPalette, resolveField, yAxisAssignment, hoveredLegend, connectNulls,\n drillEnabled, onDataPointClick, hasComparisonData, periodLabels = [],\n priorPeriodStyle = 'dashed', priorPeriodOpacity = 0.5, showPoints = true\n } = opts\n\n const originalField = resolveField(seriesKey)\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n\n const isPriorPeriod = Boolean(hasComparisonData) && isPriorPeriodSeries(seriesKey, periodLabels)\n const strokeDashArray = isPriorPeriod ? getPriorPeriodStrokeDashArray(priorPeriodStyle) : undefined\n const opacity = isPriorPeriod ? priorPeriodOpacity : 1\n const lineColor = getSeriesColor(colorPalette, index)\n\n let strokeOpacity = opacity\n if (hoveredLegend) strokeOpacity = hoveredLegend === seriesKey ? 1 : 0.3\n\n return (\n <Line\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stroke={lineColor}\n strokeWidth={isPriorPeriod ? 1.5 : 2}\n strokeDasharray={strokeDashArray}\n dot={isPriorPeriod || !showPoints ? false : (props: any) => renderDrillDot({\n props, color: lineColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n // With points hidden, surface one on hover instead — otherwise hiding\n // them would also remove the click target that drill-down relies on.\n activeDot={showPoints ? false : (props: any) => renderDrillDot({\n props, color: lineColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n strokeOpacity={strokeOpacity}\n connectNulls={connectNulls}\n />\n )\n}\n\n/** Render all line series for the Line chart. */\nexport function renderLineSeries(opts: LineSeriesOptions): React.ReactElement[] {\n return opts.seriesKeys.map((seriesKey, index) => renderOneLineSeries(seriesKey, index, opts))\n}\n\ninterface AreaSeriesOptions {\n seriesKeys: string[]\n colorPalette?: ColorPalette\n seriesKeyToField: Record<string, string>\n yAxisAssignment: Record<string, 'left' | 'right'>\n hoveredLegend: string | null\n connectNulls: boolean\n shouldStack: boolean\n /** Render a marker at every data point. Off is clearer on dense series. */\n showPoints?: boolean\n drillEnabled?: boolean\n onDataPointClick?: (payload: DataPointClickPayload) => void\n /**\n * Unique-per-chart-instance prefix for the `<defs>` gradient ids. When\n * omitted (or when stacking) the series fall back to a flat fill.\n */\n gradientIdPrefix?: string\n}\n\n/** Render the `<Area>` element for one series (Area chart). */\nfunction renderOneAreaSeries(seriesKey: string, index: number, opts: AreaSeriesOptions): React.ReactElement {\n const {\n colorPalette, seriesKeyToField, yAxisAssignment, hoveredLegend, connectNulls,\n shouldStack, drillEnabled, onDataPointClick, gradientIdPrefix, showPoints = true\n } = opts\n\n const originalField = seriesKeyToField[seriesKey]\n const axisId = originalField && yAxisAssignment[originalField] === 'right' ? 'right' : 'left'\n const areaColor = getSeriesColor(colorPalette, index)\n\n // Stacked areas read better solid — bands are bounded by their neighbours, so\n // a fade just muddies the boundaries.\n const fill = gradientIdPrefix && !shouldStack\n ? `url(#${gradientIdPrefix}-${index})`\n : areaColor\n\n let fillOpacity = 0.3\n let strokeOpacity = 1\n if (hoveredLegend) {\n const active = hoveredLegend === seriesKey\n fillOpacity = active ? 0.6 : 0.1\n strokeOpacity = active ? 1 : 0.3\n }\n\n return (\n <Area\n key={seriesKey}\n type=\"monotone\"\n dataKey={seriesKey}\n yAxisId={axisId}\n stackId={shouldStack ? 'stack' : undefined}\n stroke={areaColor}\n fill={fill}\n fillOpacity={fillOpacity}\n strokeWidth={2}\n strokeOpacity={strokeOpacity}\n connectNulls={connectNulls}\n // renderPlain follows the option: without it an area chart only ever drew\n // *drill* dots, so \"show data points\" did nothing wherever drill is off\n // (the analysis-builder preview, for one).\n dot={showPoints ? (props: any) => renderDrillDot({\n props, color: areaColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n }) : false}\n // See the line series: keep a hover target when points are hidden.\n activeDot={showPoints ? false : (props: any) => renderDrillDot({\n props, color: areaColor, drillEnabled, originalField, seriesKey, onDataPointClick, renderPlain: true\n })}\n />\n )\n}\n\n/**\n * Vertical fade gradients for the Area chart — one `<linearGradient>` per series.\n *\n * Recharts has no gradient primitive; the fade is plain SVG in `<defs>` that each\n * `<Area>` references by id. Both stops use the *same* hue (fading to white would\n * break the dark and neon themes) and the `<Area>`'s own `fillOpacity` stays the\n * master control, so the existing hover dim/highlight still works unchanged.\n */\nexport function renderAreaGradientDefs(\n seriesKeys: string[],\n colorPalette: ColorPalette | undefined,\n idPrefix: string\n): React.ReactElement {\n return (\n <defs>\n {seriesKeys.map((seriesKey, index) => {\n const color = getSeriesColor(colorPalette, index)\n return (\n <linearGradient\n key={seriesKey}\n id={`${idPrefix}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={color} stopOpacity={1} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0} />\n </linearGradient>\n )\n })}\n </defs>\n )\n}\n\n/** Render all area series for the Area chart. */\nexport function renderAreaSeries(opts: AreaSeriesOptions): React.ReactElement[] {\n return opts.seriesKeys.map((seriesKey, index) => renderOneAreaSeries(seriesKey, index, opts))\n}\n\n/**\n * Is the x-axis an ordered time series?\n *\n * The summary header's \"change since the start of the window\" only means\n * something when the x-axis is ordered. For a categorical axis (region,\n * product, status) the first and last categories are arbitrary, so the delta\n * would be noise.\n */\nexport function isTimeOrderedXAxis(queryObject: any, xAxisField: string | undefined): boolean {\n if (!xAxisField) return false\n const timeDimensions = queryObject?.timeDimensions\n if (!Array.isArray(timeDimensions)) return false\n return timeDimensions.some((td: any) => td?.dimension === xAxisField)\n}\n\n/**\n * Resolve which Y axis a series key is plotted against — the same rule the\n * `<Area>`/`<Line>` elements use, so summaries and series never disagree.\n */\nexport function makeAxisResolver(\n resolveField: (seriesKey: string) => string | undefined,\n yAxisAssignment: Record<string, 'left' | 'right'>\n): (seriesKey: string) => 'left' | 'right' {\n return (seriesKey: string) => {\n const field = resolveField(seriesKey)\n return field && yAxisAssignment[field] === 'right' ? 'right' : 'left'\n }\n}\n\nexport interface SeriesSummary {\n seriesKey: string\n color: string\n /**\n * Which Y axis this series is plotted against, so the summary can be\n * formatted with that axis' format rather than always the left one.\n */\n axis: 'left' | 'right'\n /** Latest non-null value in the window. */\n current: number | null\n /** First non-null value in the window — the baseline the delta is measured from. */\n baseline: number | null\n absoluteChange: number | null\n percentageChange: number | null\n /**\n * X-axis label of the point the delta is measured from, so the header can say\n * \"since Sep 2025\" rather than a generic \"since start of period\". Undefined\n * when the axis key is unknown or the baseline row carries no label.\n */\n baselineLabel?: string\n}\n\n/**\n * Per-series first/last/delta over the plotted window, for the summary header.\n *\n * Pure and DOM-free so it can be unit-tested directly. Nulls are skipped rather\n * than treated as zero — a gap in a series should not read as a crash to zero.\n * When a series has fewer than two non-null points there is nothing to compare,\n * so the deltas stay null and the header renders the value alone.\n */\nexport function computeSeriesSummaries(\n chartData: any[],\n seriesKeys: string[],\n colorPalette?: ColorPalette,\n resolveAxis?: (seriesKey: string) => 'left' | 'right',\n xAxisKey?: string\n): SeriesSummary[] {\n return seriesKeys.map((seriesKey, index) => {\n const axis = resolveAxis ? resolveAxis(seriesKey) : 'left'\n const numbers: number[] = []\n let baselineRow: any = undefined\n for (const row of chartData || []) {\n const raw = row?.[seriesKey]\n if (raw === null || raw === undefined) continue\n const num = typeof raw === 'number' ? raw : parseFloat(String(raw))\n if (!isNaN(num) && isFinite(num)) {\n if (numbers.length === 0) baselineRow = row\n numbers.push(num)\n }\n }\n\n const rawLabel = xAxisKey ? baselineRow?.[xAxisKey] : undefined\n const baselineLabel =\n rawLabel === null || rawLabel === undefined || rawLabel === '' ? undefined : String(rawLabel)\n\n const color = getSeriesColor(colorPalette, index)\n if (numbers.length === 0) {\n return { seriesKey, color, axis, current: null, baseline: null, absoluteChange: null, percentageChange: null }\n }\n\n const current = numbers[numbers.length - 1]\n const baseline = numbers[0]\n if (numbers.length < 2) {\n return { seriesKey, color, axis, current, baseline: null, absoluteChange: null, percentageChange: null }\n }\n\n const absoluteChange = current - baseline\n return {\n seriesKey,\n color,\n axis,\n current,\n baseline,\n absoluteChange,\n percentageChange: baseline !== 0 ? (absoluteChange / Math.abs(baseline)) * 100 : null,\n baselineLabel\n }\n })\n}\n\nexport interface TimeSeriesShape {\n chartData: any[]\n seriesKeys: string[]\n effectiveXAxisKey: string\n hasComparisonData: boolean\n periodLabels: string[]\n}\n\n/**\n * Shape raw rows for a Cartesian time-series chart. In comparison mode this\n * uses the overlay transform (aligned by period day index); otherwise the\n * standard series transform. Centralises the branch so the chart body stays\n * flat.\n */\nexport function buildTimeSeriesData(args: {\n data: any[]\n xAxisField: string\n yAxisFields: string[]\n seriesFields: string[]\n queryObject: any\n getFieldLabel: (field: string) => string\n}): TimeSeriesShape {\n const { data, xAxisField, yAxisFields, seriesFields, queryObject, getFieldLabel } = args\n const hasComparisonData = isComparisonData(data)\n\n if (hasComparisonData) {\n const overlay = transformForOverlayMode(data, yAxisFields, xAxisField, getFieldLabel)\n return {\n chartData: overlay.data,\n seriesKeys: overlay.seriesKeys,\n effectiveXAxisKey: '__periodDayIndex',\n hasComparisonData,\n periodLabels: getPeriodLabels(data)\n }\n }\n\n const standard = transformChartDataWithSeries(data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel)\n return {\n chartData: standard.data,\n seriesKeys: standard.seriesKeys,\n effectiveXAxisKey: 'name',\n hasComparisonData,\n periodLabels: []\n }\n}\n","import React from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport { POSITIVE_COLOR, NEGATIVE_COLOR } from '../../utils/chartConstants.js'\nimport type { SeriesSummary } from './cartesianChartHelpers.js'\nimport type { AxisFormatConfig } from '../../types.js'\n\ninterface ChartSummaryHeaderProps {\n summaries: SeriesSummary[]\n /** Resolves a series key to its display label. */\n getSeriesLabel: (seriesKey: string) => string\n /** Left-axis numeric format, so the header matches the axis it summarises. */\n valueFormat?: AxisFormatConfig\n /** Right-axis format, used for series assigned to the right axis. */\n rightValueFormat?: AxisFormatConfig\n /**\n * Whether a change vs. the start of the window is meaningful. False for a\n * categorical x-axis, where \"first\" and \"last\" are arbitrary categories.\n */\n showChange?: boolean\n /**\n * Distance from the container's left edge to the plot area, so the summary\n * lines up with the first data point rather than the card edge.\n */\n leftOffset?: number\n}\n\n/**\n * Summary band rendered above a time-series plot.\n *\n * Shows each series' latest value and how far it has moved since the start of\n * the window, so the chart is readable without hovering. All values are derived\n * from the already-fetched result set — this issues no queries of its own.\n */\nconst ChartSummaryHeader = React.memo(function ChartSummaryHeader({\n summaries,\n getSeriesLabel,\n valueFormat,\n rightValueFormat,\n showChange = true,\n leftOffset = 0\n}: ChartSummaryHeaderProps) {\n const { t } = useTranslation()\n\n if (summaries.length === 0) return null\n\n return (\n <div\n className=\"dc:flex dc:flex-wrap dc:items-start dc:gap-x-8 dc:gap-y-2 dc:flex-shrink-0 dc:pr-1 dc:pb-2\"\n style={{ paddingLeft: leftOffset }}\n data-testid=\"chart-summary-header\"\n >\n {summaries.map((summary) => {\n const hasChange = showChange && summary.absoluteChange !== null\n // A dual-axis chart formats each axis differently; match the series.\n const format = summary.axis === 'right' ? rightValueFormat : valueFormat\n const isPositive = (summary.absoluteChange ?? 0) >= 0\n return (\n <div key={summary.seriesKey} className=\"dc:flex dc:flex-col dc:gap-0.5 dc:min-w-0\">\n <div className=\"dc:flex dc:items-center dc:gap-1.5 dc:min-w-0\">\n <span\n className=\"dc:rounded-full dc:flex-shrink-0\"\n style={{ width: 8, height: 8, backgroundColor: summary.color }}\n />\n <span className=\"text-dc-text-secondary dc:truncate\" style={{ fontSize: '12px' }}>\n {getSeriesLabel(summary.seriesKey)}\n </span>\n </div>\n\n <div className=\"dc:font-semibold dc:leading-none text-dc-text\" style={{ fontSize: '24px' }}>\n {summary.current === null\n ? '—'\n : formatAxisValue(summary.current, format)}\n </div>\n\n {hasChange && (\n <>\n <div\n className=\"dc:font-semibold dc:truncate\"\n style={{ fontSize: '12px', color: isPositive ? POSITIVE_COLOR : NEGATIVE_COLOR }}\n >\n {isPositive ? '+' : ''}\n {formatAxisValue(summary.absoluteChange, format)}\n {summary.percentageChange !== null && (\n <> ({isPositive ? '+' : ''}{summary.percentageChange.toFixed(1)}%)</>\n )}\n </div>\n {/* On its own line, and naming the actual period start where we\n know it - \"since Sep 2025\" says more than \"since start of\n period\" and keeps the delta line short. */}\n <div className=\"text-dc-text-muted dc:truncate\" style={{ fontSize: '11px' }}>\n {summary.baselineLabel\n ? t('chart.runtime.summarySince', { period: summary.baselineLabel })\n : t('chart.runtime.summarySincePeriodStart')}\n </div>\n </>\n )}\n </div>\n )\n })}\n </div>\n )\n})\n\nexport default ChartSummaryHeader\n","import React, { useState, useMemo, useId } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { ComposedChart, XAxis, CartesianGrid } from 'recharts'\nimport ChartContainer from './ChartContainer.js'\nimport ChartTooltip from './ChartTooltip.js'\nimport AngledXAxisTick from './AngledXAxisTick.js'\nimport { ChartEmptyState, ChartConfigError, ChartRenderError } from './ChartStates.js'\nimport { resolveChartAxisFields } from './chartAxisResolution.js'\nimport {\n getDualAxisInfo,\n getYAxisChartMargins,\n resolveAngledAxisHeight,\n getPlotLeftOffset,\n withTargetData,\n renderDualYAxes,\n renderChartTargetLines,\n makeCartesianTooltipFormatter,\n renderHoverLegend\n} from './chartScaffolding.js'\nimport {\n buildSeriesKeyToFieldMap,\n computeSeriesSummaries,\n makeAxisResolver,\n isTimeOrderedXAxis,\n renderAreaGradientDefs,\n renderAreaSeries,\n resolveAreaStacking\n} from './cartesianChartHelpers.js'\nimport ChartSummaryHeader from './ChartSummaryHeader.js'\nimport { transformChartDataWithSeries } from '../../utils/chartUtils.js'\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel.js'\nimport type { ChartProps } from '../../types.js'\n\nconst AreaChart = React.memo(function AreaChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette,\n onDataPointClick,\n drillEnabled\n}: ChartProps) {\n const { t } = useTranslation()\n const [hoveredLegend, setHoveredLegend] = useState<string | null>(null)\n // Gradient ids must be unique per chart instance or two area portlets on one\n // dashboard steal each other's fills. useId() emits colons, which are not\n // reliable inside SVG url(#...) references — strip them.\n const gradientIdPrefix = `dc-area-${useId().replace(/:/g, '')}`\n // Use specialized hook to avoid re-renders from unrelated context changes\n const getFieldLabel = useCubeFieldLabel()\n\n // Resolve + validate axis fields (hooks-first to satisfy React rules)\n const { xAxisField, yAxisFields, seriesFields, errorCode } = useMemo(\n () => resolveChartAxisFields(chartConfig),\n [chartConfig]\n )\n\n // Dual Y-axis support: extract yAxisAssignment from chartConfig\n const yAxisAssignment = useMemo(() =>\n chartConfig?.yAxisAssignment || {},\n [chartConfig?.yAxisAssignment]\n )\n\n // Use shared function to transform data and handle series\n // (empty arrays when config is invalid — early returns happen after hooks)\n const { data: chartData, seriesKeys } = useMemo(() => {\n if (errorCode || !data || data.length === 0 || !xAxisField) {\n return { data: [], seriesKeys: [] }\n }\n return transformChartDataWithSeries(\n data,\n xAxisField,\n yAxisFields,\n queryObject,\n seriesFields,\n getFieldLabel\n )\n }, [data, xAxisField, yAxisFields, queryObject, seriesFields, getFieldLabel, errorCode])\n\n try {\n const safeDisplayConfig = {\n showLegend: displayConfig?.showLegend ?? true,\n showGrid: displayConfig?.showGrid ?? true,\n showTooltip: displayConfig?.showTooltip ?? true,\n connectNulls: displayConfig?.connectNulls ?? false\n }\n\n const showAllXLabels = displayConfig?.showAllXLabels ?? false\n\n // Extract axis format configs\n const leftYAxisFormat = displayConfig?.leftYAxisFormat\n const rightYAxisFormat = displayConfig?.rightYAxisFormat\n\n if (!data || data.length === 0) {\n return <ChartEmptyState height={height} hint={t('chart.runtime.noDataHint.area')} />\n }\n\n if (errorCode) {\n return <ChartConfigError height={height} hint={t(`chart.runtime.configErrorHint.${errorCode}`)} />\n }\n\n // Build mapping from series key (label) to original field name\n const seriesKeyToField = buildSeriesKeyToFieldMap(yAxisFields, getFieldLabel)\n\n // Dual Y-axis derivation + margins (shared scaffolding)\n const axisInfo = getDualAxisInfo(yAxisFields, yAxisAssignment)\n const { hasRightAxis } = axisInfo\n\n // Resolve effective stacking (disabled when dual Y-axis present)\n const { effectiveShouldStack, effectiveIsPercentStack, stackOffset } =\n resolveAreaStacking(displayConfig, hasRightAxis)\n\n // Summary header: per-series current value + change since the start of the\n // window, derived from the data already fetched for the plot.\n const showSummary = displayConfig?.showSummary === true && seriesKeys.length > 0\n const summaries = showSummary\n ? computeSeriesSummaries(\n chartData,\n seriesKeys,\n colorPalette,\n makeAxisResolver((key: string) => seriesKeyToField[key], yAxisAssignment),\n 'name'\n )\n : []\n\n // The summary carries the colour dots, so the bottom legend becomes redundant.\n const showLegend = safeDisplayConfig.showLegend && !showSummary\n\n // Use custom chart margins with extra space for Y-axis labels\n const chartMargins = getYAxisChartMargins(hasRightAxis)\n\n // Process target values and add to chart data\n const { spreadTargets, enhancedChartData } = withTargetData(chartData, displayConfig?.target)\n\n // Validate transformed data\n if (!chartData || chartData.length === 0) {\n return (\n <ChartEmptyState\n height={height}\n titleKey=\"chart.runtime.noValidData\"\n hint=\"No valid data points for area chart after transformation\"\n />\n )\n }\n\n return (\n <div className=\"dc:relative dc:w-full dc:flex dc:flex-col\" style={{ height }}>\n {showSummary && (\n <ChartSummaryHeader\n summaries={summaries}\n getSeriesLabel={(seriesKey) => seriesKey}\n valueFormat={leftYAxisFormat}\n rightValueFormat={rightYAxisFormat}\n showChange={isTimeOrderedXAxis(queryObject, xAxisField)}\n leftOffset={getPlotLeftOffset(hasRightAxis)}\n />\n )}\n {/* The header wraps, so its height is not knowable up front. Give the\n plot the remaining flex space rather than subtracting a constant\n that silently drifts out of sync once the header wraps. */}\n <div className={showSummary ? 'dc:flex-1 dc:min-h-0' : 'dc:contents'}>\n <ChartContainer height={showSummary ? '100%' : height} minHeight={showSummary ? 0 : undefined}>\n <ComposedChart data={enhancedChartData} margin={chartMargins} stackOffset={stackOffset} accessibilityLayer={false}>\n {safeDisplayConfig.showGrid && <CartesianGrid strokeDasharray=\"3 3\" style={{ pointerEvents: 'none' }} />}\n <XAxis\n dataKey=\"name\"\n type=\"category\"\n tick={<AngledXAxisTick />}\n height={resolveAngledAxisHeight(enhancedChartData.map((row: any) => row?.name))}\n interval={showAllXLabels ? 0 : undefined}\n />\n {renderDualYAxes(axisInfo, getFieldLabel, leftYAxisFormat, rightYAxisFormat, effectiveIsPercentStack)}\n {safeDisplayConfig.showTooltip && (\n <ChartTooltip\n formatter={makeCartesianTooltipFormatter({\n leftYAxisFormat,\n rightYAxisFormat,\n yAxisAssignment,\n resolveField: (name) => seriesKeyToField[name],\n isPercentStack: effectiveIsPercentStack\n })}\n />\n )}\n {renderHoverLegend({\n show: showLegend,\n iconType: 'rect',\n paddingTop: 10,\n onHover: setHoveredLegend,\n onLeave: () => setHoveredLegend(null)\n })}\n {!effectiveShouldStack && renderAreaGradientDefs(seriesKeys, colorPalette, gradientIdPrefix)}\n {renderAreaSeries({\n seriesKeys,\n colorPalette,\n seriesKeyToField,\n yAxisAssignment,\n hoveredLegend,\n connectNulls: safeDisplayConfig.connectNulls,\n shouldStack: effectiveShouldStack,\n // Default off: area charts have never drawn plain markers.\n showPoints: displayConfig?.showPoints ?? false,\n drillEnabled,\n onDataPointClick,\n gradientIdPrefix\n })}\n {renderChartTargetLines(spreadTargets)}\n </ComposedChart>\n </ChartContainer>\n </div>\n </div>\n )\n } catch (error) {\n return <ChartRenderError height={height} chartType=\"Area Chart\" error={error} />\n }\n})\n\nexport default AreaChart\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { n as e } from "./rolldown-runtime-DArdT4gl.js";
2
- import { M as t, P as n, S as r, d as i, k as a, s as o } from "./chart-activity-grid-DVOhLgxv.js";
3
- import { A as s, D as c, E as l, M as u, O as d, S as f, _ as p, b as m, g as h, j as g, k as _, m as v, v as ee, x as te, y as ne } from "./chart-area-C-5ATxvi.js";
2
+ import { M as t, P as n, S as r, d as i, k as a, s as o } from "./chart-activity-grid-4jfS8khG.js";
3
+ import { A as s, D as c, E as l, M as u, O as d, S as f, _ as p, b as m, g as h, j as g, k as _, m as v, v as ee, x as te, y as ne } from "./chart-area-Dol6s9no.js";
4
4
  import y, { useMemo as b, useState as x } from "react";
5
5
  import { jsx as S, jsxs as C } from "react/jsx-runtime";
6
6
  import { Bar as w, CartesianGrid as T, Cell as E, ComposedChart as D, XAxis as re } from "recharts";
@@ -198,4 +198,4 @@ var M = /* @__PURE__ */ e({ default: () => N }), N = y.memo(function({ data: e,
198
198
  //#endregion
199
199
  export { M as n, N as t };
200
200
 
201
- //# sourceMappingURL=chart-bar-CPiLaXHP.js.map
201
+ //# sourceMappingURL=chart-bar-5_niozi2.js.map