drizzle-cube 0.6.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -106
- package/dist/adapters/ActivityGridChart.config-DaYILvFZ.cjs +1 -0
- package/dist/adapters/ActivityGridChart.config-_SyTBEyR.js +2 -0
- package/dist/adapters/AreaChart.config-BKh6fY1_.cjs +1 -0
- package/dist/adapters/AreaChart.config-CJoxLP3Y.js +2 -0
- package/dist/adapters/BarChart.config-Bm1bfRbI.cjs +1 -0
- package/dist/adapters/BarChart.config-CGu2Bqrx.js +2 -0
- package/dist/adapters/BoxPlotChart.config-B7M9CQaE.js +2 -0
- package/dist/adapters/BoxPlotChart.config-CXQel8Hk.cjs +1 -0
- package/dist/adapters/BubbleChart.config-BJ36IuVS.cjs +1 -0
- package/dist/adapters/BubbleChart.config-CWoXeLdm.js +2 -0
- package/dist/adapters/CandlestickChart.config-CGMLZVIy.cjs +1 -0
- package/dist/adapters/CandlestickChart.config-CzOcfF1e.js +2 -0
- package/dist/adapters/DataTable.config-CdAzueTs.cjs +1 -0
- package/dist/adapters/DataTable.config-D_KmPyxV.js +2 -0
- package/dist/adapters/FunnelChart.config-D1QAUuYl.cjs +1 -0
- package/dist/adapters/FunnelChart.config-DCRHQoFc.js +2 -0
- package/dist/adapters/GaugeChart.config-DAybRXP3.js +2 -0
- package/dist/adapters/GaugeChart.config-WUPfyLP-.cjs +1 -0
- package/dist/adapters/HeatMapChart.config-CziltPnC.cjs +1 -0
- package/dist/adapters/HeatMapChart.config-DHpXNONW.js +2 -0
- package/dist/adapters/KpiDelta.config-Bw5o0ocY.js +2 -0
- package/dist/adapters/KpiDelta.config-CdAmE1pw.cjs +1 -0
- package/dist/adapters/KpiNumber.config-CQ_wq2gx.js +2 -0
- package/dist/adapters/KpiNumber.config-wxN8x4DC.cjs +1 -0
- package/dist/adapters/KpiText.config-DIRIC97F.cjs +1 -0
- package/dist/adapters/KpiText.config-eODcP6Hn.js +2 -0
- package/dist/adapters/LineChart.config-32-9zA2V.js +2 -0
- package/dist/adapters/LineChart.config-BukeFp6z.cjs +1 -0
- package/dist/adapters/MarkdownChart.config-BVsR5LDy.js +2 -0
- package/dist/adapters/MarkdownChart.config-j4veYjcZ.cjs +1 -0
- package/dist/adapters/MeasureProfileChart.config-BRDYx1hw.js +2 -0
- package/dist/adapters/MeasureProfileChart.config-CIosBxco.cjs +1 -0
- package/dist/adapters/PieChart.config-Bj8KiA0n.cjs +1 -0
- package/dist/adapters/PieChart.config-DgAj3y-I.js +2 -0
- package/dist/adapters/ProportionBarChart.config-BfFOppHY.js +2 -0
- package/dist/adapters/ProportionBarChart.config-c8GGE1aK.cjs +1 -0
- package/dist/adapters/RadarChart.config-D7iHY1v9.js +2 -0
- package/dist/adapters/RadarChart.config-ghlANG2-.cjs +1 -0
- package/dist/adapters/RadialBarChart.config-CsXIz-0v.js +2 -0
- package/dist/adapters/RadialBarChart.config-Dsvu2CPV.cjs +1 -0
- package/dist/adapters/RetentionCombinedChart.config-CdT1kXC7.js +2 -0
- package/dist/adapters/RetentionCombinedChart.config-sDjFKH9K.cjs +1 -0
- package/dist/adapters/RetentionHeatmap.config-CvKBvQmu.cjs +1 -0
- package/dist/adapters/RetentionHeatmap.config-DbM3ICwc.js +2 -0
- package/dist/adapters/SankeyChart.config-BNBcIHaD.js +2 -0
- package/dist/adapters/SankeyChart.config-DZscz3kh.cjs +1 -0
- package/dist/adapters/ScatterChart.config-BNYIddyM.cjs +1 -0
- package/dist/adapters/ScatterChart.config-CEhtoLWc.js +2 -0
- package/dist/adapters/SunburstChart.config-ClseCzji.cjs +1 -0
- package/dist/adapters/SunburstChart.config-nnphNoVO.js +2 -0
- package/dist/adapters/TreeMapChart.config-C8-75muA.js +2 -0
- package/dist/adapters/TreeMapChart.config-DoXeUg9Y.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-BOF1qxY3.cjs +1 -0
- package/dist/adapters/WaterfallChart.config-uW5YyOji.js +2 -0
- package/dist/adapters/chartConfigHelpers-BZMu_1EP.cjs +1 -0
- package/dist/adapters/{chartConfigHelpers-CcvqrIWF.js → chartConfigHelpers-BsnbxA2c.js} +30 -1
- package/dist/adapters/compiler-DAyodAnH.cjs +166 -0
- package/dist/adapters/{compiler-ZruQ85ff.js → compiler-Dq04wAjm.js} +116 -60
- package/dist/adapters/core/index.cjs +1 -1
- package/dist/adapters/core/index.js +1 -1
- package/dist/adapters/{core-BMZhIzaI.js → core-BjxfG6Uf.js} +8 -8
- package/dist/adapters/core-zV2w0hO2.cjs +1 -0
- package/dist/adapters/{dist-CH3hwAUk.js → dist-ChBfLb7x.js} +7 -4
- package/dist/adapters/{dist-BOdf-GQO.cjs → dist-CohrBmKe.cjs} +2 -2
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.js +5 -5
- package/dist/adapters/fastify/index.cjs +2 -2
- package/dist/adapters/fastify/index.js +10 -6
- package/dist/adapters/google-BhvizbFR.cjs +2 -0
- package/dist/adapters/{google-CvKM9yVM.js → google-eKAc20al.js} +3 -3
- package/dist/adapters/{handler-_PXp3G47.cjs → handler-C6Hj6_Yk.cjs} +9 -9
- package/dist/adapters/{handler-xR2P1EI4.js → handler-ox6qxLw5.js} +230 -152
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +26 -18
- package/dist/adapters/mcp-tools.cjs +1 -1
- package/dist/adapters/mcp-tools.js +2 -2
- package/dist/adapters/mcp-transport-C_t_p0wU.cjs +40 -0
- package/dist/adapters/mcp-transport-DFH9e6de.js +603 -0
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +14 -11
- package/dist/{server/openai-C3-mjSAc.cjs → adapters/openai-BffpdO4n.cjs} +1 -1
- package/dist/adapters/openai-C9LNhHfK.js +9295 -0
- package/dist/adapters/{openai-B6hWZk_r.js → openai-CmyXJWti.js} +18 -17
- package/dist/adapters/openai-DlT-0VRC.cjs +19 -0
- package/dist/adapters/utils-C5FLHK04.cjs +128 -0
- package/dist/adapters/{utils-U7gV5wQL.js → utils-tjiwXFnP.js} +69 -17
- package/dist/adapters/utils.cjs +1 -1
- package/dist/adapters/utils.js +1 -1
- package/dist/cjs/client/charts/chartConfigHelpers.d.ts +20 -0
- package/dist/cjs/client/components/AgenticNotebook/AgentChatPanel.d.ts +1 -1
- package/dist/cjs/client/components/AgenticNotebook/ChatInput.d.ts +1 -1
- package/dist/cjs/client/components/AgenticNotebook/ChatMessage.d.ts +1 -1
- package/dist/cjs/client/components/AgenticNotebook/NotebookCanvas.d.ts +2 -2
- package/dist/cjs/client/components/AgenticNotebook/NotebookMarkdownBlock.d.ts +1 -1
- package/dist/cjs/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +1 -1
- package/dist/cjs/client/components/AgenticNotebook/index.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/BreakdownComparisonToggle.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/BreakdownRow.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/BreakdownSection.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/ExecutionPlanPanel.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FieldSearchResults.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FlowConfigPanel.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FlowDepthControls.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FlowModeContent.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FlowVisualizationPicker.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FunnelBindingKeySelector.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FunnelConfigPanel.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FunnelModeContent.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FunnelStepCard.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/FunnelStepList.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/LegacyBooleanOptions.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/MetricItemCard.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/MetricRow.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/MetricsSection.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +2 -2
- package/dist/cjs/client/components/AnalysisBuilder/RetentionModeContent.d.ts +1 -1
- package/dist/cjs/client/components/AnalysisBuilder/SortToggleButton.d.ts +1 -1
- package/dist/cjs/client/components/DashboardPortletCard.d.ts +1 -1
- package/dist/cjs/client/components/DataBrowser/DataBrowserTable.d.ts +1 -1
- package/dist/cjs/client/components/PortletGroupCard.d.ts +18 -0
- package/dist/cjs/client/components/RowManagedLayout.d.ts +15 -3
- package/dist/cjs/client/components/analyticsPortlet/intrinsicChartHeight.d.ts +9 -0
- package/dist/cjs/client/components/charts/ActivityGridChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/AngledXAxisTick.d.ts +5 -0
- package/dist/cjs/client/components/charts/AreaChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/BarChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/BoxPlotChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/BubbleChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/CandlestickChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/ChartContainer.d.ts +7 -1
- package/dist/cjs/client/components/charts/ChartSummaryHeader.d.ts +31 -0
- package/dist/cjs/client/components/charts/DataTable.d.ts +1 -1
- package/dist/cjs/client/components/charts/FunnelChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/GaugeChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/HeatMapChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/KpiCompactLayout.d.ts +31 -0
- package/dist/cjs/client/components/charts/KpiDelta.d.ts +1 -1
- package/dist/cjs/client/components/charts/KpiDelta.helpers.d.ts +2 -0
- package/dist/cjs/client/components/charts/KpiNumber.d.ts +1 -1
- package/dist/cjs/client/components/charts/KpiStates.d.ts +7 -2
- package/dist/cjs/client/components/charts/KpiText.d.ts +1 -1
- package/dist/cjs/client/components/charts/LineChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/MarkdownChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/MeasureProfileChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/PieChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/ProportionBarChart.config.d.ts +10 -0
- package/dist/cjs/client/components/charts/ProportionBarChart.d.ts +12 -0
- package/dist/cjs/client/components/charts/RadarChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/RadialBarChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/RetentionCombinedChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/RetentionHeatmap.d.ts +1 -1
- package/dist/cjs/client/components/charts/SankeyChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/ScatterChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/SunburstChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/TreeMapChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/WaterfallChart.d.ts +1 -1
- package/dist/cjs/client/components/charts/cartesianChartHelpers.d.ts +62 -0
- package/dist/cjs/client/components/charts/chartScaffolding.d.ts +29 -0
- package/dist/cjs/client/components/dashboard/DashboardContext.d.ts +5 -1
- package/dist/cjs/client/components/dashboard/dashboardGridUtils.d.ts +2 -4
- package/dist/cjs/client/components/dashboardPortletCard/EditActionButtons.d.ts +34 -0
- package/dist/cjs/client/components/dashboardPortletCard/PortletCardHeader.d.ts +2 -12
- package/dist/cjs/client/components/dashboardPortletCard/PortletFloatingActions.d.ts +24 -0
- package/dist/cjs/client/components/dashboardPortletCard/cardStyles.d.ts +5 -0
- package/dist/cjs/client/components/dashboardPortletCard/propsEqual.d.ts +2 -0
- package/dist/cjs/client/components/mobileStackedLayout/memberDisplay.d.ts +21 -0
- package/dist/cjs/client/components.d.ts +1 -1
- package/dist/cjs/client/hooks/dashboard/groupGeometry.d.ts +23 -0
- package/dist/cjs/client/hooks/dashboard/groupUtils.d.ts +57 -0
- package/dist/cjs/client/hooks/dashboard/layoutUtils.d.ts +34 -3
- package/dist/cjs/client/hooks/dashboard/useDashboardController.d.ts +11 -3
- package/dist/cjs/client/hooks/dashboard/useRowLayoutEngine.d.ts +12 -2
- package/dist/cjs/client/hooks/useDashboardHook.d.ts +14 -1
- package/dist/cjs/client/icons/types.d.ts +1 -0
- package/dist/cjs/client/index.d.ts +1 -1
- package/dist/cjs/client/stores/dashboardStore.d.ts +11 -1
- package/dist/cjs/client/types.d.ts +37 -2
- package/dist/cli/index.cjs +6 -5
- package/dist/client/charts/chartConfigHelpers.d.ts +20 -0
- package/dist/client/charts.js +13 -13
- package/dist/client/chunks/DashboardEditModal-ByXLlXZD.js +11777 -0
- package/dist/client/chunks/DashboardEditModal-ByXLlXZD.js.map +1 -0
- package/dist/client/chunks/ProportionBarChart-lOeVz8ZC.js +109 -0
- package/dist/client/chunks/ProportionBarChart-lOeVz8ZC.js.map +1 -0
- package/dist/client/chunks/{RetentionCombinedChart-DY7wKLs5.js → RetentionCombinedChart-Mcm7zHFx.js} +8 -8
- package/dist/client/chunks/{RetentionCombinedChart-DY7wKLs5.js.map → RetentionCombinedChart-Mcm7zHFx.js.map} +1 -1
- package/dist/client/chunks/{RetentionHeatmap-iNCG-dLd.js → RetentionHeatmap-4VJx5KDM.js} +6 -6
- package/dist/client/chunks/{RetentionHeatmap-iNCG-dLd.js.map → RetentionHeatmap-4VJx5KDM.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-BDWychCW.js → analysis-builder-CWTJQQtL.js} +421 -413
- package/dist/client/chunks/analysis-builder-CWTJQQtL.js.map +1 -0
- package/dist/client/chunks/{analysis-builder-shared-DkL0e-wU.js → analysis-builder-shared-l-4WKVS1.js} +454 -452
- package/dist/client/chunks/analysis-builder-shared-l-4WKVS1.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-DDqFVWoa.js → chart-activity-grid-DVOhLgxv.js} +61 -6
- package/dist/client/chunks/{chart-activity-grid-DDqFVWoa.js.map → chart-activity-grid-DVOhLgxv.js.map} +1 -1
- package/dist/client/chunks/chart-area-C-5ATxvi.js +963 -0
- package/dist/client/chunks/chart-area-C-5ATxvi.js.map +1 -0
- package/dist/client/chunks/{chart-bar-DAO3PPcE.js → chart-bar-CPiLaXHP.js} +71 -64
- package/dist/client/chunks/chart-bar-CPiLaXHP.js.map +1 -0
- package/dist/client/chunks/{chart-box-plot-CUpFyQQk.js → chart-box-plot-Bae5O9xC.js} +3 -3
- package/dist/client/chunks/{chart-box-plot-CUpFyQQk.js.map → chart-box-plot-Bae5O9xC.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-DvP_6_n9.js → chart-bubble-BFN5WIpf.js} +5 -5
- package/dist/client/chunks/{chart-bubble-DvP_6_n9.js.map → chart-bubble-BFN5WIpf.js.map} +1 -1
- package/dist/client/chunks/{chart-candlestick-Dx8ZCMzl.js → chart-candlestick-PBQKp_z7.js} +3 -3
- package/dist/client/chunks/{chart-candlestick-Dx8ZCMzl.js.map → chart-candlestick-PBQKp_z7.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-BU_bkvER.js → chart-config-activity-grid-C4vXGQNu.js} +2 -2
- package/dist/client/chunks/{chart-config-activity-grid-BU_bkvER.js.map → chart-config-activity-grid-C4vXGQNu.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-DxwIZ4Uf.js → chart-config-area-DsrZCIwF.js} +35 -4
- package/dist/client/chunks/chart-config-area-DsrZCIwF.js.map +1 -0
- package/dist/client/chunks/{chart-config-bar-Cc8GY9aQ.js → chart-config-bar-BixSs43E.js} +7 -7
- package/dist/client/chunks/{chart-config-bar-Cc8GY9aQ.js.map → chart-config-bar-BixSs43E.js.map} +1 -1
- package/dist/client/chunks/{chart-config-box-plot-Bs8ovYvV.js → chart-config-box-plot-DMuJZqkr.js} +2 -2
- package/dist/client/chunks/{chart-config-box-plot-Bs8ovYvV.js.map → chart-config-box-plot-DMuJZqkr.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-BfgY7pt8.js → chart-config-bubble-1IyZinH0.js} +2 -2
- package/dist/client/chunks/{chart-config-bubble-BfgY7pt8.js.map → chart-config-bubble-1IyZinH0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-candlestick-jaeNNEtC.js → chart-config-candlestick-QwQwJB_-.js} +2 -2
- package/dist/client/chunks/{chart-config-candlestick-jaeNNEtC.js.map → chart-config-candlestick-QwQwJB_-.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-CRk0C0rW.js → chart-config-data-table-CrGyS7aJ.js} +2 -2
- package/dist/client/chunks/{chart-config-data-table-CRk0C0rW.js.map → chart-config-data-table-CrGyS7aJ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-boT_LNfl.js → chart-config-funnel-DMLLKtPF.js} +2 -2
- package/dist/client/chunks/{chart-config-funnel-boT_LNfl.js.map → chart-config-funnel-DMLLKtPF.js.map} +1 -1
- package/dist/client/chunks/{chart-config-gauge-C5uJEr97.js → chart-config-gauge-DNafFwfS.js} +2 -2
- package/dist/client/chunks/{chart-config-gauge-C5uJEr97.js.map → chart-config-gauge-DNafFwfS.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-CCarP44-.js → chart-config-heat-map-CJF65SyL.js} +2 -2
- package/dist/client/chunks/{chart-config-heat-map-CCarP44-.js.map → chart-config-heat-map-CJF65SyL.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-DYopvwyG.js → chart-config-kpi-delta-Cl7k6jTj.js} +13 -4
- package/dist/client/chunks/chart-config-kpi-delta-Cl7k6jTj.js.map +1 -0
- package/dist/client/chunks/{chart-config-kpi-number-BhMdoArB.js → chart-config-kpi-number-DCcnANWC.js} +6 -4
- package/dist/client/chunks/chart-config-kpi-number-DCcnANWC.js.map +1 -0
- package/dist/client/chunks/{chart-config-kpi-text-DE6Zdi53.js → chart-config-kpi-text-DnnxvOSA.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-text-DE6Zdi53.js.map → chart-config-kpi-text-DnnxvOSA.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line-CBfM0Rds.js → chart-config-line-CBF9Px9b.js} +9 -7
- package/dist/client/chunks/chart-config-line-CBF9Px9b.js.map +1 -0
- package/dist/client/chunks/{chart-config-markdown-BCDyBI8K.js → chart-config-markdown-C5kBQOjP.js} +2 -2
- package/dist/client/chunks/{chart-config-markdown-BCDyBI8K.js.map → chart-config-markdown-C5kBQOjP.js.map} +1 -1
- package/dist/client/chunks/{chart-config-measure-profile-BgQIH1u2.js → chart-config-measure-profile-CRSRIpKh.js} +2 -2
- package/dist/client/chunks/{chart-config-measure-profile-BgQIH1u2.js.map → chart-config-measure-profile-CRSRIpKh.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-ChfFz6DV.js → chart-config-pie-DZLa6Eqm.js} +3 -3
- package/dist/client/chunks/{chart-config-pie-ChfFz6DV.js.map → chart-config-pie-DZLa6Eqm.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-BlAIGnww.js → chart-config-radar-DR6vHHyd.js} +3 -3
- package/dist/client/chunks/{chart-config-radar-BlAIGnww.js.map → chart-config-radar-DR6vHHyd.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-VFerwbCO.js → chart-config-radial-bar-DVFou4fB.js} +3 -3
- package/dist/client/chunks/{chart-config-radial-bar-VFerwbCO.js.map → chart-config-radial-bar-DVFou4fB.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-BhrDxIgj.js → chart-config-sankey-De8E0C1A.js} +2 -2
- package/dist/client/chunks/{chart-config-sankey-BhrDxIgj.js.map → chart-config-sankey-De8E0C1A.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-q_olh54e.js → chart-config-scatter-CWA89oX4.js} +2 -2
- package/dist/client/chunks/{chart-config-scatter-q_olh54e.js.map → chart-config-scatter-CWA89oX4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-BOmkOnKn.js → chart-config-sunburst-B4NUYHMH.js} +2 -2
- package/dist/client/chunks/{chart-config-sunburst-BOmkOnKn.js.map → chart-config-sunburst-B4NUYHMH.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-BjX88YBY.js → chart-config-tree-map-Uhise6Bx.js} +3 -3
- package/dist/client/chunks/{chart-config-tree-map-BjX88YBY.js.map → chart-config-tree-map-Uhise6Bx.js.map} +1 -1
- package/dist/client/chunks/{chart-config-waterfall-QsWXVSoF.js → chart-config-waterfall-DlQb_PLh.js} +2 -2
- package/dist/client/chunks/{chart-config-waterfall-QsWXVSoF.js.map → chart-config-waterfall-DlQb_PLh.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-BP6DMdom.js → chart-data-table-SNSqZj9B.js} +1072 -1034
- package/dist/client/chunks/chart-data-table-SNSqZj9B.js.map +1 -0
- package/dist/client/chunks/{chart-funnel-xeVGBy-p.js → chart-funnel-CkHSXp6h.js} +3 -3
- package/dist/client/chunks/{chart-funnel-xeVGBy-p.js.map → chart-funnel-CkHSXp6h.js.map} +1 -1
- package/dist/client/chunks/{chart-gauge-DXQ4r3cb.js → chart-gauge-DHIGq3TH.js} +62 -62
- package/dist/client/chunks/{chart-gauge-DXQ4r3cb.js.map → chart-gauge-DHIGq3TH.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-Pnk6rhqQ.js → chart-heat-map-Bb8L1XQr.js} +4 -4
- package/dist/client/chunks/{chart-heat-map-Pnk6rhqQ.js.map → chart-heat-map-Bb8L1XQr.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-nXQnRRBr.js → chart-kpi-delta-BJCOXE-F.js} +122 -48
- package/dist/client/chunks/chart-kpi-delta-BJCOXE-F.js.map +1 -0
- package/dist/client/chunks/chart-kpi-number-Cdqgv20g.js +263 -0
- package/dist/client/chunks/chart-kpi-number-Cdqgv20g.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-text-CurpqmaD.js → chart-kpi-text-B10ZHCsI.js} +4 -4
- package/dist/client/chunks/{chart-kpi-text-CurpqmaD.js.map → chart-kpi-text-B10ZHCsI.js.map} +1 -1
- package/dist/client/chunks/chart-line-CzvVL3Be.js +117 -0
- package/dist/client/chunks/chart-line-CzvVL3Be.js.map +1 -0
- package/dist/client/chunks/{chart-markdown-BVrqqygz.js → chart-markdown-C0xxBW81.js} +1550 -1349
- package/dist/client/chunks/chart-markdown-C0xxBW81.js.map +1 -0
- package/dist/client/chunks/{chart-measure-profile-k9_QDQbB.js → chart-measure-profile-BSUPFZCR.js} +6 -5
- package/dist/client/chunks/{chart-measure-profile-k9_QDQbB.js.map → chart-measure-profile-BSUPFZCR.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-BDaaYt7a.js → chart-pie-CwRfwWWZ.js} +11 -11
- package/dist/client/chunks/{chart-pie-BDaaYt7a.js.map → chart-pie-CwRfwWWZ.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-Bz07PIVe.js → chart-radar-Dfql2E7i.js} +10 -10
- package/dist/client/chunks/{chart-radar-Bz07PIVe.js.map → chart-radar-Dfql2E7i.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DpyxKQMj.js → chart-radial-bar-oE9OZ1IX.js} +11 -11
- package/dist/client/chunks/{chart-radial-bar-DpyxKQMj.js.map → chart-radial-bar-oE9OZ1IX.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-BAeNbI-p.js → chart-sankey-tK7Oz1bC.js} +3 -3
- package/dist/client/chunks/{chart-sankey-BAeNbI-p.js.map → chart-sankey-tK7Oz1bC.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-CRhGLCcy.js → chart-scatter-BtLfAsZb.js} +10 -10
- package/dist/client/chunks/{chart-scatter-CRhGLCcy.js.map → chart-scatter-BtLfAsZb.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-D3wV5OrK.js → chart-sunburst-B7ryWwQ1.js} +4 -4
- package/dist/client/chunks/{chart-sunburst-D3wV5OrK.js.map → chart-sunburst-B7ryWwQ1.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-iI3ewOKY.js → chart-tree-map-DU5M3-qe.js} +31 -29
- package/dist/client/chunks/{chart-tree-map-iI3ewOKY.js.map → chart-tree-map-DU5M3-qe.js.map} +1 -1
- package/dist/client/chunks/{chart-waterfall-BrrYTZfs.js → chart-waterfall-CAwutpzd.js} +4 -4
- package/dist/client/chunks/{chart-waterfall-BrrYTZfs.js.map → chart-waterfall-CAwutpzd.js.map} +1 -1
- package/dist/client/chunks/{charts-core-Cs-UIsQa.js → charts-core-BxBB2zBE.js} +2 -2
- package/dist/client/chunks/{charts-core-Cs-UIsQa.js.map → charts-core-BxBB2zBE.js.map} +1 -1
- package/dist/client/chunks/charts-loader-0avVzeDd.js +85 -0
- package/dist/client/chunks/charts-loader-0avVzeDd.js.map +1 -0
- package/dist/client/chunks/{core-D7vPfUIe.js → core-BWRP9s8x.js} +9 -8
- package/dist/client/chunks/core-BWRP9s8x.js.map +1 -0
- package/dist/client/chunks/{dist-BwQr11Fz.js → dist-BPmPx7kz.js} +56 -51
- package/dist/client/chunks/{dist-BwQr11Fz.js.map → dist-BPmPx7kz.js.map} +1 -1
- package/dist/client/chunks/{exceljs.min-Dey-qIFL.js → exceljs.min-DWC_b8G9.js} +236 -202
- package/dist/client/chunks/{exceljs.min-Dey-qIFL.js.map → exceljs.min-DWC_b8G9.js.map} +1 -1
- package/dist/client/chunks/{javascript-DFnKaHmQ.js → javascript-D6aJaG8F.js} +7 -5
- package/dist/client/chunks/javascript-D6aJaG8F.js.map +1 -0
- package/dist/client/chunks/json-BrJhaXJI.js +44 -0
- package/dist/client/chunks/json-BrJhaXJI.js.map +1 -0
- package/dist/client/chunks/{nl-NL-2zTAWTej.js → nl-NL-BSMhprPr.js} +57 -2
- package/dist/client/chunks/{nl-NL-2zTAWTej.js.map → nl-NL-BSMhprPr.js.map} +1 -1
- package/dist/client/chunks/{rolldown-runtime-CWhphoD1.js → rolldown-runtime-DArdT4gl.js} +2 -2
- package/dist/client/chunks/{schema-visualization-BGT_cNon.js → schema-visualization-CGbnbzj_.js} +10 -10
- package/dist/client/chunks/schema-visualization-CGbnbzj_.js.map +1 -0
- package/dist/client/chunks/{syntaxHighlighting-Bq2Bj9Xt.js → syntaxHighlighting-Cm43as8i.js} +2 -2
- package/dist/client/chunks/{syntaxHighlighting-Bq2Bj9Xt.js.map → syntaxHighlighting-Cm43as8i.js.map} +1 -1
- package/dist/client/chunks/{useDebounce-7suCFq9v.js → useDirtyStateTracking-Dc-Si4db.js} +112 -50
- package/dist/client/chunks/useDirtyStateTracking-Dc-Si4db.js.map +1 -0
- package/dist/client/chunks/{useExplainAI-DueJjb0r.js → useExplainAI-DJbc7Lu4.js} +18 -18
- package/dist/client/chunks/{useExplainAI-DueJjb0r.js.map → useExplainAI-DJbc7Lu4.js.map} +1 -1
- package/dist/client/chunks/{utils-DjLiJKS_.js → utils-CToHkuhU.js} +2 -2
- package/dist/client/chunks/{utils-DjLiJKS_.js.map → utils-CToHkuhU.js.map} +1 -1
- package/dist/client/chunks/{vendor-ChnlgSP0.js → vendor-cTfe9Kho.js} +223 -167
- package/dist/client/chunks/vendor-cTfe9Kho.js.map +1 -0
- package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +1 -1
- package/dist/client/components/AgenticNotebook/ChatInput.d.ts +1 -1
- package/dist/client/components/AgenticNotebook/ChatMessage.d.ts +1 -1
- package/dist/client/components/AgenticNotebook/NotebookCanvas.d.ts +2 -2
- package/dist/client/components/AgenticNotebook/NotebookMarkdownBlock.d.ts +1 -1
- package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +1 -1
- package/dist/client/components/AgenticNotebook/index.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/BreakdownComparisonToggle.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/BreakdownRow.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/BreakdownSection.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/ExecutionPlanPanel.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FieldSearchResults.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FlowConfigPanel.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FlowDepthControls.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FlowModeContent.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FlowVisualizationPicker.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelBindingKeySelector.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelConfigPanel.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelModeContent.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelStepCard.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/FunnelStepList.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/LegacyBooleanOptions.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/MetricItemCard.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/MetricRow.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/MetricsSection.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +2 -2
- package/dist/client/components/AnalysisBuilder/RetentionModeContent.d.ts +1 -1
- package/dist/client/components/AnalysisBuilder/SortToggleButton.d.ts +1 -1
- package/dist/client/components/DashboardPortletCard.d.ts +1 -1
- package/dist/client/components/DataBrowser/DataBrowserTable.d.ts +1 -1
- package/dist/client/components/PortletGroupCard.d.ts +18 -0
- package/dist/client/components/RowManagedLayout.d.ts +15 -3
- package/dist/client/components/analyticsPortlet/intrinsicChartHeight.d.ts +9 -0
- package/dist/client/components/charts/ActivityGridChart.d.ts +1 -1
- package/dist/client/components/charts/AngledXAxisTick.d.ts +5 -0
- package/dist/client/components/charts/AreaChart.d.ts +1 -1
- package/dist/client/components/charts/BarChart.d.ts +1 -1
- package/dist/client/components/charts/BoxPlotChart.d.ts +1 -1
- package/dist/client/components/charts/BubbleChart.d.ts +1 -1
- package/dist/client/components/charts/CandlestickChart.d.ts +1 -1
- package/dist/client/components/charts/ChartContainer.d.ts +7 -1
- package/dist/client/components/charts/ChartSummaryHeader.d.ts +31 -0
- package/dist/client/components/charts/DataTable.d.ts +1 -1
- package/dist/client/components/charts/FunnelChart.d.ts +1 -1
- package/dist/client/components/charts/GaugeChart.d.ts +1 -1
- package/dist/client/components/charts/HeatMapChart.d.ts +1 -1
- package/dist/client/components/charts/KpiCompactLayout.d.ts +31 -0
- package/dist/client/components/charts/KpiDelta.d.ts +1 -1
- package/dist/client/components/charts/KpiDelta.helpers.d.ts +2 -0
- package/dist/client/components/charts/KpiNumber.d.ts +1 -1
- package/dist/client/components/charts/KpiStates.d.ts +7 -2
- package/dist/client/components/charts/KpiText.d.ts +1 -1
- package/dist/client/components/charts/LineChart.d.ts +1 -1
- package/dist/client/components/charts/MarkdownChart.d.ts +1 -1
- package/dist/client/components/charts/MeasureProfileChart.d.ts +1 -1
- package/dist/client/components/charts/PieChart.d.ts +1 -1
- package/dist/client/components/charts/ProportionBarChart.config.d.ts +10 -0
- package/dist/client/components/charts/ProportionBarChart.d.ts +12 -0
- package/dist/client/components/charts/RadarChart.d.ts +1 -1
- package/dist/client/components/charts/RadialBarChart.d.ts +1 -1
- package/dist/client/components/charts/RetentionCombinedChart.d.ts +1 -1
- package/dist/client/components/charts/RetentionHeatmap.d.ts +1 -1
- package/dist/client/components/charts/SankeyChart.d.ts +1 -1
- package/dist/client/components/charts/ScatterChart.d.ts +1 -1
- package/dist/client/components/charts/SunburstChart.d.ts +1 -1
- package/dist/client/components/charts/TreeMapChart.d.ts +1 -1
- package/dist/client/components/charts/WaterfallChart.d.ts +1 -1
- package/dist/client/components/charts/cartesianChartHelpers.d.ts +62 -0
- package/dist/client/components/charts/chartScaffolding.d.ts +29 -0
- package/dist/client/components/dashboard/DashboardContext.d.ts +5 -1
- package/dist/client/components/dashboard/dashboardGridUtils.d.ts +2 -4
- package/dist/client/components/dashboardPortletCard/EditActionButtons.d.ts +34 -0
- package/dist/client/components/dashboardPortletCard/PortletCardHeader.d.ts +2 -12
- package/dist/client/components/dashboardPortletCard/PortletFloatingActions.d.ts +24 -0
- package/dist/client/components/dashboardPortletCard/cardStyles.d.ts +5 -0
- package/dist/client/components/dashboardPortletCard/propsEqual.d.ts +2 -0
- package/dist/client/components/mobileStackedLayout/memberDisplay.d.ts +21 -0
- package/dist/client/components.d.ts +1 -1
- package/dist/client/components.js +3 -4
- package/dist/client/hooks/dashboard/groupGeometry.d.ts +23 -0
- package/dist/client/hooks/dashboard/groupUtils.d.ts +57 -0
- package/dist/client/hooks/dashboard/layoutUtils.d.ts +34 -3
- package/dist/client/hooks/dashboard/useDashboardController.d.ts +11 -3
- package/dist/client/hooks/dashboard/useRowLayoutEngine.d.ts +12 -2
- package/dist/client/hooks/useDashboardHook.d.ts +14 -1
- package/dist/client/hooks.js +4 -5
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +48 -49
- package/dist/client/index.js.map +1 -1
- package/dist/client/providers.js +1 -1
- package/dist/client/schema.js +1 -1
- package/dist/client/stores/dashboardStore.d.ts +11 -1
- package/dist/client/styles.css +1 -1
- package/dist/client/styles.d.css.ts +2 -0
- package/dist/client/types.d.ts +37 -2
- package/dist/client/utils.js +13 -9
- package/dist/client/utils.js.map +1 -1
- package/dist/client-bundle-stats.html +388 -33
- package/dist/mcp-app/mcp-app.html +152 -165
- package/dist/server/chartConfigHelpers-BZMu_1EP.cjs +1 -0
- package/dist/server/{chartConfigHelpers-CcvqrIWF.js → chartConfigHelpers-BsnbxA2c.js} +30 -1
- package/dist/server/{dist-CH3hwAUk.js → dist-ChBfLb7x.js} +7 -4
- package/dist/server/{dist-BOdf-GQO.cjs → dist-CohrBmKe.cjs} +2 -2
- package/dist/server/google-BhvizbFR.cjs +2 -0
- package/dist/server/{google-CvKM9yVM.js → google-eKAc20al.js} +3 -3
- package/dist/server/index.cjs +84 -84
- package/dist/server/index.js +2436 -2260
- package/dist/server/openai-CUf4vc3Q.js +9295 -0
- package/dist/server/openai-Cu4TXXjl.cjs +19 -0
- package/dist/server/{openai-B6hWZk_r.js → openai-Czk1BdHa.js} +18 -17
- package/dist/{adapters/openai-C3-mjSAc.cjs → server/openai-DBwI1OSu.cjs} +1 -1
- package/dist/server/rolldown-runtime-B0aSnxlc.js +20 -0
- package/dist/server/rolldown-runtime-DF3sbh8G.cjs +1 -0
- package/package.json +14 -10
- package/dist/adapters/ActivityGridChart.config-BK3hB9co.cjs +0 -1
- package/dist/adapters/ActivityGridChart.config-C-68HsAw.js +0 -2
- package/dist/adapters/AreaChart.config-5G7_E-7u.cjs +0 -1
- package/dist/adapters/AreaChart.config-C7S67Qt4.js +0 -2
- package/dist/adapters/BarChart.config-C6kG_uEt.cjs +0 -1
- package/dist/adapters/BarChart.config-DQcicZYy.js +0 -2
- package/dist/adapters/BoxPlotChart.config-B4xDTwop.js +0 -2
- package/dist/adapters/BoxPlotChart.config-DifAPvo0.cjs +0 -1
- package/dist/adapters/BubbleChart.config-BS2edxZ5.cjs +0 -1
- package/dist/adapters/BubbleChart.config-C5AYou9n.js +0 -2
- package/dist/adapters/CandlestickChart.config-Duknkqyk.js +0 -2
- package/dist/adapters/CandlestickChart.config-jk3ZXIAQ.cjs +0 -1
- package/dist/adapters/DataTable.config-BG_5hx63.cjs +0 -1
- package/dist/adapters/DataTable.config-Bkv6CmFa.js +0 -2
- package/dist/adapters/FunnelChart.config-Dvy0S17e.js +0 -2
- package/dist/adapters/FunnelChart.config-DzqGZgKz.cjs +0 -1
- package/dist/adapters/GaugeChart.config-DAWIU33N.js +0 -2
- package/dist/adapters/GaugeChart.config-DC0NW8XT.cjs +0 -1
- package/dist/adapters/HeatMapChart.config-BlQDS9nY.cjs +0 -1
- package/dist/adapters/HeatMapChart.config-DccGkzHI.js +0 -2
- package/dist/adapters/KpiDelta.config-DvpALT3Z.js +0 -2
- package/dist/adapters/KpiDelta.config-u2AlJkZ3.cjs +0 -1
- package/dist/adapters/KpiNumber.config-CF_LqRh-.cjs +0 -1
- package/dist/adapters/KpiNumber.config-lhEzZOFR.js +0 -2
- package/dist/adapters/KpiText.config-BCYGZdnx.js +0 -2
- package/dist/adapters/KpiText.config-FbnsbjdV.cjs +0 -1
- package/dist/adapters/LineChart.config-B7qWURRH.js +0 -2
- package/dist/adapters/LineChart.config-B9JKd48E.cjs +0 -1
- package/dist/adapters/MarkdownChart.config-BIS9PqHh.js +0 -2
- package/dist/adapters/MarkdownChart.config-BfM9NaQe.cjs +0 -1
- package/dist/adapters/MeasureProfileChart.config-1hh--3nI.js +0 -2
- package/dist/adapters/MeasureProfileChart.config-cmL8wp6a.cjs +0 -1
- package/dist/adapters/PieChart.config-DzzCeT7z.cjs +0 -1
- package/dist/adapters/PieChart.config-aRJJwYx4.js +0 -2
- package/dist/adapters/RadarChart.config-AcZ7kWG8.js +0 -2
- package/dist/adapters/RadarChart.config-CddBTWAo.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-D4qPexJV.cjs +0 -1
- package/dist/adapters/RadialBarChart.config-y-NBkq5N.js +0 -2
- package/dist/adapters/RetentionCombinedChart.config-BkRNE7lX.cjs +0 -1
- package/dist/adapters/RetentionCombinedChart.config-WoX6n6D5.js +0 -2
- package/dist/adapters/RetentionHeatmap.config-ByjWidhh.cjs +0 -1
- package/dist/adapters/RetentionHeatmap.config-DjXLk03y.js +0 -2
- package/dist/adapters/SankeyChart.config-BWO9LszQ.cjs +0 -1
- package/dist/adapters/SankeyChart.config-SuP0jjib.js +0 -2
- package/dist/adapters/ScatterChart.config-Dk1G4Eaj.cjs +0 -1
- package/dist/adapters/ScatterChart.config-DzVXd1ZM.js +0 -2
- package/dist/adapters/SunburstChart.config-Cu4ib4Ui.cjs +0 -1
- package/dist/adapters/SunburstChart.config-_0gUzNs7.js +0 -2
- package/dist/adapters/TreeMapChart.config-DbwYrje4.js +0 -2
- package/dist/adapters/TreeMapChart.config-hM8PukgE.cjs +0 -1
- package/dist/adapters/WaterfallChart.config-CjUHeE8R.js +0 -2
- package/dist/adapters/WaterfallChart.config-Dwxt0kK-.cjs +0 -1
- package/dist/adapters/chartConfigHelpers-DHQB-_v5.cjs +0 -1
- package/dist/adapters/compiler-D0v5KJhv.cjs +0 -166
- package/dist/adapters/core-VK-KVH9q.cjs +0 -1
- package/dist/adapters/google-BOnRIN1w.cjs +0 -2
- package/dist/adapters/mcp-transport-C2v5BTDF.cjs +0 -40
- package/dist/adapters/mcp-transport-CyDBoYEe.js +0 -601
- package/dist/adapters/openai-B1pC8nVM.js +0 -6178
- package/dist/adapters/openai-DQZaHN0V.cjs +0 -18
- package/dist/adapters/utils-CBR-9AMD.cjs +0 -128
- package/dist/client/chunks/ConfirmModal-D6eLc9NO.js +0 -3283
- package/dist/client/chunks/ConfirmModal-D6eLc9NO.js.map +0 -1
- package/dist/client/chunks/DashboardEditModal-9o16JNF0.js +0 -7580
- package/dist/client/chunks/DashboardEditModal-9o16JNF0.js.map +0 -1
- package/dist/client/chunks/analysis-builder-BDWychCW.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-DkL0e-wU.js.map +0 -1
- package/dist/client/chunks/chart-area-BHxPNsmc.js +0 -775
- package/dist/client/chunks/chart-area-BHxPNsmc.js.map +0 -1
- package/dist/client/chunks/chart-bar-DAO3PPcE.js.map +0 -1
- package/dist/client/chunks/chart-config-area-DxwIZ4Uf.js.map +0 -1
- package/dist/client/chunks/chart-config-kpi-delta-DYopvwyG.js.map +0 -1
- package/dist/client/chunks/chart-config-kpi-number-BhMdoArB.js.map +0 -1
- package/dist/client/chunks/chart-config-line-CBfM0Rds.js.map +0 -1
- package/dist/client/chunks/chart-data-table-BP6DMdom.js.map +0 -1
- package/dist/client/chunks/chart-kpi-delta-nXQnRRBr.js.map +0 -1
- package/dist/client/chunks/chart-kpi-number-m8UGJfBr.js +0 -244
- package/dist/client/chunks/chart-kpi-number-m8UGJfBr.js.map +0 -1
- package/dist/client/chunks/chart-line-sJK-cJc0.js +0 -101
- package/dist/client/chunks/chart-line-sJK-cJc0.js.map +0 -1
- package/dist/client/chunks/chart-markdown-BVrqqygz.js.map +0 -1
- package/dist/client/chunks/charts-loader-DAJbAD7a.js +0 -84
- package/dist/client/chunks/charts-loader-DAJbAD7a.js.map +0 -1
- package/dist/client/chunks/core-D7vPfUIe.js.map +0 -1
- package/dist/client/chunks/javascript-DFnKaHmQ.js.map +0 -1
- package/dist/client/chunks/json-Cu6rbgWf.js +0 -38
- package/dist/client/chunks/json-Cu6rbgWf.js.map +0 -1
- package/dist/client/chunks/schema-visualization-BGT_cNon.js.map +0 -1
- package/dist/client/chunks/useDebounce-7suCFq9v.js.map +0 -1
- package/dist/client/chunks/useDirtyStateTracking-D2OiqKoQ.js +0 -66
- package/dist/client/chunks/useDirtyStateTracking-D2OiqKoQ.js.map +0 -1
- package/dist/client/chunks/vendor-ChnlgSP0.js.map +0 -1
- package/dist/server/chartConfigHelpers-DHQB-_v5.cjs +0 -1
- package/dist/server/google-BOnRIN1w.cjs +0 -2
- package/dist/server/openai-B1pC8nVM.js +0 -6178
- package/dist/server/openai-DQZaHN0V.cjs +0 -18
package/dist/client/chunks/{chart-box-plot-CUpFyQQk.js.map → chart-box-plot-Bae5O9xC.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-box-plot-CUpFyQQk.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
|
+
{"version":3,"file":"chart-box-plot-Bae5O9xC.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,5 +1,5 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
2
|
-
import { P as t, S as n, a as r, c as i, h as a, i as o, l as s, n as c, o as l, r as u, s as d, w as f, x as p, y as m } from "./chart-activity-grid-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
+
import { P as t, S as n, a as r, c as i, h as a, i as o, l as s, n as c, o as l, r as u, s as d, w as f, x as p, y as m } from "./chart-activity-grid-DVOhLgxv.js";
|
|
3
3
|
import h, { useCallback as g, useEffect as _, useMemo as v, useSyncExternalStore as y } from "react";
|
|
4
4
|
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
5
5
|
import { axisBottom as S, axisLeft as C, extent as w, max as T, scaleLinear as E, scaleOrdinal as D, scaleQuantize as O, scaleSqrt as k, select as A } from "d3";
|
|
@@ -100,10 +100,10 @@ function z(e, t, n, r) {
|
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
function B(e, t, n, r, a, o) {
|
|
103
|
-
let { bubbleData: s, fields: c, options: l, colorPalette: u, getFieldLabel: d } = e, p = Math.min(...s.map((e) => e.color)), m = Math.max(...s.map((e) => e.color)), h = (e) => l.leftYAxisFormat ? f(e, l.leftYAxisFormat) : e.toFixed(2), g = n.append("g").attr("class", "color-legend").attr("transform", `translate(${r / 2 -
|
|
103
|
+
let { bubbleData: s, fields: c, options: l, colorPalette: u, getFieldLabel: d } = e, p = Math.min(...s.map((e) => e.color)), m = Math.max(...s.map((e) => e.color)), h = (e) => l.leftYAxisFormat ? f(e, l.leftYAxisFormat) : e.toFixed(2), g = n.append("g").attr("class", "color-legend").attr("transform", `translate(${r / 2 - 100}, ${a + 60})`), _ = t.append("defs").append("linearGradient").attr("id", "color-scale-gradient").attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%"), v = u?.gradient || i;
|
|
104
104
|
v.forEach((e, t) => {
|
|
105
105
|
_.append("stop").attr("offset", `${t / (v.length - 1) * 100}%`).attr("stop-color", e);
|
|
106
|
-
}), g.append("rect").attr("width", 200).attr("height", 20).style("fill", "url(#color-scale-gradient)").style("stroke", "#ccc").style("stroke-width", 1), g.append("text").attr("x", 0).attr("y", 35).attr("text-anchor", "start").style("font-size", "11px").style("fill", o).text(h(p)), g.append("text").attr("x", 200).attr("y", 35).attr("text-anchor", "end").style("font-size", "11px").style("fill", o).text(h(m)), g.append("text").attr("x",
|
|
106
|
+
}), g.append("rect").attr("width", 200).attr("height", 20).style("fill", "url(#color-scale-gradient)").style("stroke", "#ccc").style("stroke-width", 1), g.append("text").attr("x", 0).attr("y", 35).attr("text-anchor", "start").style("font-size", "11px").style("fill", o).text(h(p)), g.append("text").attr("x", 200).attr("y", 35).attr("text-anchor", "end").style("font-size", "11px").style("fill", o).text(h(m)), g.append("text").attr("x", 100).attr("y", -5).attr("text-anchor", "middle").style("font-size", "12px").style("font-weight", "bold").style("fill", o).text(d(c.colorFieldName));
|
|
107
107
|
}
|
|
108
108
|
function V(e, t, n, r, i, a, o, s) {
|
|
109
109
|
let { fields: c, options: l } = e;
|
|
@@ -218,4 +218,4 @@ var U = /* @__PURE__ */ e({ default: () => W }), W = h.memo(function({ data: e,
|
|
|
218
218
|
//#endregion
|
|
219
219
|
export { M as n, U as t };
|
|
220
220
|
|
|
221
|
-
//# sourceMappingURL=chart-bubble-
|
|
221
|
+
//# sourceMappingURL=chart-bubble-BFN5WIpf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-bubble-DvP_6_n9.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
|
+
{"version":3,"file":"chart-bubble-BFN5WIpf.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,5 +1,5 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
2
|
-
import { P as t, w as n } from "./chart-activity-grid-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
+
import { P as t, w as n } from "./chart-activity-grid-DVOhLgxv.js";
|
|
3
3
|
import r, { useLayoutEffect as i, useMemo as a, useRef as o, useState as s } from "react";
|
|
4
4
|
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
5
5
|
//#region src/client/components/charts/CandlestickChart.tsx
|
|
@@ -300,4 +300,4 @@ var y = r.memo(function({ data: e, chartConfig: r, displayConfig: c = {}, height
|
|
|
300
300
|
//#endregion
|
|
301
301
|
export { d as t };
|
|
302
302
|
|
|
303
|
-
//# sourceMappingURL=chart-candlestick-
|
|
303
|
+
//# sourceMappingURL=chart-candlestick-PBQKp_z7.js.map
|
package/dist/client/chunks/{chart-candlestick-Dx8ZCMzl.js.map → chart-candlestick-PBQKp_z7.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-candlestick-Dx8ZCMzl.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
|
+
{"version":3,"file":"chart-candlestick-PBQKp_z7.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":";;;;;iDAKM,IAAqB,WACrB,IAAqB,WACrB,IAAa,WACb,IAAc;AAYpB,SAAS,EAAS,GAA2B;CAC3C,IAAI,KAAyB,MAAM,OAAO;CAC1C,IAAM,IAAI,OAAO,KAAM,WAAW,IAAI,WAAW,OAAO,CAAC,CAAC;CAC1D,OAAO,MAAM,CAAC,IAAI,OAAO;AAC3B;AAEA,SAAS,EAAO,EACd,MACA,gBACA,UACA,WACA,UACA,SACA,cACA,cACA,cACA,cACA,YAaC;CACD,IAAM,IAAO,IAAY,IAAY,GAC/B,IAAU,KAAK,IAAI,GAAO,CAAM,GAChC,IAAa,KAAK,IAAI,GAAO,CAAM,GACnC,IAAa,KAAK,IAAI,IAAa,GAAS,CAAC,GAC7C,IAAY,IAAc;CAEhC,OACE,kBAAC,KAAD;EAAG,eAAa,UAAU;EAA1B,UAAA,CACE,kBAAC,QAAD;GACE,GAAG,IAAI;GACP,GAAG;GACH,OAAO;GACP,QAAQ;GACF;GACN,eAAa,eAAe;GAC5B,gBAAc;EACf,CAAA,GACA,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;GACE,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,QAAQ;GACR,aAAa;GACb,eAAa,aAAa;EAC3B,CAAA,GACD,kBAAC,QAAD;GACE,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,QAAQ;GACR,aAAa;GACb,eAAa,YAAY;EAC1B,CAAA,CACD,EAAA,CAAA,CAEH;;AAEP;AAEA,SAAS,EAAW,EAClB,cACA,cACA,gBACA,cACA,aAOC;CACD,IAAM,IAAQ,QAAc;EAC1B,IAAM,KAAQ,IAAY,MAAc,IAAY;EACpD,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAU,IAAI,GAAG,MAAM,IAAY,IAAI,CAAI;CACzE,GAAG;EAAC;EAAW;EAAW;CAAS,CAAC,GAE9B,KAAU,MAAc,KAAgB,IAAI,MAAc,IAAY,KAAc;CAE1F,OACE,kBAAC,KAAD;EAAG,eAAY;EAAf,UAAA,CACE,kBAAC,QAAD;GAAM,IAAI;GAAG,IAAI;GAAa,QAAO;GAAe,aAAa;EAAI,CAAA,GACpE,EAAM,KAAK,GAAM,MAChB,kBAAC,KAAD;GAAW,WAAW,gBAAgB,EAAO,CAAI,EAAE;GAAnD,UAAA;IACE,kBAAC,QAAD;KAAM,IAAI;KAAG,IAAI;KAAI,QAAO;KAAe,aAAa;IAAI,CAAA;IAC5D,kBAAC,QAAD;KACE,GAAG;KACH,YAAW;KACX,kBAAiB;KACjB,UAAU;KACV,MAAK;KACL,WAAU;KAET,UAAA,IAAS,EAAO,CAAI,IAAI,EAAK,eAAe;IACzC,CAAA;IACN,kBAAC,QAAD;KAAM,IAAI;KAAG,IAAG;KAAO,QAAO;KAAe,eAAe;KAAK,aAAa;IAAI,CAAA;GACjF;EAbK,GAAA,CAaL,CACJ,CACA;;AAEP;AAEA,IAAM,IAAmB,EAAM,KAAK,SAA0B,EAC5D,SACA,gBACA,mBAAgB,CAAC,GACjB,YAAS,QACT,qBACA,mBACa;CACb,IAAM,EAAE,SAAM,EAAe,GACvB,IAAe,EAAuB,IAAI,GAC1C,CAAC,GAAY,KAAiB,EAAS;EAAE,OAAO;EAAG,QAAQ;CAAE,CAAC;CAEpE,QAAsB;EACpB,IAAM,IAAK,EAAa;EACxB,IAAI,CAAC,GAAI;EACT,IAAM,IAAW,IAAI,gBAAgB,MAAY;GAC/C,KAAK,IAAM,KAAS,GAAS;IAC3B,IAAM,EAAE,UAAO,QAAQ,MAAM,EAAM;IACnC,AAAI,IAAQ,KAAK,IAAI,KAAG,EAAc;KAAE;KAAO,QAAQ;IAAE,CAAC;GAC5D;EACF,CAAC;EACD,EAAS,QAAQ,CAAE;EACnB,IAAM,IAAO,EAAG,sBAAsB;EAEtC,OADI,EAAK,QAAQ,KAAK,EAAK,SAAS,KAAG,EAAc;GAAE,OAAO,EAAK;GAAO,QAAQ,EAAK;EAAO,CAAC,SAClF,EAAS,WAAW;CACnC,GAAG,CAAC,CAAC;CAEL,IAAM,IAAY,GAAe,aAAa,GACxC,IAAY,GAAe,aAAa,GACxC,IAAY,GAAe,aAAa,IACxC,IAAY,GAAe,aAAa,QACxC,IAAc,GAAe,iBAE7B,EAAE,WAAQ,cAAW,eAAY,cAAW,aAAU,mBAAgB,QAAc;EACxF,IAAM,IAAS,MAAM,QAAQ,GAAa,KAAK,IAC3C,EAAY,MAAM,KAClB,GAAa,SAAS,GAAa,GAEjC,IAAwB,MAAM,QAAQ,GAAa,KAAK,IAC1D,EAAY,QACZ,CAAC,GAEC,IAAY,EAAY,MAAM,IAC9B,KAAc,MAAc,UAAU,EAAY,KAAK,EAAY,OAAO,IAC1E,KAAa,MAAc,UAAU,EAAY,KAAK,EAAY,OAAO,IACzE,KAAY,MAAc,UAAU,EAAY,KAAK,EAAY,OAAO;EAmC9E,OAjCK,IAWD,MAAc,YAAY,CAAC,KAAa,CAAC,KACpC;GACL;GACA;GACA;GACA;GACA;GACA,aAAa;EACf,IAGE,MAAc,WAAW,CAAC,KAAa,CAAC,KACnC;GACL;GACA;GACA;GACA;GACA;GACA,aAAa;EACf,IAGK;GAAE;GAAQ;GAAW;GAAY;GAAW;GAAU,aAAa;EAAK,IAhCtE;GACL;GACA;GACA;GACA;GACA;GACA,aAAa;EACf;CA0BJ,GAAG,CAAC,GAAa,CAAS,CAAC,GAErB,IAAwB,QAAc;EAC1C,IAAI,KAAe,CAAC,KAAQ,EAAK,WAAW,GAAG,OAAO,CAAC;EACvD,IAAM,IAAQ,EAAmC,MAAM,GAAG,CAAW,GAC/D,IAAuB,CAAC;EAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;GACpC,IAAM,IAAM,EAAK,IACX,IAAQ,OAAO,EAAI,MAAY,OAAO,IAAI,GAAG,GAC7C,IAAU,EAAS,EAAI,EAAU,GACjC,IAAW,EAAS,EAAI,EAAW;GACzC,IAAI,MAAY,QAAQ,MAAa,MAAM;GAE3C,IAAI,IAAO,GACP,IAAQ,GACN,IAAO,IAAa,EAAS,EAAI,EAAU,KAAK,KAAK,IAAI,GAAM,CAAK,IAAK,KAAK,IAAI,GAAM,CAAK,GAC7F,IAAM,IAAY,EAAS,EAAI,EAAS,KAAK,KAAK,IAAI,GAAM,CAAK,IAAK,KAAK,IAAI,GAAM,CAAK;GAOhG,AALI,MAAc,YAChB,IAAO,GACP,IAAQ,IAGV,EAAO,KAAK;IACV;IACA;IACA;IACA,MAAM,KAAK,IAAI,GAAM,GAAO,CAAI;IAChC,KAAK,KAAK,IAAI,GAAM,GAAO,CAAG;IAC9B,WAAW,KAAS;IACpB,eAAe;GACjB,CAAC;EACH;EACA,OAAO;CACT,GAAG;EAAC;EAAM;EAAQ;EAAW;EAAY;EAAW;EAAU;EAAW;CAAW,CAAC;CAErF,IAAI;EACF,IAAI,CAAC,KAAQ,EAAK,WAAW,GAC3B,OACE,kBAAC,OAAD;GAAK,WAAU;GAAyE,OAAO,EAAE,UAAO;GACtG,UAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAuC,UAAA,EAAE,sBAAsB;IAAO,CAAA,GACrF,kBAAC,OAAD;KAAK,WAAU;KAAqC,UAAA,EAAE,sCAAsC;IAAO,CAAA,CAChG;;EACF,CAAA;EAIT,IAAI,GACF,OACE,kBAAC,OAAD;GAAK,WAAU;GAAsE,OAAO,EAAE,UAAO;GACnG,UAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAuC,UAAA,EAAE,2BAA2B;IAAO,CAAA,GAC1F,kBAAC,OAAD;KAAK,WAAU;KAAc,UAAA;IAAiB,CAAA,CAC3C;;EACF,CAAA;EAGT,IAAM,IAAS;GAAE,KAAK;GAAI,OAAO;GAAI,QAAQ;GAAI,MAAM;EAAG,GACpD,IAAiB,EAAW,SAAS,KACrC,IACJ,OAAO,KAAW,WAAW,IAAS,EAAW,UAAU,KACvD,IAAa,KAAK,IAAI,IAAiB,EAAO,OAAO,EAAO,OAAO,EAAE,GACrE,IAAc,KAAK,KACtB,OAAO,KAAoB,WAAW,IAAkB,SAAS,OAAO,CAAe,CAAC,KAAK,OAC5F,EAAO,MACP,EAAO,QACT,EACF,GAEM,IAAY,EAAQ,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAClD,IAAS,KAAK,IAAI,GAAG,CAAS,GAC9B,IAAS,KAAK,IAAI,GAAG,CAAS,GAC9B,KAAO,IAAS,KAAU,OAAQ,GAClC,IAAY,IAAS,GACrB,IAAY,IAAS,GAErB,KAAU,MACd,KAAgB,IAAI,MAAc,IAAY,KAAc,GAExD,IAAgB,IAAa,EAAQ,QACrC,IAAc,KAAK,IAAI,IAAgB,IAAK,EAAE,GAE9C,IAAe,EAAmB,SAAS;EAEjD,OACE,kBAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAAwB,OAAO,EAAE,UAAO;GAA1E,UAAA,CACE,kBAAC,OAAD;IACE,OAAM;IACN,QAAQ,IAAc,sBAAsB;IAC5C,SAAS,OAAO,EAAe,GAAG,OAAO,KAAoB,WAAW,IAAkB;IAC1F,eAAY;IAEZ,UAAA,kBAAC,KAAD;KAAG,WAAW,aAAa,EAAO,KAAK,IAAI,EAAO,IAAI;KAAtD,UAAA,CACE,kBAAC,GAAD;MACa;MACA;MACE;MACb,WAAW;MACX,QAAQ,KAAe,MAAM,EAAgB,GAAG,CAAW,IAAI,KAAA;KAChE,CAAA,GAEA,EAAQ,KAAK,GAAQ,MAAM;MAC1B,IAAM,IAAK,IAAgB,IAAI,IAAgB;MAC/C,OACE,kBAAC,KAAD;OAEE,UAAU,MAA4B;QACpC,AAAI,KAAoB,KACtB,EAAiB;SACf,WAAW,EAAE,GAAG,EAAO;SACvB,cAAc,KAAU;SACxB,QAAQ,EAAO;SACf,UAAU;UAAE,GAAG,EAAM;UAAS,GAAG,EAAM;SAAQ;SAC/C,aAAa;QACf,CAAC;OAEL;OACA,QAAQ,IAAe,YAAY,KAAA;OAbrC,UAAA;QAeE,kBAAC,SAAD,EAAA,UAAQ,GAAG,EAAO,MAAM,MAAM,EAAO,KAAK,KAAK,EAAO,KAAK,KAAK,EAAO,IAAI,KAAK,EAAO,QAAe,CAAA;QACtG,kBAAC,GAAD;SACE,GAAG;SACU;SACb,OAAO,EAAO,EAAO,IAAI;SACzB,QAAQ,EAAO,EAAO,KAAK;SAC3B,OAAO,EAAO,EAAO,IAAI;SACzB,MAAM,EAAO,EAAO,GAAG;SACvB,WAAW,EAAO;SACP;SACA;SACA;SACX,OAAO,EAAO;QACf,CAAA;QACD,kBAAC,QAAD;SACE,GAAG;SACH,GAAG,IAAc;SACjB,YAAW;SACX,UAAU;SACV,MAAK;SACL,WAAU;SACV,eAAa,WAAW,EAAO;SAE9B,UAAA,EAAO;QACJ,CAAA;OACL;MAvCI,GAAA,EAAO,QAAQ,CAuCnB;KAEP,CAAC,CACA;;GACA,CAAA,GACJ,KACC,kBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,EAAE,uCAAuC;KACxC,KAAK;KACL,OAAQ,EAAmB;IAC7B,CAAC;GACE,CAAA,CAEJ;;CAET,SAAS,GAAO;EACd,OACE,kBAAC,OAAD;GAAK,WAAU;GAAuF,OAAO,EAAE,UAAO;GACpH,UAAA,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAAC,OAAD;MAAK,WAAU;MAAuC,UAAA,EAAE,4BAA4B,EAAE,WAAW,oBAAoB,CAAC;KAAO,CAAA;KAC7H,kBAAC,OAAD;MAAK,WAAU;MAAsB,UAAA,aAAiB,QAAQ,EAAM,UAAU,EAAE,4BAA4B;KAAO,CAAA;KACnH,kBAAC,OAAD;MAAK,WAAU;MAAiC,UAAA,EAAE,2BAA2B;KAAO,CAAA;IACjF;;EACF,CAAA;CAET;AACF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
2
|
//#region src/client/components/charts/ActivityGridChart.config.ts
|
|
3
3
|
var t = /* @__PURE__ */ e({ activityGridChartConfig: () => n }), n = {
|
|
4
4
|
dropZones: [{
|
|
@@ -45,4 +45,4 @@ var t = /* @__PURE__ */ e({ activityGridChartConfig: () => n }), n = {
|
|
|
45
45
|
//#endregion
|
|
46
46
|
export { n, t };
|
|
47
47
|
|
|
48
|
-
//# sourceMappingURL=chart-config-activity-grid-
|
|
48
|
+
//# sourceMappingURL=chart-config-activity-grid-C4vXGQNu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-config-activity-grid-
|
|
1
|
+
{"version":3,"file":"chart-config-activity-grid-C4vXGQNu.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 *\n * Eager metadata (`label`, `description`, `useCase`, `isAvailable`) lives in the\n * unified `chartRegistry` entry (the single source of truth) — see\n * `src/client/charts/chartRegistry.ts`. This file owns the lazy-loaded shape:\n * drop zones, display options, clickable elements, validation.\n */\nexport const activityGridChartConfig: ChartTypeConfig = {\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":";;iEAUa,IAA2C;CACtD,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,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
2
|
//#region src/client/charts/chartConfigHelpers.ts
|
|
3
3
|
function t({ measureCount: e, dimensionCount: t }) {
|
|
4
4
|
return e < 1 ? {
|
|
@@ -69,9 +69,38 @@ function c(e) {
|
|
|
69
69
|
description: e
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
+
var l = {
|
|
73
|
+
key: "layout",
|
|
74
|
+
label: "chart.option.kpiLayout.label",
|
|
75
|
+
type: "buttonGroup",
|
|
76
|
+
defaultValue: "auto",
|
|
77
|
+
options: [{
|
|
78
|
+
value: "auto",
|
|
79
|
+
label: "chart.option.kpiLayout.auto"
|
|
80
|
+
}, {
|
|
81
|
+
value: "compact",
|
|
82
|
+
label: "chart.option.kpiLayout.compact"
|
|
83
|
+
}],
|
|
84
|
+
description: "chart.option.kpiLayout.description"
|
|
85
|
+
}, u = {
|
|
86
|
+
key: "showSummary",
|
|
87
|
+
label: "chart.option.showSummary.label",
|
|
88
|
+
type: "boolean",
|
|
89
|
+
defaultValue: !1,
|
|
90
|
+
description: "chart.option.showSummary.description"
|
|
91
|
+
};
|
|
92
|
+
function d(e = !0) {
|
|
93
|
+
return {
|
|
94
|
+
key: "showPoints",
|
|
95
|
+
label: "chart.option.showPoints.label",
|
|
96
|
+
type: "boolean",
|
|
97
|
+
defaultValue: e,
|
|
98
|
+
description: "chart.option.showPoints.description"
|
|
99
|
+
};
|
|
100
|
+
}
|
|
72
101
|
//#endregion
|
|
73
102
|
//#region src/client/components/charts/AreaChart.config.ts
|
|
74
|
-
var
|
|
103
|
+
var f = /* @__PURE__ */ e({ areaChartConfig: () => p }), p = {
|
|
75
104
|
dropZones: [
|
|
76
105
|
{
|
|
77
106
|
key: "xAxis",
|
|
@@ -107,6 +136,8 @@ var l = /* @__PURE__ */ e({ areaChartConfig: () => u }), u = {
|
|
|
107
136
|
"hideHeader"
|
|
108
137
|
],
|
|
109
138
|
displayOptionsConfig: [
|
|
139
|
+
u,
|
|
140
|
+
d(!1),
|
|
110
141
|
c("chart.configText.how_to_stack_multiple_area_series"),
|
|
111
142
|
i,
|
|
112
143
|
r,
|
|
@@ -115,6 +146,6 @@ var l = /* @__PURE__ */ e({ areaChartConfig: () => u }), u = {
|
|
|
115
146
|
]
|
|
116
147
|
};
|
|
117
148
|
//#endregion
|
|
118
|
-
export {
|
|
149
|
+
export { a, o as c, c as d, r as f, l as i, d as l, p as n, n as o, s as p, i as r, t as s, f as t, u };
|
|
119
150
|
|
|
120
|
-
//# sourceMappingURL=chart-config-area-
|
|
151
|
+
//# sourceMappingURL=chart-config-area-DsrZCIwF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-config-area-DsrZCIwF.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\n/**\n * Layout density for the KPI charts.\n *\n * `auto` keeps the historic behaviour, where the value's font size is derived\n * from the portlet box — which makes a wide portlet render an enormous number.\n * `compact` uses a fixed type scale so several KPIs read as a tidy metric strip.\n */\nexport const kpiLayoutDisplayOption: DisplayOptionConfig = {\n key: 'layout',\n label: 'chart.option.kpiLayout.label',\n type: 'buttonGroup',\n defaultValue: 'auto',\n options: [\n { value: 'auto', label: 'chart.option.kpiLayout.auto' },\n { value: 'compact', label: 'chart.option.kpiLayout.compact' }\n ],\n description: 'chart.option.kpiLayout.description'\n}\n\n/**\n * Summary-band toggle for the time-series charts.\n *\n * Renders each series' latest value and its change since the start of the\n * window above the plot, so the chart is readable without hovering.\n */\nexport const showSummaryDisplayOption: DisplayOptionConfig = {\n key: 'showSummary',\n label: 'chart.option.showSummary.label',\n type: 'boolean',\n defaultValue: false,\n description: 'chart.option.showSummary.description'\n}\n\n/**\n * Data-point marker toggle for the time-series charts. Dense series (hundreds\n * of points) read far better without a marker on every one.\n */\nexport function showPointsDisplayOption(defaultValue = true): DisplayOptionConfig {\n return {\n key: 'showPoints',\n label: 'chart.option.showPoints.label',\n type: 'boolean',\n defaultValue,\n description: 'chart.option.showPoints.description'\n }\n}\n","import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport {\n stackTypeDisplayOption,\n connectNullsDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption,\n showSummaryDisplayOption,\n showPointsDisplayOption\n} from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the area chart type.\n *\n * Eager metadata (`label`, `description`, `useCase`, `isAvailable`) lives in the\n * unified `chartRegistry` entry (the single source of truth) — see\n * `src/client/charts/chartRegistry.ts`. This file owns the lazy-loaded shape:\n * drop zones, display options, clickable elements, validation.\n */\nexport const areaChartConfig: ChartTypeConfig = {\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 showSummaryDisplayOption,\n showPointsDisplayOption(false),\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;AASA,IAAa,IAA8C;CACzD,KAAK;CACL,OAAO;CACP,MAAM;CACN,cAAc;CACd,SAAS,CACP;EAAE,OAAO;EAAQ,OAAO;CAA8B,GACtD;EAAE,OAAO;EAAW,OAAO;CAAiC,CAC9D;CACA,aAAa;AACf,GAQa,IAAgD;CAC3D,KAAK;CACL,OAAO;CACP,MAAM;CACN,cAAc;CACd,aAAa;AACf;AAMA,SAAgB,EAAwB,IAAe,IAA2B;CAChF,OAAO;EACL,KAAK;EACL,OAAO;EACP,MAAM;EACN;EACA,aAAa;CACf;AACF;;;yDChIa,IAAmC;CAC9C,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;EACA,EAAwB,EAAK;EAC7B,EAAuB,oDAAoD;EAC3E;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
2
|
-
import {
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
|
+
import { a as t, c as n, d as r, f as i } from "./chart-config-area-DsrZCIwF.js";
|
|
3
3
|
//#region src/client/components/charts/BarChart.config.ts
|
|
4
4
|
var a = /* @__PURE__ */ e({ barChartConfig: () => o }), o = {
|
|
5
5
|
clickableElements: { bar: !0 },
|
|
@@ -38,13 +38,13 @@ var a = /* @__PURE__ */ e({ barChartConfig: () => o }), o = {
|
|
|
38
38
|
"hideHeader"
|
|
39
39
|
],
|
|
40
40
|
displayOptionsConfig: [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
r("chart.configText.how_to_stack_multiple_bar_series"),
|
|
42
|
+
i,
|
|
43
|
+
t,
|
|
44
|
+
n
|
|
45
45
|
]
|
|
46
46
|
};
|
|
47
47
|
//#endregion
|
|
48
48
|
export { o as n, a as t };
|
|
49
49
|
|
|
50
|
-
//# sourceMappingURL=chart-config-bar-
|
|
50
|
+
//# sourceMappingURL=chart-config-bar-BixSs43E.js.map
|
package/dist/client/chunks/{chart-config-bar-Cc8GY9aQ.js.map → chart-config-bar-BixSs43E.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-config-bar-
|
|
1
|
+
{"version":3,"file":"chart-config-bar-BixSs43E.js","names":[],"sources":["../../../src/client/components/charts/BarChart.config.ts"],"sourcesContent":["import type { ChartTypeConfig } from '../../charts/chartConfigs.js'\nimport {\n stackTypeDisplayOption,\n targetDisplayOption,\n leftYAxisFormatDisplayOption,\n rightYAxisFormatDisplayOption\n} from '../../charts/chartConfigHelpers.js'\n\n/**\n * Configuration for the bar chart type.\n *\n * Eager metadata (`label`, `description`, `useCase`, `isAvailable`) lives in the\n * unified `chartRegistry` entry (the single source of truth) — see\n * `src/client/charts/chartRegistry.ts`. This file owns the lazy-loaded shape:\n * drop zones, display options, clickable elements, validation.\n */\nexport const barChartConfig: ChartTypeConfig = {\n clickableElements: { bar: true },\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":";;;wDAgBa,IAAkC;CAC7C,mBAAmB,EAAE,KAAK,GAAK;CAC/B,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"}
|
package/dist/client/chunks/{chart-config-box-plot-Bs8ovYvV.js → chart-config-box-plot-DMuJZqkr.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./rolldown-runtime-
|
|
1
|
+
import { n as e } from "./rolldown-runtime-DArdT4gl.js";
|
|
2
2
|
//#region src/client/components/charts/BoxPlotChart.config.ts
|
|
3
3
|
var t = /* @__PURE__ */ e({ boxPlotChartConfig: () => n }), n = {
|
|
4
4
|
displayOptions: ["hideHeader"],
|
|
@@ -29,4 +29,4 @@ var t = /* @__PURE__ */ e({ boxPlotChartConfig: () => n }), n = {
|
|
|
29
29
|
//#endregion
|
|
30
30
|
export { n, t };
|
|
31
31
|
|
|
32
|
-
//# sourceMappingURL=chart-config-box-plot-
|
|
32
|
+
//# sourceMappingURL=chart-config-box-plot-DMuJZqkr.js.map
|