drizzle-cube 0.6.0 → 0.6.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 (544) hide show
  1. package/dist/adapters/express/index.cjs +1 -1
  2. package/dist/adapters/{adapters/express → express}/index.d.ts +3 -3
  3. package/dist/adapters/express/index.js +1 -1
  4. package/dist/adapters/fastify/index.cjs +1 -1
  5. package/dist/adapters/{adapters/fastify → fastify}/index.d.ts +3 -3
  6. package/dist/adapters/fastify/index.js +1 -1
  7. package/dist/adapters/{adapters/hono → hono}/agent-handler.d.ts +3 -3
  8. package/dist/adapters/hono/index.cjs +1 -1
  9. package/dist/adapters/{adapters/hono → hono}/index.d.ts +4 -4
  10. package/dist/adapters/hono/index.js +1 -1
  11. package/dist/adapters/{adapters/hono → hono}/mcp-handler.d.ts +2 -2
  12. package/dist/adapters/{adapters/locale.d.ts → locale.d.ts} +1 -1
  13. package/dist/adapters/{adapters/mcp-tools-handlers.d.ts → mcp-tools-handlers.d.ts} +2 -2
  14. package/dist/adapters/mcp-tools.cjs +1 -1
  15. package/dist/adapters/{adapters/mcp-tools.d.ts → mcp-tools.d.ts} +5 -5
  16. package/dist/adapters/mcp-tools.js +1 -1
  17. package/dist/adapters/mcp-transport-B7ddET3M.cjs +40 -0
  18. package/dist/adapters/mcp-transport-Dfuj4j4q.js +591 -0
  19. package/dist/adapters/{adapters/mcp-transport.d.ts → mcp-transport.d.ts} +3 -3
  20. package/dist/adapters/nextjs/index.cjs +1 -1
  21. package/dist/adapters/{adapters/nextjs → nextjs}/index.d.ts +3 -3
  22. package/dist/adapters/nextjs/index.js +1 -1
  23. package/dist/adapters/{adapters/nextjs → nextjs}/mcp-handler.d.ts +2 -2
  24. package/dist/adapters/{adapters/types.d.ts → types.d.ts} +1 -1
  25. package/dist/adapters/{adapters/utils.d.ts → utils.d.ts} +16 -16
  26. package/dist/cli/index.cjs +2 -2
  27. package/dist/client/adapters/adapterRegistry.d.ts +2 -2
  28. package/dist/client/adapters/flowModeAdapter.d.ts +2 -2
  29. package/dist/client/adapters/funnelModeAdapter.d.ts +2 -2
  30. package/dist/client/adapters/index.d.ts +9 -9
  31. package/dist/client/adapters/modeAdapter.d.ts +1 -1
  32. package/dist/client/adapters/queryModeAdapter.d.ts +3 -3
  33. package/dist/client/adapters/retentionModeAdapter.d.ts +2 -2
  34. package/dist/client/charts/ChartLoader.d.ts +2 -2
  35. package/dist/client/charts/chartComponentRegistry.d.ts +1 -1
  36. package/dist/client/charts/chartConfigHelpers.d.ts +1 -1
  37. package/dist/client/charts/chartConfigRegistry.d.ts +1 -1
  38. package/dist/client/charts/chartPlugin.d.ts +3 -3
  39. package/dist/client/charts/lazyChartConfigRegistry.d.ts +2 -2
  40. package/dist/client/charts.d.ts +8 -8
  41. package/dist/client/chunks/DashboardEditModal-okVfH8ZK.js.map +1 -1
  42. package/dist/client/chunks/RetentionCombinedChart-BgbDhsPz.js.map +1 -1
  43. package/dist/client/chunks/RetentionHeatmap-DjXZaTPq.js.map +1 -1
  44. package/dist/client/chunks/analysis-builder-DB88FojM.js.map +1 -1
  45. package/dist/client/chunks/analysis-builder-shared-BVK4TYfR.js.map +1 -1
  46. package/dist/client/chunks/chart-activity-grid-DX0SJbxs.js.map +1 -1
  47. package/dist/client/chunks/chart-area-of01_62R.js.map +1 -1
  48. package/dist/client/chunks/chart-bar-BqelQE_I.js.map +1 -1
  49. package/dist/client/chunks/chart-box-plot-kkBixZ27.js.map +1 -1
  50. package/dist/client/chunks/chart-bubble-B2he1--4.js.map +1 -1
  51. package/dist/client/chunks/chart-candlestick-DZp19Tzh.js.map +1 -1
  52. package/dist/client/chunks/chart-config-activity-grid-D_UX4NHC.js.map +1 -1
  53. package/dist/client/chunks/chart-config-area-BNigHUy8.js.map +1 -1
  54. package/dist/client/chunks/chart-config-bar-DSO_LRTx.js.map +1 -1
  55. package/dist/client/chunks/chart-config-box-plot-oW8axV2q.js.map +1 -1
  56. package/dist/client/chunks/chart-config-bubble-gIoqVyjZ.js.map +1 -1
  57. package/dist/client/chunks/chart-config-candlestick-N6DchAA3.js.map +1 -1
  58. package/dist/client/chunks/chart-config-data-table-d7VBY-y_.js.map +1 -1
  59. package/dist/client/chunks/chart-config-funnel-DEYMcxsD.js.map +1 -1
  60. package/dist/client/chunks/chart-config-gauge-Dq-_H9UN.js.map +1 -1
  61. package/dist/client/chunks/chart-config-heat-map-CfRnRNcw.js.map +1 -1
  62. package/dist/client/chunks/chart-config-kpi-delta-DSQbvqu_.js.map +1 -1
  63. package/dist/client/chunks/chart-config-kpi-number-EFSWY1We.js.map +1 -1
  64. package/dist/client/chunks/chart-config-kpi-text-KM3V5X2u.js.map +1 -1
  65. package/dist/client/chunks/chart-config-line-D6jG8PCH.js.map +1 -1
  66. package/dist/client/chunks/chart-config-markdown-BtRIe8JN.js.map +1 -1
  67. package/dist/client/chunks/chart-config-measure-profile-DxRGa-zf.js.map +1 -1
  68. package/dist/client/chunks/chart-config-pie-BhzW-fdn.js.map +1 -1
  69. package/dist/client/chunks/chart-config-radar-D7REP1q_.js.map +1 -1
  70. package/dist/client/chunks/chart-config-radial-bar-Byx6qOPU.js.map +1 -1
  71. package/dist/client/chunks/chart-config-sankey-BTnWA7EW.js.map +1 -1
  72. package/dist/client/chunks/chart-config-scatter-DSYTjwRb.js.map +1 -1
  73. package/dist/client/chunks/chart-config-sunburst-Bwjtdf7X.js.map +1 -1
  74. package/dist/client/chunks/chart-config-tree-map-DVrvf3yQ.js.map +1 -1
  75. package/dist/client/chunks/chart-config-waterfall-DmFeQdIk.js.map +1 -1
  76. package/dist/client/chunks/chart-data-table-CKauQXme.js.map +1 -1
  77. package/dist/client/chunks/chart-funnel-CToKSBaL.js.map +1 -1
  78. package/dist/client/chunks/chart-gauge-DTVezSk7.js.map +1 -1
  79. package/dist/client/chunks/chart-heat-map-DTuUl0BR.js.map +1 -1
  80. package/dist/client/chunks/chart-kpi-delta-Dn-jjO-2.js.map +1 -1
  81. package/dist/client/chunks/chart-kpi-number-P_WBiO5S.js.map +1 -1
  82. package/dist/client/chunks/chart-kpi-text-C-Y4eb5H.js.map +1 -1
  83. package/dist/client/chunks/chart-line-DKgrQA6c.js.map +1 -1
  84. package/dist/client/chunks/chart-markdown-CV75S_zL.js.map +1 -1
  85. package/dist/client/chunks/chart-measure-profile-Ket8fJyf.js.map +1 -1
  86. package/dist/client/chunks/chart-pie-ByieAX5H.js.map +1 -1
  87. package/dist/client/chunks/chart-radar-CiSwHWp4.js.map +1 -1
  88. package/dist/client/chunks/chart-radial-bar-BF6Mhl6f.js.map +1 -1
  89. package/dist/client/chunks/chart-sankey-DjrvKw6K.js.map +1 -1
  90. package/dist/client/chunks/chart-scatter-Dd9WFqnS.js.map +1 -1
  91. package/dist/client/chunks/chart-sunburst-leGpuDj7.js.map +1 -1
  92. package/dist/client/chunks/chart-tree-map-Ceq5sLZA.js.map +1 -1
  93. package/dist/client/chunks/chart-waterfall-DyvQReN5.js.map +1 -1
  94. package/dist/client/chunks/charts-core-DaXSt1Dd.js.map +1 -1
  95. package/dist/client/chunks/charts-loader-DdTeCeNo.js.map +1 -1
  96. package/dist/client/chunks/retention-ChW9jYdy.js.map +1 -1
  97. package/dist/client/chunks/schema-visualization-Cb_E9_Gd.js.map +1 -1
  98. package/dist/client/chunks/useDirtyStateTracking-MbpxH_v6.js.map +1 -1
  99. package/dist/client/chunks/useExplainAI-evnZkjCY.js.map +1 -1
  100. package/dist/client/chunks/utils-3P6z1vz5.js.map +1 -1
  101. package/dist/client/client/BatchCoordinator.d.ts +1 -1
  102. package/dist/client/client/CubeClient.d.ts +1 -1
  103. package/dist/client/components/AIAssistant/index.d.ts +3 -3
  104. package/dist/client/components/AIAssistant/utils.d.ts +1 -1
  105. package/dist/client/components/AgenticNotebook/ChatMessage.d.ts +1 -1
  106. package/dist/client/components/AgenticNotebook/NotebookCanvas.d.ts +1 -1
  107. package/dist/client/components/AgenticNotebook/NotebookMarkdownBlock.d.ts +1 -1
  108. package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +2 -2
  109. package/dist/client/components/AgenticNotebook/chatMessageParts.d.ts +1 -1
  110. package/dist/client/components/AgenticNotebook/index.d.ts +2 -2
  111. package/dist/client/components/AgenticNotebook/useAgentChatController.d.ts +1 -1
  112. package/dist/client/components/AgenticNotebook/useNotebookAutosave.d.ts +1 -1
  113. package/dist/client/components/AnalysisBuilder/AnalysisAxisDropZone.d.ts +1 -1
  114. package/dist/client/components/AnalysisBuilder/AnalysisChartConfigPanel.d.ts +4 -4
  115. package/dist/client/components/AnalysisBuilder/AnalysisDisplayConfigPanel.d.ts +1 -1
  116. package/dist/client/components/AnalysisBuilder/AnalysisFilterGroup.d.ts +2 -2
  117. package/dist/client/components/AnalysisBuilder/AnalysisFilterItem.d.ts +2 -2
  118. package/dist/client/components/AnalysisBuilder/AnalysisFilterSection.d.ts +2 -2
  119. package/dist/client/components/AnalysisBuilder/AnalysisModeErrorBoundary.d.ts +1 -1
  120. package/dist/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +1 -1
  121. package/dist/client/components/AnalysisBuilder/AnalysisQueryPanelParts.d.ts +3 -3
  122. package/dist/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +1 -1
  123. package/dist/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +1 -1
  124. package/dist/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +1 -1
  125. package/dist/client/components/AnalysisBuilder/BreakdownRow.d.ts +2 -2
  126. package/dist/client/components/AnalysisBuilder/BreakdownSection.d.ts +1 -1
  127. package/dist/client/components/AnalysisBuilder/DisplayOptionControl.d.ts +2 -2
  128. package/dist/client/components/AnalysisBuilder/ExecutionPlanPanel.d.ts +1 -1
  129. package/dist/client/components/AnalysisBuilder/ExecutionPlanPanelParts.d.ts +1 -1
  130. package/dist/client/components/AnalysisBuilder/ExplainAIPanel.d.ts +1 -1
  131. package/dist/client/components/AnalysisBuilder/FieldDetailPanel.d.ts +1 -1
  132. package/dist/client/components/AnalysisBuilder/FieldSearchItem.d.ts +1 -1
  133. package/dist/client/components/AnalysisBuilder/FieldSearchModal.d.ts +1 -1
  134. package/dist/client/components/AnalysisBuilder/FieldSearchResults.d.ts +2 -2
  135. package/dist/client/components/AnalysisBuilder/FilterConfigModal.d.ts +2 -2
  136. package/dist/client/components/AnalysisBuilder/FilterValueInput.d.ts +2 -2
  137. package/dist/client/components/AnalysisBuilder/FlowConfigPanel.d.ts +1 -1
  138. package/dist/client/components/AnalysisBuilder/FlowDepthControls.d.ts +1 -1
  139. package/dist/client/components/AnalysisBuilder/FlowModeContent.d.ts +3 -3
  140. package/dist/client/components/AnalysisBuilder/FlowVisualizationPicker.d.ts +1 -1
  141. package/dist/client/components/AnalysisBuilder/FunnelBindingKeySelector.d.ts +1 -1
  142. package/dist/client/components/AnalysisBuilder/FunnelConfigPanel.d.ts +1 -1
  143. package/dist/client/components/AnalysisBuilder/FunnelModeContent.d.ts +2 -2
  144. package/dist/client/components/AnalysisBuilder/FunnelStepCard.d.ts +1 -1
  145. package/dist/client/components/AnalysisBuilder/FunnelStepList.d.ts +1 -1
  146. package/dist/client/components/AnalysisBuilder/LegacyBooleanOptions.d.ts +1 -1
  147. package/dist/client/components/AnalysisBuilder/MetricItemCard.d.ts +1 -1
  148. package/dist/client/components/AnalysisBuilder/MetricRow.d.ts +2 -2
  149. package/dist/client/components/AnalysisBuilder/MetricsSection.d.ts +1 -1
  150. package/dist/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +2 -2
  151. package/dist/client/components/AnalysisBuilder/RetentionModeContent.d.ts +3 -3
  152. package/dist/client/components/AnalysisBuilder/filterConfigModalUtils.d.ts +2 -2
  153. package/dist/client/components/AnalysisBuilder/hooks/useAnalysisBuilderImperativeHandle.d.ts +2 -2
  154. package/dist/client/components/AnalysisBuilder/hooks/useFieldSearchKeyboard.d.ts +1 -1
  155. package/dist/client/components/AnalysisBuilder/index.d.ts +1 -1
  156. package/dist/client/components/AnalysisBuilder/types.d.ts +28 -28
  157. package/dist/client/components/AnalysisBuilder/utils/axisConfigUtils.d.ts +1 -1
  158. package/dist/client/components/AnalysisBuilder/utils/executionPlanMarkdown.d.ts +2 -2
  159. package/dist/client/components/AnalysisBuilder/utils/fieldUtils.d.ts +2 -2
  160. package/dist/client/components/AnalysisBuilder/utils/filterUtils.d.ts +1 -1
  161. package/dist/client/components/AnalysisBuilder/utils/index.d.ts +6 -6
  162. package/dist/client/components/AnalysisBuilder/utils/queryUtils.d.ts +2 -2
  163. package/dist/client/components/AnalysisBuilder/utils/recentFieldsUtils.d.ts +2 -2
  164. package/dist/client/components/AnalysisBuilder/utils/shareStateUtils.d.ts +16 -16
  165. package/dist/client/components/AnalysisBuilder/utils/storageUtils.d.ts +2 -2
  166. package/dist/client/components/AnalysisBuilderLazy.d.ts +1 -1
  167. package/dist/client/components/AnalyticsDashboard.d.ts +1 -1
  168. package/dist/client/components/AnalyticsPortlet.d.ts +1 -1
  169. package/dist/client/components/ChartTypeSelector.d.ts +2 -2
  170. package/dist/client/components/DashboardFilterPanel.d.ts +1 -1
  171. package/dist/client/components/DashboardFilters/CompactFilterBar.d.ts +1 -1
  172. package/dist/client/components/DashboardFilters/CompactFilterBarParts.d.ts +1 -1
  173. package/dist/client/components/DashboardFilters/DashboardFilterConfigModal.d.ts +2 -2
  174. package/dist/client/components/DashboardFilters/DashboardFilterConfigModalParts.d.ts +2 -2
  175. package/dist/client/components/DashboardFilters/DashboardFilterItem.d.ts +2 -2
  176. package/dist/client/components/DashboardFilters/DashboardFilterValueInput.d.ts +2 -2
  177. package/dist/client/components/DashboardFilters/EditModeFilterList.d.ts +1 -1
  178. package/dist/client/components/DashboardFilters/FilterChip.d.ts +1 -1
  179. package/dist/client/components/DashboardFilters/FilterEditModal.d.ts +2 -2
  180. package/dist/client/components/DashboardFilters/FilterValuePopover.d.ts +1 -1
  181. package/dist/client/components/DashboardFilters/ReadOnlyFilterList.d.ts +2 -2
  182. package/dist/client/components/DashboardFilters/dashboardFilterConfigModalUtils.d.ts +2 -2
  183. package/dist/client/components/DashboardFilters/useCompactFilterBar.d.ts +1 -1
  184. package/dist/client/components/DashboardFilters/useDashboardFilterConfigModal.d.ts +6 -6
  185. package/dist/client/components/DashboardFilters/useDateRangeState.d.ts +2 -2
  186. package/dist/client/components/DashboardFilters/useFilterValueFetch.d.ts +1 -1
  187. package/dist/client/components/DashboardGrid.d.ts +2 -2
  188. package/dist/client/components/DashboardPortletCard.d.ts +1 -1
  189. package/dist/client/components/DebugModal.d.ts +2 -2
  190. package/dist/client/components/DrillBreadcrumb.d.ts +1 -1
  191. package/dist/client/components/DrillMenu.d.ts +1 -1
  192. package/dist/client/components/FloatingEditToolbar.d.ts +1 -1
  193. package/dist/client/components/MobileStackedLayout.d.ts +2 -2
  194. package/dist/client/components/PortletAnalysisModal.d.ts +1 -1
  195. package/dist/client/components/PortletContainer.d.ts +1 -1
  196. package/dist/client/components/PortletFilterConfigModal.d.ts +1 -1
  197. package/dist/client/components/RowManagedLayout.d.ts +1 -1
  198. package/dist/client/components/SchemaVisualization/CubeNode.d.ts +1 -1
  199. package/dist/client/components/SchemaVisualization/FieldDetailPanel.d.ts +1 -1
  200. package/dist/client/components/SchemaVisualization/RelationshipEdge.d.ts +1 -1
  201. package/dist/client/components/SchemaVisualization/SchemaVisualizationLazy.d.ts +1 -1
  202. package/dist/client/components/TextPortletModal.d.ts +2 -2
  203. package/dist/client/components/analyticsPortlet/PortletChart.d.ts +4 -4
  204. package/dist/client/components/analyticsPortlet/PortletChartView.d.ts +5 -5
  205. package/dist/client/components/analyticsPortlet/PortletStates.d.ts +2 -2
  206. package/dist/client/components/analyticsPortlet/parsePortletQuery.d.ts +3 -3
  207. package/dist/client/components/analyticsPortlet/portletRenderState.d.ts +3 -3
  208. package/dist/client/components/analyticsPortlet/usePortletDebugData.d.ts +4 -4
  209. package/dist/client/components/analyticsPortlet/usePortletDrillState.d.ts +2 -2
  210. package/dist/client/components/analyticsPortlet/usePortletQueryResults.d.ts +4 -4
  211. package/dist/client/components/charts/ActivityGridChart.config.d.ts +1 -1
  212. package/dist/client/components/charts/ActivityGridChart.d.ts +1 -1
  213. package/dist/client/components/charts/ActivityGridChart.helpers.d.ts +1 -1
  214. package/dist/client/components/charts/ActivityGridChart.render.d.ts +3 -3
  215. package/dist/client/components/charts/AreaChart.config.d.ts +1 -1
  216. package/dist/client/components/charts/AreaChart.d.ts +1 -1
  217. package/dist/client/components/charts/AxisFormatControls.d.ts +1 -1
  218. package/dist/client/components/charts/BarChart.config.d.ts +1 -1
  219. package/dist/client/components/charts/BarChart.d.ts +1 -1
  220. package/dist/client/components/charts/BarChart.helpers.d.ts +1 -1
  221. package/dist/client/components/charts/BarSeries.d.ts +2 -2
  222. package/dist/client/components/charts/BoxPlotChart.config.d.ts +1 -1
  223. package/dist/client/components/charts/BoxPlotChart.d.ts +1 -1
  224. package/dist/client/components/charts/BubbleChart.config.d.ts +1 -1
  225. package/dist/client/components/charts/BubbleChart.d.ts +1 -1
  226. package/dist/client/components/charts/BubbleChart.helpers.d.ts +1 -1
  227. package/dist/client/components/charts/BubbleChart.render.d.ts +2 -2
  228. package/dist/client/components/charts/CandlestickChart.config.d.ts +1 -1
  229. package/dist/client/components/charts/CandlestickChart.d.ts +1 -1
  230. package/dist/client/components/charts/DataTable.config.d.ts +1 -1
  231. package/dist/client/components/charts/DataTable.d.ts +1 -1
  232. package/dist/client/components/charts/FunnelChart.config.d.ts +1 -1
  233. package/dist/client/components/charts/FunnelChart.d.ts +1 -1
  234. package/dist/client/components/charts/FunnelChart.helpers.d.ts +2 -2
  235. package/dist/client/components/charts/FunnelViews.d.ts +2 -2
  236. package/dist/client/components/charts/GaugeChart.config.d.ts +1 -1
  237. package/dist/client/components/charts/GaugeChart.d.ts +1 -1
  238. package/dist/client/components/charts/HeatMapCanvas.d.ts +1 -1
  239. package/dist/client/components/charts/HeatMapChart.config.d.ts +1 -1
  240. package/dist/client/components/charts/HeatMapChart.d.ts +1 -1
  241. package/dist/client/components/charts/HeatMapChart.helpers.d.ts +1 -1
  242. package/dist/client/components/charts/KpiDelta.config.d.ts +1 -1
  243. package/dist/client/components/charts/KpiDelta.d.ts +1 -1
  244. package/dist/client/components/charts/KpiDelta.helpers.d.ts +1 -1
  245. package/dist/client/components/charts/KpiNumber.config.d.ts +1 -1
  246. package/dist/client/components/charts/KpiNumber.d.ts +1 -1
  247. package/dist/client/components/charts/KpiNumber.helpers.d.ts +1 -1
  248. package/dist/client/components/charts/KpiText.config.d.ts +1 -1
  249. package/dist/client/components/charts/KpiText.d.ts +1 -1
  250. package/dist/client/components/charts/LineChart.config.d.ts +1 -1
  251. package/dist/client/components/charts/LineChart.d.ts +1 -1
  252. package/dist/client/components/charts/MarkdownChart.config.d.ts +1 -1
  253. package/dist/client/components/charts/MarkdownChart.d.ts +1 -1
  254. package/dist/client/components/charts/MeasureProfileChart.config.d.ts +1 -1
  255. package/dist/client/components/charts/MeasureProfileChart.d.ts +1 -1
  256. package/dist/client/components/charts/PieChart.config.d.ts +1 -1
  257. package/dist/client/components/charts/PieChart.d.ts +1 -1
  258. package/dist/client/components/charts/RadarChart.config.d.ts +1 -1
  259. package/dist/client/components/charts/RadarChart.d.ts +1 -1
  260. package/dist/client/components/charts/RadialBarChart.config.d.ts +1 -1
  261. package/dist/client/components/charts/RadialBarChart.d.ts +1 -1
  262. package/dist/client/components/charts/RetentionCombinedChart.config.d.ts +1 -1
  263. package/dist/client/components/charts/RetentionCombinedChart.d.ts +1 -1
  264. package/dist/client/components/charts/RetentionHeatmap.config.d.ts +1 -1
  265. package/dist/client/components/charts/RetentionHeatmap.d.ts +1 -1
  266. package/dist/client/components/charts/SankeyChart.config.d.ts +1 -1
  267. package/dist/client/components/charts/SankeyChart.d.ts +1 -1
  268. package/dist/client/components/charts/ScatterChart.config.d.ts +1 -1
  269. package/dist/client/components/charts/ScatterChart.d.ts +1 -1
  270. package/dist/client/components/charts/ScatterChart.helpers.d.ts +2 -2
  271. package/dist/client/components/charts/ScatterSeries.d.ts +2 -2
  272. package/dist/client/components/charts/ScatterTooltip.d.ts +2 -2
  273. package/dist/client/components/charts/SunburstChart.config.d.ts +1 -1
  274. package/dist/client/components/charts/SunburstChart.d.ts +1 -1
  275. package/dist/client/components/charts/TreeMapChart.config.d.ts +1 -1
  276. package/dist/client/components/charts/TreeMapChart.d.ts +1 -1
  277. package/dist/client/components/charts/TreeMapChart.helpers.d.ts +1 -1
  278. package/dist/client/components/charts/TreeMapContent.d.ts +3 -3
  279. package/dist/client/components/charts/TreeMapLegend.d.ts +2 -2
  280. package/dist/client/components/charts/WaterfallChart.config.d.ts +1 -1
  281. package/dist/client/components/charts/WaterfallChart.d.ts +1 -1
  282. package/dist/client/components/charts/cartesianChartHelpers.d.ts +1 -1
  283. package/dist/client/components/charts/chartAxisResolution.d.ts +1 -1
  284. package/dist/client/components/charts/chartScaffolding.d.ts +1 -1
  285. package/dist/client/components/charts/gaugeChartHelpers.d.ts +1 -1
  286. package/dist/client/components/charts/index.d.ts +21 -21
  287. package/dist/client/components/charts/kpiTextHelpers.d.ts +1 -1
  288. package/dist/client/components/charts/radialBarChartHelpers.d.ts +1 -1
  289. package/dist/client/components/dashboard/DashboardContext.d.ts +6 -6
  290. package/dist/client/components/dashboard/DashboardCoordinator.d.ts +1 -1
  291. package/dist/client/components/dashboard/DashboardProvider.d.ts +1 -1
  292. package/dist/client/components/dashboard/dashboardGridUtils.d.ts +1 -1
  293. package/dist/client/components/dashboard/index.d.ts +7 -7
  294. package/dist/client/components/dashboardPortletCard/FilterFieldChip.d.ts +1 -1
  295. package/dist/client/components/dashboardPortletCard/PortletCardHeader.d.ts +2 -2
  296. package/dist/client/components/dashboardPortletCard/cardStyles.d.ts +1 -1
  297. package/dist/client/components/dashboardPortletCard/filterField.d.ts +1 -1
  298. package/dist/client/components/dashboardPortletCard/propsEqual.d.ts +2 -2
  299. package/dist/client/components/dashboardPortletCard/usePortletCardActions.d.ts +1 -1
  300. package/dist/client/components/shared/DateRangeFilter.d.ts +1 -1
  301. package/dist/client/components/shared/FilterBuilder.d.ts +1 -1
  302. package/dist/client/components/shared/FilterGroup.d.ts +1 -1
  303. package/dist/client/components/shared/FilterItem.d.ts +1 -1
  304. package/dist/client/components/shared/FilterValueSelector.d.ts +1 -1
  305. package/dist/client/components/shared/dateRangeUtils.d.ts +1 -1
  306. package/dist/client/components/shared/filterItem/FilterDateRangeSelector.d.ts +1 -1
  307. package/dist/client/components/shared/filterItem/FilterFieldDropdown.d.ts +1 -1
  308. package/dist/client/components/shared/filterItem/dateRangeSync.d.ts +1 -1
  309. package/dist/client/components/shared/filterItem/fieldVisuals.d.ts +1 -1
  310. package/dist/client/components/shared/filterValueSelector/useFilterValueSelectorState.d.ts +2 -2
  311. package/dist/client/components/shared/queryFieldUtils.d.ts +2 -2
  312. package/dist/client/components/shared/types.d.ts +8 -8
  313. package/dist/client/components/shared/utils.d.ts +7 -7
  314. package/dist/client/components.d.ts +11 -11
  315. package/dist/client/hooks/agentChatStream.d.ts +1 -1
  316. package/dist/client/hooks/dashboard/layoutUtils.d.ts +1 -1
  317. package/dist/client/hooks/dashboard/useDashboardController.d.ts +2 -2
  318. package/dist/client/hooks/dashboard/useGridLayoutEngine.d.ts +1 -1
  319. package/dist/client/hooks/dashboard/useRowLayoutEngine.d.ts +1 -1
  320. package/dist/client/hooks/drillNavigation.d.ts +2 -2
  321. package/dist/client/hooks/queries/index.d.ts +9 -9
  322. package/dist/client/hooks/queries/useCubeLoadQuery.d.ts +2 -2
  323. package/dist/client/hooks/queries/useCubeMetaQuery.d.ts +2 -2
  324. package/dist/client/hooks/queries/useDryRunQuery.d.ts +2 -2
  325. package/dist/client/hooks/queries/useExplainAI.d.ts +1 -1
  326. package/dist/client/hooks/queries/useExplainQuery.d.ts +1 -1
  327. package/dist/client/hooks/queries/useFlowQuery.d.ts +1 -1
  328. package/dist/client/hooks/queries/useFunnelQuery.d.ts +1 -1
  329. package/dist/client/hooks/queries/useMultiCubeLoadQuery.d.ts +1 -1
  330. package/dist/client/hooks/queries/useRetentionQuery.d.ts +1 -1
  331. package/dist/client/hooks/useAgentChat.d.ts +1 -1
  332. package/dist/client/hooks/useAnalysisAI.d.ts +4 -4
  333. package/dist/client/hooks/useAnalysisBuilderHook.d.ts +27 -27
  334. package/dist/client/hooks/useAnalysisChartDefaults.d.ts +4 -4
  335. package/dist/client/hooks/useAnalysisCombinedFields.d.ts +2 -2
  336. package/dist/client/hooks/useAnalysisInitialization.d.ts +1 -1
  337. package/dist/client/hooks/useAnalysisQueryBuilder.d.ts +3 -3
  338. package/dist/client/hooks/useAnalysisQueryExecution.d.ts +7 -7
  339. package/dist/client/hooks/useAnalysisShare.d.ts +1 -1
  340. package/dist/client/hooks/useAnalysisUIState.d.ts +2 -2
  341. package/dist/client/hooks/useDashboardHook.d.ts +2 -2
  342. package/dist/client/hooks/useDataBrowser.d.ts +5 -5
  343. package/dist/client/hooks/useDrillInteraction.d.ts +1 -1
  344. package/dist/client/hooks/useTheme.d.ts +1 -1
  345. package/dist/client/hooks/useTranslation.d.ts +1 -1
  346. package/dist/client/hooks.d.ts +11 -11
  347. package/dist/client/icons/defaultIcons.d.ts +1 -1
  348. package/dist/client/icons/index.d.ts +3 -3
  349. package/dist/client/icons/registry.d.ts +1 -1
  350. package/dist/client/index.d.ts +74 -74
  351. package/dist/client/index.js.map +1 -1
  352. package/dist/client/providers/CubeApiProvider.d.ts +3 -3
  353. package/dist/client/providers/CubeFeaturesProvider.d.ts +1 -1
  354. package/dist/client/providers/CubeMetaContext.d.ts +1 -1
  355. package/dist/client/providers/CubeProvider.d.ts +7 -7
  356. package/dist/client/providers/I18nProvider.d.ts +1 -1
  357. package/dist/client/providers.d.ts +4 -4
  358. package/dist/client/schema.d.ts +2 -2
  359. package/dist/client/shared/chartConfigBuilders.d.ts +2 -2
  360. package/dist/client/shared/chartDefaults.d.ts +4 -4
  361. package/dist/client/shared/components/QueryAnalysisPanel.d.ts +1 -1
  362. package/dist/client/shared/components/QueryAnalysisPanel.sections.d.ts +1 -1
  363. package/dist/client/shared/index.d.ts +7 -7
  364. package/dist/client/shared/queryTransforms.d.ts +1 -1
  365. package/dist/client/shared/types.d.ts +1 -1
  366. package/dist/client/shared/utils.d.ts +3 -3
  367. package/dist/client/stores/analysisBuilderStore.d.ts +9 -9
  368. package/dist/client/stores/dashboardStore.d.ts +3 -3
  369. package/dist/client/stores/dataBrowserStore.d.ts +1 -1
  370. package/dist/client/stores/notebookStore.d.ts +1 -1
  371. package/dist/client/stores/optionsToAnalysisConfig.d.ts +4 -4
  372. package/dist/client/stores/slices/coreSlice.d.ts +3 -3
  373. package/dist/client/stores/slices/flowSlice.d.ts +3 -3
  374. package/dist/client/stores/slices/funnelSlice.d.ts +3 -3
  375. package/dist/client/stores/slices/index.d.ts +7 -7
  376. package/dist/client/stores/slices/querySlice.d.ts +3 -3
  377. package/dist/client/stores/slices/retentionSlice.d.ts +3 -3
  378. package/dist/client/stores/slices/uiSlice.d.ts +2 -2
  379. package/dist/client/types/analysisConfig.d.ts +4 -4
  380. package/dist/client/types/drill.d.ts +5 -5
  381. package/dist/client/types/flow.d.ts +2 -2
  382. package/dist/client/types/funnel.d.ts +1 -1
  383. package/dist/client/types/retention.d.ts +2 -2
  384. package/dist/client/types.d.ts +12 -12
  385. package/dist/client/utils/axisValueFormatting.d.ts +1 -1
  386. package/dist/client/utils/chartUtils.d.ts +1 -1
  387. package/dist/client/utils/configMigration.d.ts +2 -2
  388. package/dist/client/utils/drillQueryBuilder.d.ts +2 -2
  389. package/dist/client/utils/exportXlsx.d.ts +2 -2
  390. package/dist/client/utils/filterUtils.d.ts +1 -1
  391. package/dist/client/utils/funnelExecution.d.ts +2 -2
  392. package/dist/client/utils/funnelValidation.d.ts +2 -2
  393. package/dist/client/utils/index.d.ts +10 -10
  394. package/dist/client/utils/joinReachability.d.ts +1 -1
  395. package/dist/client/utils/multiQueryUtils.d.ts +1 -1
  396. package/dist/client/utils/multiQueryValidation.d.ts +1 -1
  397. package/dist/client/utils/pivotUtils.d.ts +1 -1
  398. package/dist/client/utils/shareUtils.d.ts +1 -1
  399. package/dist/client/utils/thumbnail.d.ts +1 -1
  400. package/dist/client/utils.d.ts +2 -2
  401. package/dist/mcp-app/mcp-app.html +33 -33
  402. package/dist/server/{server/adapters → adapters}/base-adapter.d.ts +1 -1
  403. package/dist/server/{server/adapters → adapters}/databend-adapter.d.ts +2 -2
  404. package/dist/server/{server/adapters → adapters}/duckdb-adapter.d.ts +2 -2
  405. package/dist/server/{server/adapters → adapters}/mysql-adapter.d.ts +2 -2
  406. package/dist/server/{server/adapters → adapters}/postgres-adapter.d.ts +2 -2
  407. package/dist/server/{server/adapters → adapters}/singlestore-adapter.d.ts +1 -1
  408. package/dist/server/{server/adapters → adapters}/snowflake-adapter.d.ts +2 -2
  409. package/dist/server/{server/adapters → adapters}/sqlite-adapter.d.ts +2 -2
  410. package/dist/server/{server/adapters → adapters}/window-function-builder.d.ts +1 -1
  411. package/dist/server/{server/agent → agent}/handler-steps.d.ts +3 -3
  412. package/dist/server/{server/agent → agent}/handler.d.ts +3 -3
  413. package/dist/server/agent/index.d.ts +11 -0
  414. package/dist/server/{server/agent → agent}/providers/anthropic.d.ts +1 -1
  415. package/dist/server/{server/agent → agent}/providers/factory.d.ts +1 -1
  416. package/dist/server/{server/agent → agent}/providers/google.d.ts +1 -1
  417. package/dist/server/agent/providers/index.d.ts +6 -0
  418. package/dist/server/{server/agent → agent}/providers/openai.d.ts +1 -1
  419. package/dist/server/{server/agent → agent}/system-prompt.d.ts +1 -1
  420. package/dist/server/{server/agent → agent}/tools.d.ts +4 -4
  421. package/dist/server/{server/agent → agent}/types.d.ts +1 -1
  422. package/dist/server/{server/ai → ai}/discovery-helpers.d.ts +1 -1
  423. package/dist/server/{server/ai → ai}/discovery.d.ts +2 -2
  424. package/dist/server/{server/ai → ai}/index.d.ts +6 -6
  425. package/dist/server/{server/ai → ai}/suggestion-helpers.d.ts +1 -1
  426. package/dist/server/{server/ai → ai}/suggestion.d.ts +2 -2
  427. package/dist/server/{server/ai → ai}/validation-helpers.d.ts +4 -4
  428. package/dist/server/{server/ai → ai}/validation.d.ts +2 -2
  429. package/dist/server/{server/builders → builders}/analysis-utils.d.ts +1 -1
  430. package/dist/server/{server/builders → builders}/comparison-query-builder.d.ts +2 -2
  431. package/dist/server/{server/builders → builders}/cte-builder.d.ts +2 -2
  432. package/dist/server/{server/builders → builders}/date-time-builder.d.ts +2 -2
  433. package/dist/server/{server/builders → builders}/date-time-helpers.d.ts +1 -1
  434. package/dist/server/{server/builders → builders}/filter-builder.d.ts +3 -3
  435. package/dist/server/{server/builders → builders}/filter-operators.d.ts +3 -3
  436. package/dist/server/{server/builders → builders}/flow-query-builder.d.ts +4 -4
  437. package/dist/server/{server/builders → builders}/funnel-query-builder.d.ts +3 -3
  438. package/dist/server/{server/builders → builders}/group-by-builder.d.ts +2 -2
  439. package/dist/server/builders/index.d.ts +13 -0
  440. package/dist/server/{server/builders → builders}/measure-builder.d.ts +3 -3
  441. package/dist/server/{server/builders → builders}/retention-query-builder.d.ts +3 -3
  442. package/dist/server/cache-providers/index.d.ts +5 -0
  443. package/dist/server/{server/cache-providers → cache-providers}/memory.d.ts +1 -1
  444. package/dist/server/{server/cache-utils.d.ts → cache-utils.d.ts} +1 -1
  445. package/dist/server/{server/compiler-metadata.d.ts → compiler-metadata.d.ts} +1 -1
  446. package/dist/server/{server/compiler.d.ts → compiler.d.ts} +3 -3
  447. package/dist/server/{server/cube-utils.d.ts → cube-utils.d.ts} +1 -1
  448. package/dist/server/{server/database-utils.d.ts → database-utils.d.ts} +1 -1
  449. package/dist/server/{server/execution → execution}/annotation-builder.d.ts +1 -1
  450. package/dist/server/{server/execution → execution}/filter-cache-preloader.d.ts +3 -3
  451. package/dist/server/{server/execution → execution}/mode-router.d.ts +5 -5
  452. package/dist/server/{server/execution → execution}/query-result-cache.d.ts +1 -1
  453. package/dist/server/{server/execution → execution}/result-post-processor.d.ts +2 -2
  454. package/dist/server/{server/executor.d.ts → executor.d.ts} +3 -3
  455. package/dist/server/{server/executors → executors}/base-executor.d.ts +2 -2
  456. package/dist/server/{server/executors → executors}/databend-executor.d.ts +2 -2
  457. package/dist/server/{server/executors → executors}/duckdb-executor.d.ts +2 -2
  458. package/dist/server/{server/executors → executors}/index.d.ts +9 -9
  459. package/dist/server/{server/executors → executors}/mysql-executor.d.ts +2 -2
  460. package/dist/server/{server/executors → executors}/postgres-executor.d.ts +2 -2
  461. package/dist/server/{server/executors → executors}/singlestore-executor.d.ts +2 -2
  462. package/dist/server/{server/executors → executors}/snowflake-executor.d.ts +2 -2
  463. package/dist/server/{server/executors → executors}/sqlite-executor.d.ts +2 -2
  464. package/dist/server/{server/explain → explain}/databend-parser.d.ts +1 -1
  465. package/dist/server/{server/explain → explain}/duckdb-parser.d.ts +1 -1
  466. package/dist/server/{server/explain → explain}/explain-tree.d.ts +1 -1
  467. package/dist/server/explain/index.d.ts +9 -0
  468. package/dist/server/{server/explain → explain}/mysql-parser.d.ts +1 -1
  469. package/dist/server/{server/explain → explain}/postgres-parser.d.ts +1 -1
  470. package/dist/server/{server/explain → explain}/snowflake-parser.d.ts +1 -1
  471. package/dist/server/{server/explain → explain}/sqlite-parser.d.ts +1 -1
  472. package/dist/server/{server/filter-cache.d.ts → filter-cache.d.ts} +1 -1
  473. package/dist/server/{server/gap-filler.d.ts → gap-filler.d.ts} +2 -2
  474. package/dist/server/index.d.ts +38 -2
  475. package/dist/server/{server/logical-plan → logical-plan}/cte-planner-helpers.d.ts +1 -1
  476. package/dist/server/{server/logical-plan → logical-plan}/cte-planner.d.ts +4 -4
  477. package/dist/server/{server/logical-plan → logical-plan}/filter-propagation.d.ts +1 -1
  478. package/dist/server/{server/logical-plan → logical-plan}/index.d.ts +11 -11
  479. package/dist/server/{server/logical-plan → logical-plan}/join-planner.d.ts +3 -3
  480. package/dist/server/{server/logical-plan → logical-plan}/logical-plan-builder.d.ts +5 -5
  481. package/dist/server/{server/logical-plan → logical-plan}/logical-planner.d.ts +2 -2
  482. package/dist/server/{server/logical-plan → logical-plan}/optimiser.d.ts +1 -1
  483. package/dist/server/{server/logical-plan → logical-plan}/plan-analysis-reporter.d.ts +2 -2
  484. package/dist/server/{server/logical-plan → logical-plan}/planner-utils.d.ts +2 -2
  485. package/dist/server/{server/logical-plan → logical-plan}/types.d.ts +3 -3
  486. package/dist/server/{server/measure-classification.d.ts → measure-classification.d.ts} +1 -1
  487. package/dist/server/{server/physical-plan → physical-plan}/drizzle-plan-builder.d.ts +5 -5
  488. package/dist/server/{server/physical-plan → physical-plan}/drizzle-sql-builder.d.ts +3 -3
  489. package/dist/server/physical-plan/index.d.ts +2 -0
  490. package/dist/server/{server/physical-plan → physical-plan}/processors/cte-processor.d.ts +2 -2
  491. package/dist/server/physical-plan/processors/index.d.ts +8 -0
  492. package/dist/server/{server/physical-plan → physical-plan}/processors/joins-processor.d.ts +2 -2
  493. package/dist/server/{server/physical-plan → physical-plan}/processors/keys-dedup-processor.d.ts +2 -2
  494. package/dist/server/{server/physical-plan → physical-plan}/processors/multi-fact-processor.d.ts +2 -2
  495. package/dist/server/{server/physical-plan → physical-plan}/processors/predicates-processor.d.ts +2 -2
  496. package/dist/server/{server/physical-plan → physical-plan}/processors/selection-processor.d.ts +2 -2
  497. package/dist/server/{server/physical-plan → physical-plan}/processors/shared.d.ts +4 -4
  498. package/dist/server/{server/physical-plan → physical-plan}/processors/window-processor.d.ts +2 -2
  499. package/dist/server/{server/query-handlers.d.ts → query-handlers.d.ts} +3 -3
  500. package/dist/server/{server/query-modes.d.ts → query-modes.d.ts} +1 -1
  501. package/dist/server/{server/query-validator.d.ts → query-validator.d.ts} +1 -1
  502. package/dist/server/{server/resolvers → resolvers}/calculated-measure-resolver.d.ts +1 -1
  503. package/dist/server/{server/resolvers → resolvers}/index.d.ts +2 -2
  504. package/dist/server/{server/resolvers → resolvers}/join-path-resolver.d.ts +1 -1
  505. package/dist/server/{server/template-substitution.d.ts → template-substitution.d.ts} +1 -1
  506. package/dist/server/{server/types → types}/cache.d.ts +1 -1
  507. package/dist/server/{server/types → types}/cube.d.ts +4 -4
  508. package/dist/server/{server/types → types}/executor.d.ts +2 -2
  509. package/dist/server/{server/types → types}/flow.d.ts +2 -2
  510. package/dist/server/{server/types → types}/funnel.d.ts +1 -1
  511. package/dist/server/types/index.d.ts +11 -0
  512. package/dist/server/{server/types → types}/metadata.d.ts +1 -1
  513. package/dist/server/{server/types → types}/query.d.ts +4 -4
  514. package/dist/server/{server/types → types}/retention.d.ts +1 -1
  515. package/dist/server/{server/types → types}/utils.d.ts +1 -1
  516. package/package.json +12 -4
  517. package/dist/adapters/mcp-transport-Chiaj4ll.cjs +0 -40
  518. package/dist/adapters/mcp-transport-H96VG3WY.js +0 -591
  519. package/dist/server/server/agent/index.d.ts +0 -11
  520. package/dist/server/server/agent/providers/index.d.ts +0 -6
  521. package/dist/server/server/builders/index.d.ts +0 -13
  522. package/dist/server/server/cache-providers/index.d.ts +0 -5
  523. package/dist/server/server/explain/index.d.ts +0 -9
  524. package/dist/server/server/index.d.ts +0 -38
  525. package/dist/server/server/physical-plan/index.d.ts +0 -2
  526. package/dist/server/server/physical-plan/processors/index.d.ts +0 -8
  527. package/dist/server/server/types/index.d.ts +0 -11
  528. /package/dist/server/{server/agent → agent}/chart-validation.d.ts +0 -0
  529. /package/dist/server/{server/agent → agent}/providers/types.d.ts +0 -0
  530. /package/dist/server/{server/ai → ai}/mcp-prompts.d.ts +0 -0
  531. /package/dist/server/{server/ai → ai}/query-schema.d.ts +0 -0
  532. /package/dist/server/{server/ai → ai}/schemas.d.ts +0 -0
  533. /package/dist/server/{server/executors → executors}/explain-utils.d.ts +0 -0
  534. /package/dist/server/{server/prompts → prompts}/explain-analysis-prompt.d.ts +0 -0
  535. /package/dist/server/{server/prompts → prompts}/index.d.ts +0 -0
  536. /package/dist/server/{server/prompts → prompts}/single-step-prompt.d.ts +0 -0
  537. /package/dist/server/{server/prompts → prompts}/step0-validation-prompt.d.ts +0 -0
  538. /package/dist/server/{server/prompts → prompts}/step1-shape-prompt.d.ts +0 -0
  539. /package/dist/server/{server/prompts → prompts}/step2-complete-prompt.d.ts +0 -0
  540. /package/dist/server/{server/prompts → prompts}/types.d.ts +0 -0
  541. /package/dist/server/{server/sql-format.d.ts → sql-format.d.ts} +0 -0
  542. /package/dist/server/{server/types → types}/analysis.d.ts +0 -0
  543. /package/dist/server/{server/types → types}/core.d.ts +0 -0
  544. /package/dist/server/{server/types → types}/validation.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"chart-box-plot-kkBixZ27.js","names":[],"sources":["../../../src/client/components/charts/BoxPlotChart.tsx"],"sourcesContent":["import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { CHART_COLORS } from '../../utils/chartConstants'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport type { ChartProps } from '../../types'\n\nconst MAX_BOXES = 50\n\ninterface BoxStats {\n label: string\n min: number\n q1: number\n median: number\n q3: number\n max: number\n color: string\n}\n\nfunction parseNumeric(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nfunction buildFrom5Measures(\n row: Record<string, unknown>,\n minField: string,\n q1Field: string,\n medianField: string,\n q3Field: string,\n maxField: string,\n label: string,\n color: string\n): BoxStats | null {\n const min = parseNumeric(row[minField])\n const q1 = parseNumeric(row[q1Field])\n const median = parseNumeric(row[medianField])\n const q3 = parseNumeric(row[q3Field])\n const max = parseNumeric(row[maxField])\n if (min === null || q1 === null || median === null || q3 === null || max === null) return null\n return { label, min, q1, median, q3, max, color }\n}\n\n/** Build approximate box stats assuming normality: Q1/Q3 at ±1σ, whiskers at ±2σ */\nfunction buildFrom3Measures(\n row: Record<string, unknown>,\n avgField: string,\n stddevField: string,\n medianField: string,\n label: string,\n color: string\n): BoxStats | null {\n const avg = parseNumeric(row[avgField])\n const sd = parseNumeric(row[stddevField])\n const median = parseNumeric(row[medianField])\n if (avg === null || sd === null || median === null) return null\n const absSd = Math.abs(sd)\n return {\n label,\n min: avg - 2 * absSd,\n q1: avg - absSd,\n median,\n q3: avg + absSd,\n max: avg + 2 * absSd,\n color,\n }\n}\n\nfunction BoxElement({\n x,\n boxWidth,\n minY,\n q1Y,\n medianY,\n q3Y,\n maxY,\n color,\n label,\n}: {\n x: number\n boxWidth: number\n minY: number\n q1Y: number\n medianY: number\n q3Y: number\n maxY: number\n color: string\n label: string\n}) {\n const halfWidth = boxWidth / 2\n const whiskerX = x\n const capWidth = boxWidth * 0.4\n\n return (\n <g data-testid={`box-${label}`}>\n {/* Whisker line (min to max) */}\n <line x1={whiskerX} y1={minY} x2={whiskerX} y2={maxY} stroke={color} strokeWidth={1.5} />\n {/* Min cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={minY}\n x2={whiskerX + capWidth / 2}\n y2={minY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Max cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={maxY}\n x2={whiskerX + capWidth / 2}\n y2={maxY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* IQR Box (Q1 to Q3) */}\n <rect\n x={whiskerX - halfWidth}\n y={Math.min(q1Y, q3Y)}\n width={boxWidth}\n height={Math.abs(q3Y - q1Y) || 2}\n fill={color}\n fillOpacity={0.3}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Median line */}\n <line\n x1={whiskerX - halfWidth}\n y1={medianY}\n x2={whiskerX + halfWidth}\n y2={medianY}\n stroke={color}\n strokeWidth={2.5}\n data-testid={`median-${label}`}\n />\n </g>\n )\n}\n\nfunction YAxis({\n scale,\n domainMin,\n domainMax,\n width,\n tickCount = 5,\n format,\n}: {\n scale: (v: number) => number\n domainMin: number\n domainMax: number\n width: number\n tickCount?: number\n format?: (v: number) => string\n}) {\n const ticks = useMemo(() => {\n const range = domainMax - domainMin\n if (range === 0) return [domainMin]\n const step = range / (tickCount - 1)\n return Array.from({ length: tickCount }, (_, i) => domainMin + i * step)\n }, [domainMin, domainMax, tickCount])\n\n return (\n <g data-testid=\"y-axis\">\n {ticks.map((tick, i) => (\n <g key={i} transform={`translate(0, ${scale(tick)})`}>\n <line x1={0} x2={-6} stroke=\"currentColor\" strokeWidth={1} />\n <text\n x={-10}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n >\n {format ? format(tick) : tick.toLocaleString()}\n </text>\n <line x1={0} x2={width} stroke=\"currentColor\" strokeOpacity={0.1} strokeWidth={1} />\n </g>\n ))}\n <line y1={scale(ticks[0])} y2={scale(ticks[ticks.length - 1])} stroke=\"currentColor\" strokeWidth={1} />\n </g>\n )\n}\n\nconst BoxPlotChart = React.memo(function BoxPlotChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n colorPalette,\n onDataPointClick,\n drillEnabled,\n}: ChartProps) {\n const { t } = useTranslation()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const { xField, mode, fields, configError } = useMemo(() => {\n const xField = Array.isArray(chartConfig?.xAxis)\n ? chartConfig.xAxis[0]\n : chartConfig?.xAxis ?? chartConfig?.x\n\n const yAxisFields: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n if (!xField || yAxisFields.length === 0) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires an X-Axis dimension and at least one measure in Y-Axis',\n }\n }\n\n // 5-measure mode: yAxis = [min, q1, median, q3, max]\n if (yAxisFields.length >= 5) {\n return {\n xField,\n mode: '5measure' as const,\n fields: {\n minField: yAxisFields[0],\n q1Field: yAxisFields[1],\n medianField: yAxisFields[2],\n q3Field: yAxisFields[3],\n maxField: yAxisFields[4],\n },\n configError: null,\n }\n }\n\n // 3-measure mode: yAxis = [avg, stddev, median]\n if (yAxisFields.length >= 3) {\n return {\n xField,\n mode: '3measure' as const,\n fields: {\n avgField: yAxisFields[0],\n stddevField: yAxisFields[1],\n medianField: yAxisFields[2],\n },\n configError: null,\n }\n }\n\n if (yAxisFields.length === 2) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires 1 measure (auto), 3 (avg/stddev/median), or 5 (min/q1/median/q3/max)',\n }\n }\n\n // Auto mode: use yAxis[0] as the value field (treated as median/value)\n return {\n xField,\n mode: 'auto' as const,\n fields: { valueField: yAxisFields[0] },\n configError: null,\n }\n }, [chartConfig])\n\n const boxes: BoxStats[] = useMemo(() => {\n if (configError || !data || data.length === 0 || mode === 'none') return []\n const rows = (data as Record<string, unknown>[]).slice(0, MAX_BOXES)\n const palette = colorPalette?.colors ?? CHART_COLORS\n\n const results: BoxStats[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const label = xField ? String(row[xField] ?? `Row ${i + 1}`) : `Row ${i + 1}`\n const color = palette[i % palette.length]\n\n let box: BoxStats | null = null\n if (mode === '5measure') {\n box = buildFrom5Measures(\n row,\n fields.minField!,\n fields.q1Field!,\n fields.medianField!,\n fields.q3Field!,\n fields.maxField!,\n label,\n color\n )\n } else if (mode === '3measure') {\n box = buildFrom3Measures(row, fields.avgField!, fields.stddevField!, fields.medianField!, label, color)\n } else {\n // Auto: use value as median, build minimal box (value ± 0)\n const v = parseNumeric(row[fields.valueField!])\n if (v !== null) {\n box = { label, min: v, q1: v, median: v, q3: v, max: v, color }\n }\n }\n if (box) results.push(box)\n }\n return results\n }, [data, xField, mode, fields, colorPalette, configError])\n\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.boxPlot')}</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\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 <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n if (boxes.length === 0) {\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('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noValidDataHint.boxPlot')}\n </div>\n </div>\n </div>\n )\n }\n\n try {\n const margin = { top: 20, right: 20, bottom: 60, left: 60 }\n const containerWidth = dimensions.width || 600\n const containerHeight = typeof height === 'number' ? height : (dimensions.height || 400)\n const innerWidth = Math.max(containerWidth - margin.left - margin.right, 50)\n const innerHeight = Math.max(containerHeight - margin.top - margin.bottom, 50)\n\n const allValues = boxes.flatMap((b) => [b.min, b.max])\n const rawMin = Math.min(...allValues)\n const rawMax = Math.max(...allValues)\n const padding = (rawMax - rawMin) * 0.1 || 1\n const domainMin = rawMin - padding\n const domainMax = rawMax + padding\n\n const domainRange = domainMax - domainMin\n const yScale = (v: number) =>\n domainRange === 0 ? innerHeight / 2 : innerHeight - ((v - domainMin) / domainRange) * innerHeight\n\n const boxSpacing = innerWidth / boxes.length\n const boxWidth = Math.min(boxSpacing * 0.6, 40)\n\n const isTruncated = (data as unknown[]).length > MAX_BOXES\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height={isTruncated ? `calc(100% - 20px)` : '100%'}\n viewBox={`0 0 ${containerWidth} ${typeof containerHeight === 'number' ? containerHeight : 400}`}\n preserveAspectRatio=\"none\"\n data-testid=\"boxplot-svg\"\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n <YAxis\n scale={yScale}\n domainMin={domainMin}\n domainMax={domainMax}\n width={innerWidth}\n tickCount={5}\n format={yAxisFormat ? (v) => formatAxisValue(v, yAxisFormat) : undefined}\n />\n\n {boxes.map((box, i) => {\n const cx = boxSpacing * i + boxSpacing / 2\n return (\n <g\n key={`${box.label}-${i}`}\n onClick={(event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled) {\n onDataPointClick({\n dataPoint: { ...box },\n clickedField: xField ?? '',\n xValue: box.label,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event,\n })\n }\n }}\n cursor={drillEnabled ? 'pointer' : undefined}\n >\n <title>{`${box.label}: min=${box.min}, Q1=${box.q1}, median=${box.median}, Q3=${box.q3}, max=${box.max}`}</title>\n <BoxElement\n x={cx}\n boxWidth={boxWidth}\n minY={yScale(box.min)}\n q1Y={yScale(box.q1)}\n medianY={yScale(box.median)}\n q3Y={yScale(box.q3)}\n maxY={yScale(box.max)}\n color={box.color}\n label={box.label}\n />\n <text\n x={cx}\n y={innerHeight + 20}\n textAnchor=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid={`x-label-${box.label}`}\n >\n {box.label}\n </text>\n </g>\n )\n })}\n </g>\n </svg>\n {isTruncated && (\n <div className=\"dc:text-xs text-dc-warning dc:text-center dc:mt-1\">\n {t('chart.runtime.boxPlot.truncated', {\n max: MAX_BOXES,\n total: (data as unknown[]).length\n })}\n </div>\n )}\n </div>\n )\n } catch (error) {\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: 'Box Plot Chart' })}</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})\n\nexport default BoxPlotChart\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-box-plot-kkBixZ27.js","names":[],"sources":["../../../src/client/components/charts/BoxPlotChart.tsx"],"sourcesContent":["import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { CHART_COLORS } from '../../utils/chartConstants.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport type { ChartProps } from '../../types.js'\n\nconst MAX_BOXES = 50\n\ninterface BoxStats {\n label: string\n min: number\n q1: number\n median: number\n q3: number\n max: number\n color: string\n}\n\nfunction parseNumeric(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nfunction buildFrom5Measures(\n row: Record<string, unknown>,\n minField: string,\n q1Field: string,\n medianField: string,\n q3Field: string,\n maxField: string,\n label: string,\n color: string\n): BoxStats | null {\n const min = parseNumeric(row[minField])\n const q1 = parseNumeric(row[q1Field])\n const median = parseNumeric(row[medianField])\n const q3 = parseNumeric(row[q3Field])\n const max = parseNumeric(row[maxField])\n if (min === null || q1 === null || median === null || q3 === null || max === null) return null\n return { label, min, q1, median, q3, max, color }\n}\n\n/** Build approximate box stats assuming normality: Q1/Q3 at ±1σ, whiskers at ±2σ */\nfunction buildFrom3Measures(\n row: Record<string, unknown>,\n avgField: string,\n stddevField: string,\n medianField: string,\n label: string,\n color: string\n): BoxStats | null {\n const avg = parseNumeric(row[avgField])\n const sd = parseNumeric(row[stddevField])\n const median = parseNumeric(row[medianField])\n if (avg === null || sd === null || median === null) return null\n const absSd = Math.abs(sd)\n return {\n label,\n min: avg - 2 * absSd,\n q1: avg - absSd,\n median,\n q3: avg + absSd,\n max: avg + 2 * absSd,\n color,\n }\n}\n\nfunction BoxElement({\n x,\n boxWidth,\n minY,\n q1Y,\n medianY,\n q3Y,\n maxY,\n color,\n label,\n}: {\n x: number\n boxWidth: number\n minY: number\n q1Y: number\n medianY: number\n q3Y: number\n maxY: number\n color: string\n label: string\n}) {\n const halfWidth = boxWidth / 2\n const whiskerX = x\n const capWidth = boxWidth * 0.4\n\n return (\n <g data-testid={`box-${label}`}>\n {/* Whisker line (min to max) */}\n <line x1={whiskerX} y1={minY} x2={whiskerX} y2={maxY} stroke={color} strokeWidth={1.5} />\n {/* Min cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={minY}\n x2={whiskerX + capWidth / 2}\n y2={minY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Max cap */}\n <line\n x1={whiskerX - capWidth / 2}\n y1={maxY}\n x2={whiskerX + capWidth / 2}\n y2={maxY}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* IQR Box (Q1 to Q3) */}\n <rect\n x={whiskerX - halfWidth}\n y={Math.min(q1Y, q3Y)}\n width={boxWidth}\n height={Math.abs(q3Y - q1Y) || 2}\n fill={color}\n fillOpacity={0.3}\n stroke={color}\n strokeWidth={1.5}\n />\n {/* Median line */}\n <line\n x1={whiskerX - halfWidth}\n y1={medianY}\n x2={whiskerX + halfWidth}\n y2={medianY}\n stroke={color}\n strokeWidth={2.5}\n data-testid={`median-${label}`}\n />\n </g>\n )\n}\n\nfunction YAxis({\n scale,\n domainMin,\n domainMax,\n width,\n tickCount = 5,\n format,\n}: {\n scale: (v: number) => number\n domainMin: number\n domainMax: number\n width: number\n tickCount?: number\n format?: (v: number) => string\n}) {\n const ticks = useMemo(() => {\n const range = domainMax - domainMin\n if (range === 0) return [domainMin]\n const step = range / (tickCount - 1)\n return Array.from({ length: tickCount }, (_, i) => domainMin + i * step)\n }, [domainMin, domainMax, tickCount])\n\n return (\n <g data-testid=\"y-axis\">\n {ticks.map((tick, i) => (\n <g key={i} transform={`translate(0, ${scale(tick)})`}>\n <line x1={0} x2={-6} stroke=\"currentColor\" strokeWidth={1} />\n <text\n x={-10}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n >\n {format ? format(tick) : tick.toLocaleString()}\n </text>\n <line x1={0} x2={width} stroke=\"currentColor\" strokeOpacity={0.1} strokeWidth={1} />\n </g>\n ))}\n <line y1={scale(ticks[0])} y2={scale(ticks[ticks.length - 1])} stroke=\"currentColor\" strokeWidth={1} />\n </g>\n )\n}\n\nconst BoxPlotChart = React.memo(function BoxPlotChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n colorPalette,\n onDataPointClick,\n drillEnabled,\n}: ChartProps) {\n const { t } = useTranslation()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const { xField, mode, fields, configError } = useMemo(() => {\n const xField = Array.isArray(chartConfig?.xAxis)\n ? chartConfig.xAxis[0]\n : chartConfig?.xAxis ?? chartConfig?.x\n\n const yAxisFields: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n if (!xField || yAxisFields.length === 0) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires an X-Axis dimension and at least one measure in Y-Axis',\n }\n }\n\n // 5-measure mode: yAxis = [min, q1, median, q3, max]\n if (yAxisFields.length >= 5) {\n return {\n xField,\n mode: '5measure' as const,\n fields: {\n minField: yAxisFields[0],\n q1Field: yAxisFields[1],\n medianField: yAxisFields[2],\n q3Field: yAxisFields[3],\n maxField: yAxisFields[4],\n },\n configError: null,\n }\n }\n\n // 3-measure mode: yAxis = [avg, stddev, median]\n if (yAxisFields.length >= 3) {\n return {\n xField,\n mode: '3measure' as const,\n fields: {\n avgField: yAxisFields[0],\n stddevField: yAxisFields[1],\n medianField: yAxisFields[2],\n },\n configError: null,\n }\n }\n\n if (yAxisFields.length === 2) {\n return {\n xField,\n mode: 'none' as const,\n fields: {},\n configError: 'BoxPlot requires 1 measure (auto), 3 (avg/stddev/median), or 5 (min/q1/median/q3/max)',\n }\n }\n\n // Auto mode: use yAxis[0] as the value field (treated as median/value)\n return {\n xField,\n mode: 'auto' as const,\n fields: { valueField: yAxisFields[0] },\n configError: null,\n }\n }, [chartConfig])\n\n const boxes: BoxStats[] = useMemo(() => {\n if (configError || !data || data.length === 0 || mode === 'none') return []\n const rows = (data as Record<string, unknown>[]).slice(0, MAX_BOXES)\n const palette = colorPalette?.colors ?? CHART_COLORS\n\n const results: BoxStats[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const label = xField ? String(row[xField] ?? `Row ${i + 1}`) : `Row ${i + 1}`\n const color = palette[i % palette.length]\n\n let box: BoxStats | null = null\n if (mode === '5measure') {\n box = buildFrom5Measures(\n row,\n fields.minField!,\n fields.q1Field!,\n fields.medianField!,\n fields.q3Field!,\n fields.maxField!,\n label,\n color\n )\n } else if (mode === '3measure') {\n box = buildFrom3Measures(row, fields.avgField!, fields.stddevField!, fields.medianField!, label, color)\n } else {\n // Auto: use value as median, build minimal box (value ± 0)\n const v = parseNumeric(row[fields.valueField!])\n if (v !== null) {\n box = { label, min: v, q1: v, median: v, q3: v, max: v, color }\n }\n }\n if (box) results.push(box)\n }\n return results\n }, [data, xField, mode, fields, colorPalette, configError])\n\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.boxPlot')}</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\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 <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n\n if (boxes.length === 0) {\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('chart.runtime.noValidData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">\n {t('chart.runtime.noValidDataHint.boxPlot')}\n </div>\n </div>\n </div>\n )\n }\n\n try {\n const margin = { top: 20, right: 20, bottom: 60, left: 60 }\n const containerWidth = dimensions.width || 600\n const containerHeight = typeof height === 'number' ? height : (dimensions.height || 400)\n const innerWidth = Math.max(containerWidth - margin.left - margin.right, 50)\n const innerHeight = Math.max(containerHeight - margin.top - margin.bottom, 50)\n\n const allValues = boxes.flatMap((b) => [b.min, b.max])\n const rawMin = Math.min(...allValues)\n const rawMax = Math.max(...allValues)\n const padding = (rawMax - rawMin) * 0.1 || 1\n const domainMin = rawMin - padding\n const domainMax = rawMax + padding\n\n const domainRange = domainMax - domainMin\n const yScale = (v: number) =>\n domainRange === 0 ? innerHeight / 2 : innerHeight - ((v - domainMin) / domainRange) * innerHeight\n\n const boxSpacing = innerWidth / boxes.length\n const boxWidth = Math.min(boxSpacing * 0.6, 40)\n\n const isTruncated = (data as unknown[]).length > MAX_BOXES\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height={isTruncated ? `calc(100% - 20px)` : '100%'}\n viewBox={`0 0 ${containerWidth} ${typeof containerHeight === 'number' ? containerHeight : 400}`}\n preserveAspectRatio=\"none\"\n data-testid=\"boxplot-svg\"\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n <YAxis\n scale={yScale}\n domainMin={domainMin}\n domainMax={domainMax}\n width={innerWidth}\n tickCount={5}\n format={yAxisFormat ? (v) => formatAxisValue(v, yAxisFormat) : undefined}\n />\n\n {boxes.map((box, i) => {\n const cx = boxSpacing * i + boxSpacing / 2\n return (\n <g\n key={`${box.label}-${i}`}\n onClick={(event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled) {\n onDataPointClick({\n dataPoint: { ...box },\n clickedField: xField ?? '',\n xValue: box.label,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event,\n })\n }\n }}\n cursor={drillEnabled ? 'pointer' : undefined}\n >\n <title>{`${box.label}: min=${box.min}, Q1=${box.q1}, median=${box.median}, Q3=${box.q3}, max=${box.max}`}</title>\n <BoxElement\n x={cx}\n boxWidth={boxWidth}\n minY={yScale(box.min)}\n q1Y={yScale(box.q1)}\n medianY={yScale(box.median)}\n q3Y={yScale(box.q3)}\n maxY={yScale(box.max)}\n color={box.color}\n label={box.label}\n />\n <text\n x={cx}\n y={innerHeight + 20}\n textAnchor=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid={`x-label-${box.label}`}\n >\n {box.label}\n </text>\n </g>\n )\n })}\n </g>\n </svg>\n {isTruncated && (\n <div className=\"dc:text-xs text-dc-warning dc:text-center dc:mt-1\">\n {t('chart.runtime.boxPlot.truncated', {\n max: MAX_BOXES,\n total: (data as unknown[]).length\n })}\n </div>\n )}\n </div>\n )\n } catch (error) {\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: 'Box Plot Chart' })}</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})\n\nexport default BoxPlotChart\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-bubble-B2he1--4.js","names":[],"sources":["../../../src/client/hooks/useTheme.ts","../../../src/client/components/charts/BubbleChart.render.ts","../../../src/client/components/charts/BubbleChart.tsx"],"sourcesContent":["/**\n * useTheme - External Theme State Hook\n *\n * Uses React 18's useSyncExternalStore to prevent parent component re-renders.\n * The theme state is stored externally and changes are propagated through\n * a subscribe/notify pattern.\n *\n * This prevents the ThemeToggle component from causing Layout re-renders.\n */\n\nimport { useSyncExternalStore, useCallback } from 'react'\nimport { getTheme, setTheme as setThemeUtil, watchThemeChanges, type Theme } from '../theme'\n\n// External store for theme state\nconst themeStore = {\n listeners: new Set<() => void>(),\n\n subscribe(listener: () => void) {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n },\n\n notify() {\n this.listeners.forEach(listener => listener())\n }\n}\n\n// Watch theme changes from DOM/system and notify subscribers\nwatchThemeChanges(() => {\n themeStore.notify()\n})\n\n/**\n * Hook to access and update theme\n *\n * Returns current theme and a setter function.\n * Only components using this hook will re-render on theme changes.\n */\nexport function useTheme() {\n // Subscribe to external theme store\n const theme = useSyncExternalStore(\n themeStore.subscribe.bind(themeStore),\n getTheme, // Client-side snapshot\n getTheme // Server-side snapshot (SSR)\n )\n\n // Stable setter function\n const setTheme = useCallback((newTheme: Theme) => {\n setThemeUtil(newTheme)\n themeStore.notify()\n }, [])\n\n return { theme, setTheme }\n}\n","/**\n * D3 rendering for BubbleChart, extracted from the component's render effect.\n *\n * The effect orchestrates these pure-ish drawing helpers. Behaviour matches the\n * original inline D3 exactly; only the structure changed (one function per\n * concern) to keep each helper's complexity low.\n */\nimport {\n select,\n scaleLinear,\n scaleSqrt,\n scaleOrdinal,\n scaleQuantize,\n extent,\n max,\n axisBottom,\n axisLeft,\n type Selection,\n type ScaleLinear,\n type ScalePower,\n type ScaleOrdinal,\n type ScaleQuantize\n} from 'd3'\nimport { CHART_COLORS, CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport { resolveThemeColors } from './BubbleChart.helpers'\nimport type { BubbleData, BubbleDisplayOptions, BubbleFields } from './BubbleChart.helpers'\nimport type { ColorPalette, CubeQuery } from '../../types'\n\ntype ColorScale = ScaleOrdinal<string, string> | ScaleQuantize<string>\ntype G = Selection<SVGGElement, unknown, null, undefined>\n\nexport interface BubbleRenderContext {\n svgEl: SVGSVGElement\n bubbleData: BubbleData[]\n fields: BubbleFields\n options: BubbleDisplayOptions\n dimensions: { width: number; height: number }\n queryObject: CubeQuery | undefined\n colorPalette?: ColorPalette\n isDark: boolean\n getFieldLabel: (field: string) => string\n}\n\ninterface ColorScaleResult {\n colorScale: ColorScale\n isNumericColorField: boolean\n uniqueColors: string[]\n}\n\n/** Build the bubble fill colour scale (numeric → quantize, categorical → ordinal). */\nfunction buildColorScale(\n bubbleData: BubbleData[],\n colorFieldName: string | undefined,\n colorPalette: ColorPalette | undefined\n): ColorScaleResult {\n if (colorFieldName && bubbleData.length > 0) {\n const colorValues = bubbleData\n .map((item) => (typeof item.color === 'string' ? parseFloat(item.color) : item.color))\n .filter((val): val is number => !isNaN(val as number))\n const isNumericColorField =\n colorValues.length === bubbleData.length && colorValues.every((val) => typeof val === 'number')\n\n if (isNumericColorField) {\n const colorScale = scaleQuantize<string>()\n .domain([Math.min(...colorValues), Math.max(...colorValues)])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n return { colorScale, isNumericColorField, uniqueColors: [] }\n }\n\n const uniqueColors = [...new Set(bubbleData.map((d) => String(d.color)))]\n const colorScale = scaleOrdinal<string>().domain(uniqueColors).range(colorPalette?.colors || CHART_COLORS)\n return { colorScale, isNumericColorField, uniqueColors }\n }\n\n const colorScale = scaleOrdinal<string>().domain(['default']).range([CHART_COLORS[0]])\n return { colorScale, isNumericColorField: false, uniqueColors: [] }\n}\n\n/** Format an x-axis tick for a time dimension based on its granularity. */\nfunction formatTimeTick(value: number | { valueOf(): number }, granularity: string | undefined): string {\n const date = new Date(value as number)\n if (isNaN(date.getTime())) return String(value)\n const yr = date.getUTCFullYear()\n const mo = String(date.getUTCMonth() + 1).padStart(2, '0')\n const dy = String(date.getUTCDate()).padStart(2, '0')\n switch (granularity?.toLowerCase()) {\n case 'year':\n return String(yr)\n case 'quarter':\n return `${yr}-Q${Math.floor(date.getUTCMonth() / 3) + 1}`\n case 'month':\n return `${yr}-${mo}`\n case 'week':\n case 'day':\n return `${yr}-${mo}-${dy}`\n case 'hour':\n return `${mo}-${dy} ${String(date.getUTCHours()).padStart(2, '0')}:00`\n default:\n return `${yr}-${mo}`\n }\n}\n\n/** Draw the dashed background grid. */\nfunction drawGrid(\n g: G,\n xScale: ScaleLinear<number, number>,\n yScale: ScaleLinear<number, number>,\n width: number,\n chartHeight: number,\n gridColor: string\n) {\n const styleGrid = (grid: G) => {\n grid.selectAll('line').style('stroke', gridColor).style('stroke-dasharray', '3,3').style('opacity', 0.3)\n grid.select('.domain').style('stroke', 'none')\n }\n const xGrid = g\n .append('g')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(axisBottom(xScale).tickSize(-chartHeight).tickFormat(() => '')) as unknown as G\n styleGrid(xGrid)\n const yGrid = g.append('g').call(axisLeft(yScale).tickSize(-width).tickFormat(() => '')) as unknown as G\n styleGrid(yGrid)\n}\n\n/** Draw X and Y axes with labels and theme-aware styling. */\nfunction drawAxes(\n ctx: BubbleRenderContext,\n g: G,\n xScale: ScaleLinear<number, number>,\n yScale: ScaleLinear<number, number>,\n width: number,\n chartHeight: number,\n textColor: string,\n gridColor: string\n) {\n const { fields, options, queryObject, getFieldLabel } = ctx\n const isTimeDimension =\n queryObject?.timeDimensions?.some((td: { dimension: string }) => td.dimension === fields.xAxisField) || false\n const xGranularity = queryObject?.timeDimensions?.find(\n (td: { dimension: string; granularity?: string }) => td.dimension === fields.xAxisField\n )?.granularity\n\n const xAxisGenerator = axisBottom(xScale)\n if (isTimeDimension) {\n xAxisGenerator.tickFormat((d) => formatTimeTick(d as number, xGranularity))\n } else if (options.xAxisFormat) {\n xAxisGenerator.tickFormat((d) => formatAxisValue(d as number, options.xAxisFormat))\n }\n\n const xAxis = g.append('g').attr('transform', `translate(0,${chartHeight})`).call(xAxisGenerator)\n xAxis.selectAll('text').style('fill', textColor)\n xAxis.selectAll('line, path').style('stroke', gridColor)\n xAxis\n .append('text')\n .attr('x', width / 2)\n .attr('y', 35)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(options.xAxisFormat?.label || getFieldLabel(fields.xAxisField))\n\n const yAxisGenerator = axisLeft(yScale)\n if (options.leftYAxisFormat) {\n yAxisGenerator.tickFormat((d) => formatAxisValue(d as number, options.leftYAxisFormat))\n }\n const yAxis = g.append('g').call(yAxisGenerator)\n yAxis.selectAll('text').style('fill', textColor)\n yAxis.selectAll('line, path').style('stroke', gridColor)\n yAxis\n .append('text')\n .attr('transform', 'rotate(-90)')\n .attr('y', -35)\n .attr('x', -chartHeight / 2)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(options.leftYAxisFormat?.label || getFieldLabel(fields.yAxisField))\n}\n\n/** Create the floating HTML tooltip element. */\nfunction createTooltip() {\n return select('body')\n .append('div')\n .attr('class', 'bubble-chart-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n}\n\ntype Tooltip = ReturnType<typeof createTooltip>\ntype Bubbles = Selection<SVGCircleElement, BubbleData, SVGGElement, unknown>\n\n/** Compose the multi-line tooltip HTML for a bubble. */\nfunction bubbleTooltipHtml(ctx: BubbleRenderContext, d: BubbleData): string {\n const { fields, options, getFieldLabel } = ctx\n const fmt = (v: number) => (options.leftYAxisFormat ? formatAxisValue(v, options.leftYAxisFormat) : v)\n return [\n `<strong>${d.series || 'Unknown'}</strong>`,\n `${getFieldLabel(fields.xAxisField)}: ${d.xLabel || (options.xAxisFormat ? formatAxisValue(d.x, options.xAxisFormat) : d.x)}`,\n `${getFieldLabel(fields.yAxisField)}: ${fmt(d.y)}`,\n `${getFieldLabel(fields.sizeFieldName)}: ${fmt(d.size)}`,\n fields.colorFieldName && d.color ? `${getFieldLabel(fields.colorFieldName)}: ${d.color}` : ''\n ]\n .filter(Boolean)\n .join('<br>')\n}\n\n/** Attach hover handlers showing/hiding the tooltip and growing the bubble. */\nfunction attachBubbleHover(\n ctx: BubbleRenderContext,\n bubbles: Bubbles,\n tooltip: Tooltip,\n sizeScale: ScalePower<number, number>\n) {\n bubbles\n .on('mouseover', function (event, d) {\n select(this).transition().duration(200).style('opacity', 1).attr('r', sizeScale(d.size) * 1.1)\n tooltip\n .html(bubbleTooltipHtml(ctx, d))\n .style('left', event.pageX + 10 + 'px')\n .style('top', event.pageY - 10 + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n })\n .on('mousemove', function (event) {\n tooltip.style('left', event.pageX + 10 + 'px').style('top', event.pageY - 10 + 'px')\n })\n .on('mouseout', function (_event, d) {\n select(this).transition().duration(200).style('opacity', ctx.options.bubbleOpacity).attr('r', sizeScale(d.size))\n tooltip.transition().duration(200).style('opacity', 0)\n })\n}\n\n/** Draw the gradient legend for a numeric colour field. */\nfunction drawNumericLegend(\n ctx: BubbleRenderContext,\n svg: Selection<SVGSVGElement, unknown, null, undefined>,\n g: G,\n width: number,\n chartHeight: number,\n textColor: string\n) {\n const { bubbleData, fields, options, colorPalette, getFieldLabel } = ctx\n const legendWidth = 200\n const legendHeight = 20\n const minValue = Math.min(...bubbleData.map((d) => d.color as number))\n const maxValue = Math.max(...bubbleData.map((d) => d.color as number))\n const fmt = (v: number) => (options.leftYAxisFormat ? formatAxisValue(v, options.leftYAxisFormat) : v.toFixed(2))\n\n const legend = g\n .append('g')\n .attr('class', 'color-legend')\n .attr('transform', `translate(${width / 2 - legendWidth / 2}, ${chartHeight + 60})`)\n\n const gradient = svg\n .append('defs')\n .append('linearGradient')\n .attr('id', 'color-scale-gradient')\n .attr('x1', '0%').attr('y1', '0%').attr('x2', '100%').attr('y2', '0%')\n const gradientColors = colorPalette?.gradient || CHART_COLORS_GRADIENT\n gradientColors.forEach((color, i) => {\n gradient.append('stop').attr('offset', `${(i / (gradientColors.length - 1)) * 100}%`).attr('stop-color', color)\n })\n\n legend.append('rect')\n .attr('width', legendWidth).attr('height', legendHeight)\n .style('fill', 'url(#color-scale-gradient)').style('stroke', '#ccc').style('stroke-width', 1)\n legend.append('text')\n .attr('x', 0).attr('y', legendHeight + 15).attr('text-anchor', 'start')\n .style('font-size', '11px').style('fill', textColor).text(fmt(minValue))\n legend.append('text')\n .attr('x', legendWidth).attr('y', legendHeight + 15).attr('text-anchor', 'end')\n .style('font-size', '11px').style('fill', textColor).text(fmt(maxValue))\n legend.append('text')\n .attr('x', legendWidth / 2).attr('y', -5).attr('text-anchor', 'middle')\n .style('font-size', '12px').style('font-weight', 'bold').style('fill', textColor)\n .text(getFieldLabel(fields.colorFieldName!))\n}\n\n/** Draw the categorical legend (one swatch per series) with hover highlighting. */\nfunction drawCategoricalLegend(\n ctx: BubbleRenderContext,\n g: G,\n width: number,\n chartHeight: number,\n textColor: string,\n uniqueColors: string[],\n colorScale: ScaleOrdinal<string, string>,\n bubbles: Bubbles\n) {\n const { fields, options } = ctx\n if (uniqueColors.length === 0) return\n\n const legend = g\n .append('g')\n .attr('class', 'legend')\n .attr('transform', `translate(${width / 2 - (uniqueColors.length * 80) / 2}, ${chartHeight + 60})`)\n\n const legendItem = legend\n .selectAll('.legend-item')\n .data(uniqueColors)\n .enter()\n .append('g')\n .attr('class', 'legend-item')\n .attr('transform', (_d, i) => `translate(${i * 80}, 0)`)\n .style('cursor', 'pointer')\n\n legendItem.append('circle')\n .attr('cx', 5).attr('cy', 5).attr('r', 5)\n .style('fill', (d) => colorScale(d as string)).style('opacity', options.bubbleOpacity)\n legendItem.append('text')\n .attr('x', 15).attr('y', 5).attr('dy', '.35em')\n .style('font-size', '11px').style('fill', textColor).text((d) => String(d))\n\n legendItem\n .on('mouseover', function (_event, legendKey) {\n bubbles.transition().duration(200).style('opacity', (d) =>\n fields.colorFieldName && String(d.color) === legendKey ? 1 : 0.2\n )\n })\n .on('mouseout', function () {\n bubbles.transition().duration(200).style('opacity', options.bubbleOpacity)\n })\n}\n\n/**\n * Render the bubble chart into the given SVG element. Returns a cleanup function\n * that removes the floating tooltip. Returns undefined when there is nothing to draw.\n */\nexport function renderBubbleChart(ctx: BubbleRenderContext): (() => void) | undefined {\n const { svgEl, bubbleData, fields, options, dimensions, colorPalette, isDark } = ctx\n\n select(svgEl).selectAll('*').remove()\n if (bubbleData.length === 0) return undefined\n\n const margin = {\n ...CHART_MARGINS,\n left: CHART_MARGINS.left + 30,\n bottom: options.showLegend && fields.colorFieldName ? 100 : 40\n }\n const width = dimensions.width - margin.left - margin.right\n const chartHeight = dimensions.height - margin.top - margin.bottom\n\n const svg = select(svgEl).attr('width', dimensions.width).attr('height', dimensions.height)\n const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`)\n\n const xScale = scaleLinear().domain(extent(bubbleData, (d) => d.x) as [number, number]).range([0, width]).nice()\n const yScale = scaleLinear().domain(extent(bubbleData, (d) => d.y) as [number, number]).range([chartHeight, 0]).nice()\n const sizeScale = scaleSqrt()\n .domain([0, max(bubbleData, (d) => d.size) as number])\n .range([options.minBubbleSize, options.maxBubbleSize])\n\n const { colorScale, isNumericColorField, uniqueColors } = buildColorScale(\n bubbleData,\n fields.colorFieldName,\n colorPalette\n )\n const { textColor, gridColor } = resolveThemeColors(isDark)\n\n if (options.showGrid) {\n drawGrid(g, xScale, yScale, width, chartHeight, gridColor)\n }\n drawAxes(ctx, g, xScale, yScale, width, chartHeight, textColor, gridColor)\n\n const tooltip = createTooltip()\n\n const bubbles = g\n .selectAll('.bubble')\n .data(bubbleData)\n .enter()\n .append('circle')\n .attr('class', 'bubble')\n .attr('cx', (d) => xScale(d.x))\n .attr('cy', (d) => yScale(d.y))\n .attr('r', (d) => sizeScale(d.size))\n .style('fill', (d) => {\n if (fields.colorFieldName && d.color !== undefined) {\n return isNumericColorField\n ? (colorScale as ScaleQuantize<string>)(d.color as number)\n : (colorScale as ScaleOrdinal<string, string>)(String(d.color))\n }\n return CHART_COLORS[0]\n })\n .style('opacity', options.bubbleOpacity)\n .style('stroke', '#fff')\n .style('stroke-width', 1)\n .style('cursor', 'pointer') as Bubbles\n\n if (options.showTooltip) {\n attachBubbleHover(ctx, bubbles, tooltip, sizeScale)\n }\n\n if (options.showLegend && fields.colorFieldName) {\n if (isNumericColorField) {\n drawNumericLegend(ctx, svg, g, width, chartHeight, textColor)\n } else {\n drawCategoricalLegend(ctx, g, width, chartHeight, textColor, uniqueColors, colorScale as ScaleOrdinal<string, string>, bubbles)\n }\n }\n\n return () => {\n tooltip.remove()\n }\n}\n","import React, { useEffect, useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { transition as _transition } from 'd3'\n// _transition import is for side effects only - it extends Selection.prototype with .transition()\nvoid _transition\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel'\nimport { useTheme } from '../../hooks/useTheme'\nimport { useChartDimensions } from './useChartDimensions'\nimport {\n resolveBubbleDisplayOptions,\n resolveBubbleFields,\n transformBubbleData\n} from './BubbleChart.helpers'\nimport { renderBubbleChart } from './BubbleChart.render'\nimport type { ChartProps } from '../../types'\n\nconst BubbleChart = React.memo(function BubbleChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const { t } = useTranslation()\n const svgRef = React.useRef<SVGSVGElement | null>(null)\n const { containerRef, dimensions, dimensionsReady } = useChartDimensions()\n const { theme } = useTheme()\n const getFieldLabel = useCubeFieldLabel()\n\n // Memoize display options to keep the render effect dependencies stable\n const options = useMemo(() => resolveBubbleDisplayOptions(displayConfig), [displayConfig])\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n const fields = resolveBubbleFields(chartConfig)\n if (!fields) return\n\n const bubbleData = transformBubbleData(data as Record<string, any>[], fields, queryObject)\n\n return renderBubbleChart({\n svgEl: svgRef.current,\n bubbleData,\n fields,\n options,\n dimensions,\n queryObject,\n colorPalette,\n isDark: theme !== 'light',\n getFieldLabel\n })\n }, [data, chartConfig, options, queryObject, dimensions, dimensionsReady, colorPalette, theme, getFieldLabel])\n\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.bubble')}</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.xAxis && chartConfig?.yAxis && chartConfig?.series\n if (!hasValidConfig) {\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.activityGridConfigRequired')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.bubbleRequired')}</div>\n <div className=\"dc:text-xs dc:mt-1\">{t('chart.runtime.configErrorHint.bubbleOptional')}</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:w-full dc:flex-1 dc:flex dc:flex-col dc:relative\" style={{ height, minHeight: '250px', overflow: 'hidden' }}>\n <div ref={containerRef} className=\"dc:w-full dc:h-full dc:relative\">\n <svg ref={svgRef} className=\"dc:w-full dc:h-full\" />\n {!dimensionsReady && (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center\">\n <div className=\"text-dc-text-muted dc:text-sm\">{t('chart.runtime.measuringDimensions')}</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default BubbleChart\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-bubble-B2he1--4.js","names":[],"sources":["../../../src/client/hooks/useTheme.ts","../../../src/client/components/charts/BubbleChart.render.ts","../../../src/client/components/charts/BubbleChart.tsx"],"sourcesContent":["/**\n * useTheme - External Theme State Hook\n *\n * Uses React 18's useSyncExternalStore to prevent parent component re-renders.\n * The theme state is stored externally and changes are propagated through\n * a subscribe/notify pattern.\n *\n * This prevents the ThemeToggle component from causing Layout re-renders.\n */\n\nimport { useSyncExternalStore, useCallback } from 'react'\nimport { getTheme, setTheme as setThemeUtil, watchThemeChanges, type Theme } from '../theme/index.js'\n\n// External store for theme state\nconst themeStore = {\n listeners: new Set<() => void>(),\n\n subscribe(listener: () => void) {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n },\n\n notify() {\n this.listeners.forEach(listener => listener())\n }\n}\n\n// Watch theme changes from DOM/system and notify subscribers\nwatchThemeChanges(() => {\n themeStore.notify()\n})\n\n/**\n * Hook to access and update theme\n *\n * Returns current theme and a setter function.\n * Only components using this hook will re-render on theme changes.\n */\nexport function useTheme() {\n // Subscribe to external theme store\n const theme = useSyncExternalStore(\n themeStore.subscribe.bind(themeStore),\n getTheme, // Client-side snapshot\n getTheme // Server-side snapshot (SSR)\n )\n\n // Stable setter function\n const setTheme = useCallback((newTheme: Theme) => {\n setThemeUtil(newTheme)\n themeStore.notify()\n }, [])\n\n return { theme, setTheme }\n}\n","/**\n * D3 rendering for BubbleChart, extracted from the component's render effect.\n *\n * The effect orchestrates these pure-ish drawing helpers. Behaviour matches the\n * original inline D3 exactly; only the structure changed (one function per\n * concern) to keep each helper's complexity low.\n */\nimport {\n select,\n scaleLinear,\n scaleSqrt,\n scaleOrdinal,\n scaleQuantize,\n extent,\n max,\n axisBottom,\n axisLeft,\n type Selection,\n type ScaleLinear,\n type ScalePower,\n type ScaleOrdinal,\n type ScaleQuantize\n} from 'd3'\nimport { CHART_COLORS, CHART_COLORS_GRADIENT, CHART_MARGINS } from '../../utils/chartConstants.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport { resolveThemeColors } from './BubbleChart.helpers.js'\nimport type { BubbleData, BubbleDisplayOptions, BubbleFields } from './BubbleChart.helpers.js'\nimport type { ColorPalette, CubeQuery } from '../../types.js'\n\ntype ColorScale = ScaleOrdinal<string, string> | ScaleQuantize<string>\ntype G = Selection<SVGGElement, unknown, null, undefined>\n\nexport interface BubbleRenderContext {\n svgEl: SVGSVGElement\n bubbleData: BubbleData[]\n fields: BubbleFields\n options: BubbleDisplayOptions\n dimensions: { width: number; height: number }\n queryObject: CubeQuery | undefined\n colorPalette?: ColorPalette\n isDark: boolean\n getFieldLabel: (field: string) => string\n}\n\ninterface ColorScaleResult {\n colorScale: ColorScale\n isNumericColorField: boolean\n uniqueColors: string[]\n}\n\n/** Build the bubble fill colour scale (numeric → quantize, categorical → ordinal). */\nfunction buildColorScale(\n bubbleData: BubbleData[],\n colorFieldName: string | undefined,\n colorPalette: ColorPalette | undefined\n): ColorScaleResult {\n if (colorFieldName && bubbleData.length > 0) {\n const colorValues = bubbleData\n .map((item) => (typeof item.color === 'string' ? parseFloat(item.color) : item.color))\n .filter((val): val is number => !isNaN(val as number))\n const isNumericColorField =\n colorValues.length === bubbleData.length && colorValues.every((val) => typeof val === 'number')\n\n if (isNumericColorField) {\n const colorScale = scaleQuantize<string>()\n .domain([Math.min(...colorValues), Math.max(...colorValues)])\n .range(colorPalette?.gradient || CHART_COLORS_GRADIENT)\n return { colorScale, isNumericColorField, uniqueColors: [] }\n }\n\n const uniqueColors = [...new Set(bubbleData.map((d) => String(d.color)))]\n const colorScale = scaleOrdinal<string>().domain(uniqueColors).range(colorPalette?.colors || CHART_COLORS)\n return { colorScale, isNumericColorField, uniqueColors }\n }\n\n const colorScale = scaleOrdinal<string>().domain(['default']).range([CHART_COLORS[0]])\n return { colorScale, isNumericColorField: false, uniqueColors: [] }\n}\n\n/** Format an x-axis tick for a time dimension based on its granularity. */\nfunction formatTimeTick(value: number | { valueOf(): number }, granularity: string | undefined): string {\n const date = new Date(value as number)\n if (isNaN(date.getTime())) return String(value)\n const yr = date.getUTCFullYear()\n const mo = String(date.getUTCMonth() + 1).padStart(2, '0')\n const dy = String(date.getUTCDate()).padStart(2, '0')\n switch (granularity?.toLowerCase()) {\n case 'year':\n return String(yr)\n case 'quarter':\n return `${yr}-Q${Math.floor(date.getUTCMonth() / 3) + 1}`\n case 'month':\n return `${yr}-${mo}`\n case 'week':\n case 'day':\n return `${yr}-${mo}-${dy}`\n case 'hour':\n return `${mo}-${dy} ${String(date.getUTCHours()).padStart(2, '0')}:00`\n default:\n return `${yr}-${mo}`\n }\n}\n\n/** Draw the dashed background grid. */\nfunction drawGrid(\n g: G,\n xScale: ScaleLinear<number, number>,\n yScale: ScaleLinear<number, number>,\n width: number,\n chartHeight: number,\n gridColor: string\n) {\n const styleGrid = (grid: G) => {\n grid.selectAll('line').style('stroke', gridColor).style('stroke-dasharray', '3,3').style('opacity', 0.3)\n grid.select('.domain').style('stroke', 'none')\n }\n const xGrid = g\n .append('g')\n .attr('transform', `translate(0,${chartHeight})`)\n .call(axisBottom(xScale).tickSize(-chartHeight).tickFormat(() => '')) as unknown as G\n styleGrid(xGrid)\n const yGrid = g.append('g').call(axisLeft(yScale).tickSize(-width).tickFormat(() => '')) as unknown as G\n styleGrid(yGrid)\n}\n\n/** Draw X and Y axes with labels and theme-aware styling. */\nfunction drawAxes(\n ctx: BubbleRenderContext,\n g: G,\n xScale: ScaleLinear<number, number>,\n yScale: ScaleLinear<number, number>,\n width: number,\n chartHeight: number,\n textColor: string,\n gridColor: string\n) {\n const { fields, options, queryObject, getFieldLabel } = ctx\n const isTimeDimension =\n queryObject?.timeDimensions?.some((td: { dimension: string }) => td.dimension === fields.xAxisField) || false\n const xGranularity = queryObject?.timeDimensions?.find(\n (td: { dimension: string; granularity?: string }) => td.dimension === fields.xAxisField\n )?.granularity\n\n const xAxisGenerator = axisBottom(xScale)\n if (isTimeDimension) {\n xAxisGenerator.tickFormat((d) => formatTimeTick(d as number, xGranularity))\n } else if (options.xAxisFormat) {\n xAxisGenerator.tickFormat((d) => formatAxisValue(d as number, options.xAxisFormat))\n }\n\n const xAxis = g.append('g').attr('transform', `translate(0,${chartHeight})`).call(xAxisGenerator)\n xAxis.selectAll('text').style('fill', textColor)\n xAxis.selectAll('line, path').style('stroke', gridColor)\n xAxis\n .append('text')\n .attr('x', width / 2)\n .attr('y', 35)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(options.xAxisFormat?.label || getFieldLabel(fields.xAxisField))\n\n const yAxisGenerator = axisLeft(yScale)\n if (options.leftYAxisFormat) {\n yAxisGenerator.tickFormat((d) => formatAxisValue(d as number, options.leftYAxisFormat))\n }\n const yAxis = g.append('g').call(yAxisGenerator)\n yAxis.selectAll('text').style('fill', textColor)\n yAxis.selectAll('line, path').style('stroke', gridColor)\n yAxis\n .append('text')\n .attr('transform', 'rotate(-90)')\n .attr('y', -35)\n .attr('x', -chartHeight / 2)\n .attr('fill', textColor)\n .style('text-anchor', 'middle')\n .style('font-size', '12px')\n .text(options.leftYAxisFormat?.label || getFieldLabel(fields.yAxisField))\n}\n\n/** Create the floating HTML tooltip element. */\nfunction createTooltip() {\n return select('body')\n .append('div')\n .attr('class', 'bubble-chart-tooltip')\n .style('position', 'absolute')\n .style('padding', '8px')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none')\n .style('opacity', 0)\n .style('z-index', 1000)\n}\n\ntype Tooltip = ReturnType<typeof createTooltip>\ntype Bubbles = Selection<SVGCircleElement, BubbleData, SVGGElement, unknown>\n\n/** Compose the multi-line tooltip HTML for a bubble. */\nfunction bubbleTooltipHtml(ctx: BubbleRenderContext, d: BubbleData): string {\n const { fields, options, getFieldLabel } = ctx\n const fmt = (v: number) => (options.leftYAxisFormat ? formatAxisValue(v, options.leftYAxisFormat) : v)\n return [\n `<strong>${d.series || 'Unknown'}</strong>`,\n `${getFieldLabel(fields.xAxisField)}: ${d.xLabel || (options.xAxisFormat ? formatAxisValue(d.x, options.xAxisFormat) : d.x)}`,\n `${getFieldLabel(fields.yAxisField)}: ${fmt(d.y)}`,\n `${getFieldLabel(fields.sizeFieldName)}: ${fmt(d.size)}`,\n fields.colorFieldName && d.color ? `${getFieldLabel(fields.colorFieldName)}: ${d.color}` : ''\n ]\n .filter(Boolean)\n .join('<br>')\n}\n\n/** Attach hover handlers showing/hiding the tooltip and growing the bubble. */\nfunction attachBubbleHover(\n ctx: BubbleRenderContext,\n bubbles: Bubbles,\n tooltip: Tooltip,\n sizeScale: ScalePower<number, number>\n) {\n bubbles\n .on('mouseover', function (event, d) {\n select(this).transition().duration(200).style('opacity', 1).attr('r', sizeScale(d.size) * 1.1)\n tooltip\n .html(bubbleTooltipHtml(ctx, d))\n .style('left', event.pageX + 10 + 'px')\n .style('top', event.pageY - 10 + 'px')\n .transition()\n .duration(200)\n .style('opacity', 1)\n })\n .on('mousemove', function (event) {\n tooltip.style('left', event.pageX + 10 + 'px').style('top', event.pageY - 10 + 'px')\n })\n .on('mouseout', function (_event, d) {\n select(this).transition().duration(200).style('opacity', ctx.options.bubbleOpacity).attr('r', sizeScale(d.size))\n tooltip.transition().duration(200).style('opacity', 0)\n })\n}\n\n/** Draw the gradient legend for a numeric colour field. */\nfunction drawNumericLegend(\n ctx: BubbleRenderContext,\n svg: Selection<SVGSVGElement, unknown, null, undefined>,\n g: G,\n width: number,\n chartHeight: number,\n textColor: string\n) {\n const { bubbleData, fields, options, colorPalette, getFieldLabel } = ctx\n const legendWidth = 200\n const legendHeight = 20\n const minValue = Math.min(...bubbleData.map((d) => d.color as number))\n const maxValue = Math.max(...bubbleData.map((d) => d.color as number))\n const fmt = (v: number) => (options.leftYAxisFormat ? formatAxisValue(v, options.leftYAxisFormat) : v.toFixed(2))\n\n const legend = g\n .append('g')\n .attr('class', 'color-legend')\n .attr('transform', `translate(${width / 2 - legendWidth / 2}, ${chartHeight + 60})`)\n\n const gradient = svg\n .append('defs')\n .append('linearGradient')\n .attr('id', 'color-scale-gradient')\n .attr('x1', '0%').attr('y1', '0%').attr('x2', '100%').attr('y2', '0%')\n const gradientColors = colorPalette?.gradient || CHART_COLORS_GRADIENT\n gradientColors.forEach((color, i) => {\n gradient.append('stop').attr('offset', `${(i / (gradientColors.length - 1)) * 100}%`).attr('stop-color', color)\n })\n\n legend.append('rect')\n .attr('width', legendWidth).attr('height', legendHeight)\n .style('fill', 'url(#color-scale-gradient)').style('stroke', '#ccc').style('stroke-width', 1)\n legend.append('text')\n .attr('x', 0).attr('y', legendHeight + 15).attr('text-anchor', 'start')\n .style('font-size', '11px').style('fill', textColor).text(fmt(minValue))\n legend.append('text')\n .attr('x', legendWidth).attr('y', legendHeight + 15).attr('text-anchor', 'end')\n .style('font-size', '11px').style('fill', textColor).text(fmt(maxValue))\n legend.append('text')\n .attr('x', legendWidth / 2).attr('y', -5).attr('text-anchor', 'middle')\n .style('font-size', '12px').style('font-weight', 'bold').style('fill', textColor)\n .text(getFieldLabel(fields.colorFieldName!))\n}\n\n/** Draw the categorical legend (one swatch per series) with hover highlighting. */\nfunction drawCategoricalLegend(\n ctx: BubbleRenderContext,\n g: G,\n width: number,\n chartHeight: number,\n textColor: string,\n uniqueColors: string[],\n colorScale: ScaleOrdinal<string, string>,\n bubbles: Bubbles\n) {\n const { fields, options } = ctx\n if (uniqueColors.length === 0) return\n\n const legend = g\n .append('g')\n .attr('class', 'legend')\n .attr('transform', `translate(${width / 2 - (uniqueColors.length * 80) / 2}, ${chartHeight + 60})`)\n\n const legendItem = legend\n .selectAll('.legend-item')\n .data(uniqueColors)\n .enter()\n .append('g')\n .attr('class', 'legend-item')\n .attr('transform', (_d, i) => `translate(${i * 80}, 0)`)\n .style('cursor', 'pointer')\n\n legendItem.append('circle')\n .attr('cx', 5).attr('cy', 5).attr('r', 5)\n .style('fill', (d) => colorScale(d as string)).style('opacity', options.bubbleOpacity)\n legendItem.append('text')\n .attr('x', 15).attr('y', 5).attr('dy', '.35em')\n .style('font-size', '11px').style('fill', textColor).text((d) => String(d))\n\n legendItem\n .on('mouseover', function (_event, legendKey) {\n bubbles.transition().duration(200).style('opacity', (d) =>\n fields.colorFieldName && String(d.color) === legendKey ? 1 : 0.2\n )\n })\n .on('mouseout', function () {\n bubbles.transition().duration(200).style('opacity', options.bubbleOpacity)\n })\n}\n\n/**\n * Render the bubble chart into the given SVG element. Returns a cleanup function\n * that removes the floating tooltip. Returns undefined when there is nothing to draw.\n */\nexport function renderBubbleChart(ctx: BubbleRenderContext): (() => void) | undefined {\n const { svgEl, bubbleData, fields, options, dimensions, colorPalette, isDark } = ctx\n\n select(svgEl).selectAll('*').remove()\n if (bubbleData.length === 0) return undefined\n\n const margin = {\n ...CHART_MARGINS,\n left: CHART_MARGINS.left + 30,\n bottom: options.showLegend && fields.colorFieldName ? 100 : 40\n }\n const width = dimensions.width - margin.left - margin.right\n const chartHeight = dimensions.height - margin.top - margin.bottom\n\n const svg = select(svgEl).attr('width', dimensions.width).attr('height', dimensions.height)\n const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`)\n\n const xScale = scaleLinear().domain(extent(bubbleData, (d) => d.x) as [number, number]).range([0, width]).nice()\n const yScale = scaleLinear().domain(extent(bubbleData, (d) => d.y) as [number, number]).range([chartHeight, 0]).nice()\n const sizeScale = scaleSqrt()\n .domain([0, max(bubbleData, (d) => d.size) as number])\n .range([options.minBubbleSize, options.maxBubbleSize])\n\n const { colorScale, isNumericColorField, uniqueColors } = buildColorScale(\n bubbleData,\n fields.colorFieldName,\n colorPalette\n )\n const { textColor, gridColor } = resolveThemeColors(isDark)\n\n if (options.showGrid) {\n drawGrid(g, xScale, yScale, width, chartHeight, gridColor)\n }\n drawAxes(ctx, g, xScale, yScale, width, chartHeight, textColor, gridColor)\n\n const tooltip = createTooltip()\n\n const bubbles = g\n .selectAll('.bubble')\n .data(bubbleData)\n .enter()\n .append('circle')\n .attr('class', 'bubble')\n .attr('cx', (d) => xScale(d.x))\n .attr('cy', (d) => yScale(d.y))\n .attr('r', (d) => sizeScale(d.size))\n .style('fill', (d) => {\n if (fields.colorFieldName && d.color !== undefined) {\n return isNumericColorField\n ? (colorScale as ScaleQuantize<string>)(d.color as number)\n : (colorScale as ScaleOrdinal<string, string>)(String(d.color))\n }\n return CHART_COLORS[0]\n })\n .style('opacity', options.bubbleOpacity)\n .style('stroke', '#fff')\n .style('stroke-width', 1)\n .style('cursor', 'pointer') as Bubbles\n\n if (options.showTooltip) {\n attachBubbleHover(ctx, bubbles, tooltip, sizeScale)\n }\n\n if (options.showLegend && fields.colorFieldName) {\n if (isNumericColorField) {\n drawNumericLegend(ctx, svg, g, width, chartHeight, textColor)\n } else {\n drawCategoricalLegend(ctx, g, width, chartHeight, textColor, uniqueColors, colorScale as ScaleOrdinal<string, string>, bubbles)\n }\n }\n\n return () => {\n tooltip.remove()\n }\n}\n","import React, { useEffect, useMemo } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { transition as _transition } from 'd3'\n// _transition import is for side effects only - it extends Selection.prototype with .transition()\nvoid _transition\nimport { useCubeFieldLabel } from '../../hooks/useCubeFieldLabel.js'\nimport { useTheme } from '../../hooks/useTheme.js'\nimport { useChartDimensions } from './useChartDimensions.js'\nimport {\n resolveBubbleDisplayOptions,\n resolveBubbleFields,\n transformBubbleData\n} from './BubbleChart.helpers.js'\nimport { renderBubbleChart } from './BubbleChart.render.js'\nimport type { ChartProps } from '../../types.js'\n\nconst BubbleChart = React.memo(function BubbleChart({\n data,\n chartConfig,\n displayConfig = {},\n queryObject,\n height = \"100%\",\n colorPalette\n}: ChartProps) {\n const { t } = useTranslation()\n const svgRef = React.useRef<SVGSVGElement | null>(null)\n const { containerRef, dimensions, dimensionsReady } = useChartDimensions()\n const { theme } = useTheme()\n const getFieldLabel = useCubeFieldLabel()\n\n // Memoize display options to keep the render effect dependencies stable\n const options = useMemo(() => resolveBubbleDisplayOptions(displayConfig), [displayConfig])\n\n useEffect(() => {\n if (!data || data.length === 0 || !svgRef.current || !dimensionsReady || dimensions.width === 0) {\n return\n }\n\n const fields = resolveBubbleFields(chartConfig)\n if (!fields) return\n\n const bubbleData = transformBubbleData(data as Record<string, any>[], fields, queryObject)\n\n return renderBubbleChart({\n svgEl: svgRef.current,\n bubbleData,\n fields,\n options,\n dimensions,\n queryObject,\n colorPalette,\n isDark: theme !== 'light',\n getFieldLabel\n })\n }, [data, chartConfig, options, queryObject, dimensions, dimensionsReady, colorPalette, theme, getFieldLabel])\n\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.bubble')}</div>\n </div>\n </div>\n )\n }\n\n // Validate that we have required fields\n const hasValidConfig = chartConfig?.xAxis && chartConfig?.yAxis && chartConfig?.series\n if (!hasValidConfig) {\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.activityGridConfigRequired')}</div>\n <div className=\"dc:text-xs\">{t('chart.runtime.configErrorHint.bubbleRequired')}</div>\n <div className=\"dc:text-xs dc:mt-1\">{t('chart.runtime.configErrorHint.bubbleOptional')}</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:w-full dc:flex-1 dc:flex dc:flex-col dc:relative\" style={{ height, minHeight: '250px', overflow: 'hidden' }}>\n <div ref={containerRef} className=\"dc:w-full dc:h-full dc:relative\">\n <svg ref={svgRef} className=\"dc:w-full dc:h-full\" />\n {!dimensionsReady && (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center\">\n <div className=\"text-dc-text-muted dc:text-sm\">{t('chart.runtime.measuringDimensions')}</div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default BubbleChart\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-candlestick-DZp19Tzh.js","names":[],"sources":["../../../src/client/components/charts/CandlestickChart.tsx"],"sourcesContent":["import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation'\nimport { formatAxisValue } from '../../utils/chartUtils'\nimport type { ChartProps } from '../../types'\n\nconst BULL_COLOR_DEFAULT = '#22c55e'\nconst BEAR_COLOR_DEFAULT = '#ef4444'\nconst WICK_COLOR = '#94a3b8'\nconst MAX_CANDLES = 200\n\ninterface CandleData {\n label: string\n open: number\n close: number\n high: number\n low: number\n isBullish: boolean\n originalIndex: number\n}\n\nfunction parseNum(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nfunction Candle({\n x,\n candleWidth,\n openY,\n closeY,\n highY,\n lowY,\n isBullish,\n bullColor,\n bearColor,\n showWicks,\n label,\n}: {\n x: number\n candleWidth: number\n openY: number\n closeY: number\n highY: number\n lowY: number\n isBullish: boolean\n bullColor: string\n bearColor: string\n showWicks: boolean\n label: string\n}) {\n const fill = isBullish ? bullColor : bearColor\n const bodyTop = Math.min(openY, closeY)\n const bodyBottom = Math.max(openY, closeY)\n const bodyHeight = Math.max(bodyBottom - bodyTop, 1)\n const halfWidth = candleWidth / 2\n\n return (\n <g data-testid={`candle-${label}`}>\n <rect\n x={x - halfWidth}\n y={bodyTop}\n width={candleWidth}\n height={bodyHeight}\n fill={fill}\n data-testid={`candle-body-${label}`}\n data-bullish={isBullish}\n />\n {showWicks && (\n <>\n <line\n x1={x}\n y1={highY}\n x2={x}\n y2={bodyTop}\n stroke={WICK_COLOR}\n strokeWidth={1}\n data-testid={`wick-high-${label}`}\n />\n <line\n x1={x}\n y1={bodyBottom}\n x2={x}\n y2={lowY}\n stroke={WICK_COLOR}\n strokeWidth={1}\n data-testid={`wick-low-${label}`}\n />\n </>\n )}\n </g>\n )\n}\n\nfunction YAxisTicks({\n domainMin,\n domainMax,\n innerHeight,\n tickCount,\n format,\n}: {\n domainMin: number\n domainMax: number\n innerHeight: number\n tickCount: number\n format?: (v: number) => string\n}) {\n const ticks = useMemo(() => {\n const step = (domainMax - domainMin) / (tickCount - 1)\n return Array.from({ length: tickCount }, (_, i) => domainMin + i * step)\n }, [domainMin, domainMax, tickCount])\n\n const yScale = (v: number) => innerHeight - ((v - domainMin) / (domainMax - domainMin)) * innerHeight\n\n return (\n <g data-testid=\"y-axis\">\n <line y1={0} y2={innerHeight} stroke=\"currentColor\" strokeWidth={1} />\n {ticks.map((tick, i) => (\n <g key={i} transform={`translate(0, ${yScale(tick)})`}>\n <line x1={0} x2={-6} stroke=\"currentColor\" strokeWidth={1} />\n <text\n x={-10}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n >\n {format ? format(tick) : tick.toLocaleString()}\n </text>\n <line x1={0} x2=\"100%\" stroke=\"currentColor\" strokeOpacity={0.1} strokeWidth={1} />\n </g>\n ))}\n </g>\n )\n}\n\nconst CandlestickChart = React.memo(function CandlestickChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n onDataPointClick,\n drillEnabled,\n}: ChartProps) {\n const { t } = useTranslation()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const bullColor = displayConfig?.bullColor ?? BULL_COLOR_DEFAULT\n const bearColor = displayConfig?.bearColor ?? BEAR_COLOR_DEFAULT\n const showWicks = displayConfig?.showWicks ?? true\n const rangeMode = displayConfig?.rangeMode ?? 'ohlc'\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const { xField, openField, closeField, highField, lowField, configError } = useMemo(() => {\n const xField = Array.isArray(chartConfig?.xAxis)\n ? chartConfig.xAxis[0]\n : chartConfig?.xAxis ?? chartConfig?.x\n\n const yAxisFields: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n const openField = yAxisFields[0] ?? ''\n const closeField = (rangeMode === 'range' ? yAxisFields[0] : yAxisFields[1]) ?? ''\n const highField = (rangeMode === 'range' ? yAxisFields[0] : yAxisFields[2]) ?? ''\n const lowField = (rangeMode === 'range' ? yAxisFields[1] : yAxisFields[3]) ?? ''\n\n if (!xField) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'Candlestick chart requires an X-Axis (time or category dimension)',\n }\n }\n\n if (rangeMode === 'range' && (!highField || !lowField)) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'Range mode requires at least 2 measures (high, low) in Y-Axis',\n }\n }\n\n if (rangeMode === 'ohlc' && (!openField || !closeField)) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'OHLC mode requires at least 2 measures (open, close) in Y-Axis',\n }\n }\n\n return { xField, openField, closeField, highField, lowField, configError: null }\n }, [chartConfig, rangeMode])\n\n const candles: CandleData[] = useMemo(() => {\n if (configError || !data || data.length === 0) return []\n const rows = (data as Record<string, unknown>[]).slice(0, MAX_CANDLES)\n const result: CandleData[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const label = String(row[xField!] ?? `Bar ${i + 1}`)\n const rawOpen = parseNum(row[openField])\n const rawClose = parseNum(row[closeField])\n if (rawOpen === null || rawClose === null) continue\n\n let open = rawOpen\n let close = rawClose\n const high = highField ? (parseNum(row[highField]) ?? Math.max(open, close)) : Math.max(open, close)\n const low = lowField ? (parseNum(row[lowField]) ?? Math.min(open, close)) : Math.min(open, close)\n\n if (rangeMode === 'range') {\n open = low\n close = high\n }\n\n result.push({\n label,\n open,\n close,\n high: Math.max(open, close, high),\n low: Math.min(open, close, low),\n isBullish: close >= open,\n originalIndex: i,\n })\n }\n return result\n }, [data, xField, openField, closeField, highField, lowField, rangeMode, configError])\n\n try {\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.candlestick')}</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\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 <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n const margin = { top: 20, right: 20, bottom: 60, left: 70 }\n const containerWidth = dimensions.width || 600\n const containerHeight =\n typeof height === 'number' ? height : dimensions.height || 400\n const innerWidth = Math.max(containerWidth - margin.left - margin.right, 50)\n const innerHeight = Math.max(\n (typeof containerHeight === 'number' ? containerHeight : parseInt(String(containerHeight)) || 400) -\n margin.top -\n margin.bottom,\n 50\n )\n\n const allValues = candles.flatMap((c) => [c.low, c.high])\n const rawMin = Math.min(...allValues)\n const rawMax = Math.max(...allValues)\n const pad = (rawMax - rawMin) * 0.05 || 1\n const domainMin = rawMin - pad\n const domainMax = rawMax + pad\n\n const yScale = (v: number) =>\n innerHeight - ((v - domainMin) / (domainMax - domainMin)) * innerHeight\n\n const candleSpacing = innerWidth / candles.length\n const candleWidth = Math.min(candleSpacing * 0.7, 20)\n\n const isTruncated = (data as unknown[]).length > MAX_CANDLES\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height={isTruncated ? 'calc(100% - 20px)' : '100%'}\n viewBox={`0 0 ${containerWidth} ${typeof containerHeight === 'number' ? containerHeight : 400}`}\n data-testid=\"candlestick-svg\"\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n <YAxisTicks\n domainMin={domainMin}\n domainMax={domainMax}\n innerHeight={innerHeight}\n tickCount={5}\n format={yAxisFormat ? (v) => formatAxisValue(v, yAxisFormat) : undefined}\n />\n\n {candles.map((candle, i) => {\n const cx = candleSpacing * i + candleSpacing / 2\n return (\n <g\n key={candle.label + i}\n onClick={(event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled) {\n onDataPointClick({\n dataPoint: { ...candle },\n clickedField: xField ?? '',\n xValue: candle.label,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event,\n })\n }\n }}\n cursor={drillEnabled ? 'pointer' : undefined}\n >\n <title>{`${candle.label}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close}`}</title>\n <Candle\n x={cx}\n candleWidth={candleWidth}\n openY={yScale(candle.open)}\n closeY={yScale(candle.close)}\n highY={yScale(candle.high)}\n lowY={yScale(candle.low)}\n isBullish={candle.isBullish}\n bullColor={bullColor}\n bearColor={bearColor}\n showWicks={showWicks}\n label={candle.label}\n />\n <text\n x={cx}\n y={innerHeight + 20}\n textAnchor=\"middle\"\n fontSize={10}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid={`x-label-${candle.label}`}\n >\n {candle.label}\n </text>\n </g>\n )\n })}\n </g>\n </svg>\n {isTruncated && (\n <div className=\"dc:text-xs text-dc-warning dc:text-center dc:mt-1\">\n {t('chart.runtime.candlestick.truncated', {\n max: MAX_CANDLES,\n total: (data as unknown[]).length\n })}\n </div>\n )}\n </div>\n )\n } catch (error) {\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: 'Candlestick Chart' })}</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})\n\nexport default CandlestickChart\n"],"mappings":"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"}
1
+ {"version":3,"file":"chart-candlestick-DZp19Tzh.js","names":[],"sources":["../../../src/client/components/charts/CandlestickChart.tsx"],"sourcesContent":["import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from '../../hooks/useTranslation.js'\nimport { formatAxisValue } from '../../utils/chartUtils.js'\nimport type { ChartProps } from '../../types.js'\n\nconst BULL_COLOR_DEFAULT = '#22c55e'\nconst BEAR_COLOR_DEFAULT = '#ef4444'\nconst WICK_COLOR = '#94a3b8'\nconst MAX_CANDLES = 200\n\ninterface CandleData {\n label: string\n open: number\n close: number\n high: number\n low: number\n isBullish: boolean\n originalIndex: number\n}\n\nfunction parseNum(v: unknown): number | null {\n if (v === undefined || v === null) return null\n const n = typeof v === 'number' ? v : parseFloat(String(v))\n return isNaN(n) ? null : n\n}\n\nfunction Candle({\n x,\n candleWidth,\n openY,\n closeY,\n highY,\n lowY,\n isBullish,\n bullColor,\n bearColor,\n showWicks,\n label,\n}: {\n x: number\n candleWidth: number\n openY: number\n closeY: number\n highY: number\n lowY: number\n isBullish: boolean\n bullColor: string\n bearColor: string\n showWicks: boolean\n label: string\n}) {\n const fill = isBullish ? bullColor : bearColor\n const bodyTop = Math.min(openY, closeY)\n const bodyBottom = Math.max(openY, closeY)\n const bodyHeight = Math.max(bodyBottom - bodyTop, 1)\n const halfWidth = candleWidth / 2\n\n return (\n <g data-testid={`candle-${label}`}>\n <rect\n x={x - halfWidth}\n y={bodyTop}\n width={candleWidth}\n height={bodyHeight}\n fill={fill}\n data-testid={`candle-body-${label}`}\n data-bullish={isBullish}\n />\n {showWicks && (\n <>\n <line\n x1={x}\n y1={highY}\n x2={x}\n y2={bodyTop}\n stroke={WICK_COLOR}\n strokeWidth={1}\n data-testid={`wick-high-${label}`}\n />\n <line\n x1={x}\n y1={bodyBottom}\n x2={x}\n y2={lowY}\n stroke={WICK_COLOR}\n strokeWidth={1}\n data-testid={`wick-low-${label}`}\n />\n </>\n )}\n </g>\n )\n}\n\nfunction YAxisTicks({\n domainMin,\n domainMax,\n innerHeight,\n tickCount,\n format,\n}: {\n domainMin: number\n domainMax: number\n innerHeight: number\n tickCount: number\n format?: (v: number) => string\n}) {\n const ticks = useMemo(() => {\n const step = (domainMax - domainMin) / (tickCount - 1)\n return Array.from({ length: tickCount }, (_, i) => domainMin + i * step)\n }, [domainMin, domainMax, tickCount])\n\n const yScale = (v: number) => innerHeight - ((v - domainMin) / (domainMax - domainMin)) * innerHeight\n\n return (\n <g data-testid=\"y-axis\">\n <line y1={0} y2={innerHeight} stroke=\"currentColor\" strokeWidth={1} />\n {ticks.map((tick, i) => (\n <g key={i} transform={`translate(0, ${yScale(tick)})`}>\n <line x1={0} x2={-6} stroke=\"currentColor\" strokeWidth={1} />\n <text\n x={-10}\n textAnchor=\"end\"\n dominantBaseline=\"middle\"\n fontSize={11}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n >\n {format ? format(tick) : tick.toLocaleString()}\n </text>\n <line x1={0} x2=\"100%\" stroke=\"currentColor\" strokeOpacity={0.1} strokeWidth={1} />\n </g>\n ))}\n </g>\n )\n}\n\nconst CandlestickChart = React.memo(function CandlestickChart({\n data,\n chartConfig,\n displayConfig = {},\n height = '100%',\n onDataPointClick,\n drillEnabled,\n}: ChartProps) {\n const { t } = useTranslation()\n const containerRef = useRef<HTMLDivElement>(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n useLayoutEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height: h } = entry.contentRect\n if (width > 0 && h > 0) setDimensions({ width, height: h })\n }\n })\n observer.observe(el)\n const rect = el.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0) setDimensions({ width: rect.width, height: rect.height })\n return () => observer.disconnect()\n }, [])\n\n const bullColor = displayConfig?.bullColor ?? BULL_COLOR_DEFAULT\n const bearColor = displayConfig?.bearColor ?? BEAR_COLOR_DEFAULT\n const showWicks = displayConfig?.showWicks ?? true\n const rangeMode = displayConfig?.rangeMode ?? 'ohlc'\n const yAxisFormat = displayConfig?.leftYAxisFormat\n\n const { xField, openField, closeField, highField, lowField, configError } = useMemo(() => {\n const xField = Array.isArray(chartConfig?.xAxis)\n ? chartConfig.xAxis[0]\n : chartConfig?.xAxis ?? chartConfig?.x\n\n const yAxisFields: string[] = Array.isArray(chartConfig?.yAxis)\n ? chartConfig.yAxis\n : []\n\n const openField = yAxisFields[0] ?? ''\n const closeField = (rangeMode === 'range' ? yAxisFields[0] : yAxisFields[1]) ?? ''\n const highField = (rangeMode === 'range' ? yAxisFields[0] : yAxisFields[2]) ?? ''\n const lowField = (rangeMode === 'range' ? yAxisFields[1] : yAxisFields[3]) ?? ''\n\n if (!xField) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'Candlestick chart requires an X-Axis (time or category dimension)',\n }\n }\n\n if (rangeMode === 'range' && (!highField || !lowField)) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'Range mode requires at least 2 measures (high, low) in Y-Axis',\n }\n }\n\n if (rangeMode === 'ohlc' && (!openField || !closeField)) {\n return {\n xField,\n openField,\n closeField,\n highField,\n lowField,\n configError: 'OHLC mode requires at least 2 measures (open, close) in Y-Axis',\n }\n }\n\n return { xField, openField, closeField, highField, lowField, configError: null }\n }, [chartConfig, rangeMode])\n\n const candles: CandleData[] = useMemo(() => {\n if (configError || !data || data.length === 0) return []\n const rows = (data as Record<string, unknown>[]).slice(0, MAX_CANDLES)\n const result: CandleData[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const label = String(row[xField!] ?? `Bar ${i + 1}`)\n const rawOpen = parseNum(row[openField])\n const rawClose = parseNum(row[closeField])\n if (rawOpen === null || rawClose === null) continue\n\n let open = rawOpen\n let close = rawClose\n const high = highField ? (parseNum(row[highField]) ?? Math.max(open, close)) : Math.max(open, close)\n const low = lowField ? (parseNum(row[lowField]) ?? Math.min(open, close)) : Math.min(open, close)\n\n if (rangeMode === 'range') {\n open = low\n close = high\n }\n\n result.push({\n label,\n open,\n close,\n high: Math.max(open, close, high),\n low: Math.min(open, close, low),\n isBullish: close >= open,\n originalIndex: i,\n })\n }\n return result\n }, [data, xField, openField, closeField, highField, lowField, rangeMode, configError])\n\n try {\n if (!data || data.length === 0) {\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('chart.runtime.noData')}</div>\n <div className=\"dc:text-xs text-dc-text-secondary\">{t('chart.runtime.noDataHint.candlestick')}</div>\n </div>\n </div>\n )\n }\n\n if (configError) {\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 <div className=\"dc:text-xs\">{configError}</div>\n </div>\n </div>\n )\n }\n const margin = { top: 20, right: 20, bottom: 60, left: 70 }\n const containerWidth = dimensions.width || 600\n const containerHeight =\n typeof height === 'number' ? height : dimensions.height || 400\n const innerWidth = Math.max(containerWidth - margin.left - margin.right, 50)\n const innerHeight = Math.max(\n (typeof containerHeight === 'number' ? containerHeight : parseInt(String(containerHeight)) || 400) -\n margin.top -\n margin.bottom,\n 50\n )\n\n const allValues = candles.flatMap((c) => [c.low, c.high])\n const rawMin = Math.min(...allValues)\n const rawMax = Math.max(...allValues)\n const pad = (rawMax - rawMin) * 0.05 || 1\n const domainMin = rawMin - pad\n const domainMax = rawMax + pad\n\n const yScale = (v: number) =>\n innerHeight - ((v - domainMin) / (domainMax - domainMin)) * innerHeight\n\n const candleSpacing = innerWidth / candles.length\n const candleWidth = Math.min(candleSpacing * 0.7, 20)\n\n const isTruncated = (data as unknown[]).length > MAX_CANDLES\n\n return (\n <div ref={containerRef} className=\"dc:relative dc:w-full\" style={{ height }}>\n <svg\n width=\"100%\"\n height={isTruncated ? 'calc(100% - 20px)' : '100%'}\n viewBox={`0 0 ${containerWidth} ${typeof containerHeight === 'number' ? containerHeight : 400}`}\n data-testid=\"candlestick-svg\"\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n <YAxisTicks\n domainMin={domainMin}\n domainMax={domainMax}\n innerHeight={innerHeight}\n tickCount={5}\n format={yAxisFormat ? (v) => formatAxisValue(v, yAxisFormat) : undefined}\n />\n\n {candles.map((candle, i) => {\n const cx = candleSpacing * i + candleSpacing / 2\n return (\n <g\n key={candle.label + i}\n onClick={(event: React.MouseEvent) => {\n if (onDataPointClick && drillEnabled) {\n onDataPointClick({\n dataPoint: { ...candle },\n clickedField: xField ?? '',\n xValue: candle.label,\n position: { x: event.clientX, y: event.clientY },\n nativeEvent: event,\n })\n }\n }}\n cursor={drillEnabled ? 'pointer' : undefined}\n >\n <title>{`${candle.label}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close}`}</title>\n <Candle\n x={cx}\n candleWidth={candleWidth}\n openY={yScale(candle.open)}\n closeY={yScale(candle.close)}\n highY={yScale(candle.high)}\n lowY={yScale(candle.low)}\n isBullish={candle.isBullish}\n bullColor={bullColor}\n bearColor={bearColor}\n showWicks={showWicks}\n label={candle.label}\n />\n <text\n x={cx}\n y={innerHeight + 20}\n textAnchor=\"middle\"\n fontSize={10}\n fill=\"currentColor\"\n className=\"text-dc-text-secondary\"\n data-testid={`x-label-${candle.label}`}\n >\n {candle.label}\n </text>\n </g>\n )\n })}\n </g>\n </svg>\n {isTruncated && (\n <div className=\"dc:text-xs text-dc-warning dc:text-center dc:mt-1\">\n {t('chart.runtime.candlestick.truncated', {\n max: MAX_CANDLES,\n total: (data as unknown[]).length\n })}\n </div>\n )}\n </div>\n )\n } catch (error) {\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: 'Candlestick Chart' })}</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})\n\nexport default CandlestickChart\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-activity-grid-D_UX4NHC.js","names":[],"sources":["../../../src/client/components/charts/ActivityGridChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the activity grid chart type\n */\nexport const activityGridChartConfig: ChartTypeConfig = {\n label: 'chart.activityGrid.label',\n description: 'chart.activityGrid.description',\n useCase: 'chart.activityGrid.useCase',\n isAvailable: ({ measureCount, timeDimensionCount }) => {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n if (timeDimensionCount < 1) return { available: false, reason: 'chart.availability.requiresTimeDimension' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'dateField',\n label: 'chart.configText.time_dimension',\n description: 'chart.configText.time_field_that_determines_grid_structure_granularity_affects_layout',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['timeDimension'],\n emptyText: 'chart.activityGrid.dropZone.dateField.empty'\n },\n {\n key: 'valueField',\n label: 'chart.configText.activity_measure',\n description: 'chart.configText.measure_used_for_activity_intensity_color_coding',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.activityGrid.dropZone.valueField.empty'\n }\n ],\n displayOptions: ['showLabels', 'showTooltip', 'hideHeader'],\n displayOptionsConfig: [\n {\n key: 'fitToWidth',\n label: 'chart.option.fitToWidth.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.fitToWidth.description'\n }\n ],\n validate: (config) => {\n const { dateField, valueField } = config\n\n if (!dateField || (Array.isArray(dateField) && dateField.length === 0)) {\n return {\n isValid: false,\n message: 'chart.activityGrid.validation.timeDimensionRequired'\n }\n }\n\n if (!valueField || (Array.isArray(valueField) && valueField.length === 0)) {\n return {\n isValid: false,\n message: 'chart.activityGrid.validation.measureRequired'\n }\n }\n\n return { isValid: true }\n },\n clickableElements: { cell: true }\n}"],"mappings":";;iEAKa,IAA2C;CACtD,OAAO;CACP,aAAa;CACb,SAAS;CACT,cAAc,EAAE,iBAAc,4BACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IAC1F,IAAqB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAA2C,IACnG,EAAE,WAAW,GAAK;CAE3B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,eAAe;EAC7B,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,gBAAgB;EAAC;EAAc;EAAe;CAAY;CAC1D,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,cAAc;EACd,aAAa;CACf,CACF;CACA,WAAW,MAAW;EACpB,IAAM,EAAE,cAAW,kBAAe;EAgBlC,OAdI,CAAC,KAAc,MAAM,QAAQ,CAAS,KAAK,EAAU,WAAW,IAC3D;GACL,SAAS;GACT,SAAS;EACX,IAGE,CAAC,KAAe,MAAM,QAAQ,CAAU,KAAK,EAAW,WAAW,IAC9D;GACL,SAAS;GACT,SAAS;EACX,IAGK,EAAE,SAAS,GAAK;CACzB;CACA,mBAAmB,EAAE,MAAM,GAAK;AAClC"}
1
+ {"version":3,"file":"chart-config-activity-grid-D_UX4NHC.js","names":[],"sources":["../../../src/client/components/charts/ActivityGridChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\n\n/**\n * Configuration for the activity grid chart type\n */\nexport const activityGridChartConfig: ChartTypeConfig = {\n label: 'chart.activityGrid.label',\n description: 'chart.activityGrid.description',\n useCase: 'chart.activityGrid.useCase',\n isAvailable: ({ measureCount, timeDimensionCount }) => {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n if (timeDimensionCount < 1) return { available: false, reason: 'chart.availability.requiresTimeDimension' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'dateField',\n label: 'chart.configText.time_dimension',\n description: 'chart.configText.time_field_that_determines_grid_structure_granularity_affects_layout',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['timeDimension'],\n emptyText: 'chart.activityGrid.dropZone.dateField.empty'\n },\n {\n key: 'valueField',\n label: 'chart.configText.activity_measure',\n description: 'chart.configText.measure_used_for_activity_intensity_color_coding',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.activityGrid.dropZone.valueField.empty'\n }\n ],\n displayOptions: ['showLabels', 'showTooltip', 'hideHeader'],\n displayOptionsConfig: [\n {\n key: 'fitToWidth',\n label: 'chart.option.fitToWidth.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.fitToWidth.description'\n }\n ],\n validate: (config) => {\n const { dateField, valueField } = config\n\n if (!dateField || (Array.isArray(dateField) && dateField.length === 0)) {\n return {\n isValid: false,\n message: 'chart.activityGrid.validation.timeDimensionRequired'\n }\n }\n\n if (!valueField || (Array.isArray(valueField) && valueField.length === 0)) {\n return {\n isValid: false,\n message: 'chart.activityGrid.validation.measureRequired'\n }\n }\n\n return { isValid: true }\n },\n clickableElements: { cell: true }\n}"],"mappings":";;iEAKa,IAA2C;CACtD,OAAO;CACP,aAAa;CACb,SAAS;CACT,cAAc,EAAE,iBAAc,4BACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IAC1F,IAAqB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAA2C,IACnG,EAAE,WAAW,GAAK;CAE3B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,eAAe;EAC7B,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,gBAAgB;EAAC;EAAc;EAAe;CAAY;CAC1D,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,cAAc;EACd,aAAa;CACf,CACF;CACA,WAAW,MAAW;EACpB,IAAM,EAAE,cAAW,kBAAe;EAgBlC,OAdI,CAAC,KAAc,MAAM,QAAQ,CAAS,KAAK,EAAU,WAAW,IAC3D;GACL,SAAS;GACT,SAAS;EACX,IAGE,CAAC,KAAe,MAAM,QAAQ,CAAU,KAAK,EAAW,WAAW,IAC9D;GACL,SAAS;GACT,SAAS;EACX,IAGK,EAAE,SAAS,GAAK;CACzB;CACA,mBAAmB,EAAE,MAAM,GAAK;AAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-area-BNigHUy8.js","names":[],"sources":["../../../src/client/charts/chartConfigHelpers.ts","../../../src/client/components/charts/AreaChart.config.ts"],"sourcesContent":["import type { ChartAvailabilityContext, ChartAvailability, DisplayOptionConfig } from './chartConfigs'\n\n/**\n * Shared building blocks for chart `*.config.ts` files.\n *\n * Most chart configs repeated the same `isAvailable` guard and the same\n * display-option definitions (target line, Y-axis format, stacking, …).\n * These factories centralise that boilerplate so each chart config only\n * declares what is genuinely unique to it.\n */\n\n/**\n * Standard availability rule shared by most chart types: at least one measure\n * and at least one dimension (regular or time) must be selected.\n */\nexport function requiresMeasureAndDimension({\n measureCount,\n dimensionCount\n}: ChartAvailabilityContext): ChartAvailability {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.requiresDimension' }\n return { available: true }\n}\n\n/**\n * Availability rule for charts that only need a single measure (KPI-style\n * charts and gauges): at least one measure, no dimension requirement.\n */\nexport function requiresMeasure({ measureCount }: ChartAvailabilityContext): ChartAvailability {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n return { available: true }\n}\n\n/** Target-line display option (single value or comma-separated spread). */\nexport const targetDisplayOption: DisplayOptionConfig = {\n key: 'target',\n label: 'chart.option.target.label',\n type: 'string',\n placeholder: 'e.g., 100 or 50,75 for spread',\n description: 'chart.option.target.description'\n}\n\n/** Connect-nulls toggle for line/area charts. */\nexport const connectNullsDisplayOption: DisplayOptionConfig = {\n key: 'connectNulls',\n label: 'chart.option.connectNulls.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.connectNulls.description'\n}\n\n/** Left Y-axis numeric format control (dual-axis charts). */\nexport const leftYAxisFormatDisplayOption: DisplayOptionConfig = {\n key: 'leftYAxisFormat',\n label: 'chart.option.leftYAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.leftYAxisFormat.description'\n}\n\n/** Right Y-axis numeric format control (dual-axis charts). */\nexport const rightYAxisFormatDisplayOption: DisplayOptionConfig = {\n key: 'rightYAxisFormat',\n label: 'chart.option.rightYAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.rightYAxisFormat.description'\n}\n\n/**\n * Single value-format control used by charts that only have one numeric scale\n * (pie, radar, radial bar, treemap). Stored under `leftYAxisFormat` for\n * backward compatibility with existing saved configs.\n */\nexport function valueFormatDisplayOption(\n description = 'chart.option.valueFormat.description'\n): DisplayOptionConfig {\n return {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description\n }\n}\n\n/**\n * Stacking-mode select shared by bar and area charts. `description` differs\n * per chart (bar vs area series wording).\n */\nexport function stackTypeDisplayOption(description: string): DisplayOptionConfig {\n return {\n key: 'stackType',\n label: 'chart.option.stacking.label',\n type: 'select',\n defaultValue: 'none',\n options: [\n { value: 'none', label: 'chart.option.accentBorder.none' },\n { value: 'normal', label: 'chart.option.stacking.stacked' },\n { value: 'percent', label: 'chart.option.stacking.percent' }\n ],\n description\n }\n}\n","import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport {\n requiresMeasureAndDimension,\n stackTypeDisplayOption,\n connectNullsDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n} from '../../charts/chartConfigHelpers'\n\n/**\n * Configuration for the area chart type\n */\nexport const areaChartConfig: ChartTypeConfig = {\n label: 'chart.area.label',\n description: 'chart.area.description',\n useCase: 'chart.area.useCase',\n isAvailable: requiresMeasureAndDimension,\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_time_categories',\n description: 'chart.configText.time_dimensions_or_dimensions_for_x_axis',\n mandatory: true,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.area.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.dropZone.yAxis.label',\n description: 'chart.configText.measures_for_area_values',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.area.dropZone.yAxis.empty',\n enableDualAxis: true\n },\n {\n key: 'series',\n label: 'chart.configText.series_stack_areas',\n description: 'chart.configText.dimensions_to_create_stacked_areas',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'chart.area.dropZone.series.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'showAllXLabels', 'hideHeader'],\n displayOptionsConfig: [\n stackTypeDisplayOption('chart.configText.how_to_stack_multiple_area_series'),\n connectNullsDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n ]\n}"],"mappings":";;AAeA,SAAgB,EAA4B,EAC1C,iBACA,qBAC8C;CAG9C,OAFI,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IAC1F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAuC,IAC3F,EAAE,WAAW,GAAK;AAC3B;AAMA,SAAgB,EAAgB,EAAE,mBAA6D;CAE7F,OADI,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IACvF,EAAE,WAAW,GAAK;AAC3B;AAGA,IAAa,IAA2C;CACtD,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;CACb,aAAa;AACf,GAGa,IAAiD;CAC5D,KAAK;CACL,OAAO;CACP,MAAM;CACN,cAAc;CACd,aAAa;AACf,GAGa,IAAoD;CAC/D,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;AACf,GAGa,IAAqD;CAChE,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;AACf;AAOA,SAAgB,EACd,IAAc,wCACO;CACrB,OAAO;EACL,KAAK;EACL,OAAO;EACP,MAAM;EACN;CACF;AACF;AAMA,SAAgB,EAAuB,GAA0C;CAC/E,OAAO;EACL,KAAK;EACL,OAAO;EACP,MAAM;EACN,cAAc;EACd,SAAS;GACP;IAAE,OAAO;IAAQ,OAAO;GAAiC;GACzD;IAAE,OAAO;IAAU,OAAO;GAAgC;GAC1D;IAAE,OAAO;IAAW,OAAO;GAAgC;EAC7D;EACA;CACF;AACF;;;yDCvFa,IAAmC;CAC9C,OAAO;CACP,aAAa;CACb,SAAS;CACT,aAAa;CACb,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,aAAa,eAAe;GAC1C,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,SAAS;GACvB,WAAW;GACX,gBAAgB;EAClB;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAkB;CAAY;CACxF,sBAAsB;EACpB,EAAuB,oDAAoD;EAC3E;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"chart-config-area-BNigHUy8.js","names":[],"sources":["../../../src/client/charts/chartConfigHelpers.ts","../../../src/client/components/charts/AreaChart.config.ts"],"sourcesContent":["import type { ChartAvailabilityContext, ChartAvailability, DisplayOptionConfig } from './chartConfigs.js'\n\n/**\n * Shared building blocks for chart `*.config.ts` files.\n *\n * Most chart configs repeated the same `isAvailable` guard and the same\n * display-option definitions (target line, Y-axis format, stacking, …).\n * These factories centralise that boilerplate so each chart config only\n * declares what is genuinely unique to it.\n */\n\n/**\n * Standard availability rule shared by most chart types: at least one measure\n * and at least one dimension (regular or time) must be selected.\n */\nexport function requiresMeasureAndDimension({\n measureCount,\n dimensionCount\n}: ChartAvailabilityContext): ChartAvailability {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.requiresDimension' }\n return { available: true }\n}\n\n/**\n * Availability rule for charts that only need a single measure (KPI-style\n * charts and gauges): at least one measure, no dimension requirement.\n */\nexport function requiresMeasure({ measureCount }: ChartAvailabilityContext): ChartAvailability {\n if (measureCount < 1) return { available: false, reason: 'chart.availability.requiresMeasure' }\n return { available: true }\n}\n\n/** Target-line display option (single value or comma-separated spread). */\nexport const targetDisplayOption: DisplayOptionConfig = {\n key: 'target',\n label: 'chart.option.target.label',\n type: 'string',\n placeholder: 'e.g., 100 or 50,75 for spread',\n description: 'chart.option.target.description'\n}\n\n/** Connect-nulls toggle for line/area charts. */\nexport const connectNullsDisplayOption: DisplayOptionConfig = {\n key: 'connectNulls',\n label: 'chart.option.connectNulls.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.connectNulls.description'\n}\n\n/** Left Y-axis numeric format control (dual-axis charts). */\nexport const leftYAxisFormatDisplayOption: DisplayOptionConfig = {\n key: 'leftYAxisFormat',\n label: 'chart.option.leftYAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.leftYAxisFormat.description'\n}\n\n/** Right Y-axis numeric format control (dual-axis charts). */\nexport const rightYAxisFormatDisplayOption: DisplayOptionConfig = {\n key: 'rightYAxisFormat',\n label: 'chart.option.rightYAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.rightYAxisFormat.description'\n}\n\n/**\n * Single value-format control used by charts that only have one numeric scale\n * (pie, radar, radial bar, treemap). Stored under `leftYAxisFormat` for\n * backward compatibility with existing saved configs.\n */\nexport function valueFormatDisplayOption(\n description = 'chart.option.valueFormat.description'\n): DisplayOptionConfig {\n return {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description\n }\n}\n\n/**\n * Stacking-mode select shared by bar and area charts. `description` differs\n * per chart (bar vs area series wording).\n */\nexport function stackTypeDisplayOption(description: string): DisplayOptionConfig {\n return {\n key: 'stackType',\n label: 'chart.option.stacking.label',\n type: 'select',\n defaultValue: 'none',\n options: [\n { value: 'none', label: 'chart.option.accentBorder.none' },\n { value: 'normal', label: 'chart.option.stacking.stacked' },\n { value: 'percent', label: 'chart.option.stacking.percent' }\n ],\n description\n }\n}\n","import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport {\n requiresMeasureAndDimension,\n stackTypeDisplayOption,\n connectNullsDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n} from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the area chart type\n */\nexport const areaChartConfig: ChartTypeConfig = {\n label: 'chart.area.label',\n description: 'chart.area.description',\n useCase: 'chart.area.useCase',\n isAvailable: requiresMeasureAndDimension,\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_time_categories',\n description: 'chart.configText.time_dimensions_or_dimensions_for_x_axis',\n mandatory: true,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.area.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.dropZone.yAxis.label',\n description: 'chart.configText.measures_for_area_values',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.area.dropZone.yAxis.empty',\n enableDualAxis: true\n },\n {\n key: 'series',\n label: 'chart.configText.series_stack_areas',\n description: 'chart.configText.dimensions_to_create_stacked_areas',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'chart.area.dropZone.series.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'showAllXLabels', 'hideHeader'],\n displayOptionsConfig: [\n stackTypeDisplayOption('chart.configText.how_to_stack_multiple_area_series'),\n connectNullsDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n ]\n}"],"mappings":";;AAeA,SAAgB,EAA4B,EAC1C,iBACA,qBAC8C;CAG9C,OAFI,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IAC1F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAuC,IAC3F,EAAE,WAAW,GAAK;AAC3B;AAMA,SAAgB,EAAgB,EAAE,mBAA6D;CAE7F,OADI,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAqC,IACvF,EAAE,WAAW,GAAK;AAC3B;AAGA,IAAa,IAA2C;CACtD,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;CACb,aAAa;AACf,GAGa,IAAiD;CAC5D,KAAK;CACL,OAAO;CACP,MAAM;CACN,cAAc;CACd,aAAa;AACf,GAGa,IAAoD;CAC/D,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;AACf,GAGa,IAAqD;CAChE,KAAK;CACL,OAAO;CACP,MAAM;CACN,aAAa;AACf;AAOA,SAAgB,EACd,IAAc,wCACO;CACrB,OAAO;EACL,KAAK;EACL,OAAO;EACP,MAAM;EACN;CACF;AACF;AAMA,SAAgB,EAAuB,GAA0C;CAC/E,OAAO;EACL,KAAK;EACL,OAAO;EACP,MAAM;EACN,cAAc;EACd,SAAS;GACP;IAAE,OAAO;IAAQ,OAAO;GAAiC;GACzD;IAAE,OAAO;IAAU,OAAO;GAAgC;GAC1D;IAAE,OAAO;IAAW,OAAO;GAAgC;EAC7D;EACA;CACF;AACF;;;yDCvFa,IAAmC;CAC9C,OAAO;CACP,aAAa;CACb,SAAS;CACT,aAAa;CACb,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,aAAa,eAAe;GAC1C,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,SAAS;GACvB,WAAW;GACX,gBAAgB;EAClB;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAkB;CAAY;CACxF,sBAAsB;EACpB,EAAuB,oDAAoD;EAC3E;EACA;EACA;EACA;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-bar-DSO_LRTx.js","names":[],"sources":["../../../src/client/components/charts/BarChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport {\n requiresMeasureAndDimension,\n stackTypeDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n} from '../../charts/chartConfigHelpers'\n\n/**\n * Configuration for the bar chart type\n */\nexport const barChartConfig: ChartTypeConfig = {\n label: 'chart.bar.label',\n description: 'chart.bar.description',\n useCase: 'chart.bar.useCase',\n clickableElements: { bar: true },\n isAvailable: requiresMeasureAndDimension,\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.dropZone.xAxis.label',\n description: 'chart.dropZone.xAxis.description',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.bar.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.dropZone.yAxis.label',\n description: 'chart.configText.measures_for_bar_heights',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.bar.dropZone.yAxis.empty',\n enableDualAxis: true\n },\n {\n key: 'series',\n label: 'chart.dropZone.series.label',\n description: 'chart.dropZone.series.description',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'chart.bar.dropZone.series.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'showAllXLabels', 'hideHeader'],\n displayOptionsConfig: [\n stackTypeDisplayOption('chart.configText.how_to_stack_multiple_bar_series'),\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n ]\n}"],"mappings":";;;wDAYa,IAAkC;CAC7C,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,EAAE,KAAK,GAAK;CAC/B,aAAa;CACb,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,aAAa,eAAe;GAC1C,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,SAAS;GACvB,WAAW;GACX,gBAAgB;EAClB;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAkB;CAAY;CACxF,sBAAsB;EACpB,EAAuB,mDAAmD;EAC1E;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"chart-config-bar-DSO_LRTx.js","names":[],"sources":["../../../src/client/components/charts/BarChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport {\n requiresMeasureAndDimension,\n stackTypeDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n} from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the bar chart type\n */\nexport const barChartConfig: ChartTypeConfig = {\n label: 'chart.bar.label',\n description: 'chart.bar.description',\n useCase: 'chart.bar.useCase',\n clickableElements: { bar: true },\n isAvailable: requiresMeasureAndDimension,\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.dropZone.xAxis.label',\n description: 'chart.dropZone.xAxis.description',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.bar.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.dropZone.yAxis.label',\n description: 'chart.configText.measures_for_bar_heights',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.bar.dropZone.yAxis.empty',\n enableDualAxis: true\n },\n {\n key: 'series',\n label: 'chart.dropZone.series.label',\n description: 'chart.dropZone.series.description',\n mandatory: false,\n acceptTypes: ['dimension'],\n emptyText: 'chart.bar.dropZone.series.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'showAllXLabels', 'hideHeader'],\n displayOptionsConfig: [\n stackTypeDisplayOption('chart.configText.how_to_stack_multiple_bar_series'),\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n ]\n}"],"mappings":";;;wDAYa,IAAkC;CAC7C,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,EAAE,KAAK,GAAK;CAC/B,aAAa;CACb,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,aAAa,eAAe;GAC1C,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,SAAS;GACvB,WAAW;GACX,gBAAgB;EAClB;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAkB;CAAY;CACxF,sBAAsB;EACpB,EAAuB,mDAAmD;EAC1E;EACA;EACA;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-box-plot-oW8axV2q.js","names":[],"sources":["../../../src/client/components/charts/BoxPlotChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { requiresMeasureAndDimension } from '../../charts/chartConfigHelpers'\n\n/**\n * Configuration for the box plot chart type\n */\nexport const boxPlotChartConfig: ChartTypeConfig = {\n label: 'chart.boxPlot.label',\n description: 'chart.boxPlot.description',\n useCase: 'chart.boxPlot.useCase',\n isAvailable: requiresMeasureAndDimension,\n displayOptions: ['hideHeader'],\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_groups',\n description: 'chart.configText.dimension_to_group_boxes_by_e_g_symbol_platform',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.boxPlot.dropZone.xAxis.empty',\n },\n {\n key: 'yAxis',\n label: 'chart.configText.y_axis_measures',\n description: 'chart.configText.drop_1_measure_for_auto_mode_3_for_avg_stddev_median_mode_or_5_for_min_q',\n mandatory: true,\n maxItems: 5,\n acceptTypes: ['measure'],\n emptyText: 'chart.boxPlot.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_value_axis',\n },\n ],\n}\n"],"mappings":";;;4DAMa,IAAsC;CACjD,OAAO;CACP,aAAa;CACb,SAAS;CACT,aAAa;CACb,gBAAgB,CAAC,YAAY;CAC7B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,aAAa,eAAe;EAC1C,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
1
+ {"version":3,"file":"chart-config-box-plot-oW8axV2q.js","names":[],"sources":["../../../src/client/components/charts/BoxPlotChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport { requiresMeasureAndDimension } from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the box plot chart type\n */\nexport const boxPlotChartConfig: ChartTypeConfig = {\n label: 'chart.boxPlot.label',\n description: 'chart.boxPlot.description',\n useCase: 'chart.boxPlot.useCase',\n isAvailable: requiresMeasureAndDimension,\n displayOptions: ['hideHeader'],\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_groups',\n description: 'chart.configText.dimension_to_group_boxes_by_e_g_symbol_platform',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension'],\n emptyText: 'chart.boxPlot.dropZone.xAxis.empty',\n },\n {\n key: 'yAxis',\n label: 'chart.configText.y_axis_measures',\n description: 'chart.configText.drop_1_measure_for_auto_mode_3_for_avg_stddev_median_mode_or_5_for_min_q',\n mandatory: true,\n maxItems: 5,\n acceptTypes: ['measure'],\n emptyText: 'chart.boxPlot.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_value_axis',\n },\n ],\n}\n"],"mappings":";;;4DAMa,IAAsC;CACjD,OAAO;CACP,aAAa;CACb,SAAS;CACT,aAAa;CACb,gBAAgB,CAAC,YAAY;CAC7B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,aAAa,eAAe;EAC1C,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-bubble-gIoqVyjZ.js","names":[],"sources":["../../../src/client/components/charts/BubbleChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the bubble chart type\n */\nexport const bubbleChartConfig: ChartTypeConfig = {\n label: 'chart.bubble.label',\n description: 'chart.bubble.description',\n useCase: 'chart.bubble.useCase',\n isAvailable: ({ measureCount, dimensionCount }) => {\n if (measureCount < 2) return { available: false, reason: 'chart.availability.requiresTwoMeasures' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.bubble' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.runtime.axisFormat.xAxis',\n description: 'chart.configText.horizontal_axis_position',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'chart.bubble.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.configText.y_axis', \n description: 'chart.configText.vertical_axis_position',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.bubble.dropZone.yAxis.empty'\n },\n {\n key: 'sizeField',\n label: 'chart.configText.bubble_radius',\n description: 'chart.configText.size_of_bubbles_based_on_this_measure',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.bubble.dropZone.sizeField.empty'\n },\n {\n key: 'series',\n label: 'chart.configText.bubble_labels',\n description: 'chart.configText.field_to_use_for_bubble_labels_and_identification',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension'],\n emptyText: 'chart.bubble.dropZone.series.empty'\n },\n {\n key: 'colorField',\n label: 'chart.configText.bubble_colour',\n description: 'chart.configText.color_bubbles_by_this_field_optional',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension', 'measure'],\n emptyText: 'chart.bubble.dropZone.colorField.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'minBubbleSize', 'maxBubbleSize', 'bubbleOpacity', 'hideHeader'],\n displayOptionsConfig: [\n {\n key: 'xAxisFormat',\n label: 'chart.option.xAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.xAxisFormat.description'\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_y_axis_and_values'\n }\n ]\n}"],"mappings":";;2DAKa,IAAqC;CAChD,OAAO;CACP,aAAa;CACb,SAAS;CACT,cAAc,EAAE,iBAAc,wBACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAyC,IAC9F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAA4B,IAChF,EAAE,WAAW,GAAK;CAE3B,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa;IAAC;IAAa;IAAiB;GAAS;GACrD,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,SAAS;GACvB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,SAAS;GACvB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,aAAa,SAAS;GACpC,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAiB;EAAiB;EAAiB;CAAY;CACzH,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,GACA;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
1
+ {"version":3,"file":"chart-config-bubble-gIoqVyjZ.js","names":[],"sources":["../../../src/client/components/charts/BubbleChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\n\n/**\n * Configuration for the bubble chart type\n */\nexport const bubbleChartConfig: ChartTypeConfig = {\n label: 'chart.bubble.label',\n description: 'chart.bubble.description',\n useCase: 'chart.bubble.useCase',\n isAvailable: ({ measureCount, dimensionCount }) => {\n if (measureCount < 2) return { available: false, reason: 'chart.availability.requiresTwoMeasures' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.bubble' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.runtime.axisFormat.xAxis',\n description: 'chart.configText.horizontal_axis_position',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'chart.bubble.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.configText.y_axis', \n description: 'chart.configText.vertical_axis_position',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.bubble.dropZone.yAxis.empty'\n },\n {\n key: 'sizeField',\n label: 'chart.configText.bubble_radius',\n description: 'chart.configText.size_of_bubbles_based_on_this_measure',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.bubble.dropZone.sizeField.empty'\n },\n {\n key: 'series',\n label: 'chart.configText.bubble_labels',\n description: 'chart.configText.field_to_use_for_bubble_labels_and_identification',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['dimension'],\n emptyText: 'chart.bubble.dropZone.series.empty'\n },\n {\n key: 'colorField',\n label: 'chart.configText.bubble_colour',\n description: 'chart.configText.color_bubbles_by_this_field_optional',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension', 'measure'],\n emptyText: 'chart.bubble.dropZone.colorField.empty'\n }\n ],\n displayOptions: ['showLegend', 'showGrid', 'showTooltip', 'minBubbleSize', 'maxBubbleSize', 'bubbleOpacity', 'hideHeader'],\n displayOptionsConfig: [\n {\n key: 'xAxisFormat',\n label: 'chart.option.xAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.option.xAxisFormat.description'\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_y_axis_and_values'\n }\n ]\n}"],"mappings":";;2DAKa,IAAqC;CAChD,OAAO;CACP,aAAa;CACb,SAAS;CACT,cAAc,EAAE,iBAAc,wBACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAyC,IAC9F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAA4B,IAChF,EAAE,WAAW,GAAK;CAE3B,WAAW;EACT;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa;IAAC;IAAa;IAAiB;GAAS;GACrD,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,SAAS;GACvB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,SAAS;GACvB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,WAAW;GACzB,WAAW;EACb;EACA;GACE,KAAK;GACL,OAAO;GACP,aAAa;GACb,WAAW;GACX,UAAU;GACV,aAAa,CAAC,aAAa,SAAS;GACpC,WAAW;EACb;CACF;CACA,gBAAgB;EAAC;EAAc;EAAY;EAAe;EAAiB;EAAiB;EAAiB;CAAY;CACzH,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,GACA;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-candlestick-N6DchAA3.js","names":[],"sources":["../../../src/client/components/charts/CandlestickChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the candlestick chart type\n */\nexport const candlestickChartConfig: ChartTypeConfig = {\n label: 'chart.candlestick.label',\n description: 'chart.candlestick.description',\n useCase: 'chart.candlestick.useCase',\n clickableElements: { bar: true },\n displayOptions: ['hideHeader'],\n isAvailable: ({ measureCount, dimensionCount }) => {\n if (measureCount < 2) return { available: false, reason: 'chart.availability.requiresTwoMeasures' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.requiresDimension' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_time_category',\n description: 'chart.configText.time_dimension_or_category_for_each_candle_e_g_date_symbol',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['timeDimension', 'dimension'],\n emptyText: 'chart.candlestick.dropZone.xAxis.empty',\n },\n {\n key: 'yAxis',\n label: 'chart.configText.ohlc_measures_open_close_high_low',\n description: 'chart.configText.drop_2_4_measures_in_order_open_close_high_low_ohlc_mode_for_range_mode_',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.candlestick.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'rangeMode',\n label: 'chart.option.rangeMode.label',\n type: 'select',\n defaultValue: 'ohlc',\n options: [\n { value: 'ohlc', label: 'chart.option.rangeMode.ohlc' },\n { value: 'range', label: 'chart.option.rangeMode.range' },\n ],\n description: 'chart.option.rangeMode.description',\n },\n {\n key: 'bullColor',\n label: 'chart.option.bullColor.label',\n type: 'color',\n defaultValue: '#22c55e',\n description: 'chart.option.bullColor.description',\n },\n {\n key: 'bearColor',\n label: 'chart.option.bearColor.label',\n type: 'color',\n defaultValue: '#ef4444',\n description: 'chart.option.bearColor.description',\n },\n {\n key: 'showWicks',\n label: 'chart.option.showWicks.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showWicks.description',\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_price_axis',\n },\n ],\n}\n"],"mappings":";;gEAKa,IAA0C;CACrD,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,EAAE,KAAK,GAAK;CAC/B,gBAAgB,CAAC,YAAY;CAC7B,cAAc,EAAE,iBAAc,wBACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAyC,IAC9F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAuC,IAC3F,EAAE,WAAW,GAAK;CAE3B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,iBAAiB,WAAW;EAC1C,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;GAA8B,GACtD;IAAE,OAAO;IAAS,OAAO;GAA+B,CAC1D;GACA,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;CACF;AACF"}
1
+ {"version":3,"file":"chart-config-candlestick-N6DchAA3.js","names":[],"sources":["../../../src/client/components/charts/CandlestickChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\n\n/**\n * Configuration for the candlestick chart type\n */\nexport const candlestickChartConfig: ChartTypeConfig = {\n label: 'chart.candlestick.label',\n description: 'chart.candlestick.description',\n useCase: 'chart.candlestick.useCase',\n clickableElements: { bar: true },\n displayOptions: ['hideHeader'],\n isAvailable: ({ measureCount, dimensionCount }) => {\n if (measureCount < 2) return { available: false, reason: 'chart.availability.requiresTwoMeasures' }\n if (dimensionCount < 1) return { available: false, reason: 'chart.availability.requiresDimension' }\n return { available: true }\n },\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.x_axis_time_category',\n description: 'chart.configText.time_dimension_or_category_for_each_candle_e_g_date_symbol',\n mandatory: true,\n maxItems: 1,\n acceptTypes: ['timeDimension', 'dimension'],\n emptyText: 'chart.candlestick.dropZone.xAxis.empty',\n },\n {\n key: 'yAxis',\n label: 'chart.configText.ohlc_measures_open_close_high_low',\n description: 'chart.configText.drop_2_4_measures_in_order_open_close_high_low_ohlc_mode_for_range_mode_',\n mandatory: true,\n acceptTypes: ['measure'],\n emptyText: 'chart.candlestick.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'rangeMode',\n label: 'chart.option.rangeMode.label',\n type: 'select',\n defaultValue: 'ohlc',\n options: [\n { value: 'ohlc', label: 'chart.option.rangeMode.ohlc' },\n { value: 'range', label: 'chart.option.rangeMode.range' },\n ],\n description: 'chart.option.rangeMode.description',\n },\n {\n key: 'bullColor',\n label: 'chart.option.bullColor.label',\n type: 'color',\n defaultValue: '#22c55e',\n description: 'chart.option.bullColor.description',\n },\n {\n key: 'bearColor',\n label: 'chart.option.bearColor.label',\n type: 'color',\n defaultValue: '#ef4444',\n description: 'chart.option.bearColor.description',\n },\n {\n key: 'showWicks',\n label: 'chart.option.showWicks.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showWicks.description',\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.yAxisFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_price_axis',\n },\n ],\n}\n"],"mappings":";;gEAKa,IAA0C;CACrD,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,EAAE,KAAK,GAAK;CAC/B,gBAAgB,CAAC,YAAY;CAC7B,cAAc,EAAE,iBAAc,wBACxB,IAAe,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAyC,IAC9F,IAAiB,IAAU;EAAE,WAAW;EAAO,QAAQ;CAAuC,IAC3F,EAAE,WAAW,GAAK;CAE3B,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,iBAAiB,WAAW;EAC1C,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;GAA8B,GACtD;IAAE,OAAO;IAAS,OAAO;GAA+B,CAC1D;GACA,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-data-table-d7VBY-y_.js","names":[],"sources":["../../../src/client/components/charts/DataTable.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the data table type\n */\nexport const dataTableConfig: ChartTypeConfig = {\n label: 'chart.table.label',\n description: 'chart.table.description',\n useCase: 'chart.table.useCase',\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.columns',\n description: 'chart.configText.all_fields_to_display_as_columns',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'chart.table.dropZone.xAxis.empty'\n }\n ],\n displayOptions: ['hideHeader'],\n displayOptionsConfig: [\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_numeric_values'\n }\n ]\n}"],"mappings":";;yDAKa,IAAmC;CAC9C,OAAO;CACP,aAAa;CACb,SAAS;CACT,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa;GAAC;GAAa;GAAiB;EAAS;EACrD,WAAW;CACb,CACF;CACA,gBAAgB,CAAC,YAAY;CAC7B,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
1
+ {"version":3,"file":"chart-config-data-table-d7VBY-y_.js","names":[],"sources":["../../../src/client/components/charts/DataTable.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\n\n/**\n * Configuration for the data table type\n */\nexport const dataTableConfig: ChartTypeConfig = {\n label: 'chart.table.label',\n description: 'chart.table.description',\n useCase: 'chart.table.useCase',\n dropZones: [\n {\n key: 'xAxis',\n label: 'chart.configText.columns',\n description: 'chart.configText.all_fields_to_display_as_columns',\n mandatory: false,\n acceptTypes: ['dimension', 'timeDimension', 'measure'],\n emptyText: 'chart.table.dropZone.xAxis.empty'\n }\n ],\n displayOptions: ['hideHeader'],\n displayOptionsConfig: [\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_numeric_values'\n }\n ]\n}"],"mappings":";;yDAKa,IAAmC;CAC9C,OAAO;CACP,aAAa;CACb,SAAS;CACT,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,aAAa;GAAC;GAAa;GAAiB;EAAS;EACrD,WAAW;CACb,CACF;CACA,gBAAgB,CAAC,YAAY;CAC7B,sBAAsB,CACpB;EACE,KAAK;EACL,OAAO;EACP,MAAM;EACN,aAAa;CACf,CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-funnel-DEYMcxsD.js","names":[],"sources":["../../../src/client/components/charts/FunnelChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\n\n/**\n * Configuration for the funnel chart type\n *\n * Funnel charts visualize sequential conversion data.\n * They work with data from useFunnelQuery which provides\n * pre-calculated step names, values, and conversion rates.\n */\nexport const funnelChartConfig: ChartTypeConfig = {\n label: 'chart.funnel.label',\n description: 'chart.funnel.description',\n useCase: 'chart.funnel.useCase',\n dropZones: [\n // Funnel charts don't use traditional drop zones since they work with\n // pre-calculated funnel data from useFunnelQuery. The steps are defined\n // in the funnel configuration, not through drag-and-drop.\n // However, we keep xAxis and yAxis for compatibility with chart system.\n {\n key: 'xAxis',\n label: 'chart.configText.step_name',\n description: 'chart.configText.step_names_auto_populated_from_funnel_steps',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension'],\n emptyText: 'chart.funnel.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.configText.step_count',\n description: 'chart.configText.count_at_each_step_auto_calculated',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.funnel.dropZone.yAxis.empty'\n }\n ],\n displayOptions: ['hideHeader'],\n displayOptionsConfig: [\n {\n key: 'funnelStyle',\n label: 'chart.option.funnelStyle.label',\n type: 'buttonGroup',\n defaultValue: 'bars',\n options: [\n { value: 'bars', label: 'chart.option.funnelStyle.bars' },\n { value: 'funnel', label: 'chart.option.funnelStyle.funnel' }\n ],\n description: 'chart.configText.visualization_style'\n },\n {\n key: 'funnelOrientation',\n label: 'chart.option.funnelOrientation.label',\n type: 'buttonGroup',\n defaultValue: 'horizontal',\n options: [\n { value: 'horizontal', label: 'chart.option.funnelOrientation.horizontal' },\n { value: 'vertical', label: 'chart.option.funnelOrientation.vertical' }\n ]\n },\n {\n key: 'hideSummaryFooter',\n label: 'chart.option.hideSummaryFooter.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.hideSummaryFooter.description'\n },\n {\n key: 'showFunnelConversion',\n label: 'chart.option.showConversion.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showConversion.description'\n },\n {\n key: 'showFunnelAvgTime',\n label: 'chart.option.showAvgTime.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showAvgTime.description'\n },\n {\n key: 'showFunnelMedianTime',\n label: 'chart.option.showMedianTime.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showMedianTime.description'\n },\n {\n key: 'showFunnelP90Time',\n label: 'chart.option.showP90Time.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showP90Time.description'\n }\n ]\n}\n"],"mappings":";;2DASa,IAAqC;CAChD,OAAO;CACP,aAAa;CACb,SAAS;CACT,WAAW,CAKT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,WAAW;EACzB,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,gBAAgB,CAAC,YAAY;CAC7B,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;GAAgC,GACxD;IAAE,OAAO;IAAU,OAAO;GAAkC,CAC9D;GACA,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAc,OAAO;GAA4C,GAC1E;IAAE,OAAO;IAAY,OAAO;GAA0C,CACxE;EACF;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;CACF;AACF"}
1
+ {"version":3,"file":"chart-config-funnel-DEYMcxsD.js","names":[],"sources":["../../../src/client/components/charts/FunnelChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\n\n/**\n * Configuration for the funnel chart type\n *\n * Funnel charts visualize sequential conversion data.\n * They work with data from useFunnelQuery which provides\n * pre-calculated step names, values, and conversion rates.\n */\nexport const funnelChartConfig: ChartTypeConfig = {\n label: 'chart.funnel.label',\n description: 'chart.funnel.description',\n useCase: 'chart.funnel.useCase',\n dropZones: [\n // Funnel charts don't use traditional drop zones since they work with\n // pre-calculated funnel data from useFunnelQuery. The steps are defined\n // in the funnel configuration, not through drag-and-drop.\n // However, we keep xAxis and yAxis for compatibility with chart system.\n {\n key: 'xAxis',\n label: 'chart.configText.step_name',\n description: 'chart.configText.step_names_auto_populated_from_funnel_steps',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['dimension'],\n emptyText: 'chart.funnel.dropZone.xAxis.empty'\n },\n {\n key: 'yAxis',\n label: 'chart.configText.step_count',\n description: 'chart.configText.count_at_each_step_auto_calculated',\n mandatory: false,\n maxItems: 1,\n acceptTypes: ['measure'],\n emptyText: 'chart.funnel.dropZone.yAxis.empty'\n }\n ],\n displayOptions: ['hideHeader'],\n displayOptionsConfig: [\n {\n key: 'funnelStyle',\n label: 'chart.option.funnelStyle.label',\n type: 'buttonGroup',\n defaultValue: 'bars',\n options: [\n { value: 'bars', label: 'chart.option.funnelStyle.bars' },\n { value: 'funnel', label: 'chart.option.funnelStyle.funnel' }\n ],\n description: 'chart.configText.visualization_style'\n },\n {\n key: 'funnelOrientation',\n label: 'chart.option.funnelOrientation.label',\n type: 'buttonGroup',\n defaultValue: 'horizontal',\n options: [\n { value: 'horizontal', label: 'chart.option.funnelOrientation.horizontal' },\n { value: 'vertical', label: 'chart.option.funnelOrientation.vertical' }\n ]\n },\n {\n key: 'hideSummaryFooter',\n label: 'chart.option.hideSummaryFooter.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.hideSummaryFooter.description'\n },\n {\n key: 'showFunnelConversion',\n label: 'chart.option.showConversion.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showConversion.description'\n },\n {\n key: 'showFunnelAvgTime',\n label: 'chart.option.showAvgTime.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showAvgTime.description'\n },\n {\n key: 'showFunnelMedianTime',\n label: 'chart.option.showMedianTime.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showMedianTime.description'\n },\n {\n key: 'showFunnelP90Time',\n label: 'chart.option.showP90Time.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showP90Time.description'\n }\n ]\n}\n"],"mappings":";;2DASa,IAAqC;CAChD,OAAO;CACP,aAAa;CACb,SAAS;CACT,WAAW,CAKT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,WAAW;EACzB,WAAW;CACb,GACA;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,gBAAgB,CAAC,YAAY;CAC7B,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;GAAgC,GACxD;IAAE,OAAO;IAAU,OAAO;GAAkC,CAC9D;GACA,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAc,OAAO;GAA4C,GAC1E;IAAE,OAAO;IAAY,OAAO;GAA0C,CACxE;EACF;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"chart-config-gauge-Dq-_H9UN.js","names":[],"sources":["../../../src/client/components/charts/GaugeChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs'\nimport { requiresMeasure } from '../../charts/chartConfigHelpers'\n\n/**\n * Configuration for the gauge chart type\n */\nexport const gaugeChartConfig: ChartTypeConfig = {\n label: 'chart.gauge.label',\n description: 'chart.gauge.description',\n useCase: 'chart.gauge.useCase',\n clickableElements: {},\n displayOptions: ['hideHeader'],\n isAvailable: requiresMeasure,\n dropZones: [\n {\n key: 'yAxis',\n label: 'chart.configText.value_measure',\n description: 'chart.configText.current_value_to_display_on_the_gauge_e_g_current_equity_margin_used',\n mandatory: true,\n maxItems: 2,\n acceptTypes: ['measure'],\n emptyText: 'chart.gauge.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'minValue',\n label: 'chart.option.minValue.label',\n type: 'number',\n defaultValue: 0,\n description: 'chart.option.minValue.description',\n },\n {\n key: 'maxValue',\n label: 'chart.option.maxValue.label',\n type: 'number',\n description: 'chart.option.maxValue.description',\n },\n {\n key: 'thresholds',\n label: 'chart.configText.threshold_bands',\n type: 'string',\n placeholder: '[{\"value\":0.33,\"color\":\"#22c55e\"},{\"value\":0.66,\"color\":\"#f59e0b\"},{\"value\":1,\"color\":\"#ef4444\"}]',\n description: 'chart.configText.array_of_value_0_1_fraction_color_bands_shown_as_outer_arc_markers',\n },\n {\n key: 'showCenterLabel',\n label: 'chart.option.showCentreLabel.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showCentreLabel.description',\n },\n {\n key: 'showPercentage',\n label: 'chart.option.showPercentage.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showPercentage.description',\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_displayed_value_and_axis_labels',\n },\n ],\n}\n"],"mappings":";;;0DAMa,IAAoC;CAC/C,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,CAAC;CACpB,gBAAgB,CAAC,YAAY;CAC7B,aAAa;CACb,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;CACF;AACF"}
1
+ {"version":3,"file":"chart-config-gauge-Dq-_H9UN.js","names":[],"sources":["../../../src/client/components/charts/GaugeChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport { requiresMeasure } from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the gauge chart type\n */\nexport const gaugeChartConfig: ChartTypeConfig = {\n label: 'chart.gauge.label',\n description: 'chart.gauge.description',\n useCase: 'chart.gauge.useCase',\n clickableElements: {},\n displayOptions: ['hideHeader'],\n isAvailable: requiresMeasure,\n dropZones: [\n {\n key: 'yAxis',\n label: 'chart.configText.value_measure',\n description: 'chart.configText.current_value_to_display_on_the_gauge_e_g_current_equity_margin_used',\n mandatory: true,\n maxItems: 2,\n acceptTypes: ['measure'],\n emptyText: 'chart.gauge.dropZone.yAxis.empty',\n },\n ],\n displayOptionsConfig: [\n {\n key: 'minValue',\n label: 'chart.option.minValue.label',\n type: 'number',\n defaultValue: 0,\n description: 'chart.option.minValue.description',\n },\n {\n key: 'maxValue',\n label: 'chart.option.maxValue.label',\n type: 'number',\n description: 'chart.option.maxValue.description',\n },\n {\n key: 'thresholds',\n label: 'chart.configText.threshold_bands',\n type: 'string',\n placeholder: '[{\"value\":0.33,\"color\":\"#22c55e\"},{\"value\":0.66,\"color\":\"#f59e0b\"},{\"value\":1,\"color\":\"#ef4444\"}]',\n description: 'chart.configText.array_of_value_0_1_fraction_color_bands_shown_as_outer_arc_markers',\n },\n {\n key: 'showCenterLabel',\n label: 'chart.option.showCentreLabel.label',\n type: 'boolean',\n defaultValue: true,\n description: 'chart.option.showCentreLabel.description',\n },\n {\n key: 'showPercentage',\n label: 'chart.option.showPercentage.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showPercentage.description',\n },\n {\n key: 'leftYAxisFormat',\n label: 'chart.option.valueFormat.label',\n type: 'axisFormat',\n description: 'chart.configText.number_formatting_for_the_displayed_value_and_axis_labels',\n },\n ],\n}\n"],"mappings":";;;0DAMa,IAAoC;CAC/C,OAAO;CACP,aAAa;CACb,SAAS;CACT,mBAAmB,CAAC;CACpB,gBAAgB,CAAC,YAAY;CAC7B,aAAa;CACb,WAAW,CACT;EACE,KAAK;EACL,OAAO;EACP,aAAa;EACb,WAAW;EACX,UAAU;EACV,aAAa,CAAC,SAAS;EACvB,WAAW;CACb,CACF;CACA,sBAAsB;EACpB;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,cAAc;GACd,aAAa;EACf;EACA;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;EACf;CACF;AACF"}