drizzle-cube 0.3.13 → 0.3.15
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/dist/adapters/{compiler-DTOU8IsK.js → compiler-DdcGVWIl.js} +7429 -4165
- package/dist/adapters/compiler-mAJDpIQx.cjs +214 -0
- package/dist/adapters/express/index.cjs +1 -1
- package/dist/adapters/express/index.d.ts +1 -1
- package/dist/adapters/express/index.js +1 -1
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.d.ts +1 -1
- package/dist/adapters/fastify/index.js +1 -1
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.d.ts +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.d.ts +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/utils.d.ts +29 -0
- package/dist/client/adapters/index.d.ts +2 -0
- package/dist/client/adapters/retentionModeAdapter.d.ts +3 -0
- package/dist/client/charts.js +12 -12
- package/dist/client/chunks/RetentionCombinedChart-CqMAkdcR.js +256 -0
- package/dist/client/chunks/RetentionCombinedChart-CqMAkdcR.js.map +1 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js +47 -0
- package/dist/client/chunks/RetentionCombinedChart.config-C-ILIaEb.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js +178 -0
- package/dist/client/chunks/RetentionHeatmap-Bofadstm.js.map +1 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js +28 -0
- package/dist/client/chunks/RetentionHeatmap.config-CIvhc-GT.js.map +1 -0
- package/dist/client/chunks/analysis-builder-D0MIKiKS.js +6939 -0
- package/dist/client/chunks/analysis-builder-D0MIKiKS.js.map +1 -0
- package/dist/client/chunks/analysis-builder-shared-gS0TDC6Y.js +2779 -0
- package/dist/client/chunks/analysis-builder-shared-gS0TDC6Y.js.map +1 -0
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js → chart-activity-grid-B37W8fcE.js} +11 -11
- package/dist/client/chunks/{chart-activity-grid-CuPARsr1.js.map → chart-activity-grid-B37W8fcE.js.map} +1 -1
- package/dist/client/chunks/{chart-area-cPrJnhLj.js → chart-area-DZcxSVB1.js} +2 -2
- package/dist/client/chunks/{chart-area-cPrJnhLj.js.map → chart-area-DZcxSVB1.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-D68HFPpa.js → chart-bar-BFAdRj-E.js} +2 -2
- package/dist/client/chunks/{chart-bar-D68HFPpa.js.map → chart-bar-BFAdRj-E.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js → chart-bubble-eoCCbl3h.js} +2 -2
- package/dist/client/chunks/{chart-bubble-CquyYfNO.js.map → chart-bubble-eoCCbl3h.js.map} +1 -1
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js → chart-config-activity-grid-BBSNCbkb.js} +2 -2
- package/dist/client/chunks/{chart-config-activity-grid-Bkvx0F-G.js.map → chart-config-activity-grid-BBSNCbkb.js.map} +1 -1
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js → chart-config-area-CyyJOO2T.js} +2 -2
- package/dist/client/chunks/{chart-config-area-OApsRaYC.js.map → chart-config-area-CyyJOO2T.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js → chart-config-bar-BJKGnfLt.js} +2 -2
- package/dist/client/chunks/{chart-config-bar-Dy21oaIA.js.map → chart-config-bar-BJKGnfLt.js.map} +1 -1
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js → chart-config-bubble-CuSsCHZ4.js} +2 -2
- package/dist/client/chunks/{chart-config-bubble-Chv0SoFm.js.map → chart-config-bubble-CuSsCHZ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js → chart-config-data-table-BhgqwoqT.js} +2 -2
- package/dist/client/chunks/{chart-config-data-table-DTIdC35a.js.map → chart-config-data-table-BhgqwoqT.js.map} +1 -1
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js → chart-config-funnel-BlSQYng0.js} +4 -4
- package/dist/client/chunks/{chart-config-funnel-f17Livgr.js.map → chart-config-funnel-BlSQYng0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js → chart-config-heat-map-DHQGFZhX.js} +2 -2
- package/dist/client/chunks/{chart-config-heat-map-DPhNICha.js.map → chart-config-heat-map-DHQGFZhX.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js → chart-config-kpi-delta-yTA5ug_l.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-delta-CCl1d-St.js.map → chart-config-kpi-delta-yTA5ug_l.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js → chart-config-kpi-number-nVAwDXzq.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-number-DkE3eSwH.js.map → chart-config-kpi-number-nVAwDXzq.js.map} +1 -1
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js → chart-config-kpi-text-DZjqsx-b.js} +2 -2
- package/dist/client/chunks/{chart-config-kpi-text-BMbgdxZm.js.map → chart-config-kpi-text-DZjqsx-b.js.map} +1 -1
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js → chart-config-line-DR0ThxZy.js} +2 -2
- package/dist/client/chunks/{chart-config-line-BnLlRUQE.js.map → chart-config-line-DR0ThxZy.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js → chart-config-markdown-DZxdGNVQ.js} +2 -2
- package/dist/client/chunks/{chart-config-markdown-DIaMFC0Z.js.map → chart-config-markdown-DZxdGNVQ.js.map} +1 -1
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js → chart-config-pie-BM5lgH-w.js} +2 -2
- package/dist/client/chunks/{chart-config-pie-O9y_T0BQ.js.map → chart-config-pie-BM5lgH-w.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js → chart-config-radar-BBAVIF0S.js} +2 -2
- package/dist/client/chunks/{chart-config-radar-CXa0354h.js.map → chart-config-radar-BBAVIF0S.js.map} +1 -1
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js → chart-config-radial-bar-CTwjDRnB.js} +2 -2
- package/dist/client/chunks/{chart-config-radial-bar-BppJU8-Q.js.map → chart-config-radial-bar-CTwjDRnB.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js → chart-config-sankey-CNAgsMQ4.js} +2 -2
- package/dist/client/chunks/{chart-config-sankey-BfBHgL4x.js.map → chart-config-sankey-CNAgsMQ4.js.map} +1 -1
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js → chart-config-scatter-CWvN2E-X.js} +2 -2
- package/dist/client/chunks/{chart-config-scatter-BTt8a10R.js.map → chart-config-scatter-CWvN2E-X.js.map} +1 -1
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js → chart-config-sunburst-W_SKwaj0.js} +4 -4
- package/dist/client/chunks/{chart-config-sunburst-DNmQpIIx.js.map → chart-config-sunburst-W_SKwaj0.js.map} +1 -1
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js → chart-config-tree-map-CLmRvvMR.js} +2 -2
- package/dist/client/chunks/{chart-config-tree-map-HVgG4oa0.js.map → chart-config-tree-map-CLmRvvMR.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js → chart-data-table-kudRwZxJ.js} +4 -4
- package/dist/client/chunks/{chart-data-table-D4WDqbM0.js.map → chart-data-table-kudRwZxJ.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js → chart-funnel-CA0XJkfh.js} +2 -2
- package/dist/client/chunks/{chart-funnel-Csdn4FbN.js.map → chart-funnel-CA0XJkfh.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js → chart-heat-map-DUy9_pWM.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-v1afxnjq.js.map → chart-heat-map-DUy9_pWM.js.map} +1 -1
- package/dist/client/chunks/chart-kpi-delta-MIGGCpkG.js +351 -0
- package/dist/client/chunks/chart-kpi-delta-MIGGCpkG.js.map +1 -0
- package/dist/client/chunks/chart-kpi-number-DM0Brd91.js +473 -0
- package/dist/client/chunks/chart-kpi-number-DM0Brd91.js.map +1 -0
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js → chart-kpi-text-BAb28V4X.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-CRp8QWYG.js.map → chart-kpi-text-BAb28V4X.js.map} +1 -1
- package/dist/client/chunks/{chart-line-DqqE7ky9.js → chart-line-e3h8sa1R.js} +5 -5
- package/dist/client/chunks/{chart-line-DqqE7ky9.js.map → chart-line-e3h8sa1R.js.map} +1 -1
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js → chart-pie-CFoHYqDB.js} +2 -2
- package/dist/client/chunks/{chart-pie-B5WBzIRH.js.map → chart-pie-CFoHYqDB.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js → chart-radar-CPPwkfxj.js} +2 -2
- package/dist/client/chunks/{chart-radar-DL_dvhA-.js.map → chart-radar-CPPwkfxj.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js → chart-radial-bar-BdEOM-P1.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-DDRo6nz-.js.map → chart-radial-bar-BdEOM-P1.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js → chart-sankey-Bbady-8g.js} +2 -2
- package/dist/client/chunks/{chart-sankey-C_bgIfg-.js.map → chart-sankey-Bbady-8g.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js → chart-scatter-JFu0Pv3a.js} +15 -15
- package/dist/client/chunks/{chart-scatter-DjmJRlK0.js.map → chart-scatter-JFu0Pv3a.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js → chart-sunburst-sayxze15.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-CbMEnaes.js.map → chart-sunburst-sayxze15.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js → chart-tree-map-Ks2xev8b.js} +30 -30
- package/dist/client/chunks/{chart-tree-map-DEfJtJVC.js.map → chart-tree-map-Ks2xev8b.js.map} +1 -1
- package/dist/client/chunks/chartConfigRegistry-BumUIPw4.js +44 -0
- package/dist/client/chunks/{chartConfigRegistry-CiOq-PqX.js.map → chartConfigRegistry-BumUIPw4.js.map} +1 -1
- package/dist/client/chunks/charts-_yZ9gBJU.js +230 -0
- package/dist/client/chunks/charts-_yZ9gBJU.js.map +1 -0
- package/dist/client/chunks/{charts-core-CXrhEEVF.js → charts-core-Bzu9PzMd.js} +10 -10
- package/dist/client/chunks/{charts-core-CXrhEEVF.js.map → charts-core-Bzu9PzMd.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-BtsnUO4Q.js → charts-loader-cMtx4zHx.js} +30 -28
- package/dist/client/chunks/charts-loader-cMtx4zHx.js.map +1 -0
- package/dist/client/chunks/{components-BDrlf9Er.js → components-DQuPThfA.js} +3575 -3208
- package/dist/client/chunks/components-DQuPThfA.js.map +1 -0
- package/dist/client/chunks/{core-B8zw0qRf.js → core-DwOXVb87.js} +2 -2
- package/dist/client/chunks/{core-B8zw0qRf.js.map → core-DwOXVb87.js.map} +1 -1
- package/dist/client/chunks/hooks-DPRv1Xhb.js +150 -0
- package/dist/client/chunks/{hooks-B8Zw5PfL.js.map → hooks-DPRv1Xhb.js.map} +1 -1
- package/dist/client/chunks/{icons-NzFHtqeM.js → icons-DRreo6m8.js} +128 -112
- package/dist/client/chunks/{icons-NzFHtqeM.js.map → icons-DRreo6m8.js.map} +1 -1
- package/dist/client/chunks/{providers-CqCiJTEj.js → providers-BW8D7Wso.js} +2 -2
- package/dist/client/chunks/{providers-CqCiJTEj.js.map → providers-BW8D7Wso.js.map} +1 -1
- package/dist/client/chunks/retention-CzCo8262.js +120 -0
- package/dist/client/chunks/retention-CzCo8262.js.map +1 -0
- package/dist/client/chunks/{useDirtyStateTracking-C_mitVwh.js → useDirtyStateTracking-Yu_qQXb-.js} +101 -99
- package/dist/client/chunks/useDirtyStateTracking-Yu_qQXb-.js.map +1 -0
- package/dist/client/chunks/{vendor-DzzxS7Ay.js → vendor-BSkQZgtm.js} +548 -540
- package/dist/client/chunks/vendor-BSkQZgtm.js.map +1 -0
- package/dist/client/components/AnalysisBuilder/AnalysisTypeSelector.d.ts +3 -1
- package/dist/client/components/AnalysisBuilder/RetentionConfigPanel.d.ts +36 -0
- package/dist/client/components/AnalysisBuilder/RetentionModeContent.d.ts +71 -0
- package/dist/client/components/AnalysisBuilder/types.d.ts +99 -0
- package/dist/client/components/DebugModal.d.ts +2 -1
- package/dist/client/components/charts/RetentionCombinedChart.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionCombinedChart.d.ts +14 -0
- package/dist/client/components/charts/RetentionHeatmap.config.d.ts +2 -0
- package/dist/client/components/charts/RetentionHeatmap.d.ts +7 -0
- package/dist/client/components.js +2 -2
- package/dist/client/hooks/queries/index.d.ts +2 -1
- package/dist/client/hooks/queries/useDryRunQuery.d.ts +26 -0
- package/dist/client/hooks/queries/useExplainQuery.d.ts +3 -1
- package/dist/client/hooks/queries/useFlowQuery.d.ts +5 -0
- package/dist/client/hooks/queries/useRetentionQuery.d.ts +67 -0
- package/dist/client/hooks/useAnalysisBuilderHook.d.ts +61 -0
- package/dist/client/hooks/useAnalysisQueryExecution.d.ts +42 -1
- package/dist/client/hooks.js +3 -3
- package/dist/client/icons/customIcons.d.ts +7 -0
- package/dist/client/icons/types.d.ts +1 -0
- package/dist/client/icons.js +1 -1
- package/dist/client/index.js +11 -11
- package/dist/client/providers.js +1 -1
- package/dist/client/stores/analysisBuilderStore.d.ts +86 -1
- package/dist/client/stores/dashboardStore.d.ts +2 -1
- package/dist/client/stores/slices/index.d.ts +2 -0
- package/dist/client/stores/slices/retentionSlice.d.ts +66 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/types/analysisConfig.d.ts +29 -4
- package/dist/client/types/funnel.d.ts +5 -0
- package/dist/client/types/retention.d.ts +301 -0
- package/dist/client/types.d.ts +6 -3
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +76 -54
- package/dist/server/index.d.ts +217 -0
- package/dist/server/index.js +7363 -4152
- package/package.json +5 -2
- package/dist/adapters/compiler-CO13DaEb.cjs +0 -192
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js +0 -6013
- package/dist/client/chunks/analysis-builder-Dc9NrG_N.js.map +0 -1
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js +0 -2540
- package/dist/client/chunks/analysis-builder-shared-B3-UWqQ2.js.map +0 -1
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js +0 -435
- package/dist/client/chunks/chart-kpi-delta-Bs5R5xr4.js.map +0 -1
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js +0 -392
- package/dist/client/chunks/chart-kpi-number-Cf4Pgkm9.js.map +0 -1
- package/dist/client/chunks/chartConfigRegistry-CiOq-PqX.js +0 -44
- package/dist/client/chunks/charts-loader-BtsnUO4Q.js.map +0 -1
- package/dist/client/chunks/charts-xNubY0vm.js +0 -226
- package/dist/client/chunks/charts-xNubY0vm.js.map +0 -1
- package/dist/client/chunks/components-BDrlf9Er.js.map +0 -1
- package/dist/client/chunks/hooks-B8Zw5PfL.js +0 -123
- package/dist/client/chunks/useDirtyStateTracking-C_mitVwh.js.map +0 -1
- package/dist/client/chunks/vendor-DzzxS7Ay.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis-builder-D0MIKiKS.js","sources":["../../../src/client/hooks/queries/useExplainQuery.ts","../../../src/client/hooks/queries/useExplainAI.ts","../../../src/client/components/AIAssistant/utils.ts","../../../src/client/hooks/useAnalysisAI.ts","../../../src/client/hooks/useAnalysisShare.ts","../../../src/client/shared/components/QueryAnalysisPanel.tsx","../../../src/client/shared/components/CodeBlock.tsx","../../../src/client/components/AnalysisBuilder/ExplainAIPanel.tsx","../../../src/client/components/AnalysisBuilder/ExecutionPlanPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisResultsPanel.tsx","../../../src/client/components/AnalysisBuilder/MetricItemCard.tsx","../../../src/client/components/AnalysisBuilder/MetricsSection.tsx","../../../src/client/components/AnalysisBuilder/types.ts","../../../src/client/components/AnalysisBuilder/BreakdownItemCard.tsx","../../../src/client/components/AnalysisBuilder/BreakdownSection.tsx","../../../src/client/components/AnalysisBuilder/FilterConfigModal.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterItem.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterGroup.tsx","../../../src/client/components/AnalysisBuilder/AnalysisFilterSection.tsx","../../../src/client/components/AnalysisBuilder/AnalysisAxisDropZone.tsx","../../../src/client/components/ChartTypeSelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisDisplayConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/FunnelBindingKeySelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisTypeSelector.tsx","../../../src/client/components/AnalysisBuilder/FunnelConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/FunnelStepCard.tsx","../../../src/client/components/AnalysisBuilder/FunnelStepList.tsx","../../../src/client/components/AnalysisBuilder/FunnelModeContent.tsx","../../../src/client/components/AnalysisBuilder/FlowConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/FlowModeContent.tsx","../../../src/client/components/AnalysisBuilder/RetentionConfigPanel.tsx","../../../src/client/components/AnalysisBuilder/RetentionModeContent.tsx","../../../src/client/components/AnalysisBuilder/AnalysisQueryPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisAIPanel.tsx","../../../src/client/components/AnalysisBuilder/AnalysisModeErrorBoundary.tsx","../../../src/client/components/AnalysisBuilder/index.tsx"],"sourcesContent":["/**\n * useExplainQuery - TanStack Query hook for EXPLAIN PLAN execution\n *\n * Features:\n * - Manually triggered (not automatic like useCubeLoadQuery)\n * - Returns normalized execution plan across PostgreSQL, MySQL, and SQLite\n * - Supports EXPLAIN ANALYZE for actual timing data\n * - No caching - always fetches fresh data to reflect schema/index changes\n *\n * Usage:\n * ```tsx\n * const { explainResult, isLoading, error, runExplain } = useExplainQuery(query)\n *\n * // Trigger explain manually\n * <button onClick={() => runExplain({ analyze: true })}>Explain with Timing</button>\n * ```\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCubeApi } from '../../providers/CubeApiProvider'\nimport type { CubeQuery, ExplainResult, ExplainOptions } from '../../types'\nimport { cleanQueryForServer } from '../../shared/utils'\nimport { stableStringify } from '../../shared/queryKey'\n\n/**\n * Query type that can be explained - includes standard queries, funnel queries, flow queries, and retention queries\n */\nexport type ExplainableQuery = CubeQuery | { funnel: unknown } | { flow: unknown } | { retention: unknown } | unknown\n\n/**\n * Create a stable query key for explain\n */\nexport function createExplainQueryKey(\n query: ExplainableQuery | null,\n options?: ExplainOptions\n): readonly unknown[] {\n if (!query) return ['cube', 'explain', null, null] as const\n return ['cube', 'explain', stableStringify(query), options?.analyze ?? false] as const\n}\n\nexport interface UseExplainQueryOptions {\n /**\n * Whether to skip the query (prevent execution even when triggered)\n * @default false\n */\n skip?: boolean\n}\n\nexport interface UseExplainQueryResult {\n /** The explain result from the server */\n explainResult: ExplainResult | null\n /** Whether the explain query is loading */\n isLoading: boolean\n /** Whether an explain has been triggered */\n hasRun: boolean\n /** Error if explain failed */\n error: Error | null\n /**\n * Manually trigger the explain query\n * @param options - Optional explain options (e.g., { analyze: true } for actual timing)\n */\n runExplain: (options?: ExplainOptions) => void\n /** Clear the explain result */\n clearExplain: () => void\n}\n\n/**\n * Check if query is a funnel query\n */\nfunction isFunnelQuery(query: unknown): query is { funnel: unknown } {\n return typeof query === 'object' && query !== null && 'funnel' in query\n}\n\n/**\n * Check if query is a flow query\n */\nfunction isFlowQuery(query: unknown): query is { flow: unknown } {\n return typeof query === 'object' && query !== null && 'flow' in query\n}\n\n/**\n * Check if query is a retention query\n */\nfunction isRetentionQuery(query: unknown): query is { retention: unknown } {\n return typeof query === 'object' && query !== null && 'retention' in query\n}\n\n/**\n * TanStack Query hook for EXPLAIN PLAN execution\n *\n * Unlike useDryRunQuery, this hook is manually triggered via `runExplain()`.\n * This is intentional because:\n * 1. EXPLAIN queries have performance overhead\n * 2. EXPLAIN ANALYZE actually executes the query\n * 3. Users should explicitly choose when to run explain\n *\n * Supports standard queries, funnel queries, and flow queries.\n *\n * Usage:\n * ```tsx\n * const { explainResult, isLoading, runExplain } = useExplainQuery(query, { skip: !isValidQuery })\n *\n * // Trigger explain\n * <button onClick={() => runExplain()}>Explain Plan</button>\n *\n * // Trigger explain with timing\n * <button onClick={() => runExplain({ analyze: true })}>Explain with Timing</button>\n * ```\n */\nexport function useExplainQuery(\n query: ExplainableQuery | null,\n options: UseExplainQueryOptions = {}\n): UseExplainQueryResult {\n const { skip = false } = options\n const { cubeApi } = useCubeApi()\n\n // Track whether explain has been triggered and with what options\n const [explainOptions, setExplainOptions] = useState<ExplainOptions | null>(null)\n const [hasTriggered, setHasTriggered] = useState(false)\n\n // Transform query for server\n // For funnel/flow/retention queries, pass them directly without cleaning\n const serverQuery = useMemo(() => {\n if (!query) return null\n // Funnel, flow, and retention queries have their own format, don't clean them\n if (isFunnelQuery(query) || isFlowQuery(query) || isRetentionQuery(query)) {\n return query\n }\n // Standard queries get cleaned\n return cleanQueryForServer(query as CubeQuery)\n }, [query])\n\n // Query is enabled only when:\n // 1. We have a query\n // 2. Skip is false\n // 3. User has triggered the explain\n const queryEnabled = !!serverQuery && !skip && hasTriggered\n\n const queryResult = useQuery({\n queryKey: createExplainQueryKey(serverQuery, explainOptions ?? undefined),\n queryFn: async () => {\n if (!serverQuery) throw new Error('No query provided')\n const result = await cubeApi.explain(serverQuery, explainOptions ?? undefined)\n return result\n },\n enabled: queryEnabled,\n // EXPLAIN queries should never be cached - always fetch fresh data\n // This ensures users see the latest execution plan after schema/index changes\n staleTime: 0,\n gcTime: 0,\n // Don't refetch automatically - this is manually triggered\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n refetchOnMount: false,\n })\n\n // Manual trigger function\n const runExplain = useCallback((opts?: ExplainOptions) => {\n if (skip || !serverQuery) return\n setExplainOptions(opts ?? null)\n setHasTriggered(true)\n // If already triggered with same options, refetch\n if (hasTriggered) {\n queryResult.refetch()\n }\n }, [skip, serverQuery, hasTriggered, queryResult])\n\n // Clear function\n const clearExplain = useCallback(() => {\n setHasTriggered(false)\n setExplainOptions(null)\n }, [])\n\n return {\n explainResult: queryResult.data ?? null,\n isLoading: queryResult.isLoading || queryResult.isFetching,\n hasRun: hasTriggered,\n error: queryResult.error ?? null,\n runExplain,\n clearExplain,\n }\n}\n","/**\n * useExplainAI - TanStack Query hook for AI analysis of EXPLAIN plans\n *\n * Features:\n * - Manually triggered via useMutation (not automatic)\n * - Analyzes execution plans and provides actionable recommendations\n * - Returns structured recommendations (indexes, table changes, cube improvements)\n * - No caching - always fetches fresh analysis\n * - Uses the /api/ai/explain/analyze endpoint\n *\n * Usage:\n * ```tsx\n * const { analysis, isAnalyzing, error, analyze, clearAnalysis } = useExplainAI()\n *\n * // After getting an explain result, trigger AI analysis\n * <button onClick={() => analyze(explainResult, query)}>Analyze with AI</button>\n * ```\n */\n\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport type { ExplainResult, AIExplainAnalysis } from '../../types'\nimport { useCubeFeatures } from '../../providers/CubeFeaturesProvider'\n\nexport interface UseExplainAIOptions {\n /**\n * Custom AI endpoint for explain analysis\n * @default '/api/ai/explain/analyze'\n */\n aiEndpoint?: string\n}\n\nexport interface UseExplainAIResult {\n /** The AI analysis result */\n analysis: AIExplainAnalysis | null\n /** Whether AI analysis is in progress */\n isAnalyzing: boolean\n /** Error if AI analysis failed */\n error: Error | null\n /**\n * Trigger AI analysis of an explain result\n * @param explainResult - The EXPLAIN result to analyze\n * @param query - The original semantic query\n */\n analyze: (explainResult: ExplainResult, query: unknown) => void\n /** Clear the analysis result */\n clearAnalysis: () => void\n}\n\n/**\n * Query key for AI explain analysis\n */\nexport const EXPLAIN_AI_QUERY_KEY = ['cube', 'explain', 'ai'] as const\n\n/**\n * TanStack Query hook for AI analysis of EXPLAIN plans\n *\n * This hook uses useMutation to call the AI endpoint and analyze execution plans,\n * providing actionable recommendations for performance improvement.\n *\n * Recommendations focus on what users CAN control:\n * - Index creation (with CREATE INDEX statements)\n * - Table structure changes\n * - Cube definition improvements (segments, pre-aggregations, joins)\n *\n * Usage:\n * ```tsx\n * const { analysis, isAnalyzing, analyze } = useExplainAI()\n *\n * // After running EXPLAIN\n * if (explainResult) {\n * <button onClick={() => analyze(explainResult, query)}>\n * {isAnalyzing ? 'Analyzing...' : 'Analyze with AI'}\n * </button>\n * }\n *\n * // Display recommendations\n * {analysis?.recommendations.map(rec => (\n * <div key={rec.title}>\n * <h4>{rec.title}</h4>\n * <p>{rec.description}</p>\n * {rec.sql && <pre>{rec.sql}</pre>}\n * {rec.cubeCode && <pre>{rec.cubeCode}</pre>}\n * </div>\n * ))}\n * ```\n */\nexport function useExplainAI(options: UseExplainAIOptions = {}): UseExplainAIResult {\n const { features } = useCubeFeatures()\n const enableAI = features.enableAI ?? true\n const queryClient = useQueryClient()\n\n // AI endpoint - defaults to /api/ai/explain/analyze\n // This is the standard path for AI routes in the dev server\n const aiEndpoint = options.aiEndpoint ?? '/api/ai/explain/analyze'\n\n const mutation = useMutation({\n mutationKey: EXPLAIN_AI_QUERY_KEY,\n mutationFn: async ({ explainResult, query }: { explainResult: ExplainResult; query: unknown }) => {\n // Check if AI is enabled\n if (!enableAI) {\n throw new Error('AI features are disabled')\n }\n\n const response = await fetch(aiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify({\n explainResult,\n query,\n }),\n })\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}))\n throw new Error(\n errorData.error ||\n errorData.message ||\n `AI analysis failed: ${response.status} ${response.statusText}`\n )\n }\n\n const result: AIExplainAnalysis = await response.json()\n return result\n },\n // No caching - each mutation is independent\n gcTime: 0,\n })\n\n const analyze = useCallback((explainResult: ExplainResult, query: unknown) => {\n mutation.mutate({ explainResult, query })\n }, [mutation])\n\n const clearAnalysis = useCallback(() => {\n mutation.reset()\n // Also invalidate any cached queries\n queryClient.removeQueries({ queryKey: EXPLAIN_AI_QUERY_KEY })\n }, [mutation, queryClient])\n\n return {\n analysis: mutation.data ?? null,\n isAnalyzing: mutation.isPending,\n error: mutation.error ?? null,\n analyze,\n clearAnalysis,\n }\n}\n","/**\n * Utility functions for AI Assistant\n */\n\nimport type { \n AIQueryRequest,\n AIQueryResponse,\n AIConfig\n} from './types'\nimport { \n AI_STORAGE_KEY,\n DEFAULT_AI_CONFIG\n} from './constants'\n\n/**\n * Send a user prompt to AI proxy (server builds system prompt)\n */\nexport async function sendGeminiMessage(\n apiKey: string,\n userPrompt: string,\n endpoint: string = '/api/ai/generate'\n): Promise<AIQueryResponse> {\n const requestBody: AIQueryRequest = {\n text: userPrompt // Send only the user's prompt, server handles system prompt\n }\n\n // Only add API key header if provided (allow empty string for server key)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n }\n \n if (apiKey && apiKey.trim()) {\n headers['X-API-Key'] = apiKey\n }\n\n console.log('🤖 Client: Sending user prompt to AI proxy')\n console.log(' URL:', endpoint)\n console.log(' Headers:', headers)\n console.log(' User prompt length:', userPrompt.length)\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody)\n })\n\n console.log('📥 Client: Proxy response')\n console.log(' Status:', response.status)\n console.log(' Status Text:', response.statusText)\n\n if (!response.ok) {\n let errorMessage = `Failed to generate content: ${response.status} ${response.statusText}`\n \n try {\n // Try to parse JSON error response first\n const errorData = await response.json()\n console.error('❌ Client: Proxy error:', errorData)\n \n // Handle rate limit errors specially\n if (response.status === 429 && errorData.error === 'Daily quota exceeded') {\n throw new Error(\n `${errorData.message}\\n\\n${errorData.suggestion || 'Add your own Gemini API key for unlimited access.'}`\n )\n }\n \n // Handle other structured errors\n if (errorData.error) {\n errorMessage = errorData.message || errorData.error\n if (errorData.suggestion) {\n errorMessage += `\\n\\n💡 ${errorData.suggestion}`\n }\n }\n } catch {\n // Fallback to text if JSON parsing fails\n try {\n const errorText = await response.text()\n console.error('❌ Client: Proxy text error:', errorText)\n errorMessage = errorText || errorMessage\n } catch {\n console.error('❌ Client: Could not parse error response')\n }\n }\n \n throw new Error(errorMessage)\n }\n\n const data = await response.json()\n console.log('✅ Client: Successfully generated content')\n return data\n}\n\n// Removed: buildSystemPrompt and formatCubeSchemaForPrompt \n// These functions are now handled server-side for better security\n\n/**\n * Save AI configuration to localStorage\n */\nexport function saveAIConfig(config: AIConfig): void {\n try {\n localStorage.setItem(AI_STORAGE_KEY, JSON.stringify(config))\n } catch (error) {\n console.warn('Failed to save AI config to localStorage:', error)\n }\n}\n\n/**\n * Load AI configuration from localStorage\n */\nexport function loadAIConfig(): AIConfig {\n try {\n const saved = localStorage.getItem(AI_STORAGE_KEY)\n if (saved) {\n const parsed = JSON.parse(saved)\n return { ...DEFAULT_AI_CONFIG, ...parsed }\n }\n } catch (error) {\n console.warn('Failed to load AI config from localStorage:', error)\n }\n return { ...DEFAULT_AI_CONFIG }\n}\n\n/**\n * Extract query text from simplified AI response and clean up formatting\n */\nexport function extractTextFromResponse(response: AIQueryResponse): string {\n const rawText = response.query || ''\n\n // Clean up common markdown formatting that might appear\n return rawText\n .replace(/```json\\s*/g, '') // Remove ```json\n .replace(/```\\s*/g, '') // Remove ```\n .replace(/^\\s*```.*\\n/gm, '') // Remove any remaining code block markers\n .trim()\n}","/**\n * Hook for AI query generation in AnalysisBuilder\n *\n * Manages:\n * - AI panel state (open/close, prompt, generating, error)\n * - State snapshots for undo functionality\n * - AI query generation and application\n */\n\nimport { useState, useCallback } from 'react'\nimport type { AnalysisBuilderState, AIState } from '../components/AnalysisBuilder/types'\nimport type { CubeQuery, ChartType, ChartAxisConfig, ChartDisplayConfig } from '../types'\nimport type { ServerFunnelQuery } from '../types/funnel'\nimport type { AnalysisType, AnalysisConfig } from '../types/analysisConfig'\nimport { sendGeminiMessage, extractTextFromResponse } from '../components/AIAssistant/utils'\nimport { generateId, generateMetricLabel } from '../components/AnalysisBuilder/utils'\n\n/**\n * Check if a query object is a ServerFunnelQuery\n */\nfunction isServerFunnelQuery(query: unknown): query is ServerFunnelQuery {\n return (\n typeof query === 'object' &&\n query !== null &&\n 'funnel' in query &&\n typeof (query as ServerFunnelQuery).funnel === 'object'\n )\n}\n\ninterface UseAnalysisAIOptions {\n /** Current state for snapshotting */\n state: AnalysisBuilderState\n /** Set state function for applying AI-generated queries */\n setState: (updater: (prev: AnalysisBuilderState) => AnalysisBuilderState) => void\n /** Current chart type */\n chartType: ChartType\n /** Set chart type */\n setChartType: (type: ChartType) => void\n /** Current chart config */\n chartConfig: ChartAxisConfig\n /** Set chart config */\n setChartConfig: (config: ChartAxisConfig) => void\n /** Current display config */\n displayConfig: ChartDisplayConfig\n /** Set display config */\n setDisplayConfig: (config: ChartDisplayConfig) => void\n /** Set whether user manually selected chart */\n setUserManuallySelectedChart: (value: boolean) => void\n /** Set active view */\n setActiveView: (view: 'table' | 'chart') => void\n /** AI endpoint URL */\n aiEndpoint?: string\n /** Current analysis type */\n analysisType?: AnalysisType\n /** Set analysis type (for switching to funnel mode) */\n setAnalysisType?: (type: AnalysisType) => void\n /** Load funnel config from ServerFunnelQuery */\n loadFunnelFromServerQuery?: (query: ServerFunnelQuery) => void\n /** Get full AnalysisConfig for snapshotting (for complete undo) */\n getFullConfig?: () => AnalysisConfig\n /** Load full AnalysisConfig (for restoring on cancel) */\n loadFullConfig?: (config: AnalysisConfig) => void\n}\n\ninterface UseAnalysisAIResult {\n /** Current AI state */\n aiState: AIState\n /** Open the AI panel */\n handleOpenAI: () => void\n /** Close the AI panel */\n handleCloseAI: () => void\n /** Update the AI prompt */\n handleAIPromptChange: (prompt: string) => void\n /** Generate query from AI */\n handleGenerateAI: () => Promise<void>\n /** Accept the AI-generated query */\n handleAcceptAI: () => void\n /** Cancel and restore previous state */\n handleCancelAI: () => void\n}\n\nexport function useAnalysisAI({\n state,\n setState,\n chartType,\n setChartType,\n chartConfig,\n setChartConfig,\n displayConfig,\n setDisplayConfig,\n setUserManuallySelectedChart,\n setActiveView,\n aiEndpoint = '/api/ai',\n analysisType,\n setAnalysisType,\n loadFunnelFromServerQuery,\n getFullConfig,\n loadFullConfig\n}: UseAnalysisAIOptions): UseAnalysisAIResult {\n // AI state\n const [aiState, setAIState] = useState<AIState>({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null,\n previousConfig: null\n })\n\n /**\n * Open the AI panel and snapshot current state for undo\n */\n const handleOpenAI = useCallback(() => {\n // Snapshot full config if available (for complete restore including funnel state)\n const fullConfig = getFullConfig?.() ?? null\n\n setAIState({\n isOpen: true,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: {\n metrics: [...state.metrics],\n breakdowns: [...state.breakdowns],\n filters: [...state.filters],\n chartType,\n chartConfig: { ...chartConfig },\n displayConfig: { ...displayConfig },\n analysisType: analysisType || 'query'\n },\n previousConfig: fullConfig\n })\n }, [state.metrics, state.breakdowns, state.filters, chartType, chartConfig, displayConfig, analysisType, getFullConfig])\n\n /**\n * Close the AI panel\n */\n const handleCloseAI = useCallback(() => {\n setAIState(prev => ({\n ...prev,\n isOpen: false,\n userPrompt: '',\n error: null,\n hasGeneratedQuery: false\n }))\n }, [])\n\n /**\n * Update the AI prompt\n */\n const handleAIPromptChange = useCallback((prompt: string) => {\n setAIState(prev => ({ ...prev, userPrompt: prompt }))\n }, [])\n\n /**\n * Generate query from AI and apply to builder\n */\n const handleGenerateAI = useCallback(async () => {\n if (!aiState.userPrompt.trim()) return\n\n setAIState(prev => ({ ...prev, isGenerating: true, error: null }))\n\n try {\n const response = await sendGeminiMessage(\n '', // API key not needed for server-side AI\n aiState.userPrompt,\n aiEndpoint\n )\n\n const responseText = extractTextFromResponse(response)\n const parsed = JSON.parse(responseText) as {\n query?: CubeQuery | ServerFunnelQuery\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n } | CubeQuery | ServerFunnelQuery\n\n // Support both new format (with query/chartType/chartConfig) and legacy format (just query)\n const query = ('query' in parsed && parsed.query) ? parsed.query : parsed as CubeQuery | ServerFunnelQuery\n const aiChartType = ('chartType' in parsed) ? parsed.chartType : undefined\n const aiChartConfig = ('chartConfig' in parsed) ? parsed.chartConfig : undefined\n\n // Check if AI generated a funnel query\n if (isServerFunnelQuery(query)) {\n // Switch to funnel mode and load the funnel config\n if (setAnalysisType && loadFunnelFromServerQuery) {\n setAnalysisType('funnel')\n loadFunnelFromServerQuery(query)\n\n // Apply funnel chart type\n setChartType('funnel')\n setUserManuallySelectedChart(true)\n\n // Apply chart config if provided\n if (aiChartConfig) {\n setChartConfig(aiChartConfig)\n }\n\n // Switch to chart view\n setActiveView('chart')\n\n setAIState(prev => ({\n ...prev,\n isGenerating: false,\n hasGeneratedQuery: true\n }))\n return\n } else {\n // Funnel mode not supported in current context\n throw new Error('Funnel queries require funnel mode support. Please switch to funnel mode manually.')\n }\n }\n\n // Handle regular CubeQuery\n const cubeQuery = query as CubeQuery\n\n // Load query into builder state\n setState(prev => ({\n ...prev,\n metrics: (cubeQuery.measures || []).map((field, index) => ({\n id: generateId(),\n field,\n label: generateMetricLabel(index)\n })),\n breakdowns: [\n ...(cubeQuery.dimensions || []).map((field) => ({\n id: generateId(),\n field,\n isTimeDimension: false\n })),\n ...(cubeQuery.timeDimensions || []).map((td) => ({\n id: generateId(),\n field: td.dimension,\n granularity: td.granularity,\n isTimeDimension: true\n }))\n ],\n filters: cubeQuery.filters || []\n }))\n\n // If we were in funnel mode, switch back to query mode\n if (analysisType === 'funnel' && setAnalysisType) {\n setAnalysisType('query')\n }\n\n // Apply chart type if provided by AI\n if (aiChartType) {\n setChartType(aiChartType)\n setUserManuallySelectedChart(true) // Prevent auto-switching\n }\n\n // Apply chart config if provided by AI\n if (aiChartConfig) {\n setChartConfig(aiChartConfig)\n }\n\n // Switch to chart view so user can see the visualization\n setActiveView('chart')\n\n setAIState(prev => ({\n ...prev,\n isGenerating: false,\n hasGeneratedQuery: true\n }))\n } catch (error) {\n setAIState(prev => ({\n ...prev,\n isGenerating: false,\n error: error instanceof Error ? error.message : 'Failed to generate query'\n }))\n }\n }, [aiState.userPrompt, aiEndpoint, setState, setChartType, setUserManuallySelectedChart, setChartConfig, setActiveView, analysisType, setAnalysisType, loadFunnelFromServerQuery])\n\n /**\n * Accept the AI-generated query (keep changes, close panel)\n */\n const handleAcceptAI = useCallback(() => {\n setAIState({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null,\n previousConfig: null\n })\n }, [])\n\n /**\n * Cancel and restore previous state\n */\n const handleCancelAI = useCallback(() => {\n // Prefer full config restore (handles funnel mode properly)\n if (aiState.previousConfig && loadFullConfig) {\n loadFullConfig(aiState.previousConfig)\n } else if (aiState.previousState) {\n // Fallback to individual state restore\n setState(prev => ({\n ...prev,\n metrics: aiState.previousState!.metrics,\n breakdowns: aiState.previousState!.breakdowns,\n filters: aiState.previousState!.filters\n }))\n setChartType(aiState.previousState.chartType)\n setChartConfig(aiState.previousState.chartConfig)\n setDisplayConfig(aiState.previousState.displayConfig)\n\n // Restore analysis type if it was changed\n if (setAnalysisType && aiState.previousState.analysisType) {\n setAnalysisType(aiState.previousState.analysisType)\n }\n }\n\n // Close panel\n setAIState({\n isOpen: false,\n userPrompt: '',\n isGenerating: false,\n error: null,\n hasGeneratedQuery: false,\n previousState: null,\n previousConfig: null\n })\n }, [aiState.previousState, aiState.previousConfig, setState, setChartType, setChartConfig, setDisplayConfig, setAnalysisType, loadFullConfig])\n\n return {\n aiState,\n handleOpenAI,\n handleCloseAI,\n handleAIPromptChange,\n handleGenerateAI,\n handleAcceptAI,\n handleCancelAI\n }\n}\n","/**\n * Hook for share URL functionality in AnalysisBuilder\n *\n * Manages:\n * - Share button state (idle, copied, copied-no-chart)\n * - Share URL generation and clipboard copy\n *\n * Phase 3: Now uses store.save() to get AnalysisConfig directly.\n */\n\nimport { useState, useCallback } from 'react'\nimport type { AnalysisConfig } from '../types/analysisConfig'\nimport { compressWithFallback } from '../utils/shareUtils'\n\ninterface UseAnalysisShareOptions {\n /** Whether the current query is valid */\n isValidQuery: boolean\n /**\n * Getter for the AnalysisConfig (from store.save())\n * This is the new Phase 3 API - returns complete AnalysisConfig\n */\n getAnalysisConfig: () => AnalysisConfig\n}\n\ninterface UseAnalysisShareResult {\n /** Current share button state */\n shareButtonState: 'idle' | 'copied' | 'copied-no-chart'\n /** Handle share button click */\n handleShare: () => Promise<void>\n}\n\nexport function useAnalysisShare({\n isValidQuery,\n getAnalysisConfig,\n}: UseAnalysisShareOptions): UseAnalysisShareResult {\n const [shareButtonState, setShareButtonState] = useState<'idle' | 'copied' | 'copied-no-chart'>('idle')\n\n /**\n * Generate share URL and copy to clipboard\n */\n const handleShare = useCallback(async () => {\n if (!isValidQuery) return\n\n // Get AnalysisConfig from store's save() method\n const config = getAnalysisConfig()\n\n // Try full config first, fall back to minimal if too large\n const { encoded, queryOnly } = compressWithFallback(config)\n\n // If even minimal is too large, don't share\n if (!encoded) {\n return\n }\n\n const url = `${window.location.origin}${window.location.pathname}#share=${encoded}`\n\n try {\n await navigator.clipboard.writeText(url)\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement('textarea')\n textArea.value = url\n document.body.appendChild(textArea)\n textArea.select()\n document.execCommand('copy')\n document.body.removeChild(textArea)\n }\n\n // Update button state\n setShareButtonState(queryOnly ? 'copied-no-chart' : 'copied')\n\n // Reset button state after 2 seconds\n setTimeout(() => {\n setShareButtonState('idle')\n }, 2000)\n }, [isValidQuery, getAnalysisConfig])\n\n return {\n shareButtonState,\n handleShare\n }\n}\n","/**\n * QueryAnalysisPanel Component\n * Displays query planning analysis for debugging and transparency\n */\n\nimport React from 'react'\nimport { getIcon } from '../../icons'\nimport type { QueryAnalysis } from '../types'\n\ninterface QueryAnalysisPanelProps {\n analysis: QueryAnalysis\n}\n\n/**\n * Format reason string for display\n */\nfunction formatReason(reason: string): string {\n return reason.replace(/_/g, ' ')\n}\n\n/**\n * Get badge color based on reason\n */\nfunction getReasonBadgeClasses(reason: string): string {\n switch (reason) {\n case 'most_dimensions':\n return 'bg-dc-info-bg text-dc-info'\n case 'most_connected':\n return 'bg-dc-accent-bg text-dc-accent'\n case 'alphabetical_fallback':\n return 'bg-dc-warning-bg text-dc-warning'\n case 'single_cube':\n return 'bg-dc-success-bg text-dc-success'\n default:\n return 'bg-dc-muted-bg text-dc-muted'\n }\n}\n\nconst QueryAnalysisPanel: React.FC<QueryAnalysisPanelProps> = ({ analysis }) => {\n const InfoIcon = getIcon('info')\n const ArrowRightIcon = getIcon('chevronRight')\n const WarningIcon = getIcon('warning')\n const TableIcon = getIcon('table')\n const LinkIcon = getIcon('link')\n const SuccessIcon = getIcon('success')\n const ErrorIcon = getIcon('error')\n\n return (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded-lg p-4 space-y-4\">\n {/* Query Summary Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <InfoIcon className=\"w-4 h-4 mr-2\" />\n Query Summary\n </h4>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2 text-xs\">\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Type:</span>\n <span className=\"ml-1 font-medium text-dc-text\">\n {formatReason(analysis.querySummary.queryType)}\n </span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Cubes:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.cubeCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Joins:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.joinCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">CTEs:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.cteCount}</span>\n </div>\n </div>\n </div>\n\n {/* Primary Cube Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Primary Cube (FROM table)\n </h4>\n <div className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-primary\">\n {analysis.primaryCube.selectedCube}\n </span>\n <span className={`text-xs px-2 py-0.5 rounded ${getReasonBadgeClasses(analysis.primaryCube.reason)}`}>\n {formatReason(analysis.primaryCube.reason)}\n </span>\n </div>\n <p className=\"text-dc-text-secondary text-xs\">\n {analysis.primaryCube.explanation}\n </p>\n {analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1 && (\n <details className=\"mt-2\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Show candidates ({analysis.primaryCube.candidates.length})\n </summary>\n <div className=\"mt-2 space-y-1 ml-2\">\n {analysis.primaryCube.candidates.map((c, i) => (\n <div key={i} className=\"text-xs flex items-center gap-2 flex-wrap\">\n <span className={`font-mono ${c.cubeName === analysis.primaryCube.selectedCube ? 'font-bold text-dc-primary' : 'text-dc-text-muted'}`}>\n {c.cubeName}\n </span>\n <span className=\"text-dc-text-muted\">\n dims: {c.dimensionCount}, joins: {c.joinCount}\n </span>\n {c.canReachAll ? (\n <span className=\"text-dc-success flex items-center gap-0.5\">\n <SuccessIcon className=\"w-3 h-3\" />\n reachable\n </span>\n ) : (\n <span className=\"text-dc-error flex items-center gap-0.5\">\n <ErrorIcon className=\"w-3 h-3\" />\n cannot reach all\n </span>\n )}\n </div>\n ))}\n </div>\n </details>\n )}\n </div>\n </div>\n\n {/* Join Paths Section */}\n {analysis.joinPaths.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <LinkIcon className=\"w-4 h-4 mr-2\" />\n Join Paths\n </h4>\n <div className=\"space-y-2\">\n {analysis.joinPaths.map((jp, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{analysis.primaryCube.selectedCube}</span>\n <ArrowRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n <span className=\"font-mono font-medium text-dc-text\">{jp.targetCube}</span>\n {jp.pathFound ? (\n <span className=\"text-xs px-2 py-0.5 bg-dc-success-bg text-dc-success rounded\">\n {jp.pathLength} step{jp.pathLength !== 1 ? 's' : ''}\n </span>\n ) : (\n <span className=\"text-xs px-2 py-0.5 bg-dc-error-bg text-dc-error rounded\">\n No path\n </span>\n )}\n </div>\n {jp.pathFound && jp.path && jp.path.length > 0 && (\n <div className=\"space-y-1 ml-2\">\n {jp.path.map((step, stepIdx) => (\n <div key={stepIdx} className=\"flex items-center gap-1 text-xs flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{step.fromCube}</span>\n <ArrowRightIcon className=\"w-3 h-3 text-dc-text-muted\" />\n <span className=\"font-mono text-dc-text\">{step.toCube}</span>\n <span className=\"text-dc-text-muted\">\n ({step.relationship}, {step.joinType} join)\n </span>\n {step.joinColumns.length > 0 && (\n <span className=\"text-dc-text-muted\">\n on {step.joinColumns.map(jc => `${jc.sourceColumn}=${jc.targetColumn}`).join(', ')}\n </span>\n )}\n </div>\n ))}\n </div>\n )}\n {!jp.pathFound && jp.error && (\n <p className=\"text-xs text-dc-error mt-1\">{jp.error}</p>\n )}\n {jp.visitedCubes && jp.visitedCubes.length > 0 && !jp.pathFound && (\n <details className=\"mt-1\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Cubes visited during search ({jp.visitedCubes.length})\n </summary>\n <div className=\"mt-1 text-xs text-dc-text-muted ml-2\">\n {jp.visitedCubes.join(' → ')}\n </div>\n </details>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Pre-Aggregations Section */}\n {analysis.preAggregations.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Pre-Aggregation CTEs\n </h4>\n <div className=\"space-y-2\">\n {analysis.preAggregations.map((pa, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-1 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-text\">{pa.cubeName}</span>\n <span className=\"text-xs text-dc-text-muted\">as</span>\n <code className=\"text-xs bg-dc-surface-secondary px-1 rounded font-mono\">{pa.cteAlias}</code>\n </div>\n <p className=\"text-xs text-dc-text-secondary\">{pa.reason}</p>\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Measures:</span> {pa.measures.join(', ')}\n </div>\n {pa.joinKeys.length > 0 && (\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Join keys:</span> {pa.joinKeys.map(jk => `${jk.sourceColumn}=${jk.targetColumn}`).join(', ')}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Warnings Section */}\n {analysis.warnings && analysis.warnings.length > 0 && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-warning mb-2 flex items-center\">\n <WarningIcon className=\"w-4 h-4 mr-2\" />\n Warnings\n </h4>\n <ul className=\"list-disc list-inside text-xs text-dc-warning space-y-1\">\n {analysis.warnings.map((w, i) => (\n <li key={i}>{w}</li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Cubes Involved */}\n {analysis.cubesInvolved.length > 0 && (\n <div className=\"text-xs text-dc-text-muted pt-2 border-t border-dc-border\">\n <span className=\"font-medium\">Cubes involved:</span> {analysis.cubesInvolved.join(', ')}\n </div>\n )}\n </div>\n )\n}\n\nexport default QueryAnalysisPanel\n","/**\n * CodeBlock Component\n * Displays syntax-highlighted code with copy-to-clipboard functionality\n */\n\nimport React, { useState, useEffect, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport { getSyntaxHighlighter, loadSyntaxHighlighter } from '../../utils/syntaxHighlighting'\nimport './CodeBlock.css'\n\ninterface CodeBlockProps {\n code: string\n language: 'json' | 'sql'\n title?: string\n maxHeight?: string\n height?: string\n className?: string\n /** Additional content to render on the right side of the header (before Copy button) */\n headerRight?: React.ReactNode\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n language,\n title,\n maxHeight = '16rem',\n height,\n className = '',\n headerRight\n}) => {\n const [copied, setCopied] = useState(false)\n const codeRef = useRef<HTMLElement>(null)\n const CopyIcon = getIcon('copy')\n const CheckIcon = getIcon('check')\n\n // Apply syntax highlighting\n useEffect(() => {\n if (!codeRef.current) return\n const element = codeRef.current\n let isActive = true\n\n element.textContent = code\n\n loadSyntaxHighlighter()\n .then(() => {\n if (!isActive) return\n const hljs = getSyntaxHighlighter()\n if (!hljs) return\n element.innerHTML = hljs.highlight(code, { language }).value\n })\n .catch(() => {\n if (isActive) {\n element.textContent = code\n }\n })\n\n return () => {\n isActive = false\n }\n }, [code, language])\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement('textarea')\n textArea.value = code\n textArea.style.position = 'fixed'\n textArea.style.left = '-999999px'\n document.body.appendChild(textArea)\n textArea.select()\n document.execCommand('copy')\n document.body.removeChild(textArea)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n return (\n <div className={`relative ${className}`}>\n {/* Header with title, optional extra controls, and copy button */}\n <div className=\"flex items-center justify-between mb-2 gap-2\">\n {title && (\n <h4 className=\"text-sm font-semibold text-dc-text\">{title}</h4>\n )}\n <div className=\"flex items-center gap-2 ml-auto\">\n {headerRight}\n <button\n onClick={handleCopy}\n className=\"px-2 py-1 text-xs rounded hover:bg-dc-surface-secondary border border-dc-border transition-colors flex items-center gap-1.5\"\n title={copied ? 'Copied!' : 'Copy to clipboard'}\n >\n {copied ? (\n <>\n <CheckIcon className=\"w-3.5 h-3.5 text-dc-success\" />\n <span className=\"text-dc-success\">Copied</span>\n </>\n ) : (\n <>\n <CopyIcon className=\"w-3.5 h-3.5 text-dc-text-secondary\" />\n <span className=\"text-dc-text-secondary\">Copy</span>\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Code block with syntax highlighting */}\n <div\n className=\"bg-dc-surface-secondary border border-dc-border rounded overflow-auto\"\n style={height ? { height, minHeight: height, maxHeight: height } : { maxHeight }}\n >\n <pre className=\"p-3 text-xs m-0\">\n <code\n ref={codeRef}\n className={`hljs language-${language}`}\n >\n {code}\n </code>\n </pre>\n </div>\n </div>\n )\n}\n\nexport default CodeBlock\n","/**\n * ExplainAIPanel - Display AI analysis of EXPLAIN plans in a modal\n *\n * Shows:\n * - Assessment badge (good/warning/critical)\n * - Query understanding\n * - Issues identified\n * - Actionable recommendations with code snippets\n *\n * Displayed in a near full-screen modal with scrolling support\n */\n\nimport React from 'react'\nimport type { AIExplainAnalysis, ExplainRecommendation, ExplainIssue } from '../../types'\nimport CodeBlock from '../../shared/components/CodeBlock'\n\ninterface ExplainAIPanelProps {\n /** AI analysis result */\n analysis: AIExplainAnalysis\n /** Callback to close the modal */\n onClose?: () => void\n /** Legacy: Callback to clear/close (backward compatible with old API) */\n onClear?: () => void\n}\n\n/**\n * Helper to safely render text that might be an object from AI\n * AI responses sometimes return objects instead of strings for text fields\n */\nfunction safeText(value: unknown): string {\n if (typeof value === 'string') return value\n if (typeof value === 'object' && value !== null) return JSON.stringify(value)\n return String(value ?? '')\n}\n\n/**\n * Color classes for assessment badges\n */\nconst assessmentColors = {\n good: 'bg-dc-success-bg text-dc-success border-dc-success',\n warning: 'bg-dc-warning-bg text-dc-warning border-dc-warning',\n critical: 'bg-dc-danger-bg text-dc-error border-dc-error',\n}\n\n/**\n * Color classes for severity badges\n */\nconst severityColors = {\n critical: 'bg-dc-danger-bg text-dc-error',\n warning: 'bg-dc-warning-bg text-dc-warning',\n suggestion: 'bg-dc-accent-bg text-dc-accent',\n}\n\n/**\n * Color classes for issue severity\n */\nconst issueSeverityColors = {\n high: 'text-dc-error',\n medium: 'text-dc-warning',\n low: 'text-dc-text-muted',\n}\n\n/**\n * Assessment badge component\n */\nfunction AssessmentBadge({ assessment, reason }: { assessment: 'good' | 'warning' | 'critical'; reason: unknown }) {\n const labels = {\n good: 'Good',\n warning: 'Warning',\n critical: 'Critical',\n }\n\n return (\n <div className={`p-4 rounded-lg border ${assessmentColors[assessment]}`}>\n <div className=\"flex items-center gap-2 mb-1\">\n <span className=\"font-semibold uppercase text-base\">\n {assessment === 'good' && '✓ '}\n {assessment === 'warning' && '⚠ '}\n {assessment === 'critical' && '✕ '}\n {labels[assessment]}\n </span>\n </div>\n <p className=\"text-sm\">{safeText(reason)}</p>\n </div>\n )\n}\n\n/**\n * Issue item component\n */\nfunction IssueItem({ issue }: { issue: ExplainIssue }) {\n return (\n <div className=\"flex items-start gap-2 py-2\">\n <span className={`text-sm ${issueSeverityColors[issue.severity]}`}>\n {issue.severity === 'high' && '●'}\n {issue.severity === 'medium' && '○'}\n {issue.severity === 'low' && '○'}\n </span>\n <span className=\"text-sm text-dc-text-secondary\">{safeText(issue.description)}</span>\n </div>\n )\n}\n\n/**\n * Copy button component\n */\nfunction CopyButton({ text }: { text: string }) {\n const [copied, setCopied] = React.useState(false)\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error('Failed to copy:', err)\n }\n }\n\n return (\n <button\n onClick={handleCopy}\n className=\"px-2 py-1 text-xs rounded bg-dc-surface hover:bg-dc-surface-hover text-dc-text-muted\"\n title=\"Copy to clipboard\"\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n )\n}\n\n/**\n * Recommendation card component\n */\nfunction RecommendationCard({ rec }: { rec: ExplainRecommendation }) {\n const typeLabels = {\n index: 'INDEX',\n table: 'TABLE',\n cube: 'CUBE',\n general: 'TIP',\n }\n\n return (\n <div className=\"p-4 border border-dc-border rounded-lg bg-dc-surface\">\n {/* Header */}\n <div className=\"flex items-center gap-2 mb-2\">\n <span\n className={`px-2 py-0.5 text-xs font-medium rounded ${severityColors[rec.severity]}`}\n >\n {typeLabels[rec.type]}\n </span>\n <h5 className=\"font-medium text-dc-text\">{safeText(rec.title)}</h5>\n </div>\n\n {/* Description */}\n <p className=\"text-sm text-dc-text-secondary mb-3\">{safeText(rec.description)}</p>\n\n {/* SQL code for index/table recommendations */}\n {rec.sql && (\n <div className=\"mt-2\">\n <CodeBlock\n code={rec.sql}\n language=\"sql\"\n headerRight={<CopyButton text={rec.sql} />}\n />\n </div>\n )}\n\n {/* TypeScript code for cube recommendations - display as text since CodeBlock doesn't support TS */}\n {rec.cubeCode && (\n <div className=\"mt-2\">\n {rec.cubeName && (\n <p className=\"text-xs text-dc-text-muted mb-1\">\n Add to <code className=\"bg-dc-surface-secondary px-1 rounded\">{rec.cubeName}</code> cube:\n </p>\n )}\n <div className=\"relative\">\n <pre className=\"p-3 text-xs bg-dc-surface-secondary rounded overflow-x-auto font-mono text-dc-text\">\n {rec.cubeCode}\n </pre>\n <div className=\"absolute top-1 right-1\">\n <CopyButton text={rec.cubeCode} />\n </div>\n </div>\n </div>\n )}\n\n {/* Expected impact */}\n {rec.estimatedImpact && (\n <p className=\"text-xs text-dc-text-muted mt-2\">\n <strong>Expected impact:</strong> {safeText(rec.estimatedImpact)}\n </p>\n )}\n </div>\n )\n}\n\n/**\n * ExplainAIPanel - Modal component for displaying AI analysis results\n * Shows in a near full-screen modal with scrolling\n */\nexport function ExplainAIPanel({ analysis, onClose, onClear }: ExplainAIPanelProps) {\n // Support both onClose (new) and onClear (legacy) for backward compatibility\n const handleClose = onClose || onClear\n\n // Close on Escape key\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && handleClose) {\n handleClose()\n }\n }\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [handleClose])\n\n // Prevent body scroll when modal is open\n React.useEffect(() => {\n document.body.style.overflow = 'hidden'\n return () => {\n document.body.style.overflow = ''\n }\n }, [])\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50\">\n {/* Modal backdrop */}\n <div\n className=\"absolute inset-0\"\n onClick={handleClose}\n aria-hidden=\"true\"\n />\n\n {/* Modal content */}\n <div className=\"relative w-full max-w-4xl max-h-[90vh] bg-dc-surface rounded-lg shadow-xl flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-dc-border flex-shrink-0\">\n <div className=\"flex items-center gap-3\">\n <span className=\"text-lg\">✨</span>\n <h3 className=\"text-lg font-semibold text-dc-text\">AI Performance Analysis</h3>\n </div>\n <button\n onClick={handleClose}\n className=\"p-2 rounded-lg hover:bg-dc-surface-hover text-dc-text-secondary hover:text-dc-text transition-colors\"\n aria-label=\"Close\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Scrollable content */}\n <div className=\"flex-1 overflow-y-auto px-6 py-4 space-y-6\">\n {/* Assessment */}\n <AssessmentBadge\n assessment={analysis.assessment}\n reason={analysis.assessmentReason}\n />\n\n {/* Summary */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text-muted uppercase mb-2\">Summary</h4>\n <p className=\"text-dc-text\">{safeText(analysis.summary)}</p>\n </div>\n\n {/* Query Understanding */}\n {analysis.queryUnderstanding && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text-muted uppercase mb-2\">Query Analysis</h4>\n <p className=\"text-dc-text-secondary\">{safeText(analysis.queryUnderstanding)}</p>\n </div>\n )}\n\n {/* Issues */}\n {analysis.issues && analysis.issues.length > 0 && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text-muted uppercase mb-2\">\n Issues Found ({analysis.issues.length})\n </h4>\n <div className=\"space-y-1 bg-dc-surface-secondary rounded-lg p-3\">\n {analysis.issues.map((issue, i) => (\n <IssueItem key={i} issue={issue} />\n ))}\n </div>\n </div>\n )}\n\n {/* Recommendations */}\n {analysis.recommendations && analysis.recommendations.length > 0 && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text-muted uppercase mb-3\">\n Recommendations ({analysis.recommendations.length})\n </h4>\n <div className=\"space-y-4\">\n {analysis.recommendations.map((rec, i) => (\n <RecommendationCard key={i} rec={rec} />\n ))}\n </div>\n </div>\n )}\n\n {/* No recommendations case */}\n {(!analysis.recommendations || analysis.recommendations.length === 0) && (\n <div className=\"text-dc-text-muted italic p-4 bg-dc-surface-secondary rounded-lg\">\n No specific recommendations. The query appears to be well-optimized.\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-between px-6 py-3 border-t border-dc-border flex-shrink-0 bg-dc-surface-secondary\">\n {/* Meta info */}\n {analysis._meta && (\n <div className=\"text-xs text-dc-text-muted\">\n Model: {analysis._meta.model}\n {analysis._meta.usingUserKey && ' (using your API key)'}\n </div>\n )}\n <button\n onClick={handleClose}\n className=\"px-4 py-2 text-sm font-medium rounded-lg bg-dc-primary text-white hover:bg-dc-primary-hover transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default ExplainAIPanel\n","/**\n * ExecutionPlanPanel - Shared component for SQL display, EXPLAIN plans, and AI analysis\n *\n * Used across all analysis modes (query, funnel, flow) to show:\n * - Generated SQL with copy functionality\n * - Explain Plan button with \"Include timing\" toggle\n * - EXPLAIN results with summary badges\n * - AI Analysis button (in Explain Plan header) and modal\n *\n * This is a composable component - the parent handles the layout,\n * this component handles the SQL -> Explain -> AI workflow.\n */\n\nimport { useState, memo } from 'react'\nimport { CodeBlock } from '../../shared'\nimport { ExplainAIPanel } from './ExplainAIPanel'\nimport type { ExplainResult, AIExplainAnalysis } from '../../types'\n\ninterface ExecutionPlanPanelProps {\n /** The generated SQL to display */\n sql: { sql: string; params?: unknown[] } | null | undefined\n /** Whether SQL is loading */\n sqlLoading?: boolean\n /** Error loading SQL */\n sqlError?: Error | null\n /** Placeholder text when no SQL */\n sqlPlaceholder?: string\n\n /** EXPLAIN plan result */\n explainResult: ExplainResult | null\n /** Whether EXPLAIN is running */\n explainLoading?: boolean\n /** Whether EXPLAIN has been run at least once */\n explainHasRun?: boolean\n /** Error running EXPLAIN */\n explainError?: Error | null\n /** Run EXPLAIN with options */\n runExplain: (options: { analyze: boolean }) => void\n\n /** AI analysis result */\n aiAnalysis?: AIExplainAnalysis | null\n /** Whether AI analysis is in progress */\n aiAnalysisLoading?: boolean\n /** Error from AI analysis */\n aiAnalysisError?: Error | null\n /** Run AI analysis */\n runAIAnalysis?: (explainResult: ExplainResult, query: unknown) => void\n /** Clear AI analysis (unused but kept for interface compatibility) */\n clearAIAnalysis?: () => void\n /** Whether AI is enabled */\n enableAI?: boolean\n\n /** The query object for AI context */\n query?: unknown\n\n /** Title for the SQL block */\n title?: string\n /** Height for the SQL block */\n height?: string\n}\n\n/**\n * ExecutionPlanPanel - Displays SQL, EXPLAIN results, and AI analysis\n */\nexport const ExecutionPlanPanel = memo(function ExecutionPlanPanel({\n sql,\n sqlLoading = false,\n sqlError,\n sqlPlaceholder = 'Add metrics to generate SQL',\n\n explainResult,\n explainLoading = false,\n explainHasRun = false,\n explainError,\n runExplain,\n\n aiAnalysis,\n aiAnalysisLoading = false,\n aiAnalysisError,\n runAIAnalysis,\n clearAIAnalysis: _clearAIAnalysis,\n enableAI = false,\n\n query,\n\n title = 'Generated SQL',\n height = '16rem',\n}: ExecutionPlanPanelProps) {\n const [useAnalyze, setUseAnalyze] = useState(false)\n const [showAIModal, setShowAIModal] = useState(false)\n\n // Format SQL with parameters\n const formattedSql = sql\n ? sql.sql +\n (sql.params && sql.params.length > 0\n ? '\\n\\n-- Parameters:\\n' + JSON.stringify(sql.params, null, 2)\n : '')\n : ''\n\n // Handle AI analysis - always re-run to get fresh results after schema/index changes\n const handleAIClick = () => {\n if (runAIAnalysis && explainResult && query) {\n // Always run fresh analysis - indexes may have been added since last run\n runAIAnalysis(explainResult, query)\n setShowAIModal(true)\n }\n }\n\n // Close modal\n const handleCloseModal = () => {\n setShowAIModal(false)\n }\n\n // Build the AI button for use in Explain Plan header\n const aiButton = enableAI && explainResult ? (\n <button\n onClick={handleAIClick}\n disabled={aiAnalysisLoading}\n className=\"px-2 py-1 text-xs font-medium rounded bg-dc-accent text-white hover:bg-dc-accent-hover disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1\"\n >\n {aiAnalysisLoading ? (\n <>\n <span className=\"animate-spin\">⟳</span>\n Analyzing...\n </>\n ) : (\n <>✨ AI Analysis</>\n )}\n </button>\n ) : null\n\n return (\n <div className=\"space-y-3\">\n {/* SQL Block */}\n {sqlLoading ? (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">{title}</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm animate-pulse\" style={{ height }}>\n Loading SQL...\n </div>\n </>\n ) : sqlError ? (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">{title}</h4>\n <div className=\"text-dc-error text-sm bg-dc-danger-bg p-3 rounded border border-dc-error\" style={{ height }}>\n {sqlError.message}\n </div>\n </>\n ) : sql ? (\n <CodeBlock\n code={formattedSql}\n language=\"sql\"\n title={title}\n height={height}\n headerRight={\n <>\n {/* Include timing checkbox */}\n <label className=\"flex items-center gap-1 text-xs text-dc-text-secondary cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={useAnalyze}\n onChange={(e) => setUseAnalyze(e.target.checked)}\n className=\"w-3 h-3 rounded border-dc-border text-dc-accent focus:ring-dc-accent\"\n />\n Include timing\n </label>\n\n {/* Explain Plan button */}\n <button\n onClick={() => runExplain({ analyze: useAnalyze })}\n disabled={explainLoading}\n className=\"px-2 py-1 text-xs font-medium rounded border border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text-secondary hover:text-dc-text transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {explainLoading ? 'Running...' : 'Explain Plan'}\n </button>\n </>\n }\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">{title}</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\" style={{ height }}>\n {sqlPlaceholder}\n </div>\n </>\n )}\n\n {/* EXPLAIN Results */}\n {explainHasRun && (\n <div>\n {explainLoading ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm animate-pulse\">\n Running EXPLAIN{useAnalyze ? ' ANALYZE' : ''}...\n </div>\n ) : explainError ? (\n <div className=\"text-dc-error text-sm bg-dc-danger-bg p-3 rounded border border-dc-error\">\n <strong>Explain Error:</strong> {explainError.message}\n </div>\n ) : explainResult ? (\n <div className=\"space-y-3\">\n {/* Summary badges */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-accent text-white rounded\">\n {explainResult.summary.database.toUpperCase()}\n </span>\n {explainResult.summary.hasSequentialScans && (\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-warning-bg text-dc-warning border border-dc-warning rounded\">\n Sequential Scans Detected\n </span>\n )}\n {explainResult.summary.usedIndexes.length > 0 && (\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-success-bg text-dc-success border border-dc-success rounded\">\n {explainResult.summary.usedIndexes.length} Index{explainResult.summary.usedIndexes.length !== 1 ? 'es' : ''} Used\n </span>\n )}\n {explainResult.summary.executionTime !== undefined && (\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-surface-secondary text-dc-text-secondary border border-dc-border rounded\">\n Execution: {explainResult.summary.executionTime.toFixed(2)}ms\n </span>\n )}\n {explainResult.summary.planningTime !== undefined && (\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-surface-secondary text-dc-text-secondary border border-dc-border rounded\">\n Planning: {explainResult.summary.planningTime.toFixed(2)}ms\n </span>\n )}\n {explainResult.summary.totalCost !== undefined && (\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-surface-secondary text-dc-text-secondary border border-dc-border rounded\">\n Cost: {explainResult.summary.totalCost.toFixed(2)}\n </span>\n )}\n </div>\n\n {/* Index usage details */}\n {explainResult.summary.usedIndexes.length > 0 && (\n <div className=\"text-xs text-dc-text-muted\">\n <strong>Indexes:</strong> {explainResult.summary.usedIndexes.join(', ')}\n </div>\n )}\n\n {/* Raw EXPLAIN output with AI button in header */}\n <CodeBlock\n code={explainResult.raw}\n language=\"sql\"\n title={`Execution Plan (${explainResult.summary.database})`}\n height=\"16rem\"\n headerRight={aiButton}\n />\n </div>\n ) : null}\n </div>\n )}\n\n {/* AI Analysis Error (shown inline) */}\n {aiAnalysisError && (\n <div className=\"text-dc-error text-sm bg-dc-danger-bg p-3 rounded border border-dc-error\">\n <strong>AI Analysis Error:</strong> {aiAnalysisError.message}\n </div>\n )}\n\n {/* AI Analysis Modal */}\n {showAIModal && aiAnalysis && (\n <ExplainAIPanel\n analysis={aiAnalysis}\n onClose={handleCloseModal}\n />\n )}\n </div>\n )\n})\n\nexport default ExecutionPlanPanel\n","/**\n * AnalysisResultsPanel Component\n *\n * Displays query execution results with chart and table views.\n * Used in the left panel of AnalysisBuilder.\n */\n\nimport { useState, useEffect, useMemo, memo, useRef } from 'react'\nimport type { AnalysisResultsPanelProps } from './types'\nimport { LazyChart, isValidChartType } from '../../charts/ChartLoader'\nimport { getIcon } from '../../icons'\nimport { QueryAnalysisPanel, CodeBlock } from '../../shared'\nimport ConfirmModal from '../ConfirmModal'\nimport ColorPaletteSelector from '../ColorPaletteSelector'\nimport { useExplainQuery } from '../../hooks/queries/useExplainQuery'\nimport { useExplainAI } from '../../hooks/queries/useExplainAI'\nimport type { CubeQuery } from '../../types'\nimport { ExecutionPlanPanel } from './ExecutionPlanPanel'\n\n/**\n * AnalysisResultsPanel displays query results with chart/table toggle.\n *\n * Features:\n * - Chart visualization with LazyChart\n * - Table view with DataTable\n * - Loading, error, and empty states\n * - Stale results indicator\n * - Display limit control for tables\n */\nconst AnalysisResultsPanel = memo(function AnalysisResultsPanel({\n executionStatus,\n executionResults,\n executionError,\n totalRowCount,\n resultsStale = false,\n chartType = 'line',\n chartConfig = {},\n displayConfig = {},\n colorPalette,\n currentPaletteName,\n onColorPaletteChange,\n allQueries,\n funnelExecutedQueries,\n activeView = 'chart',\n onActiveViewChange,\n displayLimit = 100,\n onDisplayLimitChange,\n hasMetrics = false,\n // Debug props - per-query for multi-query mode\n debugDataPerQuery = [],\n // Share props\n onShareClick,\n canShare = false,\n shareButtonState = 'idle',\n // Refresh functionality\n onRefreshClick,\n canRefresh = false,\n isRefreshing = false,\n needsRefresh = false,\n // Clear functionality\n onClearClick,\n canClear = false,\n // AI functionality\n enableAI = false,\n isAIOpen = false,\n onAIToggle,\n // Multi-query props\n queryCount = 1,\n perQueryResults,\n activeTableIndex = 0,\n onActiveTableChange,\n // Analysis type (new) - primary way to detect funnel mode\n analysisType,\n // Legacy funnel mode prop (deprecated - use analysisType === 'funnel' instead)\n isFunnelMode: isFunnelModeProp = false,\n // Funnel-specific debug props\n funnelServerQuery,\n funnelDebugData,\n // Flow-specific debug props\n flowServerQuery,\n flowDebugData,\n // Retention-specific props\n retentionServerQuery,\n retentionDebugData,\n retentionChartData,\n retentionValidation\n}: AnalysisResultsPanelProps) {\n // Determine funnel mode from analysisType (preferred) or legacy prop\n const isFunnelMode = analysisType === 'funnel' || isFunnelModeProp\n // Determine flow mode from analysisType\n const isFlowMode = analysisType === 'flow'\n // Determine retention mode from analysisType\n const isRetentionMode = analysisType === 'retention'\n // Debug view toggle state\n const [showDebug, setShowDebug] = useState(false)\n // Active debug query tab (independent of main query tabs)\n const [activeDebugIndex, setActiveDebugIndex] = useState(0)\n const [isClearConfirmOpen, setIsClearConfirmOpen] = useState(false)\n // Track shift key + hover state for cache bust visual feedback\n const [isShiftHeld, setIsShiftHeld] = useState(false)\n const [isHoveringRefresh, setIsHoveringRefresh] = useState(false)\n\n // Listen for shift key up/down to show visual feedback on refresh button (only when hovering)\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Shift') setIsShiftHeld(true)\n }\n const handleKeyUp = (e: KeyboardEvent) => {\n if (e.key === 'Shift') setIsShiftHeld(false)\n }\n window.addEventListener('keydown', handleKeyDown)\n window.addEventListener('keyup', handleKeyUp)\n return () => {\n window.removeEventListener('keydown', handleKeyDown)\n window.removeEventListener('keyup', handleKeyUp)\n }\n }, [])\n\n // Show warning styling only when hovering AND shift is held\n const showCacheBustIndicator = isShiftHeld && isHoveringRefresh\n\n // Clamp activeDebugIndex when queries are removed\n useEffect(() => {\n if (debugDataPerQuery.length > 0 && activeDebugIndex >= debugDataPerQuery.length) {\n setActiveDebugIndex(debugDataPerQuery.length - 1)\n }\n }, [debugDataPerQuery.length, activeDebugIndex])\n\n // Get current debug data based on active index\n const currentDebugData = debugDataPerQuery[activeDebugIndex] || {\n sql: null,\n analysis: null,\n loading: false,\n error: null\n }\n const debugSql = currentDebugData.sql\n const debugAnalysis = currentDebugData.analysis\n const debugLoading = currentDebugData.loading\n const debugError = currentDebugData.error\n // Get the query for the active debug tab\n // In funnel mode, prefer showing the executed queries which include:\n // - The binding key dimension (auto-added)\n // - The IN filter for steps 2+ (with values from previous step)\n const debugQuery = funnelExecutedQueries?.[activeDebugIndex] ?? allQueries?.[activeDebugIndex] ?? null\n\n // Determine if we're showing funnel executed queries (for visual indicator)\n const isShowingFunnelQuery = Boolean(funnelExecutedQueries?.length && funnelExecutedQueries[activeDebugIndex])\n\n // EXPLAIN PLAN hook - for standard query mode\n // Uses the current active debug query\n const {\n explainResult,\n isLoading: explainLoading,\n hasRun: explainHasRun,\n error: explainError,\n runExplain,\n clearExplain,\n } = useExplainQuery(debugQuery as CubeQuery | null, {\n skip: isFunnelMode || isFlowMode || isRetentionMode || !debugQuery,\n })\n\n // EXPLAIN PLAN hook - for funnel mode\n const {\n explainResult: funnelExplainResult,\n isLoading: funnelExplainLoading,\n hasRun: funnelExplainHasRun,\n error: funnelExplainError,\n runExplain: runFunnelExplain,\n clearExplain: clearFunnelExplain,\n } = useExplainQuery(funnelServerQuery, {\n skip: !isFunnelMode || !funnelServerQuery,\n })\n\n // EXPLAIN PLAN hook - for flow mode\n const {\n explainResult: flowExplainResult,\n isLoading: flowExplainLoading,\n hasRun: flowExplainHasRun,\n error: flowExplainError,\n runExplain: runFlowExplain,\n clearExplain: clearFlowExplain,\n } = useExplainQuery(flowServerQuery, {\n skip: !isFlowMode || !flowServerQuery,\n })\n\n // EXPLAIN PLAN hook - for retention mode\n const {\n explainResult: retentionExplainResult,\n isLoading: retentionExplainLoading,\n hasRun: retentionExplainHasRun,\n error: retentionExplainError,\n runExplain: runRetentionExplain,\n // clearExplain: clearRetentionExplain, - unused for now\n } = useExplainQuery(retentionServerQuery, {\n skip: !isRetentionMode || !retentionServerQuery,\n })\n\n // AI Analysis hook for EXPLAIN plans\n const {\n analysis: aiAnalysis,\n isAnalyzing: aiAnalysisLoading,\n error: aiAnalysisError,\n analyze: runAIAnalysis,\n clearAnalysis: clearAIAnalysis,\n } = useExplainAI()\n\n // Clear explain results when the active debug query changes\n useEffect(() => {\n clearExplain()\n }, [activeDebugIndex, clearExplain])\n\n // Clear funnel explain results when funnel query changes\n useEffect(() => {\n clearFunnelExplain()\n }, [funnelServerQuery, clearFunnelExplain])\n\n // Clear flow explain results when flow query changes\n useEffect(() => {\n clearFlowExplain()\n }, [flowServerQuery, clearFlowExplain])\n\n // Track if this effect has run once - skip forcing table view on the first run\n // to allow share URLs and portlet configs to restore their saved view\n const isFirstRunRef = useRef(true)\n\n // Force table view when no metrics are selected (only for query mode)\n // In funnel mode, we allow chart view even during loading since funnel charts\n // don't require traditional \"metrics\" - they have funnel steps instead\n useEffect(() => {\n // Skip on first run to allow share/portlet state to load first\n if (isFirstRunRef.current) {\n isFirstRunRef.current = false\n return\n }\n\n // Don't force table view in funnel, flow, or retention mode - they work differently\n // Check both analysisType directly AND computed isFunnelMode to avoid stale closure issues\n if (analysisType === 'funnel' || analysisType === 'flow' || analysisType === 'retention' || isFunnelMode) return\n\n if (!hasMetrics && activeView === 'chart') {\n onActiveViewChange('table')\n }\n }, [hasMetrics, activeView, onActiveViewChange, isFunnelMode, analysisType])\n\n // Create a combined query object for the chart (includes measures from ALL queries)\n const combinedQueryForChart = useMemo(() => {\n if (!allQueries || allQueries.length === 0) return undefined\n if (allQueries.length === 1) return allQueries[0]\n\n // Combine measures from all queries, dimensions are shared (from Q1)\n const allMeasures = allQueries.flatMap(q => q?.measures || [])\n return {\n ...allQueries[0],\n measures: allMeasures\n }\n }, [allQueries])\n\n // Icons\n const SuccessIcon = getIcon('success')\n const ErrorIcon = getIcon('error')\n const WarningIcon = getIcon('warning')\n const TableIcon = getIcon('table')\n const ChartIcon = getIcon('measure')\n const CodeIcon = getIcon('codeBracket')\n const ShareIcon = getIcon('share')\n const CheckIcon = getIcon('check')\n const TrashIcon = getIcon('delete')\n const SparklesIcon = getIcon('sparkles')\n const RefreshIcon = getIcon('arrowPath')\n\n // Loading state - initial load\n const renderLoading = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Executing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Running your query against the cube API\n </div>\n </div>\n </div>\n )\n\n // Error state - no previous results\n const renderError = () => (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n <div className=\"flex-1 flex items-center justify-center p-4\">\n {showDebug ? (\n <div className=\"w-full h-full overflow-auto\">\n {renderDebug()}\n </div>\n ) : (\n <div className=\"text-center max-w-md\">\n <ErrorIcon className=\"w-12 h-12 mx-auto text-dc-error mb-4\" />\n <div className=\"text-sm font-semibold text-dc-text mb-2\">\n Query Execution Failed\n </div>\n <div className=\"text-sm text-dc-text-secondary mb-4\">\n There was an error executing your query. Please check the query and try again.\n </div>\n {executionError && (\n <div className=\"bg-dc-danger-bg border border-dc-error rounded-lg p-3 text-left\">\n <div className=\"text-xs font-mono text-dc-error break-words\">\n {executionError}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n\n // Check if any query has content (pending execution)\n const hasQueryContent = !!(allQueries?.some(q =>\n (q?.measures && q.measures.length > 0) ||\n (q?.dimensions && q.dimensions.length > 0) ||\n (q?.timeDimensions && q.timeDimensions.length > 0)\n ))\n\n // Determine if current mode has valid pending content (mode-specific)\n // This is used to decide whether to show \"Preparing Query...\" or \"No Results Yet\"\n const hasModeSpecificContent = useMemo(() => {\n if (isRetentionMode) {\n // Retention mode: need valid server query (cube + binding key + time dimension configured)\n return retentionServerQuery !== null\n }\n if (isFunnelMode) {\n // Funnel mode: need valid server query\n return funnelServerQuery !== null\n }\n if (isFlowMode) {\n // Flow mode: need valid server query\n return flowServerQuery !== null\n }\n // Query mode: standard check for measures/dimensions/timeDimensions\n return hasQueryContent\n }, [isRetentionMode, isFunnelMode, isFlowMode, retentionServerQuery, funnelServerQuery, flowServerQuery, hasQueryContent])\n\n // Waiting state - query built but not yet executed (debounce period)\n const renderWaiting = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Preparing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Your query will execute shortly\n </div>\n </div>\n </div>\n )\n\n // Manual refresh mode - query ready but needs user to click refresh\n const renderNeedsRefreshEmpty = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <svg className=\"w-12 h-12 mx-auto text-dc-warning mb-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Ready to Execute\n </div>\n <div className=\"text-xs text-dc-text-muted mb-4\">\n Click refresh to run your query\n </div>\n {onRefreshClick && (\n <button\n onClick={() => onRefreshClick()}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-dc-accent hover:opacity-90 rounded-lg transition-colors shadow-sm\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n Run Query\n </button>\n )}\n </div>\n </div>\n )\n\n // Empty state - no query built yet\n // Shows mode-specific guidance based on analysis type\n const renderEmpty = () => {\n // Mode-specific empty message\n let emptyMessage = 'Add metrics or breakdowns from the panel on the right to see results'\n if (isRetentionMode) {\n emptyMessage = 'Select a cube and configure retention settings to see results'\n } else if (isFunnelMode) {\n emptyMessage = 'Add funnel steps to see conversion analysis'\n } else if (isFlowMode) {\n emptyMessage = 'Configure flow analysis to see user journey paths'\n }\n\n return (\n <div className=\"h-full flex items-center justify-center pt-6\">\n <div className=\"text-center mb-16\">\n <ChartIcon className=\"w-12 h-12 mx-auto text-dc-text-muted mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n No Results Yet\n </div>\n <div className=\"text-xs text-dc-text-muted mb-4\">\n {emptyMessage}\n </div>\n {/* Prominent AI button when enabled (only for query mode) */}\n {enableAI && onAIToggle && !isRetentionMode && !isFunnelMode && !isFlowMode && (\n <button\n onClick={onAIToggle}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-dc-accent hover:bg-dc-accent rounded-lg transition-colors shadow-sm\"\n >\n <SparklesIcon className=\"w-4 h-4\" />\n Analyse with AI\n </button>\n )}\n </div>\n </div>\n )\n }\n\n // No data returned state\n const renderNoData = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <SuccessIcon className=\"w-12 h-12 mx-auto text-dc-success mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text mb-1\">\n Query Successful\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n No data returned from the query\n </div>\n </div>\n </div>\n )\n\n // Render chart\n const renderChart = () => {\n if (!executionResults || executionResults.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <ChartIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see chart visualization</div>\n </div>\n </div>\n )\n }\n\n // Determine effective chart type (handles sankey/sunburst toggle)\n const effectiveChartType = chartType === 'sankey' &&\n (displayConfig as Record<string, unknown>)?.flowVisualization === 'sunburst'\n ? 'sunburst'\n : chartType\n\n if (!isValidChartType(effectiveChartType)) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <WarningIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">Unsupported chart type</div>\n <div className=\"text-xs\">{effectiveChartType}</div>\n </div>\n </div>\n )\n }\n\n // For retention mode, use retentionChartData which is already transformed\n // into the cohort × period matrix format expected by RetentionHeatmap\n // Cast to any[] since LazyChart expects array type but RetentionHeatmap handles the object format\n const chartData = isRetentionMode && retentionChartData\n ? (retentionChartData as unknown as any[])\n : executionResults\n\n return (\n <LazyChart\n chartType={effectiveChartType}\n data={chartData}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n queryObject={combinedQueryForChart}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Type for funnel metadata\n interface FunnelMetadata {\n stepCount: number\n steps: Array<{\n index: number\n name: string\n timeToConvert?: string\n cube?: string\n }>\n bindingKey: unknown\n timeDimension: unknown\n }\n\n // Render debug view for funnel mode (unified single query view)\n const renderFunnelDebug = () => {\n const funnelSql = funnelDebugData?.sql\n const funnelLoading = funnelDebugData?.loading || false\n const funnelError = funnelDebugData?.error\n const funnelMeta = funnelDebugData?.funnelMetadata as FunnelMetadata | undefined\n\n return (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Funnel Mode Header */}\n <div className=\"flex items-center gap-2 mb-4\">\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-accent text-white rounded\">Funnel Query</span>\n {funnelMeta?.stepCount && (\n <span className=\"text-xs text-dc-text-muted\">\n {funnelMeta.stepCount} steps\n </span>\n )}\n {funnelLoading && (\n <span className=\"text-xs text-dc-text-muted animate-pulse\">Loading SQL...</span>\n )}\n </div>\n\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg border border-dc-error dark:border-dc-error rounded p-3\">\n <h4 className=\"text-sm font-semibold text-dc-error dark:text-dc-error mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )}\n\n {/* Funnel Server Query - full width */}\n <div>\n {funnelServerQuery ? (\n <CodeBlock\n code={JSON.stringify(funnelServerQuery, null, 2)}\n language=\"json\"\n title=\"Funnel Server Query\"\n height=\"16rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Funnel Server Query</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n No funnel query configured\n </div>\n </>\n )}\n </div>\n\n {/* Generated SQL with Explain Plan and AI Analysis - full width */}\n <ExecutionPlanPanel\n sql={funnelSql}\n sqlLoading={funnelLoading}\n sqlError={funnelError}\n sqlPlaceholder=\"Configure funnel binding key to generate SQL\"\n explainResult={funnelExplainResult}\n explainLoading={funnelExplainLoading}\n explainHasRun={funnelExplainHasRun}\n explainError={funnelExplainError}\n runExplain={runFunnelExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={funnelServerQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {/* Funnel Metadata (step info) */}\n {funnelMeta && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Funnel Steps</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <div className=\"flex flex-wrap gap-2\">\n {funnelMeta.steps.map((step, idx) => (\n <div key={idx} className=\"flex items-center gap-2 px-3 py-1.5 bg-dc-bg border border-dc-border rounded text-sm\">\n <span className=\"w-5 h-5 flex items-center justify-center bg-dc-accent text-white text-xs rounded-full\">\n {idx + 1}\n </span>\n <span className=\"text-dc-text\">{step.name}</span>\n {step.timeToConvert && (\n <span className=\"text-xs text-dc-text-muted\">({step.timeToConvert})</span>\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Chart Config & Display Config in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <CodeBlock\n code={JSON.stringify(chartConfig, null, 2)}\n language=\"json\"\n title=\"Chart Config\"\n height=\"16rem\"\n />\n </div>\n <div>\n <CodeBlock\n code={JSON.stringify(displayConfig, null, 2)}\n language=\"json\"\n title=\"Display Config\"\n height=\"16rem\"\n />\n </div>\n </div>\n\n {/* Server Response - full width */}\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={`Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n </div>\n )\n }\n\n // Render debug view for flow mode (unified single query view)\n const renderFlowDebug = () => {\n const flowSql = flowDebugData?.sql\n const flowLoading = flowDebugData?.loading || false\n const flowError = flowDebugData?.error\n const flowMeta = flowDebugData?.flowMetadata as {\n stepsBefore?: number\n stepsAfter?: number\n bindingKey?: unknown\n timeDimension?: unknown\n eventDimension?: string\n startingStep?: { name?: string; filter?: unknown }\n } | undefined\n\n return (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Flow Mode Header */}\n <div className=\"flex items-center gap-2 mb-4\">\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-accent text-white rounded\">Flow Query</span>\n {flowMeta && (\n <span className=\"text-xs text-dc-text-muted\">\n {flowMeta.stepsBefore} before, {flowMeta.stepsAfter} after\n </span>\n )}\n {flowLoading && (\n <span className=\"text-xs text-dc-text-muted animate-pulse\">Loading SQL...</span>\n )}\n </div>\n\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg border border-dc-error dark:border-dc-error rounded p-3\">\n <h4 className=\"text-sm font-semibold text-dc-error dark:text-dc-error mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )}\n\n {/* Flow Server Query - full width */}\n <div>\n {flowServerQuery ? (\n <CodeBlock\n code={JSON.stringify(flowServerQuery, null, 2)}\n language=\"json\"\n title=\"Flow Server Query\"\n height=\"16rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Flow Server Query</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n No flow query configured\n </div>\n </>\n )}\n </div>\n\n {/* Generated SQL with Explain Plan and AI Analysis - full width */}\n <ExecutionPlanPanel\n sql={flowSql}\n sqlLoading={flowLoading}\n sqlError={flowError}\n sqlPlaceholder=\"Configure flow to generate SQL\"\n explainResult={flowExplainResult}\n explainLoading={flowExplainLoading}\n explainHasRun={flowExplainHasRun}\n explainError={flowExplainError}\n runExplain={runFlowExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={flowServerQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {/* Flow Metadata */}\n {flowMeta && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Flow Configuration</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Starting Step:</span>{' '}\n <span className=\"text-dc-text\">{flowMeta.startingStep?.name || 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Event Dimension:</span>{' '}\n <span className=\"text-dc-text\">{flowMeta.eventDimension || 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps Before:</span>{' '}\n <span className=\"text-dc-text\">{flowMeta.stepsBefore ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps After:</span>{' '}\n <span className=\"text-dc-text\">{flowMeta.stepsAfter ?? 'Not set'}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Chart Config & Display Config in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <CodeBlock\n code={JSON.stringify(chartConfig, null, 2)}\n language=\"json\"\n title=\"Chart Config\"\n height=\"16rem\"\n />\n </div>\n <div>\n <CodeBlock\n code={JSON.stringify(displayConfig, null, 2)}\n language=\"json\"\n title=\"Display Config\"\n height=\"16rem\"\n />\n </div>\n </div>\n\n {/* Server Response - full width */}\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title=\"Server Response (Sankey Data)\"\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n </div>\n )\n }\n\n // Render debug view for retention mode (cohort retention analysis)\n const renderRetentionDebug = () => {\n const retentionSql = retentionDebugData?.sql\n const retentionLoading = retentionDebugData?.loading || false\n const retentionError = retentionDebugData?.error\n const retentionMeta = retentionDebugData?.retentionMetadata as {\n totalUsers?: number\n segmentCount?: number\n periods?: number\n granularity?: string\n retentionType?: string\n } | undefined\n\n return (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Retention Mode Header */}\n <div className=\"flex items-center gap-2 mb-4\">\n <span className=\"px-2 py-1 text-xs font-medium bg-dc-accent text-white rounded\">Retention Query</span>\n {retentionMeta && (\n <span className=\"text-xs text-dc-text-muted\">\n {retentionMeta.segmentCount || 1} segment(s), {retentionMeta.totalUsers} users\n </span>\n )}\n {retentionLoading && (\n <span className=\"text-xs text-dc-text-muted animate-pulse\">Loading SQL...</span>\n )}\n </div>\n\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg border border-dc-error dark:border-dc-error rounded p-3\">\n <h4 className=\"text-sm font-semibold text-dc-error dark:text-dc-error mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )}\n\n {/* Retention Server Query - full width */}\n <div>\n {retentionServerQuery ? (\n <CodeBlock\n code={JSON.stringify(retentionServerQuery, null, 2)}\n language=\"json\"\n title=\"Retention Server Query\"\n height=\"16rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Retention Server Query</h4>\n <div className=\"bg-dc-warning-bg border border-dc-warning rounded p-3 text-sm h-64 overflow-auto\">\n <div className=\"text-dc-warning font-medium mb-2\">Configuration Incomplete</div>\n {retentionValidation && retentionValidation.errors.length > 0 ? (\n <ul className=\"list-disc list-inside text-dc-text-secondary space-y-1\">\n {retentionValidation.errors.map((error, i) => (\n <li key={i}>{error}</li>\n ))}\n </ul>\n ) : (\n <p className=\"text-dc-text-muted\">Configure the retention analysis settings to generate a query.</p>\n )}\n </div>\n </>\n )}\n </div>\n\n {/* Generated SQL with Explain Plan and AI Analysis - full width */}\n <ExecutionPlanPanel\n sql={retentionSql}\n sqlLoading={retentionLoading}\n sqlError={retentionError}\n sqlPlaceholder=\"Configure retention to generate SQL\"\n explainResult={retentionExplainResult}\n explainLoading={retentionExplainLoading}\n explainHasRun={retentionExplainHasRun}\n explainError={retentionExplainError}\n runExplain={runRetentionExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={retentionServerQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {/* Retention Metadata */}\n {retentionMeta && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Retention Configuration</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Retention Type:</span>{' '}\n <span className=\"text-dc-text\">{retentionMeta.retentionType || 'Classic'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Periods:</span>{' '}\n <span className=\"text-dc-text\">{retentionMeta.periods ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Granularity:</span>{' '}\n <span className=\"text-dc-text\">{retentionMeta.granularity || 'Week'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Segments:</span>{' '}\n <span className=\"text-dc-text\">{retentionMeta.segmentCount || 1}</span>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Summary Statistics */}\n {retentionChartData?.summary && (\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Retention Summary</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <div className=\"grid grid-cols-3 gap-4 text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Avg Period 1:</span>{' '}\n <span className=\"text-dc-text font-medium\">\n {(retentionChartData.summary.avgPeriod1Retention * 100).toFixed(1)}%\n </span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Max Period 1:</span>{' '}\n <span className=\"text-dc-text font-medium\">\n {(retentionChartData.summary.maxPeriod1Retention * 100).toFixed(1)}%\n </span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Min Period 1:</span>{' '}\n <span className=\"text-dc-text font-medium\">\n {(retentionChartData.summary.minPeriod1Retention * 100).toFixed(1)}%\n </span>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Chart Config & Display Config in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <CodeBlock\n code={JSON.stringify(chartConfig, null, 2)}\n language=\"json\"\n title=\"Chart Config\"\n height=\"16rem\"\n />\n </div>\n <div>\n <CodeBlock\n code={JSON.stringify(displayConfig, null, 2)}\n language=\"json\"\n title=\"Display Config\"\n height=\"16rem\"\n />\n </div>\n </div>\n\n {/* Server Response - full width */}\n <div>\n {retentionChartData ? (\n <CodeBlock\n code={JSON.stringify(retentionChartData, null, 2)}\n language=\"json\"\n title={`Server Response (${retentionChartData.rows.length} rows, ${retentionChartData.periods.length} periods)`}\n maxHeight=\"24rem\"\n />\n ) : executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={`Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n </div>\n )\n }\n\n // Render debug view (multi-query or single query)\n const renderStandardDebug = () => (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Query tabs for multi-query mode */}\n {debugDataPerQuery.length > 1 && (\n <div className=\"flex items-center gap-1 mb-4\">\n <span className=\"text-xs font-medium text-dc-text-muted mr-2\">Query:</span>\n <div className=\"flex border border-dc-border rounded-md overflow-hidden\">\n {debugDataPerQuery.map((data, idx) => (\n <button\n key={idx}\n onClick={() => setActiveDebugIndex(idx)}\n className={`px-3 py-1 text-xs font-medium transition-colors border-r last:border-r-0 border-dc-border ${\n activeDebugIndex === idx\n ? 'bg-dc-accent text-white'\n : 'bg-dc-bg text-dc-text-secondary hover:bg-dc-bg-secondary'\n }`}\n >\n Q{idx + 1}\n {data.loading && (\n <span className=\"ml-1 opacity-70\">•</span>\n )}\n {data.error && (\n <span className=\"ml-1 text-dc-error\">!</span>\n )}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg border border-dc-error dark:border-dc-error rounded p-3\">\n <h4 className=\"text-sm font-semibold text-dc-error dark:text-dc-error mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )}\n\n {/* Query Analysis - full width (at top for visibility) */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Query Analysis</h4>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n Loading...\n </div>\n ) : debugAnalysis ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <QueryAnalysisPanel analysis={debugAnalysis} />\n </div>\n ) : (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n {debugError ? 'Analysis unavailable due to error' : 'Add metrics to see analysis'}\n </div>\n )}\n </div>\n\n {/* Cube Query - full width */}\n <div>\n {debugQuery ? (\n <>\n <CodeBlock\n code={JSON.stringify(debugQuery, null, 2)}\n language=\"json\"\n title={isShowingFunnelQuery ? \"Executed Query (with funnel filters)\" : \"Cube Query\"}\n height=\"16rem\"\n />\n {isShowingFunnelQuery && activeDebugIndex > 0 && (\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"text-dc-accent\">ℹ</span> This query includes an IN filter with binding key values from the previous step\n </div>\n )}\n </>\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Cube Query</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm h-64 overflow-auto\">\n No query\n </div>\n </>\n )}\n </div>\n\n {/* Generated SQL with Explain Plan and AI Analysis - full width */}\n <ExecutionPlanPanel\n sql={debugSql}\n sqlLoading={debugLoading}\n sqlError={debugError}\n sqlPlaceholder=\"Add metrics to generate SQL\"\n explainResult={explainResult}\n explainLoading={explainLoading}\n explainHasRun={explainHasRun}\n explainError={explainError}\n runExplain={runExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={debugQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {/* Chart Config & Display Config in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {/* Chart Config */}\n <div>\n <CodeBlock\n code={JSON.stringify(chartConfig, null, 2)}\n language=\"json\"\n title=\"Chart Config\"\n height=\"16rem\"\n />\n </div>\n\n {/* Display Config */}\n <div>\n <CodeBlock\n code={JSON.stringify(displayConfig, null, 2)}\n language=\"json\"\n title=\"Display Config\"\n height=\"16rem\"\n />\n </div>\n </div>\n\n {/* Server Response - full width */}\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={`Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n </div>\n )\n\n // Route to appropriate debug view based on mode\n const renderDebug = () => {\n if (isRetentionMode) {\n return renderRetentionDebug()\n }\n if (isFlowMode) {\n return renderFlowDebug()\n }\n if (isFunnelMode) {\n return renderFunnelDebug()\n }\n return renderStandardDebug()\n }\n\n // Determine if we're in multi-query mode (but NOT funnel mode)\n // Funnel mode always shows unified results, not per-query tables\n const isMultiQuery = !isFunnelMode && queryCount > 1 && perQueryResults && perQueryResults.length > 1\n\n // Render flow-specific table view showing nodes and links\n const renderFlowTable = () => {\n // Flow results from server are wrapped: [{ nodes: [...], links: [...] }]\n // The executor returns data: [flowData] where flowData = { nodes, links }\n let nodes: Record<string, unknown>[] = []\n let links: Record<string, unknown>[] = []\n\n if (!executionResults || (Array.isArray(executionResults) && executionResults.length === 0)) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <TableIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No flow data to display</div>\n <div className=\"text-xs\">Configure flow analysis to see results</div>\n </div>\n </div>\n )\n }\n\n // Server returns [{ nodes: [...], links: [...] }] - unwrap the first element\n if (Array.isArray(executionResults) && executionResults.length > 0) {\n const firstResult = executionResults[0] as Record<string, unknown>\n // Check if it's flow data structure (has nodes/links arrays)\n if (firstResult && 'nodes' in firstResult && 'links' in firstResult) {\n nodes = (firstResult.nodes || []) as Record<string, unknown>[]\n links = (firstResult.links || []) as Record<string, unknown>[]\n } else if ('record_type' in firstResult) {\n // Fallback: raw format with record_type discriminator\n nodes = executionResults.filter((r: Record<string, unknown>) => r.record_type === 'node')\n links = executionResults.filter((r: Record<string, unknown>) => r.record_type === 'link')\n }\n }\n\n // If no data after parsing, show empty state\n if (nodes.length === 0 && links.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <TableIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No flow data to display</div>\n <div className=\"text-xs\">Configure flow analysis to see results</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"h-full overflow-auto p-4 space-y-6\">\n {/* Nodes Table */}\n <div>\n <h3 className=\"text-sm font-semibold text-dc-text mb-2\">\n Nodes ({nodes.length})\n </h3>\n <div className=\"border border-dc-border rounded overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\">Layer</th>\n <th className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\">Name</th>\n <th className=\"px-3 py-2 text-right text-xs font-medium text-dc-text-muted uppercase tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-dc-border bg-dc-surface\">\n {nodes\n .sort((a: Record<string, unknown>, b: Record<string, unknown>) => (a.layer as number) - (b.layer as number))\n .map((node: Record<string, unknown>, idx: number) => (\n <tr key={idx} className=\"hover:bg-dc-surface-hover\">\n <td className=\"px-3 py-2 whitespace-nowrap\">\n <span className={`inline-flex items-center justify-center w-6 h-6 rounded text-xs font-medium ${\n (node.layer as number) === 0\n ? 'bg-dc-primary text-white'\n : (node.layer as number) < 0\n ? 'bg-dc-accent-bg text-dc-accent'\n : 'bg-dc-success-bg text-dc-success'\n }`}>\n {(node.layer as number) === 0 ? '★' : node.layer as number}\n </span>\n </td>\n <td className=\"px-3 py-2 text-dc-text\">{node.name as string}</td>\n <td className=\"px-3 py-2 text-right text-dc-text font-mono\">\n {(node.value as number)?.toLocaleString()}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n\n {/* Links Table */}\n <div>\n <h3 className=\"text-sm font-semibold text-dc-text mb-2\">\n Transitions ({links.length})\n </h3>\n <div className=\"border border-dc-border rounded overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\">From</th>\n <th className=\"px-3 py-2 text-center text-xs font-medium text-dc-text-muted uppercase tracking-wider\">→</th>\n <th className=\"px-3 py-2 text-left text-xs font-medium text-dc-text-muted uppercase tracking-wider\">To</th>\n <th className=\"px-3 py-2 text-right text-xs font-medium text-dc-text-muted uppercase tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-dc-border bg-dc-surface\">\n {links.map((link: Record<string, unknown>, idx: number) => {\n // SankeyLink uses `source` and `target` (transformed), fallback to source_id/target_id (raw)\n const sourceId = (link.source || link.source_id) as string || ''\n const targetId = (link.target || link.target_id) as string || ''\n // IDs are like \"before_5_created\" or \"start_created\" - extract the event name\n const sourceName = sourceId.split('_').slice(-1)[0] || sourceId\n const targetName = targetId.split('_').slice(-1)[0] || targetId\n\n return (\n <tr key={idx} className=\"hover:bg-dc-surface-hover\">\n <td className=\"px-3 py-2 text-dc-text\">{sourceName}</td>\n <td className=\"px-3 py-2 text-center text-dc-text-muted\">→</td>\n <td className=\"px-3 py-2 text-dc-text\">{targetName}</td>\n <td className=\"px-3 py-2 text-right text-dc-text font-mono\">\n {(link.value as number)?.toLocaleString()}\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n )\n }\n\n // Render table - uses per-query results in multi-query mode\n const renderTable = (tableIndex?: number) => {\n // In multi-query mode, use specific query's results and query object\n // tableIndex: undefined = single query, -1 = merged view, 0+ = per-query view\n let tableData: any[] | null = null\n let tableQuery = allQueries?.[0] // Default to first query\n\n if (isMultiQuery && tableIndex !== undefined && tableIndex >= 0 && perQueryResults) {\n // Per-query table view\n tableData = perQueryResults[tableIndex] || null\n tableQuery = allQueries?.[tableIndex]\n } else {\n // Merged view (tableIndex === -1) or single query mode\n tableData = executionResults\n // For merged view, use combined query\n if (isMultiQuery) {\n tableQuery = combinedQueryForChart\n }\n }\n\n if (!tableData || tableData.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <TableIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see table data</div>\n </div>\n </div>\n )\n }\n\n // Apply display limit\n const limitedData = tableData.slice(0, displayLimit)\n\n return (\n <LazyChart\n chartType=\"table\"\n data={limitedData}\n colorPalette={colorPalette}\n queryObject={tableQuery}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Overlay spinner for refreshing\n const renderOverlaySpinner = () => (\n <div className=\"absolute inset-0 flex items-center justify-center bg-dc-surface bg-opacity-75 z-10\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-10 w-10 border-b-2 mx-auto mb-2\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-xs text-dc-text-secondary\">Refreshing results...</div>\n </div>\n </div>\n )\n\n // Render header - shown whenever we have query content\n const renderHeader = () => {\n const hasResults = executionResults && executionResults.length > 0\n\n return (\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-surface-secondary flex-shrink-0\">\n <div className=\"flex items-center justify-between\">\n {/* Left side: Status and row count */}\n <div className=\"flex items-center\">\n {executionStatus === 'refreshing' ? (\n <div\n className=\"w-4 h-4 mr-2 rounded-full border-b-2 animate-spin\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n ) : hasResults ? (\n <SuccessIcon className=\"w-4 h-4 text-dc-success mr-2\" />\n ) : executionStatus === 'error' ? (\n <ErrorIcon className=\"w-4 h-4 text-dc-error mr-2\" />\n ) : (\n <WarningIcon className=\"w-4 h-4 text-dc-text-muted mr-2\" />\n )}\n <span className=\"text-sm text-dc-text-secondary\">\n {hasResults ? (\n <>\n {executionResults.length} row{executionResults.length !== 1 ? 's' : ''}\n {totalRowCount !== null && totalRowCount > executionResults.length && (\n <span className=\"text-dc-text-muted\"> of {totalRowCount.toLocaleString()}</span>\n )}\n {resultsStale && (\n <span className=\"text-dc-warning ml-2\">• Results may be outdated</span>\n )}\n </>\n ) : executionStatus === 'error' ? (\n 'Query failed'\n ) : executionStatus === 'loading' ? (\n 'Executing...'\n ) : (\n 'No results'\n )}\n </span>\n </div>\n\n {/* Right side: Display limit (table only) and Debug toggle */}\n <div className=\"flex items-center gap-2\">\n {/* Display Limit (only for table view) */}\n {hasResults && activeView === 'table' && !showDebug && onDisplayLimitChange && (\n <select\n value={displayLimit}\n onChange={(e) => onDisplayLimitChange(Number(e.target.value))}\n className=\"text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n >\n <option value={50}>50 rows</option>\n <option value={100}>100 rows</option>\n <option value={250}>250 rows</option>\n <option value={500}>500 rows</option>\n </select>\n )}\n\n {/* AI Button - positioned before palette selector */}\n {enableAI && onAIToggle && (\n <button\n onClick={onAIToggle}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n isAIOpen\n ? 'text-white bg-dc-accent border border-dc-accent'\n : 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n }`}\n title={isAIOpen ? 'Close AI assistant' : 'Analyse with AI'}\n >\n <SparklesIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Analyse with AI</span>\n </button>\n )}\n\n {/* Color Palette Selector (only when callback is provided, i.e., standalone mode) */}\n {onColorPaletteChange && hasResults && (\n <ColorPaletteSelector\n currentPalette={currentPaletteName || 'default'}\n onPaletteChange={onColorPaletteChange}\n />\n )}\n\n {/* Share Button */}\n {onShareClick && (\n <button\n onClick={onShareClick}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n shareButtonState === 'idle' && canShare\n ? 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n : shareButtonState !== 'idle'\n ? 'text-dc-success dark:text-dc-success bg-dc-success-bg dark:bg-dc-success-bg border border-dc-success dark:border-dc-success'\n : 'text-dc-text-muted bg-dc-surface-secondary border border-dc-border cursor-not-allowed'\n }`}\n title={shareButtonState === 'idle' ? 'Share this analysis' : 'Link copied!'}\n disabled={!canShare || shareButtonState !== 'idle'}\n >\n {shareButtonState === 'idle' ? (\n <>\n <ShareIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Share</span>\n </>\n ) : shareButtonState === 'copied' ? (\n <>\n <CheckIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Copied!</span>\n </>\n ) : (\n <>\n <CheckIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Copied!</span>\n <span className=\"hidden lg:inline text-[10px] opacity-75\">(no chart)</span>\n </>\n )}\n </button>\n )}\n\n {/* Refresh Button - Shift+click bypasses cache */}\n {onRefreshClick && canRefresh && (\n <button\n onClick={(e) => onRefreshClick({ bustCache: e.shiftKey })}\n onMouseEnter={() => setIsHoveringRefresh(true)}\n onMouseLeave={() => setIsHoveringRefresh(false)}\n disabled={isRefreshing}\n className={`flex items-center gap-1 px-2 py-1.5 text-xs font-medium rounded transition-colors ${\n isRefreshing\n ? 'text-dc-text-muted bg-dc-surface-secondary border border-dc-border cursor-wait'\n : showCacheBustIndicator\n ? 'text-dc-warning bg-dc-warning-bg border border-dc-warning font-semibold'\n : 'text-dc-accent bg-dc-accent-bg border border-dc-accent hover:bg-dc-accent-bg'\n }`}\n title={isRefreshing ? 'Refreshing...' : showCacheBustIndicator ? 'Click to refresh and bypass cache' : 'Refresh data (Shift+click to bypass cache)'}\n >\n <RefreshIcon className={`w-3 h-3 ${isRefreshing ? 'animate-spin' : ''}`} />\n <span className=\"hidden sm:inline\">{isRefreshing ? 'Refreshing' : 'Refresh'}</span>\n </button>\n )}\n\n {/* Clear Button */}\n {onClearClick && canClear && (\n <button\n onClick={() => setIsClearConfirmOpen(true)}\n className=\"flex items-center gap-1 px-2 py-1.5 text-xs font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover border border-dc-border rounded transition-colors\"\n title={isFunnelMode ? 'Clear funnel' : 'Clear all query data'}\n >\n <TrashIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">Clear</span>\n </button>\n )}\n\n {/* Debug Toggle Button */}\n <button\n onClick={() => setShowDebug(!showDebug)}\n className={`p-1.5 rounded transition-colors relative ${\n showDebug\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:text-dc-text hover:bg-dc-surface-hover'\n }`}\n title={showDebug ? 'Hide debug info' : 'Show debug info'}\n >\n <CodeIcon className=\"w-4 h-4\" />\n {/* Error indicator dot - show if ANY query has an error */}\n {(executionError || debugDataPerQuery.some(d => d.error)) && !showDebug && (\n <span className=\"absolute -top-0.5 -right-0.5 w-2 h-2 bg-dc-danger-bg0 rounded-full\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Performance Warning */}\n {hasResults && totalRowCount !== null && totalRowCount > 1000 && (\n <div className=\"mt-2 bg-dc-warning-bg border border-dc-warning rounded-lg p-2 flex items-start\">\n <WarningIcon className=\"w-4 h-4 text-dc-warning mr-2 shrink-0 mt-0.5\" />\n <div className=\"text-xs text-dc-warning\">\n <span className=\"font-semibold\">Large dataset:</span> {totalRowCount.toLocaleString()} rows.\n Consider adding filters to improve performance.\n </div>\n </div>\n )}\n </div>\n )\n }\n\n // \"Needs refresh\" banner for manual refresh mode\n const renderNeedsRefreshBanner = () => {\n if (!needsRefresh || !onRefreshClick) return null\n\n return (\n <div className=\"px-4 py-2 bg-dc-warning-bg border-b border-dc-warning flex items-center justify-between gap-3 flex-shrink-0\">\n <div className=\"flex items-center gap-2 text-dc-warning\">\n <svg className=\"w-4 h-4 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n <span className=\"text-sm font-medium\">Query configuration changed. Results may be outdated.</span>\n </div>\n <button\n onClick={() => onRefreshClick()}\n className=\"px-3 py-1 text-xs font-medium bg-dc-warning text-white rounded hover:bg-dc-warning/90 transition-colors\"\n >\n Refresh Now\n </button>\n </div>\n )\n }\n\n // Success state with data\n const renderSuccess = () => {\n const hasResults = executionResults && executionResults.length > 0\n\n if (!hasResults) {\n return (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n <div className=\"flex-1 min-h-0 relative overflow-auto\">\n {showDebug ? renderDebug() : renderNoData()}\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"h-full flex flex-col\">\n {renderHeader()}\n {renderNeedsRefreshBanner()}\n\n {/* Results Content */}\n <div className=\"flex-1 min-h-0 relative overflow-auto\">\n {showDebug ? (\n renderDebug()\n ) : activeView === 'chart' ? (\n <div className=\"p-4 h-full\">{renderChart()}</div>\n ) : isFlowMode ? (\n <div className=\"h-full\" key=\"table-flow\">{renderFlowTable()}</div>\n ) : isMultiQuery ? (\n <div className=\"h-full\" key={`table-${activeTableIndex}`}>{renderTable(activeTableIndex)}</div>\n ) : (\n <div className=\"h-full\" key=\"table-single\">{renderTable()}</div>\n )}\n </div>\n\n {/* View Toggle - Below content, centered */}\n {!showDebug && (\n <div className=\"px-4 py-3 border-t border-dc-border bg-dc-surface flex justify-center flex-shrink-0\">\n <div className=\"flex items-center bg-dc-surface-secondary border border-dc-border rounded-md overflow-hidden\">\n {/* Chart button - always enabled for flow/funnel/retention modes which don't need traditional metrics */}\n <button\n onClick={() => (hasMetrics || isFlowMode || isFunnelMode || isRetentionMode) && onActiveViewChange('chart')}\n disabled={!hasMetrics && !isFlowMode && !isFunnelMode && !isRetentionMode}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'chart'\n ? 'bg-dc-primary text-white'\n : (!hasMetrics && !isFlowMode && !isFunnelMode && !isRetentionMode)\n ? 'text-dc-text-disabled bg-dc-surface-tertiary cursor-not-allowed'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title={(hasMetrics || isFlowMode || isFunnelMode || isRetentionMode) ? 'Chart view' : 'Add metrics to enable chart view'}\n >\n <ChartIcon className=\"w-4 h-4\" />\n Chart\n </button>\n\n {/* Table buttons - show multiple when in multi-query mode */}\n {isMultiQuery ? (\n <>\n {/* Per-query table buttons */}\n {Array.from({ length: queryCount }).map((_, index) => (\n <button\n key={`table-${index}`}\n onClick={() => {\n onActiveViewChange('table')\n onActiveTableChange?.(index)\n }}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table' && activeTableIndex === index\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title={`Table Q${index + 1}`}\n >\n <TableIcon className=\"w-4 h-4\" />\n Q{index + 1}\n </button>\n ))}\n {/* Merged table button */}\n <button\n onClick={() => {\n onActiveViewChange('table')\n onActiveTableChange?.(-1) // -1 = merged view\n }}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table' && activeTableIndex === -1\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title=\"Merged table view\"\n >\n <TableIcon className=\"w-4 h-4\" />\n Merged\n </button>\n </>\n ) : (\n <button\n onClick={() => onActiveViewChange('table')}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table'\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title=\"Table view\"\n >\n <TableIcon className=\"w-4 h-4\" />\n Table\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n\n // Determine what to render based on execution status\n // Check for meaningful results - handles different data structures per mode\n const hasResults = useMemo(() => {\n if (executionResults === null) return false\n if (!Array.isArray(executionResults)) return true\n if (executionResults.length === 0) return false\n\n // For flow mode, check if we have actual nodes/links data\n // Flow wraps results as [{ nodes: [...], links: [...] }] - need to check inner content\n if (isFlowMode && executionResults.length === 1) {\n const flowData = executionResults[0] as { nodes?: unknown[]; links?: unknown[] } | undefined\n if (flowData && typeof flowData === 'object' && 'nodes' in flowData && 'links' in flowData) {\n const hasNodes = Array.isArray(flowData.nodes) && flowData.nodes.length > 0\n const hasLinks = Array.isArray(flowData.links) && flowData.links.length > 0\n return hasNodes || hasLinks\n }\n }\n\n // For retention mode, check if we have chart data with rows\n if (isRetentionMode && retentionChartData) {\n return retentionChartData.rows.length > 0\n }\n\n // For funnel mode, results are chart data items - check length\n // For query mode, results are data rows - check length\n return executionResults.length > 0\n }, [executionResults, isFlowMode, isRetentionMode, retentionChartData])\n\n // Don't show results if we're in idle state with no query content (cleared state)\n const shouldShowResults = hasResults && (executionStatus !== 'idle' || hasModeSpecificContent)\n\n // Priority 1: Manual refresh mode with no results - show centered refresh prompt\n // This takes precedence over all other states for consistent UX across all modes\n if (needsRefresh && !hasResults) {\n return (\n <div className=\"h-full min-h-[400px] flex flex-col bg-dc-surface relative\">\n {renderNeedsRefreshEmpty()}\n </div>\n )\n }\n\n return (\n <div className=\"h-full min-h-[400px] flex flex-col bg-dc-surface relative\">\n {/* Main content */}\n {executionStatus === 'idle' && !hasModeSpecificContent && renderEmpty()}\n {executionStatus === 'idle' && hasModeSpecificContent && !hasResults && renderWaiting()}\n {executionStatus === 'loading' && !hasResults && renderLoading()}\n {executionStatus === 'error' && !hasResults && renderError()}\n {(executionStatus === 'success' || shouldShowResults) && renderSuccess()}\n\n {/* Overlay states */}\n {(executionStatus === 'loading' || executionStatus === 'refreshing') && hasResults && renderOverlaySpinner()}\n\n {onClearClick && (\n <ConfirmModal\n isOpen={isClearConfirmOpen}\n onClose={() => setIsClearConfirmOpen(false)}\n onConfirm={() => {\n onClearClick()\n setIsClearConfirmOpen(false)\n }}\n title={isFunnelMode ? 'Clear Funnel' : 'Clear Query'}\n message={\n <>\n {isFunnelMode\n ? 'Are you sure you want to clear this funnel? This action cannot be undone.'\n : 'Are you sure you want to clear this query? This action cannot be undone.'}\n </>\n }\n confirmText=\"Clear\"\n confirmVariant=\"warning\"\n />\n )}\n </div>\n )\n})\n\nexport default AnalysisResultsPanel\n","/**\n * MetricItemCard Component\n *\n * Displays a single metric item with remove button.\n */\n\nimport { memo } from 'react'\nimport type { MetricItemCardProps } from './types'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\n\n/**\n * MetricItemCard displays a selected metric with:\n * - Field icon based on measure type\n * - Field title or full name\n * - Sort toggle button (visible on hover, or always visible when sorted)\n * - Remove button (visible on hover)\n * - Drag handle for reordering\n */\nconst MetricItemCard = memo(function MetricItemCard({\n metric,\n fieldMeta,\n onRemove,\n sortDirection,\n sortPriority,\n onToggleSort,\n index,\n isDragging,\n onDragStart,\n onDragEnd\n}: MetricItemCardProps) {\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get the appropriate icon based on measure type\n const measureType = fieldMeta?.type || 'count'\n const MeasureIcon = getMeasureTypeIcon(measureType) || getIcon('measure')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || metric.field.split('.').pop() || metric.field\n\n // Get the cube name from the field\n const cubeName = metric.field.split('.')[0]\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n // Check if drag/drop is enabled\n const isDraggable = typeof index === 'number' && onDragStart && onDragEnd\n\n return (\n <div\n className={`flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 ${\n isDraggable ? 'cursor-grab active:cursor-grabbing' : ''\n } ${isDragging ? 'opacity-30' : ''}`}\n draggable={isDraggable ? true : undefined}\n onDragStart={isDraggable ? (e) => onDragStart(e, index) : undefined}\n onDragEnd={isDraggable ? onDragEnd : undefined}\n >\n {/* Icon - colored background matching field selector */}\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n {MeasureIcon && <MeasureIcon className=\"w-4 h-4\" />}\n </span>\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={metric.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-100 sm:opacity-0 sm:group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove metric\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n})\n\nexport default MetricItemCard\n","/**\n * MetricsSection Component\n *\n * Displays the Metrics section in the query panel with expandable list of metrics.\n */\n\nimport { useMemo, useState, useCallback, useRef, memo, DragEvent } from 'react'\nimport type { MetricsSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport MetricItemCard from './MetricItemCard'\nimport SectionHeading from './SectionHeading'\nimport { getIcon } from '../../icons'\n\n// Get icon once at module level to avoid recreating\nconst AddIcon = getIcon('add')\n\n/**\n * Find field metadata by field name\n */\nfunction findFieldMeta(fieldName: string, schema: MetricsSectionProps['schema']): MetaField | null {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n return cube.measures?.find((m) => m.name === fieldName) || null\n}\n\n/**\n * Get next sort direction in the cycle: null -> asc -> desc -> null\n */\nfunction getNextSortDirection(current: 'asc' | 'desc' | null): 'asc' | 'desc' | null {\n switch (current) {\n case null:\n return 'asc'\n case 'asc':\n return 'desc'\n case 'desc':\n return null\n default:\n return 'asc'\n }\n}\n\n/**\n * MetricsSection displays a collapsible section with:\n * - Header with title and add button\n * - List of selected metrics (using MetricItemCard)\n * - Drag/drop reordering support\n */\nconst MetricsSection = memo(function MetricsSection({\n metrics,\n schema,\n onAdd,\n onRemove,\n order,\n onOrderChange,\n onReorder\n}: MetricsSectionProps) {\n\n // Drag/drop state\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null)\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null) // Index where item will be inserted\n\n // Use refs to track current values for use in drop handler (avoids stale closure issues)\n const draggedIndexRef = useRef<number | null>(null)\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Get the ordered keys to calculate priority\n const orderKeys = useMemo(() => order ? Object.keys(order) : [], [order])\n\n // Resolve field metadata for all metrics with sort info\n const metricsWithMeta = useMemo(() => {\n return metrics.map((metric, index) => {\n const sortDirection = order?.[metric.field] || null\n const sortPriority = sortDirection ? orderKeys.indexOf(metric.field) + 1 : undefined\n return {\n metric,\n fieldMeta: findFieldMeta(metric.field, schema),\n sortDirection,\n sortPriority,\n index\n }\n })\n }, [metrics, schema, order, orderKeys])\n\n // Track drag clone for cleanup\n const dragCloneRef = useRef<HTMLElement | null>(null)\n\n // Drag handlers\n const handleDragStart = useCallback((e: DragEvent, index: number) => {\n setDraggedIndex(index)\n draggedIndexRef.current = index\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'metric', index, field: metrics[index].field }))\n\n // Create a semi-transparent, slightly tilted drag image\n const target = e.currentTarget as HTMLElement\n const clone = target.cloneNode(true) as HTMLElement\n clone.style.cssText = `\n position: absolute;\n top: -9999px;\n left: -9999px;\n width: ${target.offsetWidth}px;\n opacity: 0.7;\n transform: rotate(2deg);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n `\n document.body.appendChild(clone)\n dragCloneRef.current = clone\n\n // Calculate offset from click position\n const rect = target.getBoundingClientRect()\n const offsetX = e.clientX - rect.left\n const offsetY = e.clientY - rect.top\n e.dataTransfer.setDragImage(clone, offsetX, offsetY)\n }, [metrics])\n\n const handleDragEnd = useCallback(() => {\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n // Clean up the drag clone\n if (dragCloneRef.current) {\n document.body.removeChild(dragCloneRef.current)\n dragCloneRef.current = null\n }\n }, [])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent, itemIndex: number) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Only process if we're dragging from this section\n const currentDraggedIndex = draggedIndexRef.current\n if (currentDraggedIndex === null) return\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === currentDraggedIndex || targetIndex === currentDraggedIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n }\n }, [])\n\n // Handle drop on an item\n const handleItemDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Use refs to get current values (avoids stale closure issues)\n const currentDraggedIndex = draggedIndexRef.current\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Reset visual state immediately\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n\n // Validate and reorder - use refs directly, no dataTransfer parsing needed\n if (currentDraggedIndex === null || currentDropTargetIndex === null || !onReorder) {\n return\n }\n\n // Adjust target index when dragging down (after splice, indices shift)\n const adjustedTarget = currentDropTargetIndex > currentDraggedIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (adjustedTarget !== currentDraggedIndex) {\n onReorder(currentDraggedIndex, adjustedTarget)\n }\n }, [onReorder])\n\n // Clear drop target when leaving the section\n const handleSectionDragLeave = useCallback((e: DragEvent) => {\n const relatedTarget = e.relatedTarget as HTMLElement | null\n if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {\n setDropTargetIndex(null)\n }\n }, [])\n\n // Calculate if an item should be shifted to make room for the drop\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (draggedIndex === null || dropTargetIndex === null) return ''\n\n // Gap size in pixels\n const gapSize = 40\n\n // If this is the dragged item, no transform needed (it's already faded)\n if (itemIndex === draggedIndex) return ''\n\n // Items at or after drop target need to shift down\n // But we need to account for the dragged item's position\n if (draggedIndex < dropTargetIndex) {\n // Dragging down: items between dragged+1 and dropTarget-1 shift up\n if (itemIndex > draggedIndex && itemIndex < dropTargetIndex) {\n return '' // No gap needed, item stays in place\n }\n // Item at dropTarget-1 position should show gap after it\n if (itemIndex === dropTargetIndex - 1) {\n return `translateY(-${gapSize / 2}px)` // Shift up to make room\n }\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down\n }\n } else {\n // Dragging up: items from dropTarget to draggedIndex-1 shift down\n if (itemIndex >= dropTargetIndex && itemIndex < draggedIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down to make room\n }\n }\n\n return ''\n }, [draggedIndex, dropTargetIndex])\n\n // Determine if gap indicator should show at a position\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (draggedIndex === null || dropTargetIndex === null) return false\n\n // Show indicator before the item that matches dropTargetIndex\n return itemIndex === dropTargetIndex\n }, [draggedIndex, dropTargetIndex])\n\n return (\n <div>\n {/* Section Header - entire row is clickable */}\n <button\n onClick={onAdd}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add metric\"\n >\n <SectionHeading>Metrics</SectionHeading>\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </button>\n\n {/* Metrics List */}\n <div\n className=\"space-y-2\"\n onDragLeave={onReorder ? handleSectionDragLeave : undefined}\n onDragOver={onReorder ? (e) => e.preventDefault() : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {metricsWithMeta.map(({ metric, fieldMeta, sortDirection, sortPriority, index }) => {\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={metric.id}\n className=\"relative\"\n style={{\n transform,\n transition: draggedIndex !== null ? 'transform 0.15s ease-out' : 'none'\n }}\n onDragOver={onReorder ? (e) => handleItemDragOver(e, index) : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n <MetricItemCard\n metric={metric}\n fieldMeta={fieldMeta}\n onRemove={() => onRemove(metric.id)}\n sortDirection={sortDirection}\n sortPriority={sortPriority}\n onToggleSort={onOrderChange ? () => {\n const nextDirection = getNextSortDirection(sortDirection)\n onOrderChange(metric.field, nextDirection)\n } : undefined}\n index={index}\n isDragging={draggedIndex === index}\n onDragStart={onReorder ? handleDragStart : undefined}\n onDragEnd={onReorder ? handleDragEnd : undefined}\n />\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {onReorder && draggedIndex !== null && dropTargetIndex === metrics.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list */}\n {onReorder && metrics.length > 0 && draggedIndex !== null && (\n <div\n className=\"h-8\"\n onDragOver={(e) => {\n e.preventDefault()\n // Set drop target to end of list\n const lastIndex = metrics.length\n const currentDraggedIndex = draggedIndexRef.current\n if (dropTargetIndexRef.current !== lastIndex && currentDraggedIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n </div>\n )\n})\n\nexport default MetricsSection\n","/**\n * Type definitions for AnalysisBuilder components\n *\n * AnalysisBuilder is a redesigned query builder with:\n * - Results panel on the left (large)\n * - Query builder panel on the right\n * - Search-based field selection via modal\n * - Sections: Metrics (measures), Breakdown (dimensions), Filters\n */\n\nimport type { MouseEvent, DragEvent } from 'react'\nimport type {\n CubeQuery,\n Filter,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig,\n MultiQueryConfig,\n QueryMergeStrategy,\n FunnelBindingKey,\n AnalysisType,\n FunnelStepState,\n} from '../../types'\nimport type { ColorPalette } from '../../utils/colorPalettes'\nimport type { MetaResponse, MetaField, MetaCube, QueryAnalysis } from '../../shared/types'\nimport type { ChartAvailabilityMap } from '../../shared/chartDefaults'\nimport type { MultiQueryValidationResult } from '../../utils/multiQueryValidation'\nimport type { ValidationResult } from '../../adapters/modeAdapter'\n\n// Re-export types from shared for convenience\nexport type { MetaResponse, MetaField, MetaCube, QueryAnalysis }\n\n// ============================================================================\n// Metric and Breakdown Items\n// ============================================================================\n\n/**\n * A selected metric (measure) with a letter label (A, B, C, ...)\n */\nexport interface MetricItem {\n /** Unique identifier for this metric selection */\n id: string\n /** Full field name, e.g., \"Employees.count\" */\n field: string\n /** Display label (A, B, C, ...) */\n label: string\n}\n\n/**\n * A selected breakdown (dimension or time dimension)\n */\nexport interface BreakdownItem {\n /** Unique identifier for this breakdown selection */\n id: string\n /** Full field name, e.g., \"Employees.departmentName\" */\n field: string\n /** Granularity for time dimensions (day, week, month, quarter, year) */\n granularity?: string\n /** Whether this is a time dimension */\n isTimeDimension: boolean\n /** Enable period comparison for time dimensions (compares current filter period vs prior period) */\n enableComparison?: boolean\n}\n\n// ============================================================================\n// State Types\n// ============================================================================\n\n/** Validation status for query building */\nexport type ValidationStatus = 'idle' | 'validating' | 'valid' | 'invalid'\n\n/** Execution status for query results */\nexport type ExecutionStatus = 'idle' | 'loading' | 'refreshing' | 'success' | 'error'\n\n/**\n * Main state for the AnalysisBuilder component\n *\n * Note: Execution state (results, loading, error) is NOT stored here.\n * All server state is managed by TanStack Query. This state only contains\n * client-side configuration (metrics, breakdowns, filters, validation).\n */\nexport interface AnalysisBuilderState {\n /** Selected metrics (measures) */\n metrics: MetricItem[]\n /** Selected breakdowns (dimensions and time dimensions) */\n breakdowns: BreakdownItem[]\n /** Applied filters */\n filters: Filter[]\n /** Sort order for this query (field name -> 'asc' | 'desc') */\n order?: Record<string, 'asc' | 'desc'>\n\n // Validation state (client-side query validation)\n validationStatus: ValidationStatus\n validationError: string | null\n}\n\n/**\n * State for the AI query generation panel\n */\nexport interface AIState {\n /** Whether the AI panel is open */\n isOpen: boolean\n /** User's natural language prompt */\n userPrompt: string\n /** Whether a query is being generated */\n isGenerating: boolean\n /** Error message from generation */\n error: string | null\n /** Whether the AI has generated a query that's been loaded */\n hasGeneratedQuery: boolean\n /** Snapshot of state before AI was opened (for undo) */\n previousState: {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n /** Analysis type for restoring mode on cancel */\n analysisType?: AnalysisType\n } | null\n /** Full AnalysisConfig snapshot for complete restore (handles funnel mode properly) */\n previousConfig?: import('../../types/analysisConfig').AnalysisConfig | null\n}\n\n// ============================================================================\n// Field Search Modal Types\n// ============================================================================\n\n/**\n * Mode for the field search modal - determines which field types are shown\n * - 'metrics': Only measures\n * - 'breakdown': Only dimensions (including time dimensions)\n * - 'filter': Both measures and dimensions\n * - 'dimensionFilter': Only dimensions (for funnel step filters where measures don't work)\n */\nexport type FieldSearchMode = 'metrics' | 'breakdown' | 'filter' | 'dimensionFilter'\n\n/**\n * Field type categorization\n */\nexport type FieldType = 'measure' | 'dimension' | 'timeDimension'\n\n/**\n * A field option for display in the search modal\n */\nexport interface FieldOption {\n /** Full field name, e.g., \"Employees.count\" */\n name: string\n /** Display title */\n title: string\n /** Short title for compact display */\n shortTitle: string\n /** Field type (count, sum, avg, string, time, number, etc.) */\n type: string\n /** Optional description */\n description?: string\n /** Parent cube name */\n cubeName: string\n /** Categorized field type */\n fieldType: FieldType\n}\n\n/**\n * Props for the FieldSearchModal component\n */\nexport interface FieldSearchModalProps {\n /** Whether the modal is open */\n isOpen: boolean\n /** Callback to close the modal */\n onClose: () => void\n /** Callback when a field is selected. keepOpen=true when shift-click multi-selecting */\n onSelect: (field: MetaField, fieldType: FieldType, cubeName: string, keepOpen?: boolean) => void\n /** Mode determines which field types to show */\n mode: FieldSearchMode\n /** Schema metadata */\n schema: MetaResponse | null\n /** Already selected field names (to show checkmarks) */\n selectedFields: string[]\n /** Recently used field names */\n recentFields?: string[]\n}\n\n/**\n * Props for the FieldSearchItem component\n */\nexport interface FieldSearchItemProps {\n /** Field data */\n field: FieldOption\n /** Whether this field is selected */\n isSelected: boolean\n /** Whether this field is focused/highlighted */\n isFocused: boolean\n /** Click handler - receives mouse event for shift-click multi-select */\n onClick: (e: MouseEvent) => void\n /** Mouse enter handler (for detail panel) */\n onMouseEnter: () => void\n}\n\n/**\n * Props for the FieldDetailPanel component\n */\nexport interface FieldDetailPanelProps {\n /** Field to display details for */\n field: FieldOption | null\n}\n\n// ============================================================================\n// Panel Component Props\n// ============================================================================\n\n/**\n * Tab options for the query panel\n */\nexport type QueryPanelTab = 'query' | 'chart' | 'display'\n\n/**\n * Tab options for the funnel panel\n */\nexport type FunnelPanelTab = 'steps' | 'display'\n\n/**\n * Props for the AnalysisQueryPanel component\n */\nexport interface AnalysisQueryPanelProps {\n /** Selected metrics */\n metrics: MetricItem[]\n /** Selected breakdowns */\n breakdowns: BreakdownItem[]\n /** Applied filters */\n filters: Filter[]\n /** Schema metadata */\n schema: MetaResponse | null\n\n /** Currently active tab */\n activeTab: QueryPanelTab\n /** Callback when active tab changes */\n onActiveTabChange: (tab: QueryPanelTab) => void\n\n // Metric actions\n onAddMetric: () => void\n onRemoveMetric: (id: string) => void\n onReorderMetrics?: (fromIndex: number, toIndex: number) => void\n\n // Breakdown actions\n onAddBreakdown: () => void\n onRemoveBreakdown: (id: string) => void\n onBreakdownGranularityChange: (id: string, granularity: string) => void\n onBreakdownComparisonToggle?: (id: string) => void\n onReorderBreakdowns?: (fromIndex: number, toIndex: number) => void\n\n // Filter actions\n onFiltersChange: (filters: Filter[]) => void\n onDropFieldToFilter?: (field: string) => void\n\n // Sorting\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n\n // Chart configuration\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n /** Color palette for display config options */\n colorPalette?: ColorPalette\n /** Map of chart type availability for disabling unavailable chart types */\n chartAvailability?: ChartAvailabilityMap\n onChartTypeChange: (type: ChartType) => void\n onChartConfigChange: (config: ChartAxisConfig) => void\n onDisplayConfigChange: (config: ChartDisplayConfig) => void\n\n // Validation state (for showing errors)\n validationStatus: ValidationStatus\n validationError: string | null\n\n // Multi-query props\n /** Number of queries (determines single vs multi-query display) */\n queryCount?: number\n /** Index of the currently active query tab */\n activeQueryIndex?: number\n /** Strategy for merging results from multiple queries */\n mergeStrategy?: QueryMergeStrategy\n /** Callback when active query tab changes */\n onActiveQueryChange?: (index: number) => void\n /** Callback to add a new query */\n onAddQuery?: () => void\n /** Callback to remove a query at specified index */\n onRemoveQuery?: (index: number) => void\n /** Callback when merge strategy changes */\n onMergeStrategyChange?: (strategy: QueryMergeStrategy) => void\n /** Whether breakdowns are locked (synced from Q1 in merge mode) */\n breakdownsLocked?: boolean\n /** Combined metrics from all queries (for chart config in multi-query mode) */\n combinedMetrics?: MetricItem[]\n /** Combined breakdowns from all queries (for chart config in multi-query mode) */\n combinedBreakdowns?: BreakdownItem[]\n /** Validation result for multi-query mode (errors and warnings) */\n multiQueryValidation?: MultiQueryValidationResult | null\n /** Validation result from adapter (NEW - Phase 5) */\n adapterValidation?: ValidationResult | null\n\n // Funnel-specific props (when mergeStrategy === 'funnel')\n /** Binding key dimension that links funnel steps together */\n funnelBindingKey?: FunnelBindingKey | null\n /** Callback when funnel binding key changes */\n onFunnelBindingKeyChange?: (bindingKey: FunnelBindingKey | null) => void\n\n // Analysis Type props (explicit mode selection)\n /** Current analysis type (query, multi, funnel) */\n analysisType?: AnalysisType\n /** Callback when analysis type changes */\n onAnalysisTypeChange?: (type: AnalysisType) => void\n\n // Funnel Mode props (when analysisType === 'funnel')\n /** Selected cube for funnel mode (all steps use this cube) */\n funnelCube?: string | null\n /** Dedicated funnel steps (separate from queryStates) */\n funnelSteps?: FunnelStepState[]\n /** Index of currently active funnel step */\n activeFunnelStepIndex?: number\n /** Time dimension for funnel temporal ordering */\n funnelTimeDimension?: string | null\n /** Callback when funnel cube changes */\n onFunnelCubeChange?: (cube: string | null) => void\n /** Add a new funnel step */\n onAddFunnelStep?: () => void\n /** Remove a funnel step by index */\n onRemoveFunnelStep?: (index: number) => void\n /** Update a funnel step by index */\n onUpdateFunnelStep?: (index: number, updates: Partial<FunnelStepState>) => void\n /** Set the active funnel step index */\n onSelectFunnelStep?: (index: number) => void\n /** Reorder funnel steps */\n onReorderFunnelSteps?: (fromIndex: number, toIndex: number) => void\n /** Set the time dimension for funnel */\n onFunnelTimeDimensionChange?: (dimension: string | null) => void\n /** Funnel display config (for Display tab in funnel mode) */\n funnelDisplayConfig?: ChartDisplayConfig\n /** Callback when funnel display config changes */\n onFunnelDisplayConfigChange?: (config: ChartDisplayConfig) => void\n\n // Flow Mode props (when analysisType === 'flow')\n /** Selected cube for flow analysis */\n flowCube?: string | null\n /** Binding key for flow mode (entity linking) */\n flowBindingKey?: FunnelBindingKey | null\n /** Time dimension for flow mode (event ordering) */\n flowTimeDimension?: string | null\n /** Event dimension for flow mode (node labels in Sankey) */\n eventDimension?: string | null\n /** Starting step configuration for flow mode */\n startingStep?: import('../../types/flow').FlowStartingStep\n /** Number of steps to explore before starting step */\n stepsBefore?: number\n /** Number of steps to explore after starting step */\n stepsAfter?: number\n /** Join strategy for flow execution */\n flowJoinStrategy?: 'auto' | 'lateral' | 'window'\n /** Callback when flow cube changes */\n onFlowCubeChange?: (cube: string | null) => void\n /** Callback when flow binding key changes */\n onFlowBindingKeyChange?: (key: FunnelBindingKey | null) => void\n /** Callback when flow time dimension changes */\n onFlowTimeDimensionChange?: (dim: string | null) => void\n /** Callback when event dimension changes */\n onEventDimensionChange?: (dim: string | null) => void\n /** Callback when starting step filters change */\n onStartingStepFiltersChange?: (filters: Filter[]) => void\n /** Callback when steps before changes */\n onStepsBeforeChange?: (count: number) => void\n /** Callback when steps after changes */\n onStepsAfterChange?: (count: number) => void\n /** Callback when join strategy changes */\n onFlowJoinStrategyChange?: (strategy: 'auto' | 'lateral' | 'window') => void\n /** Flow display config (for Display tab in flow mode) */\n flowDisplayConfig?: ChartDisplayConfig\n /** Callback when flow display config changes */\n onFlowDisplayConfigChange?: (config: ChartDisplayConfig) => void\n\n // Retention Mode props (when analysisType === 'retention' - simplified Mixpanel-style)\n /** Single cube for retention analysis */\n retentionCube?: string | null\n /** Binding key for retention analysis */\n retentionBindingKey?: import('../../types').FunnelBindingKey | null\n /** Single timestamp dimension for retention */\n retentionTimeDimension?: string | null\n /** Date range for cohort analysis (REQUIRED) */\n retentionDateRange?: import('../../types/retention').DateRange\n /** Cohort filters - define who enters the cohort */\n retentionCohortFilters?: Filter[]\n /** Activity filters - define what counts as a return */\n retentionActivityFilters?: Filter[]\n /** Breakdown dimensions for segmentation */\n retentionBreakdowns?: import('../../types/retention').RetentionBreakdownItem[]\n /** Granularity for viewing retention periods */\n retentionViewGranularity?: import('../../types/retention').RetentionGranularity\n /** Number of periods */\n retentionPeriods?: number\n /** Retention type */\n retentionType?: import('../../types/retention').RetentionType\n /** Retention display config */\n retentionDisplayConfig?: ChartDisplayConfig\n /** Callback when cube changes */\n onRetentionCubeChange?: (cube: string | null) => void\n /** Callback when retention binding key changes */\n onRetentionBindingKeyChange?: (key: import('../../types').FunnelBindingKey | null) => void\n /** Callback when time dimension changes */\n onRetentionTimeDimensionChange?: (dim: string | null) => void\n /** Callback when date range changes */\n onRetentionDateRangeChange?: (range: import('../../types/retention').DateRange) => void\n /** Callback when cohort filters change */\n onRetentionCohortFiltersChange?: (filters: Filter[]) => void\n /** Callback when activity filters change */\n onRetentionActivityFiltersChange?: (filters: Filter[]) => void\n /** Callback when breakdowns change (set all) */\n onRetentionBreakdownsChange?: (breakdowns: import('../../types/retention').RetentionBreakdownItem[]) => void\n /** Callback to add a breakdown */\n onAddRetentionBreakdown?: (breakdown: import('../../types/retention').RetentionBreakdownItem) => void\n /** Callback to remove a breakdown */\n onRemoveRetentionBreakdown?: (field: string) => void\n /** Callback when granularity changes */\n onRetentionViewGranularityChange?: (granularity: import('../../types/retention').RetentionGranularity) => void\n /** Callback when periods changes */\n onRetentionPeriodsChange?: (periods: number) => void\n /** Callback when retention type changes */\n onRetentionTypeChange?: (type: import('../../types/retention').RetentionType) => void\n /** Callback when retention display config changes */\n onRetentionDisplayConfigChange?: (config: ChartDisplayConfig) => void\n}\n\n/**\n * Props for the AnalysisResultsPanel component\n */\nexport interface AnalysisResultsPanelProps {\n /** Current execution status */\n executionStatus: ExecutionStatus\n /** Execution results (raw data) */\n executionResults: any[] | null\n /** Execution error message */\n executionError: string | null\n /** Total row count (before limit) */\n totalRowCount: number | null\n /** Whether results are stale (query changed) */\n resultsStale: boolean\n\n /** Chart type for visualization */\n chartType: ChartType\n /** Chart axis configuration */\n chartConfig: ChartAxisConfig\n /** Chart display configuration */\n displayConfig: ChartDisplayConfig\n /** Color palette for charts */\n colorPalette?: ColorPalette\n /** Current palette name (for selector) */\n currentPaletteName?: string\n /** Callback when color palette changes (shows selector when provided) */\n onColorPaletteChange?: (paletteName: string) => void\n\n /** All queries for multi-query mode (used for table column headers per-query) */\n allQueries?: CubeQuery[]\n /**\n * In funnel mode, the actually executed queries with:\n * - Binding key dimension auto-added\n * - IN filter applied for steps 2+\n * Use these for debug display instead of allQueries.\n */\n funnelExecutedQueries?: CubeQuery[]\n /** Schema metadata */\n schema: MetaResponse | null\n\n /** Active view (table or chart) */\n activeView: 'table' | 'chart'\n /** Callback when active view changes */\n onActiveViewChange: (view: 'table' | 'chart') => void\n\n /** Display limit for table */\n displayLimit: number\n /** Callback when display limit changes */\n onDisplayLimitChange: (limit: number) => void\n\n /** Whether the query has metrics (measures) - needed to enable/disable chart view */\n hasMetrics: boolean\n\n // Debug information (from dry-run) - per-query for multi-query mode\n /** Debug data for each query (SQL, analysis, loading/error state) */\n debugDataPerQuery?: Array<{\n sql: { sql: string; params: unknown[] } | null\n analysis: QueryAnalysis | null\n loading: boolean\n error: Error | null\n }>\n\n // Share functionality\n onShareClick?: () => void\n canShare?: boolean\n shareButtonState?: 'idle' | 'copied' | 'copied-no-chart'\n\n // Refresh functionality\n /** Callback when refresh button is clicked. Receives options.bustCache when Shift+click */\n onRefreshClick?: (options?: { bustCache?: boolean }) => void\n canRefresh?: boolean\n isRefreshing?: boolean\n /**\n * Whether the query configuration has changed but results haven't been refreshed yet.\n * When true, shows a \"Needs refresh\" banner (manual refresh mode only).\n */\n needsRefresh?: boolean\n\n // Clear functionality\n onClearClick?: () => void\n canClear?: boolean\n\n // AI functionality\n enableAI?: boolean\n isAIOpen?: boolean\n onAIToggle?: () => void\n\n // Multi-query support\n /** Number of queries (for showing Table 1, Table 2 tabs) */\n queryCount?: number\n /** Per-query results (for table view in multi-query mode) */\n perQueryResults?: (any[] | null)[]\n /** Active table index in multi-query mode */\n activeTableIndex?: number\n /** Callback when active table changes */\n onActiveTableChange?: (index: number) => void\n /** Current analysis type (query or funnel) - primary way to detect mode */\n analysisType?: AnalysisType\n /**\n * Whether in funnel mode (always show unified results, no per-query tables)\n * @deprecated Use analysisType === 'funnel' instead\n */\n isFunnelMode?: boolean\n\n // Funnel-specific debug data (when analysisType === 'funnel')\n /**\n * The actual server funnel query { funnel: {...} } sent to the server.\n * Use this for debug display instead of per-query debug data.\n */\n funnelServerQuery?: unknown\n /**\n * Unified debug data for funnel queries (SQL, analysis, loading/error state).\n * Contains the CTE-based SQL for the entire funnel.\n */\n funnelDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n loading: boolean\n error: Error | null\n funnelMetadata?: unknown\n } | null\n /**\n * The actual server flow query { flow: {...} } sent to the server.\n * Use this for debug display instead of per-query debug data.\n */\n flowServerQuery?: unknown\n /**\n * Unified debug data for flow queries (SQL, analysis, loading/error state).\n * Contains the CTE-based SQL for the flow analysis.\n */\n flowDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n loading: boolean\n error: Error | null\n flowMetadata?: unknown\n } | null\n /**\n * In retention mode, the actual server query { retention: {...} } sent to the API.\n * Use this for debug display.\n */\n retentionServerQuery?: unknown\n /**\n * Unified debug data for retention queries (SQL, analysis, loading/error state).\n * Contains the CTE-based SQL for the retention analysis.\n */\n retentionDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n loading: boolean\n error: Error | null\n retentionMetadata?: unknown\n } | null\n /**\n * Retention chart data (cohort × period matrix) for rendering.\n */\n retentionChartData?: import('../../types/retention').RetentionChartData | null\n /**\n * Retention validation result (errors explaining why query cannot be built).\n */\n retentionValidation?: { isValid: boolean; errors: string[]; warnings: string[] } | null\n}\n\n// ============================================================================\n// Section Component Props\n// ============================================================================\n\n/**\n * Props for the MetricsSection component\n */\nexport interface MetricsSectionProps {\n /** Selected metrics */\n metrics: MetricItem[]\n /** Schema for resolving field titles */\n schema: MetaResponse | null\n /** Add metric handler */\n onAdd: () => void\n /** Remove metric handler */\n onRemove: (id: string) => void\n /** Whether the section is expanded */\n isExpanded?: boolean\n /** Toggle expansion */\n onToggleExpanded?: () => void\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n /** Callback when metrics are reordered via drag/drop */\n onReorder?: (fromIndex: number, toIndex: number) => void\n /** Callback when a metric is dragged to the filter section */\n onDragToFilter?: (field: string) => void\n}\n\n/**\n * Props for the BreakdownSection component\n */\nexport interface BreakdownSectionProps {\n /** Selected breakdowns */\n breakdowns: BreakdownItem[]\n /** Schema for resolving field titles */\n schema: MetaResponse | null\n /** Add breakdown handler */\n onAdd: () => void\n /** Remove breakdown handler */\n onRemove: (id: string) => void\n /** Change granularity for time dimension */\n onGranularityChange: (id: string, granularity: string) => void\n /** Toggle comparison for time dimension */\n onComparisonToggle?: (id: string) => void\n /** Whether the section is expanded */\n isExpanded?: boolean\n /** Toggle expansion */\n onToggleExpanded?: () => void\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n /** Callback when breakdowns are reordered via drag/drop */\n onReorder?: (fromIndex: number, toIndex: number) => void\n /** Callback when a breakdown is dragged to the filter section */\n onDragToFilter?: (field: string) => void\n}\n\n/**\n * Props for MetricItemCard component\n */\nexport interface MetricItemCardProps {\n /** Metric item data */\n metric: MetricItem\n /** Field metadata (for title, description) */\n fieldMeta: MetaField | null\n /** Remove handler */\n onRemove: () => void\n /** Current sort direction for this field */\n sortDirection?: 'asc' | 'desc' | null\n /** Sort priority (1, 2, 3...) if sorted */\n sortPriority?: number\n /** Toggle sort handler */\n onToggleSort?: () => void\n /** Index in the list (for drag/drop) */\n index?: number\n /** Whether this item is being dragged */\n isDragging?: boolean\n /** Whether dragging over this item */\n isDragOver?: boolean\n /** Drag start handler */\n onDragStart?: (e: DragEvent, index: number) => void\n /** Drag over handler */\n onDragOver?: (e: DragEvent, index: number) => void\n /** Drop handler */\n onDrop?: (e: DragEvent, index: number) => void\n /** Drag end handler */\n onDragEnd?: () => void\n}\n\n/**\n * Props for BreakdownItemCard component\n */\nexport interface BreakdownItemCardProps {\n /** Breakdown item data */\n breakdown: BreakdownItem\n /** Field metadata (for title, description) */\n fieldMeta: MetaField | null\n /** Remove handler */\n onRemove: () => void\n /** Granularity change handler (for time dimensions) */\n onGranularityChange?: (granularity: string) => void\n /** Toggle comparison for time dimensions */\n onComparisonToggle?: () => void\n /** Whether another time dimension already has comparison enabled */\n comparisonDisabled?: boolean\n /** Current sort direction for this field */\n sortDirection?: 'asc' | 'desc' | null\n /** Sort priority (1, 2, 3...) if sorted */\n sortPriority?: number\n /** Toggle sort handler */\n onToggleSort?: () => void\n /** Index in the list (for drag/drop) */\n index?: number\n /** Whether this item is being dragged */\n isDragging?: boolean\n /** Whether dragging over this item */\n isDragOver?: boolean\n /** Drag start handler */\n onDragStart?: (e: DragEvent, index: number) => void\n /** Drag over handler */\n onDragOver?: (e: DragEvent, index: number) => void\n /** Drop handler */\n onDrop?: (e: DragEvent, index: number) => void\n /** Drag end handler */\n onDragEnd?: () => void\n}\n\n// ============================================================================\n// Main Component Props\n// ============================================================================\n\n/**\n * Initial funnel state for AnalysisBuilder (matches InitialFunnelState in store)\n */\nexport interface AnalysisBuilderInitialFunnelState {\n funnelCube?: string | null\n funnelSteps?: FunnelStepState[]\n funnelTimeDimension?: string | null\n funnelBindingKey?: FunnelBindingKey | null\n funnelChartType?: ChartType\n funnelChartConfig?: ChartAxisConfig\n funnelDisplayConfig?: ChartDisplayConfig\n}\n\n/**\n * Initial flow state for AnalysisBuilder (matches FlowSliceState in store)\n */\nexport interface AnalysisBuilderInitialFlowState {\n flowCube?: string | null\n flowBindingKey?: FunnelBindingKey | null\n flowTimeDimension?: string | null\n startingStep?: import('../../types/flow').FlowStartingStep\n stepsBefore?: number\n stepsAfter?: number\n eventDimension?: string | null\n joinStrategy?: 'auto' | 'lateral' | 'window'\n flowChartType?: ChartType\n flowChartConfig?: ChartAxisConfig\n flowDisplayConfig?: ChartDisplayConfig\n}\n\n/**\n * Initial retention state for AnalysisBuilder (matches RetentionSliceState in store)\n */\nexport interface AnalysisBuilderInitialRetentionState {\n retentionCube?: string | null\n retentionBindingKey?: FunnelBindingKey | null\n retentionTimeDimension?: string | null\n retentionDateRange?: import('../../types/retention').DateRange\n retentionCohortFilters?: Filter[]\n retentionActivityFilters?: Filter[]\n retentionBreakdowns?: import('../../types/retention').RetentionBreakdownItem[]\n retentionViewGranularity?: import('../../types/retention').RetentionGranularity\n retentionPeriods?: number\n retentionType?: import('../../types/retention').RetentionType\n retentionChartType?: ChartType\n retentionChartConfig?: ChartAxisConfig\n retentionDisplayConfig?: ChartDisplayConfig\n}\n\n/**\n * Props for the main AnalysisBuilder component\n */\nexport interface AnalysisBuilderProps {\n /** Additional CSS classes */\n className?: string\n /** Maximum height for the component (e.g., '800px', '100vh', 'calc(100vh - 64px)') */\n maxHeight?: string\n /**\n * Initial query configuration to load.\n * Accepts either a single CubeQuery or a MultiQueryConfig - the component handles both internally.\n * This keeps multi-query complexity contained within AnalysisBuilder.\n */\n initialQuery?: CubeQuery | MultiQueryConfig\n /** Initial chart configuration (for editing existing portlets) */\n initialChartConfig?: {\n chartType?: ChartType\n chartConfig?: ChartAxisConfig\n displayConfig?: ChartDisplayConfig\n }\n /** Initial analysis type (query or funnel) - defaults to 'query' */\n initialAnalysisType?: AnalysisType\n /** Initial funnel state (when initialAnalysisType === 'funnel') */\n initialFunnelState?: AnalysisBuilderInitialFunnelState\n /** Initial flow state (when initialAnalysisType === 'flow') */\n initialFlowState?: AnalysisBuilderInitialFlowState\n /** Initial retention state (when initialAnalysisType === 'retention') */\n initialRetentionState?: AnalysisBuilderInitialRetentionState\n /** Initial data to display (avoids re-fetching when editing existing portlets) */\n initialData?: any[]\n /** Color palette for chart visualization */\n colorPalette?: ColorPalette\n /** Disable localStorage persistence */\n disableLocalStorage?: boolean\n /** Hide settings button */\n hideSettings?: boolean\n /** Callback when query changes (for modal integration) */\n onQueryChange?: (query: CubeQuery) => void\n /** Callback when chart config changes */\n onChartConfigChange?: (config: { chartType: ChartType; chartConfig: ChartAxisConfig; displayConfig: ChartDisplayConfig }) => void\n}\n\n/**\n * Funnel state returned by getFunnelState\n */\nexport interface FunnelStateSnapshot {\n funnelCube: string | null\n funnelSteps: FunnelStepState[]\n funnelTimeDimension: string | null\n funnelBindingKey: FunnelBindingKey | null\n funnelChartType: ChartType\n funnelChartConfig: ChartAxisConfig\n funnelDisplayConfig: ChartDisplayConfig\n activeFunnelStepIndex: number\n}\n\n/**\n * Ref interface for AnalysisBuilder (for external access)\n */\nexport interface AnalysisBuilderRef {\n /**\n * Get the current query configuration.\n * Returns CubeQuery (single query), MultiQueryConfig (multiple queries), or ServerFunnelQuery (funnel mode).\n * Consumers should just JSON.stringify the result - no need to check the type.\n * @deprecated Use getAnalysisConfig() for Phase 3+ integrations\n */\n getQueryConfig: () => CubeQuery | MultiQueryConfig | import('../../types/funnel').ServerFunnelQuery\n /** Get current chart configuration */\n getChartConfig: () => { chartType: ChartType; chartConfig: ChartAxisConfig; displayConfig: ChartDisplayConfig }\n /** Get the current analysis type (query or funnel) */\n getAnalysisType: () => AnalysisType\n /** Get the current funnel state (for persisting funnel mode configuration) */\n getFunnelState: () => FunnelStateSnapshot\n /**\n * Phase 3: Get the complete AnalysisConfig.\n * This is the canonical format for persisting analysis state.\n * Replaces getQueryConfig + getChartConfig + getAnalysisType.\n */\n getAnalysisConfig: () => import('../../types/analysisConfig').AnalysisConfig\n /** Execute the current query */\n executeQuery: () => void\n /** Clear the current query */\n clearQuery: () => void\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Local storage state shape for persistence\n */\nexport interface AnalysisBuilderStorageState {\n // Legacy single-query format (for backward compatibility)\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n order?: Record<string, 'asc' | 'desc'>\n chartType: ChartType\n chartConfig: ChartAxisConfig\n displayConfig: ChartDisplayConfig\n activeView: 'table' | 'chart'\n\n // Multi-query format (when multiple queries are configured)\n queryStates?: AnalysisBuilderState[]\n activeQueryIndex?: number\n mergeStrategy?: QueryMergeStrategy\n /** Dimension keys used for merging in 'merge' strategy */\n mergeKeys?: string[]\n /** Binding key for funnel strategy (links steps together) */\n funnelBindingKey?: FunnelBindingKey | null\n /** Time window per step for funnel strategy (ISO 8601 duration) */\n stepTimeToConvert?: (string | null)[]\n}\n\n/**\n * Recent fields storage shape\n */\nexport interface RecentFieldsStorage {\n metrics: string[]\n breakdowns: string[]\n}\n\n/**\n * Time granularity options\n */\nexport const TIME_GRANULARITIES = [\n { value: 'hour', label: 'Hour' },\n { value: 'day', label: 'Day' },\n { value: 'week', label: 'Week' },\n { value: 'month', label: 'Month' },\n { value: 'quarter', label: 'Quarter' },\n { value: 'year', label: 'Year' }\n] as const\n\nexport type TimeGranularity = typeof TIME_GRANULARITIES[number]['value']\n","/**\n * BreakdownItemCard Component\n *\n * Displays a single breakdown (dimension) item with optional granularity selector.\n */\n\nimport { memo } from 'react'\nimport type { BreakdownItemCardProps, TimeGranularity } from './types'\nimport { TIME_GRANULARITIES } from './types'\nimport { getIcon } from '../../icons'\n\n/**\n * BreakdownItemCard displays a selected breakdown with:\n * - Field icon (dimension or time dimension)\n * - Field title or full name\n * - Granularity dropdown (for time dimensions)\n * - Sort toggle button (visible on hover, or always visible when sorted)\n * - Remove button (visible on hover)\n * - Drag handle for reordering\n */\nconst BreakdownItemCard = memo(function BreakdownItemCard({\n breakdown,\n fieldMeta,\n onRemove,\n onGranularityChange,\n onComparisonToggle,\n comparisonDisabled,\n sortDirection,\n sortPriority,\n onToggleSort,\n index,\n isDragging,\n onDragStart,\n onDragEnd\n}: BreakdownItemCardProps) {\n const DimensionIcon = getIcon('dimension')\n const TimeIcon = getIcon('timeDimension')\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || breakdown.field.split('.').pop() || breakdown.field\n\n // Get the cube name from the field\n const cubeName = breakdown.field.split('.')[0]\n\n // Choose icon based on dimension type\n const Icon = breakdown.isTimeDimension ? TimeIcon : DimensionIcon\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n // Check if drag/drop is enabled\n const isDraggable = typeof index === 'number' && onDragStart && onDragEnd\n\n return (\n <div\n className={`flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 ${\n isDraggable ? 'cursor-grab active:cursor-grabbing' : ''\n } ${isDragging ? 'opacity-30' : ''}`}\n draggable={isDraggable ? true : undefined}\n onDragStart={isDraggable ? (e) => onDragStart(e, index) : undefined}\n onDragEnd={isDraggable ? onDragEnd : undefined}\n >\n {/* Icon - colored background matching field selector */}\n <span className={`w-6 h-6 flex items-center justify-center rounded flex-shrink-0 ${\n breakdown.isTimeDimension\n ? 'bg-dc-time-dimension text-dc-time-dimension-text'\n : 'bg-dc-dimension text-dc-dimension-text'\n }`}>\n <Icon className=\"w-4 h-4\" />\n </span>\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={breakdown.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Granularity Selector (for time dimensions) */}\n {breakdown.isTimeDimension && onGranularityChange && (\n <select\n value={breakdown.granularity || 'day'}\n onChange={(e) => onGranularityChange(e.target.value as TimeGranularity)}\n onClick={(e) => e.stopPropagation()}\n className=\"text-xs bg-dc-surface border border-dc-border rounded px-2 py-1 text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary flex-shrink-0\"\n >\n {TIME_GRANULARITIES.map((g) => (\n <option key={g.value} value={g.value}>\n {g.label}\n </option>\n ))}\n </select>\n )}\n\n {/* Comparison Toggle (for time dimensions) */}\n {breakdown.isTimeDimension && onComparisonToggle && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onComparisonToggle()\n }}\n disabled={comparisonDisabled && !breakdown.enableComparison}\n className={`text-xs px-2 py-1 rounded flex-shrink-0 transition-colors ${\n breakdown.enableComparison\n ? 'bg-dc-accent text-white'\n : 'bg-dc-surface border border-dc-border text-dc-text-muted hover:text-dc-text hover:bg-dc-surface-hover'\n } ${comparisonDisabled && !breakdown.enableComparison ? 'opacity-50 cursor-not-allowed' : ''}`}\n title={\n comparisonDisabled && !breakdown.enableComparison\n ? 'Another time dimension already has comparison enabled'\n : breakdown.enableComparison\n ? 'Click to disable comparison'\n : 'Compare with previous period'\n }\n >\n vs prior\n </button>\n )}\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-100 sm:opacity-0 sm:group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove breakdown\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n})\n\nexport default BreakdownItemCard\n","/**\n * BreakdownSection Component\n *\n * Displays the Breakdown section in the query panel with expandable list of breakdowns.\n */\n\nimport { useMemo, useState, useCallback, useRef, memo, DragEvent } from 'react'\nimport type { BreakdownSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport BreakdownItemCard from './BreakdownItemCard'\nimport SectionHeading from './SectionHeading'\nimport { getIcon } from '../../icons'\n\n// Get icon once at module level to avoid recreating\nconst AddIcon = getIcon('add')\n\n/**\n * Find field metadata by field name\n */\nfunction findFieldMeta(fieldName: string, schema: BreakdownSectionProps['schema']): MetaField | null {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n // Check dimensions first, then try to find in other arrays\n return cube.dimensions?.find((d) => d.name === fieldName) || null\n}\n\n/**\n * Get next sort direction in the cycle: null -> asc -> desc -> null\n */\nfunction getNextSortDirection(current: 'asc' | 'desc' | null): 'asc' | 'desc' | null {\n switch (current) {\n case null:\n return 'asc'\n case 'asc':\n return 'desc'\n case 'desc':\n return null\n default:\n return 'asc'\n }\n}\n\n/**\n * BreakdownSection displays a collapsible section with:\n * - Header with title and add button\n * - List of selected breakdowns (using BreakdownItemCard)\n * - Drag/drop reordering support\n */\nconst BreakdownSection = memo(function BreakdownSection({\n breakdowns,\n schema,\n onAdd,\n onRemove,\n onGranularityChange,\n onComparisonToggle,\n order,\n onOrderChange,\n onReorder\n}: BreakdownSectionProps) {\n\n // Drag/drop state\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null)\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null) // Index where item will be inserted\n\n // Use refs to track current values for use in drop handler (avoids stale closure issues)\n const draggedIndexRef = useRef<number | null>(null)\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Get the ordered keys to calculate priority\n const orderKeys = useMemo(() => order ? Object.keys(order) : [], [order])\n\n // Calculate which breakdown has comparison enabled (only one allowed at a time)\n const activeComparisonId = useMemo(() => {\n const withComparison = breakdowns.find(b => b.isTimeDimension && b.enableComparison)\n return withComparison?.id || null\n }, [breakdowns])\n\n // Resolve field metadata for all breakdowns with sort info\n const breakdownsWithMeta = useMemo(() => {\n return breakdowns.map((breakdown, index) => {\n const sortDirection = order?.[breakdown.field] || null\n const sortPriority = sortDirection ? orderKeys.indexOf(breakdown.field) + 1 : undefined\n return {\n breakdown,\n fieldMeta: findFieldMeta(breakdown.field, schema),\n sortDirection,\n sortPriority,\n index\n }\n })\n }, [breakdowns, schema, order, orderKeys])\n\n // Track drag clone for cleanup\n const dragCloneRef = useRef<HTMLElement | null>(null)\n\n // Drag handlers\n const handleDragStart = useCallback((e: DragEvent, index: number) => {\n setDraggedIndex(index)\n draggedIndexRef.current = index\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'breakdown', index, field: breakdowns[index].field }))\n\n // Create a semi-transparent, slightly tilted drag image\n const target = e.currentTarget as HTMLElement\n const clone = target.cloneNode(true) as HTMLElement\n clone.style.cssText = `\n position: absolute;\n top: -9999px;\n left: -9999px;\n width: ${target.offsetWidth}px;\n opacity: 0.7;\n transform: rotate(2deg);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n `\n document.body.appendChild(clone)\n dragCloneRef.current = clone\n\n // Calculate offset from click position\n const rect = target.getBoundingClientRect()\n const offsetX = e.clientX - rect.left\n const offsetY = e.clientY - rect.top\n e.dataTransfer.setDragImage(clone, offsetX, offsetY)\n }, [breakdowns])\n\n const handleDragEnd = useCallback(() => {\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n // Clean up the drag clone\n if (dragCloneRef.current) {\n document.body.removeChild(dragCloneRef.current)\n dragCloneRef.current = null\n }\n }, [])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent, itemIndex: number) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Only process if we're dragging from this section\n const currentDraggedIndex = draggedIndexRef.current\n if (currentDraggedIndex === null) return\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === currentDraggedIndex || targetIndex === currentDraggedIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n }\n }, [])\n\n // Handle drop on an item\n const handleItemDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n // Use refs to get current values (avoids stale closure issues)\n const currentDraggedIndex = draggedIndexRef.current\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Reset visual state immediately\n setDraggedIndex(null)\n setDropTargetIndex(null)\n draggedIndexRef.current = null\n dropTargetIndexRef.current = null\n\n // Validate and reorder - use refs directly, no dataTransfer parsing needed\n if (currentDraggedIndex === null || currentDropTargetIndex === null || !onReorder) {\n return\n }\n\n // Adjust target index when dragging down (after splice, indices shift)\n const adjustedTarget = currentDropTargetIndex > currentDraggedIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (adjustedTarget !== currentDraggedIndex) {\n onReorder(currentDraggedIndex, adjustedTarget)\n }\n }, [onReorder])\n\n // Clear drop target when leaving the section\n const handleSectionDragLeave = useCallback((e: DragEvent) => {\n const relatedTarget = e.relatedTarget as HTMLElement | null\n if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {\n setDropTargetIndex(null)\n }\n }, [])\n\n // Calculate if an item should be shifted to make room for the drop\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (draggedIndex === null || dropTargetIndex === null) return ''\n\n // Gap size in pixels\n const gapSize = 40\n\n // If this is the dragged item, no transform needed (it's already faded)\n if (itemIndex === draggedIndex) return ''\n\n // Items at or after drop target need to shift down\n // But we need to account for the dragged item's position\n if (draggedIndex < dropTargetIndex) {\n // Dragging down: items between dragged+1 and dropTarget-1 shift up\n if (itemIndex > draggedIndex && itemIndex < dropTargetIndex) {\n return '' // No gap needed, item stays in place\n }\n // Item at dropTarget-1 position should show gap after it\n if (itemIndex === dropTargetIndex - 1) {\n return `translateY(-${gapSize / 2}px)` // Shift up to make room\n }\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down\n }\n } else {\n // Dragging up: items from dropTarget to draggedIndex-1 shift down\n if (itemIndex >= dropTargetIndex && itemIndex < draggedIndex) {\n return `translateY(${gapSize / 2}px)` // Shift down to make room\n }\n }\n\n return ''\n }, [draggedIndex, dropTargetIndex])\n\n // Determine if gap indicator should show at a position\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (draggedIndex === null || dropTargetIndex === null) return false\n\n // Show indicator before the item that matches dropTargetIndex\n return itemIndex === dropTargetIndex\n }, [draggedIndex, dropTargetIndex])\n\n return (\n <div>\n {/* Section Header - entire row is clickable */}\n <button\n onClick={onAdd}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add breakdown\"\n >\n <SectionHeading>Breakdown</SectionHeading>\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </button>\n\n {/* Breakdowns List */}\n <div\n className=\"space-y-2\"\n onDragLeave={onReorder ? handleSectionDragLeave : undefined}\n onDragOver={onReorder ? (e) => e.preventDefault() : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {breakdownsWithMeta.map(({ breakdown, fieldMeta, sortDirection, sortPriority, index }) => {\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={breakdown.id}\n className=\"relative\"\n style={{\n transform,\n transition: draggedIndex !== null ? 'transform 0.15s ease-out' : 'none'\n }}\n onDragOver={onReorder ? (e) => handleItemDragOver(e, index) : undefined}\n onDrop={onReorder ? handleItemDrop : undefined}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n <BreakdownItemCard\n breakdown={breakdown}\n fieldMeta={fieldMeta}\n onRemove={() => onRemove(breakdown.id)}\n onGranularityChange={\n breakdown.isTimeDimension\n ? (granularity) => onGranularityChange(breakdown.id, granularity)\n : undefined\n }\n onComparisonToggle={\n breakdown.isTimeDimension && onComparisonToggle\n ? () => onComparisonToggle(breakdown.id)\n : undefined\n }\n comparisonDisabled={activeComparisonId !== null && activeComparisonId !== breakdown.id}\n sortDirection={sortDirection}\n sortPriority={sortPriority}\n onToggleSort={onOrderChange ? () => {\n const nextDirection = getNextSortDirection(sortDirection)\n onOrderChange(breakdown.field, nextDirection)\n } : undefined}\n index={index}\n isDragging={draggedIndex === index}\n onDragStart={onReorder ? handleDragStart : undefined}\n onDragEnd={onReorder ? handleDragEnd : undefined}\n />\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {onReorder && draggedIndex !== null && dropTargetIndex === breakdowns.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list */}\n {onReorder && breakdowns.length > 0 && draggedIndex !== null && (\n <div\n className=\"h-8\"\n onDragOver={(e) => {\n e.preventDefault()\n // Set drop target to end of list\n const lastIndex = breakdowns.length\n const currentDraggedIndex = draggedIndexRef.current\n if (dropTargetIndexRef.current !== lastIndex && currentDraggedIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n </div>\n )\n})\n\nexport default BreakdownSection\n","/**\n * FilterConfigModal Component\n *\n * Modal for configuring filter settings with full UI for:\n * - Field selection with search\n * - Operator selection\n * - Value input (varies by operator and field type)\n * - Date range selection\n * - Multi-value support\n */\n\nimport React, { useState, useRef, useEffect, useCallback, ChangeEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport type { SimpleFilter, FilterOperator } from '../../types'\nimport type { MetaResponse, DateRangeType } from '../../shared/types'\nimport {\n FILTER_OPERATORS,\n DATE_RANGE_OPTIONS\n} from '../../shared/types'\nimport {\n getAvailableOperators,\n convertDateRangeTypeToValue,\n requiresNumberInput\n} from '../../shared/utils'\nimport { findFieldInSchema, getFieldTitle } from './utils'\nimport { useFilterValues } from '../../hooks/useFilterValues'\nimport { useDebounce } from '../../hooks/useDebounce'\n\nconst CloseIcon = getIcon('close')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface FilterConfigModalProps {\n /** The filter being edited */\n filter: SimpleFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when user saves changes */\n onSave: (filter: SimpleFilter) => void\n /** Callback when user cancels */\n onCancel: () => void\n /** Element to position the modal near */\n anchorElement?: HTMLElement | null\n}\n\nexport default function FilterConfigModal({\n filter: initialFilter,\n schema,\n onSave,\n onCancel,\n anchorElement\n}: FilterConfigModalProps) {\n const [filter, setFilter] = useState<SimpleFilter>(initialFilter)\n const [isOperatorDropdownOpen, setIsOperatorDropdownOpen] = useState(false)\n const [isValueDropdownOpen, setIsValueDropdownOpen] = useState(false)\n const [isDateRangeDropdownOpen, setIsDateRangeDropdownOpen] = useState(false)\n const [rangeType, setRangeType] = useState<DateRangeType>('this_month')\n const [numberValue, setNumberValue] = useState(1)\n const [searchText, setSearchText] = useState('')\n const [modalPosition, setModalPosition] = useState<{ top?: number; bottom?: number; left: number } | null>(null)\n const [highlightedIndex, setHighlightedIndex] = useState(-1)\n const containerRef = useRef<HTMLDivElement>(null)\n const valueListRef = useRef<HTMLDivElement>(null)\n\n // Debounce search text for API calls\n const debouncedSearchText = useDebounce(searchText, 300)\n\n // Get field info\n const fieldInfo = findFieldInSchema(filter.member, schema)\n const fieldType = fieldInfo?.field.type || 'string'\n const isTimeField = fieldType === 'time'\n const isMeasureField = fieldInfo?.fieldType === 'measure'\n const isDimensionField = fieldInfo?.fieldType === 'dimension'\n\n // Get display title for field\n const fieldTitle = getFieldTitle(filter.member, schema)\n\n // Get operator metadata\n const operatorMeta = FILTER_OPERATORS[filter.operator as FilterOperator]\n\n // Get available operators for this field type\n const availableOperators = getAvailableOperators(fieldType)\n\n // Should show date range selector\n const shouldShowDateRange = isTimeField && filter.operator === 'inDateRange'\n\n // Should use combo box for value selection\n const shouldShowComboBox = useCallback(() => {\n const comboOperators = ['equals', 'notEquals', 'in', 'notIn']\n return comboOperators.includes(filter.operator) && isDimensionField && !isTimeField\n }, [filter.operator, isDimensionField, isTimeField])()\n\n // Fetch distinct values for combo box\n const {\n values: distinctValues,\n loading: valuesLoading,\n error: valuesError,\n searchValues\n } = useFilterValues(filter.member, shouldShowComboBox)\n\n // Calculate modal position relative to anchor element\n useEffect(() => {\n if (!anchorElement) {\n setModalPosition(null)\n return\n }\n\n const rect = anchorElement.getBoundingClientRect()\n const modalHeight = 500 // Approximate modal height\n const spaceAbove = rect.top\n const spaceBelow = window.innerHeight - rect.bottom\n const modalWidth = 400 // Modal max-width\n\n // Determine if modal should appear above or below\n const shouldAppearAbove = spaceAbove > modalHeight || spaceAbove > spaceBelow\n\n // Calculate left position (try to align with anchor, but keep within viewport)\n const left = Math.max(16, Math.min(rect.left, window.innerWidth - modalWidth - 16))\n\n if (shouldAppearAbove) {\n // Position above the anchor\n setModalPosition({\n bottom: window.innerHeight - rect.top + 8,\n left\n })\n } else {\n // Position below the anchor\n setModalPosition({\n top: rect.bottom + 8,\n left\n })\n }\n }, [anchorElement])\n\n // Close dropdowns when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n }\n }\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n\n // Load values when dropdown opens\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues) {\n searchValues('', true)\n }\n // Reset highlighted index when dropdown opens/closes\n if (!isValueDropdownOpen) {\n setHighlightedIndex(-1)\n }\n }, [isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Scroll highlighted item into view\n useEffect(() => {\n if (highlightedIndex >= 0 && valueListRef.current) {\n const highlightedElement = valueListRef.current.children[highlightedIndex] as HTMLElement\n if (highlightedElement) {\n highlightedElement.scrollIntoView({ block: 'nearest' })\n }\n }\n }, [highlightedIndex])\n\n // Search when debounced text changes\n useEffect(() => {\n if (isValueDropdownOpen && shouldShowComboBox && searchValues && debouncedSearchText !== undefined) {\n searchValues(debouncedSearchText)\n }\n }, [debouncedSearchText, isValueDropdownOpen, shouldShowComboBox, searchValues])\n\n // Sync rangeType state with filter.dateRange\n useEffect(() => {\n if (!shouldShowDateRange || !filter.dateRange) return\n\n if (Array.isArray(filter.dateRange)) {\n setRangeType('custom')\n } else {\n // Find matching range type - prioritize \"last N\" patterns\n // Match \"last N days/weeks/months/quarters/years\"\n const flexMatch = filter.dateRange.match(/^last (\\d+) (days|weeks|months|quarters|years)$/)\n // Match singular forms: \"last day/week/month/quarter/year\" (when N=1)\n const singularMatch = !flexMatch && filter.dateRange.match(/^last (day|week|month|quarter|year)$/)\n\n if (flexMatch) {\n const [, num, unit] = flexMatch\n setRangeType(`last_n_${unit}` as DateRangeType)\n setNumberValue(parseInt(num) || 1)\n } else if (singularMatch) {\n // Handle singular forms as \"last_n_*\" with value of 1\n const [, unit] = singularMatch\n const pluralUnit = unit === 'day' ? 'days' :\n unit === 'week' ? 'weeks' :\n unit === 'month' ? 'months' :\n unit === 'quarter' ? 'quarters' : 'years'\n setRangeType(`last_n_${pluralUnit}` as DateRangeType)\n setNumberValue(1)\n } else {\n // Check predefined ranges (only if not a \"last N\" pattern)\n let found = false\n for (const option of DATE_RANGE_OPTIONS) {\n if (option.value !== 'custom' && !requiresNumberInput(option.value)) {\n if (convertDateRangeTypeToValue(option.value) === filter.dateRange) {\n setRangeType(option.value)\n found = true\n break\n }\n }\n }\n if (!found) setRangeType('custom')\n }\n }\n }, [filter.dateRange, shouldShowDateRange])\n\n // Handle operator change\n const handleOperatorChange = useCallback((operator: FilterOperator) => {\n setFilter({\n member: filter.member,\n operator,\n values: []\n })\n setIsOperatorDropdownOpen(false)\n }, [filter.member])\n\n // Handle value selection from combo box\n const handleValueSelect = useCallback((value: unknown, event?: React.MouseEvent | { shiftKey: boolean }) => {\n const isShiftHeld = event?.shiftKey ?? false\n const values = filter.values || []\n\n if (operatorMeta?.supportsMultipleValues) {\n if (values.includes(value)) {\n // Toggle off - remove the value\n setFilter({ ...filter, values: values.filter((v: unknown) => v !== value) })\n } else {\n // Add the value\n setFilter({ ...filter, values: [...values, value] })\n }\n // Close dropdown unless shift is held\n if (!isShiftHeld) {\n setIsValueDropdownOpen(false)\n }\n } else {\n setFilter({ ...filter, values: [value] })\n setIsValueDropdownOpen(false)\n }\n setSearchText('')\n setHighlightedIndex(-1)\n }, [filter, operatorMeta?.supportsMultipleValues])\n\n // Handle value removal\n const handleValueRemove = useCallback((valueToRemove: unknown) => {\n const values = (filter.values || []).filter((v: unknown) => v !== valueToRemove)\n setFilter({ ...filter, values })\n }, [filter])\n\n // Handle keyboard navigation in value dropdown\n const handleValueKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (!isValueDropdownOpen || distinctValues.length === 0) return\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setHighlightedIndex(prev =>\n prev < distinctValues.length - 1 ? prev + 1 : 0\n )\n break\n case 'ArrowUp':\n e.preventDefault()\n setHighlightedIndex(prev =>\n prev > 0 ? prev - 1 : distinctValues.length - 1\n )\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex >= 0 && highlightedIndex < distinctValues.length) {\n handleValueSelect(distinctValues[highlightedIndex], { shiftKey: e.shiftKey })\n }\n break\n case 'Escape':\n e.preventDefault()\n setIsValueDropdownOpen(false)\n setHighlightedIndex(-1)\n break\n }\n }, [isValueDropdownOpen, distinctValues, highlightedIndex, handleValueSelect])\n\n // Handle direct text/number input\n const handleDirectInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operatorMeta?.valueType === 'number') {\n const numValue = parseFloat(value)\n if (!isNaN(numValue)) {\n setFilter({ ...filter, values: [numValue] })\n } else if (value === '' || value === '-') {\n setFilter({ ...filter, values: [] })\n }\n } else {\n setFilter({ ...filter, values: value ? [value] : [] })\n }\n }, [filter, operatorMeta?.valueType])\n\n // Handle between range inputs\n const handleBetweenStartInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = filter.values?.length >= 2 ? filter.values : ['', '']\n const newValues = [!isNaN(value) ? value : '', currentValues[1]].filter(v => v !== '')\n setFilter({ ...filter, values: newValues })\n }, [filter])\n\n const handleBetweenEndInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = parseFloat(e.target.value)\n const currentValues = filter.values?.length >= 2 ? filter.values : ['', '']\n const newValues = [currentValues[0], !isNaN(value) ? value : ''].filter(v => v !== '')\n setFilter({ ...filter, values: newValues })\n }, [filter])\n\n // Handle date input\n const handleDateInput = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setFilter({ ...filter, values: value ? [value] : [] })\n }, [filter])\n\n // Handle date range type change\n const handleRangeTypeChange = useCallback((newRangeType: DateRangeType) => {\n setRangeType(newRangeType)\n setIsDateRangeDropdownOpen(false)\n\n let dateRange: string | string[]\n if (newRangeType === 'custom') {\n const today = new Date().toISOString().split('T')[0]\n dateRange = [today, today]\n } else if (requiresNumberInput(newRangeType)) {\n dateRange = convertDateRangeTypeToValue(newRangeType, numberValue)\n } else {\n dateRange = convertDateRangeTypeToValue(newRangeType)\n }\n\n setFilter({ ...filter, dateRange } as SimpleFilter)\n }, [filter, numberValue])\n\n // Handle number value change for \"last N days/weeks/etc\"\n const handleNumberValueChange = useCallback((value: number) => {\n setNumberValue(value)\n if (requiresNumberInput(rangeType)) {\n const dateRange = convertDateRangeTypeToValue(rangeType, value)\n setFilter({ ...filter, dateRange } as SimpleFilter)\n }\n }, [filter, rangeType])\n\n // Handle custom date range inputs\n const handleCustomStartDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const start = e.target.value\n const currentRange = Array.isArray(filter.dateRange) ? filter.dateRange : [filter.dateRange || '', '']\n const end = currentRange[1] || start\n setFilter({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter])\n\n const handleCustomEndDate = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const end = e.target.value\n const currentRange = Array.isArray(filter.dateRange) ? filter.dateRange : ['', filter.dateRange || '']\n const start = currentRange[0] || end\n setFilter({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter])\n\n // Get current operator label\n const operatorLabel = availableOperators.find(op => op.operator === filter.operator)?.label || filter.operator\n\n // Get current date range label\n const dateRangeLabel = DATE_RANGE_OPTIONS.find(opt => opt.value === rangeType)?.label || 'Select range'\n\n // Get icon for field type\n const FieldIcon = isTimeField ? TimeDimensionIcon : isMeasureField ? MeasureIcon : DimensionIcon\n\n // Render value input based on operator type\n const renderValueInput = () => {\n // No value required for set/notSet\n if (!operatorMeta?.requiresValues) {\n return (\n <div className=\"text-sm text-dc-text-muted italic py-2\">\n No value required\n </div>\n )\n }\n\n // Date range selector for inDateRange on time fields\n if (shouldShowDateRange) {\n return (\n <div className=\"space-y-2\">\n {/* Range type dropdown */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isDateRangeDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n option.value === rangeType ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {option.label}\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Number input for \"last N\" ranges */}\n {requiresNumberInput(rangeType) && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min=\"1\"\n max=\"1000\"\n value={numberValue}\n onChange={(e) => handleNumberValueChange(Math.max(1, parseInt(e.target.value) || 1))}\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text w-20\"\n />\n <span className=\"text-sm text-dc-text-muted\">\n {rangeType.replace('last_n_', '')}\n </span>\n </div>\n )}\n\n {/* Custom date inputs */}\n {rangeType === 'custom' && (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[1] : ''}\n onChange={handleCustomEndDate}\n className=\"flex-1 text-sm border border-dc-border rounded px-2 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )}\n </div>\n )\n }\n\n // Between/notBetween range inputs\n if (filter.operator === 'between' || filter.operator === 'notBetween') {\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-sm text-dc-text-muted\">to</span>\n <input\n type=\"number\"\n value={filter.values?.[1] ?? ''}\n onChange={handleBetweenEndInput}\n placeholder=\"Max\"\n className=\"flex-1 text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n </div>\n )\n }\n\n // Date picker for date operators\n if (operatorMeta?.valueType === 'date') {\n return (\n <input\n type=\"date\"\n value={filter.values?.[0] || ''}\n onChange={handleDateInput}\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Number input\n if (operatorMeta?.valueType === 'number') {\n return (\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter number\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Combo box for equals/notEquals/in/notIn on dimensions\n if (shouldShowComboBox) {\n return (\n <div className=\"space-y-2\">\n {/* Selected values as tags */}\n {filter.values && filter.values.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {filter.values.map((value: unknown, index: number) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 bg-dc-primary/10 text-dc-primary text-sm px-2 py-1 rounded\"\n >\n <span className=\"max-w-[150px] truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-dc-danger\"\n >\n <CloseIcon className=\"w-3.5 h-3.5\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isValueDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-56 overflow-hidden\">\n {/* Search input with keyboard navigation */}\n <div className=\"p-2 border-b border-dc-border\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => {\n setSearchText(e.target.value)\n setHighlightedIndex(-1)\n }}\n onKeyDown={handleValueKeyDown}\n placeholder=\"Search...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div ref={valueListRef} className=\"max-h-40 overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"px-3 py-2 text-sm text-dc-error\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"px-3 py-2 text-sm text-dc-text-muted\">No values found</div>\n ) : (\n distinctValues.map((value, index) => {\n const isSelected = filter.values?.includes(value)\n const isHighlighted = index === highlightedIndex\n return (\n <button\n key={`${value}-${index}`}\n onClick={(e) => handleValueSelect(value, e)}\n className={`w-full text-left px-3 py-2 text-sm transition-colors ${\n isHighlighted\n ? 'bg-dc-surface-hover'\n : ''\n } ${\n isSelected ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text hover:bg-dc-surface-hover'\n }`}\n >\n {String(value)}\n {isSelected && <span className=\"float-right\">✓</span>}\n </button>\n )\n })\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Helper text for multi-select */}\n {operatorMeta?.supportsMultipleValues && (\n <p className=\"text-xs text-dc-text-muted\">\n Hold Shift to select multiple values\n </p>\n )}\n </div>\n )\n }\n\n // Default: text input\n return (\n <input\n type=\"text\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter value...\"\n className=\"w-full text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n />\n )\n }\n\n // Determine modal positioning style\n const getModalStyle = (): React.CSSProperties => {\n if (modalPosition) {\n return {\n position: 'fixed',\n ...modalPosition,\n maxWidth: '400px',\n width: '100%'\n }\n }\n return {}\n }\n\n const modalClassName = modalPosition\n ? 'bg-dc-surface rounded-lg border border-dc-border'\n : 'bg-dc-surface rounded-lg border border-dc-border max-w-md w-full'\n\n return (\n <>\n {/* Modal overlay */}\n <div\n className={`fixed inset-0 bg-dc-overlay z-50 ${modalPosition ? '' : 'flex items-center justify-center p-4'}`}\n onClick={onCancel}\n >\n <div\n ref={containerRef}\n className={modalClassName}\n style={{ ...getModalStyle(), boxShadow: 'var(--dc-shadow-xl)' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-4 border-b border-dc-border\">\n <h2 className=\"text-lg font-semibold text-dc-text\">Edit Filter</h2>\n <button\n onClick={onCancel}\n className=\"p-1 text-dc-text-muted hover:text-dc-text transition-colors\"\n >\n <CloseIcon className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"p-4 space-y-4\">\n {/* Field display */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Field\n </label>\n <div className=\"flex items-center gap-2 p-3 bg-dc-surface-secondary rounded\">\n <FieldIcon className=\"w-5 h-5 text-dc-filter-text\" />\n <span className=\"text-sm font-medium text-dc-text\">{fieldTitle}</span>\n </div>\n </div>\n\n {/* Operator selector */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Operator\n </label>\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-sm border border-dc-border rounded px-3 py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`w-4 h-4 text-dc-text-muted shrink-0 ml-2 transition-transform ${\n isOperatorDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"absolute z-[60] left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-dc-surface-hover ${\n op.operator === filter.operator ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {op.label}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Value input */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text-secondary mb-2\">\n Value\n </label>\n {renderValueInput()}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-2 p-4 border-t border-dc-border\">\n <button\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-dc-text-secondary hover:text-dc-text transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={() => onSave(filter)}\n className=\"px-4 py-2 text-sm font-medium text-dc-primary-content bg-dc-primary hover:bg-dc-primary-hover rounded transition-colors\"\n >\n Save\n </button>\n </div>\n </div>\n </div>\n </>\n )\n}\n","/**\n * AnalysisFilterItem Component\n *\n * Compact filter chip for the AnalysisBuilder's narrow column layout.\n * Displays filter as a chip with icon, field name, operator, and value.\n * Clicking the chip opens a modal for editing the filter configuration.\n */\n\nimport { useState, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport type { SimpleFilter } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\nimport { FILTER_OPERATORS } from '../../shared/types'\nimport { getFieldTitle, findFieldInSchema } from './utils'\nimport FilterConfigModal from './FilterConfigModal'\n\nconst CloseIcon = getIcon('close')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface AnalysisFilterItemProps {\n /** The filter to display */\n filter: SimpleFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback to remove this filter */\n onRemove: () => void\n /** Callback to update this filter */\n onUpdate: (filter: SimpleFilter) => void\n}\n\nexport default function AnalysisFilterItem({\n filter,\n schema,\n onRemove,\n onUpdate\n}: AnalysisFilterItemProps) {\n const [isModalOpen, setIsModalOpen] = useState(false)\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Get field info to determine icon\n const fieldInfo = findFieldInSchema(filter.member, schema)\n const fieldType = fieldInfo?.field.type || 'string'\n const isTimeField = fieldType === 'time'\n const isMeasureField = fieldInfo?.fieldType === 'measure'\n\n // Get display title for field\n const fieldTitle = getFieldTitle(filter.member, schema)\n\n // Get operator metadata\n const operatorMeta = FILTER_OPERATORS[filter.operator]\n const operatorLabel = operatorMeta?.label || filter.operator\n\n // Format value display\n const valueDisplay = formatValueDisplay(filter, operatorMeta)\n\n // Get appropriate icon and colors based on field type\n const FieldIcon = isTimeField ? TimeDimensionIcon : isMeasureField ? MeasureIcon : DimensionIcon\n const iconBgClass = isTimeField ? 'bg-dc-time-dimension' : isMeasureField ? 'bg-dc-measure' : 'bg-dc-dimension'\n const iconTextClass = isTimeField ? 'text-dc-time-dimension-text' : isMeasureField ? 'text-dc-measure-text' : 'text-dc-dimension-text'\n\n return (\n <>\n <div\n className=\"flex items-start gap-2 px-2 py-1.5 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-all duration-150 w-full\"\n >\n {/* Field type icon with appropriate background color */}\n <span className={`w-6 h-6 flex items-center justify-center rounded ${iconBgClass} ${iconTextClass} flex-shrink-0 mt-0.5`}>\n {FieldIcon && <FieldIcon className=\"w-4 h-4\" />}\n </span>\n\n {/* Filter description - clickable to edit */}\n <button\n ref={buttonRef}\n onClick={() => setIsModalOpen(true)}\n className=\"flex-1 min-w-0 text-left\"\n title={`${fieldTitle} ${operatorLabel} ${valueDisplay}`}\n >\n <div className=\"text-sm text-dc-text break-words\">\n <span className=\"font-medium\">{fieldTitle}</span>\n <span className=\"text-dc-text-muted mx-1\">{operatorLabel}</span>\n <span className=\"text-dc-primary\">{valueDisplay}</span>\n </div>\n </button>\n\n {/* Remove button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0 mt-0.5\"\n title=\"Remove filter\"\n >\n {CloseIcon && <CloseIcon className=\"w-4 h-4\" />}\n </button>\n </div>\n\n {/* Filter configuration modal */}\n {isModalOpen && (\n <FilterConfigModal\n filter={filter}\n schema={schema}\n onSave={(updatedFilter) => {\n onUpdate(updatedFilter)\n setIsModalOpen(false)\n }}\n onCancel={() => setIsModalOpen(false)}\n anchorElement={buttonRef.current}\n />\n )}\n </>\n )\n}\n\n/**\n * Formats the filter value(s) for display in the chip.\n * Handles various value types and multiple values.\n */\nfunction formatValueDisplay(filter: SimpleFilter, operatorMeta: any): string {\n // No value required for set/notSet operators\n if (!operatorMeta?.requiresValues) {\n return ''\n }\n\n // Handle date range\n if (filter.dateRange) {\n if (Array.isArray(filter.dateRange)) {\n return `${filter.dateRange[0]} to ${filter.dateRange[1]}`\n }\n return filter.dateRange\n }\n\n const values = filter.values || []\n\n // No values selected\n if (values.length === 0) {\n return '(empty)'\n }\n\n // Single value\n if (values.length === 1) {\n return String(values[0])\n }\n\n // Two values\n if (values.length === 2) {\n return `${values[0]}, ${values[1]}`\n }\n\n // More than two values - show first two plus count\n return `${values[0]}, ${values[1]}, +${values.length - 2} more`\n}\n","/**\n * AnalysisFilterGroup Component\n *\n * Renders a group of filters with AND/OR logic.\n * Supports infinite nesting for complex filter conditions.\n * Compact design for the AnalysisBuilder's narrow column.\n */\n\nimport { useState, useRef, useEffect, useCallback } from 'react'\nimport { getIcon } from '../../icons'\nimport type { Filter, SimpleFilter, GroupFilter } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\nimport AnalysisFilterItem from './AnalysisFilterItem'\n\nconst AddIcon = getIcon('add')\nconst CloseIcon = getIcon('close')\n\ninterface AnalysisFilterGroupProps {\n /** The group filter to render */\n group: GroupFilter\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when group changes */\n onUpdate: (group: GroupFilter) => void\n /** Callback to remove this group */\n onRemove: () => void\n /** Callback to add a new filter - receives path relative to this group */\n onAddFilter: (relativePath?: number[]) => void\n /** Depth level for styling */\n depth?: number\n /** Whether to hide the remove button (for top-level groups) */\n hideRemoveButton?: boolean\n}\n\n/**\n * Check if a filter is a simple filter\n */\nfunction isSimpleFilter(filter: Filter): filter is SimpleFilter {\n return 'member' in filter && typeof (filter as SimpleFilter).member === 'string'\n}\n\n/**\n * Check if a filter is a group filter\n */\nfunction isGroupFilter(filter: Filter): filter is GroupFilter {\n return 'type' in filter && ((filter as GroupFilter).type === 'and' || (filter as GroupFilter).type === 'or')\n}\n\nexport default function AnalysisFilterGroup({\n group,\n schema,\n onUpdate,\n onRemove,\n onAddFilter,\n depth = 0,\n hideRemoveButton = false\n}: AnalysisFilterGroupProps) {\n const [isAddMenuOpen, setIsAddMenuOpen] = useState(false)\n const addMenuRef = useRef<HTMLDivElement>(null)\n\n // Close add menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (addMenuRef.current && !addMenuRef.current.contains(event.target as Node)) {\n setIsAddMenuOpen(false)\n }\n }\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [])\n\n // Toggle group type (AND <-> OR)\n const handleToggleType = useCallback(() => {\n const newType = group.type === 'and' ? 'or' : 'and'\n onUpdate({ ...group, type: newType })\n }, [group, onUpdate])\n\n // Update a nested filter at a specific index\n const handleUpdateFilter = useCallback((index: number, newFilter: Filter) => {\n const newFilters = [...group.filters]\n newFilters[index] = newFilter\n onUpdate({ ...group, filters: newFilters })\n }, [group, onUpdate])\n\n // Remove a filter at a specific index\n const handleRemoveFilter = useCallback((index: number) => {\n const newFilters = group.filters.filter((_, i) => i !== index)\n\n // If only one filter remains, we might want to unwrap\n // But for now, just update with remaining filters\n if (newFilters.length === 0) {\n // If group is empty, remove the group itself\n onRemove()\n } else if (newFilters.length === 1 && depth > 0) {\n // Unwrap single-filter groups at non-root level by updating parent\n // This is handled by the parent component\n onUpdate({ ...group, filters: newFilters })\n } else {\n onUpdate({ ...group, filters: newFilters })\n }\n }, [group, onUpdate, onRemove, depth])\n\n // Add a nested group at a specific index\n const handleAddNestedGroup = useCallback((type: 'and' | 'or') => {\n const newGroup: GroupFilter = { type, filters: [] }\n onUpdate({ ...group, filters: [...group.filters, newGroup] })\n setIsAddMenuOpen(false)\n }, [group, onUpdate])\n\n // Handle add filter button - add to this group\n const handleAddFilterClick = useCallback(() => {\n onAddFilter([]) // Empty path means add to this group\n setIsAddMenuOpen(false)\n }, [onAddFilter])\n\n // Create handler for nested group to add filters\n const createNestedAddFilterHandler = useCallback((nestedIndex: number) => {\n return (relativePath: number[] = []) => {\n // Prepend this nested index to the relative path\n onAddFilter([nestedIndex, ...relativePath])\n }\n }, [onAddFilter])\n\n // Get border color based on depth\n const getBorderColor = () => {\n if (depth % 2 === 0) {\n return 'border-dc-border'\n }\n return 'border-dc-border dark:border-dc-border'\n }\n\n // Get background color based on group type\n const getGroupBgColor = () => {\n return group.type === 'and' ? 'bg-dc-info-bg/50' : 'bg-dc-warning-bg/50'\n }\n\n const conditionCount = group.filters.length\n const conditionLabel = conditionCount === 1 ? 'condition' : 'conditions'\n\n return (\n <div className={`border ${getBorderColor()} rounded-lg bg-dc-surface w-full`}>\n {/* Group Header */}\n <div className={`flex items-center justify-between px-2 py-1.5 border-b border-dc-border/50 rounded-t-lg ${getGroupBgColor()}`}>\n <div className=\"flex items-center gap-2\">\n {/* AND/OR Toggle Button */}\n <button\n onClick={handleToggleType}\n className={`px-2 py-0.5 text-xs font-semibold rounded transition-colors ${\n group.type === 'and'\n ? 'bg-dc-info-bg text-dc-info hover:opacity-80'\n : 'bg-dc-warning-bg text-dc-warning hover:opacity-80'\n }`}\n title={`Click to switch to ${group.type === 'and' ? 'OR' : 'AND'}`}\n >\n {group.type.toUpperCase()}\n </button>\n\n {/* Condition Count */}\n <span className=\"text-xs text-dc-text-muted\">\n {conditionCount} {conditionLabel}\n </span>\n </div>\n\n <div className=\"flex items-center gap-1\">\n {/* Add Button with Dropdown */}\n <div className=\"relative\" ref={addMenuRef}>\n <button\n onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-hover rounded transition-colors\"\n title=\"Add condition\"\n >\n <AddIcon className=\"w-4 h-4\" />\n </button>\n\n {isAddMenuOpen && (\n <div className=\"absolute right-0 mt-1 z-40 bg-dc-surface border border-dc-border rounded shadow-lg py-1 min-w-[120px]\">\n <button\n onClick={handleAddFilterClick}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add Filter\n </button>\n <button\n onClick={() => handleAddNestedGroup('and')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add AND Group\n </button>\n <button\n onClick={() => handleAddNestedGroup('or')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add OR Group\n </button>\n </div>\n )}\n </div>\n\n {/* Remove Group Button */}\n {!hideRemoveButton && (\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger transition-colors\"\n title=\"Remove group\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Group Body - Filter List */}\n <div className=\"p-1.5 flex flex-wrap gap-2\">\n {group.filters.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-dc-text-muted mb-1\">No conditions in this group</p>\n <button\n onClick={() => onAddFilter([])}\n className=\"text-xs text-dc-primary hover:underline\"\n >\n Add a filter\n </button>\n </div>\n ) : (\n group.filters.map((filter, index) => {\n if (isSimpleFilter(filter)) {\n return (\n <AnalysisFilterItem\n key={`filter-${index}`}\n filter={filter}\n schema={schema}\n onUpdate={(newFilter) => handleUpdateFilter(index, newFilter)}\n onRemove={() => handleRemoveFilter(index)}\n />\n )\n } else if (isGroupFilter(filter)) {\n return (\n <AnalysisFilterGroup\n key={`group-${index}`}\n group={filter}\n schema={schema}\n onUpdate={(newGroup) => handleUpdateFilter(index, newGroup)}\n onRemove={() => handleRemoveFilter(index)}\n onAddFilter={createNestedAddFilterHandler(index)}\n depth={depth + 1}\n />\n )\n }\n return null\n })\n )}\n </div>\n </div>\n )\n}\n","/**\n * AnalysisFilterSection Component\n *\n * Compact filter section for the AnalysisBuilder's narrow column layout.\n * Renders hierarchical filter structure with AND/OR groups.\n * Uses FieldSearchModal for field selection.\n */\n\nimport { useState, useCallback, useRef, DragEvent } from 'react'\nimport { getIcon } from '../../icons'\nimport SectionHeading from './SectionHeading'\nimport type { Filter, SimpleFilter, GroupFilter } from '../../types'\nimport type { MetaResponse, MetaField } from '../../shared/types'\nimport FieldSearchModal from './FieldSearchModal'\nimport AnalysisFilterItem from './AnalysisFilterItem'\nimport AnalysisFilterGroup from './AnalysisFilterGroup'\nimport { convertDateRangeTypeToValue } from '../../shared/utils'\n\nconst AddIcon = getIcon('add')\n\ninterface AnalysisFilterSectionProps {\n /** Current filters */\n filters: Filter[]\n /** Schema for field metadata */\n schema: MetaResponse | null\n /** Callback when filters change */\n onFiltersChange: (filters: Filter[]) => void\n /** Callback when a field is dropped from another section */\n onFieldDropped?: (field: string) => void\n /** Only allow dimension filters (no measures) - used for funnel step filters */\n dimensionsOnly?: boolean\n}\n\n/**\n * Check if a filter is a simple filter (has member property)\n */\nfunction isSimpleFilter(filter: Filter): filter is SimpleFilter {\n return 'member' in filter && typeof (filter as SimpleFilter).member === 'string'\n}\n\n/**\n * Check if a filter is a group filter\n */\nfunction isGroupFilter(filter: Filter): filter is GroupFilter {\n return 'type' in filter && ((filter as GroupFilter).type === 'and' || (filter as GroupFilter).type === 'or')\n}\n\n/**\n * Count all simple filters in a filter tree\n */\nfunction countFilters(filters: Filter[]): number {\n let count = 0\n for (const filter of filters) {\n if (isSimpleFilter(filter)) {\n count++\n } else if (isGroupFilter(filter)) {\n count += countFilters(filter.filters)\n }\n }\n return count\n}\n\n/**\n * Get all simple filter member names from a filter tree\n */\nfunction getSelectedFields(filters: Filter[]): string[] {\n const fields: string[] = []\n for (const filter of filters) {\n if (isSimpleFilter(filter)) {\n fields.push(filter.member)\n } else if (isGroupFilter(filter)) {\n fields.push(...getSelectedFields(filter.filters))\n }\n }\n return fields\n}\n\n/**\n * Add a filter at a specific path in the filter tree\n * Path is an array of indices, e.g., [0, 2] means filters[0].filters[2]\n */\nfunction addFilterAtPath(filters: Filter[], path: number[], newFilter: SimpleFilter): Filter[] {\n if (path.length === 0) {\n // Add to root level\n if (filters.length === 0) {\n return [newFilter]\n } else if (filters.length === 1 && isSimpleFilter(filters[0])) {\n // Wrap in AND group\n return [{ type: 'and', filters: [filters[0], newFilter] }]\n } else if (filters.length === 1 && isGroupFilter(filters[0])) {\n // Add to existing group\n return [{\n ...filters[0],\n filters: [...filters[0].filters, newFilter]\n }]\n } else {\n // Wrap all in AND group\n return [{ type: 'and', filters: [...filters, newFilter] }]\n }\n }\n\n // Navigate to the target group and add\n const [firstIndex, ...restPath] = path\n const newFilters = [...filters]\n const targetFilter = newFilters[firstIndex]\n\n if (isGroupFilter(targetFilter)) {\n if (restPath.length === 0) {\n // Add to this group\n newFilters[firstIndex] = {\n ...targetFilter,\n filters: [...targetFilter.filters, newFilter]\n }\n } else {\n // Recurse deeper\n newFilters[firstIndex] = {\n ...targetFilter,\n filters: addFilterAtPath(targetFilter.filters, restPath, newFilter)\n }\n }\n }\n\n return newFilters\n}\n\nexport default function AnalysisFilterSection({\n filters,\n schema,\n onFiltersChange,\n onFieldDropped,\n dimensionsOnly = false\n}: AnalysisFilterSectionProps) {\n const [showFieldModal, setShowFieldModal] = useState(false)\n const [isDragOver, setIsDragOver] = useState(false)\n // Track which group we're adding a filter to (path of indices, empty = root)\n const pendingAddPath = useRef<number[]>([])\n\n // Get total filter count for display\n const totalFilterCount = countFilters(filters)\n\n // Handle drag over for drop zone\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(true)\n }, [])\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(false)\n }, [])\n\n const handleDrop = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDragOver(false)\n\n try {\n const data = JSON.parse(e.dataTransfer.getData('text/plain'))\n if (data.field && onFieldDropped) {\n onFieldDropped(data.field)\n }\n } catch {\n // Ignore invalid drop data\n }\n }, [onFieldDropped])\n\n // Get selected field names for the modal\n const selectedFields = getSelectedFields(filters)\n\n // Handle adding a new filter via field selection\n const handleFieldSelected = useCallback(\n (field: MetaField, _fieldType: 'measure' | 'dimension' | 'timeDimension', _cubeName: string) => {\n // Determine default operator based on field type\n const isTime = field.type === 'time'\n const defaultOperator = isTime ? 'inDateRange' : 'equals'\n\n // Create new filter with appropriate defaults\n const newFilter: SimpleFilter = {\n member: field.name,\n operator: defaultOperator,\n values: []\n }\n\n // For time fields with inDateRange, set a default dateRange so the filter is immediately active\n if (isTime && defaultOperator === 'inDateRange') {\n (newFilter as any).dateRange = convertDateRangeTypeToValue('this_month')\n }\n\n // Add filter at the pending path\n const updatedFilters = addFilterAtPath(filters, pendingAddPath.current, newFilter)\n onFiltersChange(updatedFilters)\n\n setShowFieldModal(false)\n pendingAddPath.current = []\n },\n [filters, onFiltersChange]\n )\n\n // Handle updating a top-level filter\n const handleUpdateTopLevelFilter = useCallback(\n (index: number, newFilter: Filter) => {\n const newFilters = [...filters]\n newFilters[index] = newFilter\n onFiltersChange(newFilters)\n },\n [filters, onFiltersChange]\n )\n\n // Handle removing a top-level filter\n const handleRemoveTopLevelFilter = useCallback(\n (index: number) => {\n const newFilters = filters.filter((_, i) => i !== index)\n\n // If we have a single group with one filter, unwrap it\n if (newFilters.length === 1 && isGroupFilter(newFilters[0])) {\n const group = newFilters[0]\n if (group.filters.length === 1) {\n onFiltersChange([group.filters[0]])\n return\n }\n }\n\n onFiltersChange(newFilters)\n },\n [filters, onFiltersChange]\n )\n\n // Handle clearing all filters\n const handleClearAll = useCallback(() => {\n onFiltersChange([])\n }, [onFiltersChange])\n\n // Handle add filter button at root level\n const handleAddFilterClick = useCallback(() => {\n pendingAddPath.current = []\n setShowFieldModal(true)\n }, [])\n\n // Create a handler for adding filters at a specific path\n // The handler receives an optional relativePath from nested groups\n const createAddFilterHandler = useCallback((basePath: number[]) => {\n return (relativePath: number[] = []) => {\n pendingAddPath.current = [...basePath, ...relativePath]\n setShowFieldModal(true)\n }\n }, [])\n\n // Render a single filter (SimpleFilter or GroupFilter)\n const renderFilter = (filter: Filter, index: number, parentPath: number[] = []) => {\n const currentPath = [...parentPath, index]\n\n if (isSimpleFilter(filter)) {\n return (\n <AnalysisFilterItem\n key={`filter-${currentPath.join('-')}`}\n filter={filter}\n schema={schema}\n onUpdate={(newFilter) => handleUpdateTopLevelFilter(index, newFilter)}\n onRemove={() => handleRemoveTopLevelFilter(index)}\n />\n )\n } else if (isGroupFilter(filter)) {\n return (\n <AnalysisFilterGroup\n key={`group-${currentPath.join('-')}`}\n group={filter}\n schema={schema}\n onUpdate={(newGroup) => handleUpdateTopLevelFilter(index, newGroup)}\n onRemove={() => handleRemoveTopLevelFilter(index)}\n onAddFilter={createAddFilterHandler(currentPath)}\n hideRemoveButton={filters.length === 1}\n />\n )\n }\n return null\n }\n\n return (\n <div>\n {/* Header - entire row is clickable to add filter */}\n <button\n onClick={handleAddFilterClick}\n className=\"flex items-center justify-between mb-3 w-full py-1 px-2 -ml-2 rounded-lg hover:bg-dc-primary/10 transition-colors group\"\n title=\"Add filter\"\n >\n <SectionHeading>\n Filter\n {totalFilterCount > 0 && (\n <span className=\"ml-1.5 text-xs font-normal text-dc-text-muted normal-case tracking-normal\">\n ({totalFilterCount})\n </span>\n )}\n </SectionHeading>\n <div className=\"flex items-center gap-2\">\n {totalFilterCount > 0 && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation()\n handleClearAll()\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation()\n handleClearAll()\n }\n }}\n className=\"text-xs text-dc-text-muted hover:text-dc-error underline cursor-pointer\"\n >\n Clear all\n </span>\n )}\n <AddIcon className=\"w-5 h-5 text-dc-text-secondary group-hover:text-dc-primary transition-colors\" />\n </div>\n </button>\n\n {/* Drop Zone Container - Only wraps content, not header */}\n <div\n onDragOver={onFieldDropped ? handleDragOver : undefined}\n onDragLeave={onFieldDropped ? handleDragLeave : undefined}\n onDrop={onFieldDropped ? handleDrop : undefined}\n className={`p-2 -mx-2 rounded-lg border-2 border-dashed transition-all ${\n isDragOver\n ? 'border-dc-primary bg-dc-primary/5'\n : 'border-transparent'\n }`}\n >\n {/* Filter List - Hierarchical Rendering */}\n {filters.length === 0 ? (\n <p className={`text-sm ${isDragOver ? 'text-dc-primary font-medium' : 'text-dc-text-muted'}`}>\n {isDragOver ? 'Drop to add filter' : 'No filters applied'}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {filters.map((filter, index) => renderFilter(filter, index))}\n </div>\n )}\n </div>\n\n {/* Field Search Modal - mode determines which field types to show */}\n <FieldSearchModal\n isOpen={showFieldModal}\n onClose={() => {\n setShowFieldModal(false)\n pendingAddPath.current = []\n }}\n onSelect={handleFieldSelected}\n mode={dimensionsOnly ? 'dimensionFilter' : 'filter'}\n schema={schema}\n selectedFields={selectedFields}\n />\n </div>\n )\n}\n","/**\n * AnalysisAxisDropZone Component\n *\n * A styled version of AxisDropZone that matches the Query Panel card styling.\n * Used in the Analysis Builder's Chart tab for configuring chart axes.\n *\n * Key differences from AxisDropZone:\n * - Vertical card layout instead of inline chips\n * - Two-line display (title + cube name)\n * - Colored icon boxes for measures, plain icons for dimensions\n * - Hidden-on-hover remove buttons\n */\n\nimport { useState, useCallback, useRef, useEffect, DragEvent } from 'react'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\nimport type { AxisDropZoneConfig } from '../../charts/chartConfigs'\n\nconst CloseIcon = getIcon('close')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst MeasureIcon = getIcon('measure')\n\ninterface FieldMeta {\n title?: string\n shortTitle?: string\n cubeName: string\n type: 'measure' | 'dimension' | 'timeDimension'\n measureType?: string\n}\n\ninterface AnalysisAxisDropZoneProps {\n config: AxisDropZoneConfig\n fields: string[]\n onDrop: (e: DragEvent<HTMLDivElement>, toKey: string) => void\n onRemove: (field: string, fromKey: string) => void\n onDragStart: (\n e: DragEvent<HTMLDivElement>,\n field: string,\n fromKey: string,\n fromIndex?: number\n ) => void\n onDragEnd?: (e: DragEvent<HTMLDivElement>) => void\n onDragOver: (e: DragEvent<HTMLDivElement>) => void\n onReorder?: (fromIndex: number, toIndex: number, axisKey: string) => void\n draggedItem?: { field: string; fromAxis: string; fromIndex?: number } | null\n getFieldMeta?: (field: string) => FieldMeta\n // Dual Y-axis support\n yAxisAssignment?: Record<string, 'left' | 'right'>\n onYAxisAssignmentChange?: (field: string, axis: 'left' | 'right') => void\n}\n\nexport default function AnalysisAxisDropZone({\n config,\n fields,\n onDrop,\n onRemove,\n onDragStart,\n onDragEnd,\n onDragOver,\n onReorder,\n draggedItem,\n getFieldMeta,\n yAxisAssignment,\n onYAxisAssignmentChange\n}: AnalysisAxisDropZoneProps) {\n const { key, label, description, mandatory, maxItems, emptyText } = config\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null)\n const [isDraggedOver, setIsDraggedOver] = useState(false)\n const [isReorderDraggedOver, setIsReorderDraggedOver] = useState(false)\n\n // Track the field being dragged from this axis for drag-out-to-remove\n const draggingFieldRef = useRef<string | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n // Keep fields in a ref to avoid stale closure issues\n const fieldsRef = useRef(fields)\n fieldsRef.current = fields\n // Keep dropTargetIndex in a ref to avoid stale closure issues in drop handler\n const dropTargetIndexRef = useRef<number | null>(null)\n\n // Calculate acceptance considering what's being dragged\n const getCanAcceptMore = () => {\n let effectiveCount = fields.length\n\n // If we're dragging FROM this axis, we effectively have one less item\n if (draggedItem && draggedItem.fromAxis === key) {\n effectiveCount = Math.max(0, fields.length - 1)\n }\n\n return !maxItems || effectiveCount < maxItems\n }\n\n const getIsFull = () => {\n let effectiveCount = fields.length\n\n // If we're dragging FROM this axis, we effectively have one less item\n if (draggedItem && draggedItem.fromAxis === key) {\n effectiveCount = Math.max(0, fields.length - 1)\n }\n\n return maxItems && effectiveCount >= maxItems\n }\n\n const canAcceptMore = getCanAcceptMore()\n const isFull = getIsFull()\n\n // Add a global drag end listener to reset visual state\n useEffect(() => {\n const handleGlobalDragEnd = () => {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n draggingFieldRef.current = null\n }\n\n document.addEventListener('dragend', handleGlobalDragEnd)\n return () => {\n document.removeEventListener('dragend', handleGlobalDragEnd)\n }\n }, [])\n\n // Clear states when transitioning between different drag operations\n useEffect(() => {\n if (draggedItem) {\n // If we have a dragged item but it's not from this axis, clear reorder state\n if (draggedItem.fromAxis !== key) {\n setIsReorderDraggedOver(false)\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n }\n // If we have a dragged item from this axis, clear regular drag state\n else if (draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n setIsDraggedOver(false)\n }\n } else {\n // No dragged item, clear all states\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }, [draggedItem, key])\n\n // Handle drag over an item - determine drop position based on mouse position\n const handleItemDragOver = useCallback((e: DragEvent<HTMLDivElement>, itemIndex: number) => {\n // Check if this is a reorder operation (same axis)\n if (!draggedItem || draggedItem.fromAxis !== key || draggedItem.fromIndex === undefined) return\n\n e.preventDefault()\n e.stopPropagation()\n\n // Determine if we're in the top or bottom half of the item\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseY = e.clientY - rect.top\n const isTopHalf = mouseY < rect.height / 2\n\n // Calculate target index based on position\n const fromIndex = draggedItem.fromIndex\n let targetIndex = isTopHalf ? itemIndex : itemIndex + 1\n\n // Don't set drop target if it would result in no movement\n if (targetIndex === fromIndex || targetIndex === fromIndex + 1) {\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n } else {\n setDropTargetIndex(targetIndex)\n dropTargetIndexRef.current = targetIndex\n setIsReorderDraggedOver(true)\n }\n }, [draggedItem, key])\n\n // Handle drop on an item for reordering\n const handleItemDrop = useCallback((e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n // DON'T stopPropagation here yet - only stop if this is a reorder operation\n\n // Use ref to get current dropTargetIndex (avoids stale closure)\n const currentDropTargetIndex = dropTargetIndexRef.current\n\n // Check if this is a reorder operation (same axis with valid indices)\n const isReorderOperation = draggedItem &&\n draggedItem.fromAxis === key &&\n draggedItem.fromIndex !== undefined &&\n currentDropTargetIndex !== null\n\n if (!isReorderOperation) {\n // Let the event bubble up to container for external drops\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n return // Don't stop propagation - container will handle external drops\n }\n\n // This IS a reorder operation - stop propagation and handle it\n e.stopPropagation()\n\n // Adjust target index when dragging down (after splice, indices shift)\n const fromIndex = draggedItem!.fromIndex!\n const adjustedTarget = currentDropTargetIndex > fromIndex\n ? currentDropTargetIndex - 1\n : currentDropTargetIndex\n\n if (onReorder && adjustedTarget !== fromIndex) {\n onReorder(fromIndex, adjustedTarget, key)\n }\n\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n }, [draggedItem, key, onReorder])\n\n // Handle drag end - check if dropped outside container to remove\n const handleFieldDragEnd = useCallback((e: DragEvent<HTMLDivElement>, field: string) => {\n const container = containerRef.current\n if (container && draggingFieldRef.current === field) {\n const rect = container.getBoundingClientRect()\n const isInside =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom\n\n // If dropped outside the container\n if (!isInside) {\n // Use a small delay to let other drop handlers fire first\n // Then check if the field is still in this axis (wasn't moved elsewhere)\n setTimeout(() => {\n // Check using ref to get current fields, avoiding stale closure\n if (fieldsRef.current.includes(field)) {\n onRemove(field, key)\n }\n }, 0)\n }\n }\n\n draggingFieldRef.current = null\n setDropTargetIndex(null)\n dropTargetIndexRef.current = null\n setIsReorderDraggedOver(false)\n\n onDragEnd?.(e)\n }, [key, onRemove, onDragEnd])\n\n // Calculate transform for gap animation\n const getItemTransform = useCallback((itemIndex: number): string => {\n if (!draggedItem || draggedItem.fromAxis !== key || draggedItem.fromIndex === undefined || dropTargetIndex === null) {\n return ''\n }\n\n const fromIndex = draggedItem.fromIndex\n const gapSize = 40\n\n // If this is the dragged item, no transform needed\n if (itemIndex === fromIndex) return ''\n\n if (fromIndex < dropTargetIndex) {\n // Dragging down\n if (itemIndex >= dropTargetIndex) {\n return `translateY(${gapSize / 2}px)`\n }\n } else {\n // Dragging up\n if (itemIndex >= dropTargetIndex && itemIndex < fromIndex) {\n return `translateY(${gapSize / 2}px)`\n }\n }\n\n return ''\n }, [draggedItem, key, dropTargetIndex])\n\n // Determine if gap indicator should show\n const shouldShowGapIndicator = useCallback((itemIndex: number): boolean => {\n if (!draggedItem || draggedItem.fromAxis !== key || dropTargetIndex === null) return false\n return itemIndex === dropTargetIndex\n }, [draggedItem, key, dropTargetIndex])\n\n // Get default field meta from field name\n const getDefaultFieldMeta = (field: string): FieldMeta => {\n const parts = field.split('.')\n const cubeName = parts[0] || field\n const fieldName = parts[1] || field\n\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: 'dimension' // Default assumption\n }\n }\n\n // Render icon based on field type\n const renderFieldIcon = (meta: FieldMeta) => {\n if (meta.type === 'measure') {\n // Measures get colored icon box with type-specific icon\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n )\n } else if (meta.type === 'timeDimension') {\n // Time dimensions get colored background matching field selector\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-time-dimension text-dc-time-dimension-text flex-shrink-0\">\n <TimeDimensionIcon className=\"w-4 h-4\" />\n </span>\n )\n } else {\n // Regular dimensions get colored background matching field selector\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-dimension text-dc-dimension-text flex-shrink-0\">\n <DimensionIcon className=\"w-4 h-4\" />\n </span>\n )\n }\n }\n\n return (\n <div className=\"mb-3\">\n {/* Header */}\n <div className=\"mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text flex items-center\">\n {label}\n {mandatory && <span className=\"text-dc-error ml-1\">*</span>}\n </h4>\n {description && <div className=\"text-xs text-dc-text-muted mt-0.5\">{description}</div>}\n </div>\n\n {/* Drop Zone Container */}\n <div\n ref={containerRef}\n data-axis-container={key}\n className={`min-h-[48px] border-2 border-dashed rounded-lg p-2 transition-all duration-200 ${\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'shadow-sm border-solid'\n : isFull\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface-secondary hover:bg-dc-surface-hover'\n }`}\n style={{\n borderColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'var(--dc-primary)'\n : 'var(--dc-border)',\n backgroundColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'rgba(var(--dc-primary-rgb), 0.1)'\n : undefined\n }}\n onDragOver={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const canAccept = canAcceptMore || maxItems === 1\n\n if (canAccept) {\n setIsDraggedOver(true)\n onDragOver(e)\n } else {\n e.preventDefault()\n e.dataTransfer.dropEffect = 'none'\n }\n }}\n onDragLeave={(e) => {\n // Check if we're truly leaving the container\n const rect = e.currentTarget.getBoundingClientRect()\n const isLeavingContainer =\n e.clientX < rect.left ||\n e.clientX > rect.right ||\n e.clientY < rect.top ||\n e.clientY > rect.bottom\n\n // Also check if the related target is outside this container\n const relatedTarget = e.relatedTarget as Element | null\n const isRelatedTargetOutside = relatedTarget && !e.currentTarget.contains(relatedTarget)\n\n if (isLeavingContainer || isRelatedTargetOutside || e.currentTarget === e.target) {\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }}\n onDrop={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const shouldAcceptDrop = canAcceptMore || maxItems === 1\n\n if (shouldAcceptDrop) {\n onDrop(e, key)\n } else {\n e.preventDefault()\n }\n\n // Reset drag state on drop\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }}\n >\n {fields.length === 0 ? (\n <div className=\"text-sm text-dc-text-muted text-center py-2\">\n {isFull ? 'Maximum items reached' : emptyText || `Drop fields here`}\n </div>\n ) : (\n <div\n className=\"space-y-2\"\n onDragOver={(e) => {\n // Allow dropping for reorder operations\n if (draggedItem && draggedItem.fromAxis === key) {\n e.preventDefault()\n }\n }}\n onDrop={(e) => {\n // Handle reorder drops at container level\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n handleItemDrop(e)\n }\n }}\n >\n {fields.map((field, index) => {\n const meta = getFieldMeta ? getFieldMeta(field) : getDefaultFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === key\n const transform = getItemTransform(index)\n const showGapBefore = shouldShowGapIndicator(index)\n\n return (\n <div\n key={`${field}-${index}`}\n className=\"relative\"\n style={{\n transform,\n transition: draggedItem && draggedItem.fromAxis === key ? 'transform 0.15s ease-out' : 'none'\n }}\n >\n {/* Gap indicator line - shows where item will be inserted */}\n {showGapBefore && (\n <div className=\"absolute -top-5 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n )}\n\n <div\n draggable\n onDragStart={(e) => {\n draggingFieldRef.current = field\n onDragStart(e, field, key, index)\n }}\n onDragEnd={(e) => handleFieldDragEnd(e, field)}\n onDragOver={(e) => handleItemDragOver(e, index)}\n onDrop={handleItemDrop}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg group hover:bg-dc-surface-tertiary transition-colors cursor-move ${\n isBeingDragged ? 'opacity-30 cursor-grabbing' : ''\n }`}\n >\n {/* Icon */}\n {renderFieldIcon(meta)}\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={field}>\n {meta.shortTitle || meta.title || field.split('.').pop()}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n\n {/* L/R Axis Toggle - only for yAxis with dual axis enabled */}\n {config.enableDualAxis && onYAxisAssignmentChange && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n const currentAxis = yAxisAssignment?.[field] || 'left'\n onYAxisAssignmentChange(field, currentAxis === 'left' ? 'right' : 'left')\n }}\n className={`px-1.5 py-0.5 text-xs font-medium rounded transition-colors flex-shrink-0 ${\n (yAxisAssignment?.[field] || 'left') === 'left'\n ? 'bg-dc-info-bg text-dc-info hover:opacity-80'\n : 'bg-dc-accent-bg text-dc-accent hover:opacity-80'\n }`}\n title={`Y-Axis: ${(yAxisAssignment?.[field] || 'left') === 'left' ? 'Left' : 'Right'} (click to toggle)`}\n >\n {(yAxisAssignment?.[field] || 'left') === 'left' ? 'L' : 'R'}\n </button>\n )}\n\n {/* Remove Button - hidden until hover */}\n <button\n type=\"button\"\n onClick={() => onRemove(field, key)}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title={`Remove from ${label}`}\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n )\n })}\n {/* Gap indicator after the last item - shows when dropping at end */}\n {draggedItem && draggedItem.fromAxis === key && dropTargetIndex === fields.length && (\n <div className=\"relative h-2\">\n <div className=\"absolute top-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10\">\n <div className=\"h-0.5 w-full bg-dc-primary rounded-full\" />\n </div>\n </div>\n )}\n {/* Handle drop at the end of the list for reordering */}\n {draggedItem && draggedItem.fromAxis === key && fields.length > 1 && (\n <div\n className=\"h-6\"\n onDragOver={(e) => {\n if (draggedItem.fromIndex !== undefined) {\n e.preventDefault()\n const lastIndex = fields.length\n if (dropTargetIndexRef.current !== lastIndex && draggedItem.fromIndex !== lastIndex - 1) {\n setDropTargetIndex(lastIndex)\n dropTargetIndexRef.current = lastIndex\n setIsReorderDraggedOver(true)\n }\n }\n }}\n onDrop={handleItemDrop}\n />\n )}\n </div>\n )}\n </div>\n\n {mandatory && fields.length === 0 && (\n <div className=\"text-xs text-dc-error mt-1\">This field is required</div>\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\nimport type { ChartConfigRegistry } from '../charts/chartConfigs'\n\ninterface ChartTypeSelectorProps {\n selectedType: ChartType\n onTypeChange: (type: ChartType) => void\n className?: string\n /** Compact mode for narrow containers - uses 2 columns and constrains width */\n compact?: boolean\n /** Map of chart type availability - when provided, unavailable charts are disabled */\n availability?: ChartAvailabilityMap\n /** Chart types to exclude from the list (e.g., ['funnel'] to hide funnel in query mode) */\n excludeTypes?: ChartType[]\n}\n\n// Chart type display names (defined outside component to avoid recreation)\nconst chartTypeLabels: Record<ChartType, string> = {\n activityGrid: 'Activity Grid',\n area: 'Area Chart',\n bar: 'Bar Chart',\n bubble: 'Bubble Chart',\n funnel: 'Funnel Chart',\n heatmap: 'Heatmap',\n kpiDelta: 'KPI Delta',\n kpiNumber: 'KPI Number',\n kpiText: 'KPI Text',\n line: 'Line Chart',\n markdown: 'Markdown',\n pie: 'Pie Chart',\n radar: 'Radar Chart',\n radialBar: 'Radial Bar Chart',\n retentionCombined: 'Retention Chart',\n retentionHeatmap: 'Retention Matrix',\n sankey: 'Sankey Chart',\n scatter: 'Scatter Plot',\n sunburst: 'Sunburst Chart',\n table: 'Data Table',\n treemap: 'TreeMap'\n}\n\nexport default function ChartTypeSelector({\n selectedType,\n onTypeChange,\n className = '',\n compact = false,\n availability,\n excludeTypes = []\n}: ChartTypeSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [configRegistry, setConfigRegistry] = useState<ChartConfigRegistry | null>(null)\n\n useEffect(() => {\n let isActive = true\n\n import('../charts/chartConfigRegistry')\n .then((module) => {\n if (isActive) {\n setConfigRegistry(module.chartConfigRegistry)\n }\n })\n .catch(() => {\n if (isActive) {\n setConfigRegistry(null)\n }\n })\n\n return () => {\n isActive = false\n }\n }, [])\n\n // Get chart types, filter excluded ones, and sort alphabetically by label\n const chartTypes = (Object.keys(chartTypeLabels) as ChartType[])\n .filter((type) => !excludeTypes.includes(type))\n .sort((a, b) => {\n const labelA = chartTypeLabels[a] || a\n const labelB = chartTypeLabels[b] || b\n return labelA.localeCompare(labelB)\n })\n\n const selectedConfig = configRegistry?.[selectedType]\n const SelectedIcon = selectedConfig?.icon\n const selectedLabel = chartTypeLabels[selectedType]\n\n return (\n <div className={`${className} relative`}>\n {/* Dropdown Button */}\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"w-full flex items-center justify-between px-3 py-2 border border-dc-border rounded-md bg-dc-surface hover:bg-dc-surface-hover focus:outline-hidden focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n >\n <div className=\"flex items-center space-x-2\">\n {SelectedIcon && (\n <SelectedIcon className=\"h-5 w-5 text-dc-text-secondary\" />\n )}\n <span className=\"text-sm font-medium text-dc-text\">{selectedLabel}</span>\n </div>\n <svg\n className={`h-4 w-4 text-dc-text-muted transform transition-transform ${isOpen ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n\n {/* Dropdown Menu - Grid Layout */}\n {isOpen && (\n <div className={`absolute z-10 mt-1 w-full bg-dc-surface border border-dc-border rounded-md shadow-lg max-h-80 overflow-auto ${compact ? '' : 'min-w-max'}`}>\n <div className=\"p-2\">\n <div className={`grid gap-1.5 ${compact ? 'grid-cols-2' : 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-4'}`}>\n {chartTypes.map((type) => {\n const config = configRegistry?.[type]\n const IconComponent = config?.icon\n const label = chartTypeLabels[type]\n const isSelected = selectedType === type\n const description = config?.description\n const useCase = config?.useCase\n\n // Check availability if provided\n const chartAvailability = availability?.[type]\n const isAvailable = chartAvailability?.available ?? true\n const unavailableReason = chartAvailability?.reason\n\n // Build tooltip text - show unavailable reason if not available, otherwise show description\n const tooltipText = !isAvailable && unavailableReason\n ? unavailableReason\n : [description, useCase].filter(Boolean).join('. ')\n\n return (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n if (!isAvailable) return // Don't allow clicking disabled charts\n onTypeChange(type)\n setIsOpen(false)\n }}\n disabled={!isAvailable}\n className={`\n relative p-1.5 rounded border transition-colors duration-150\n text-left group min-h-[30px] flex items-center justify-start\n ${!isAvailable\n ? 'opacity-50 cursor-not-allowed bg-dc-surface'\n : isSelected\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface hover:bg-dc-surface-hover'\n }\n `}\n style={{\n borderColor: isSelected && isAvailable ? 'var(--dc-primary)' : 'var(--dc-border)'\n }}\n title={tooltipText}\n >\n <div className=\"flex items-center space-x-1.5\">\n {/* Icon */}\n {IconComponent && (\n <IconComponent\n className={`h-4 w-4 shrink-0 ${\n !isAvailable\n ? 'text-dc-text-muted'\n : isSelected\n ? 'text-dc-text'\n : 'text-dc-text-secondary'\n }`}\n />\n )}\n\n {/* Chart name */}\n <span className={`text-xs font-medium leading-tight truncate ${\n !isAvailable\n ? 'text-dc-text-muted'\n : isSelected\n ? ''\n : 'text-dc-text'\n }`}\n style={isSelected && isAvailable ? { color: 'var(--dc-primary)' } : undefined}>\n {label}\n </span>\n </div>\n\n {/* Selected indicator - smaller dot */}\n {isSelected && isAvailable && (\n <div className=\"absolute top-0.5 right-0.5\">\n <div className=\"w-1.5 h-1.5 rounded-full\" style={{ backgroundColor: 'var(--dc-primary)' }}></div>\n </div>\n )}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * AnalysisChartConfigPanel Component\n *\n * A single-column chart configuration panel for the AnalysisBuilder.\n * Uses fields from the Query tab (metrics/breakdowns) as available fields.\n * Renders axis drop zones and display options based on chart type.\n */\n\nimport { useMemo, useEffect, useState, useCallback, DragEvent } from 'react'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\nimport SectionHeading from './SectionHeading'\nimport AnalysisAxisDropZone from './AnalysisAxisDropZone'\nimport ChartTypeSelector from '../ChartTypeSelector'\nimport { useChartConfig } from '../../charts/lazyChartConfigRegistry'\nimport type { ChartType, ChartAxisConfig } from '../../types'\nimport type { MetricItem, BreakdownItem } from './types'\nimport type { ChartAvailabilityMap } from '../../shared/chartDefaults'\nimport type { MetaResponse } from '../../shared/types'\n\nconst MeasureIcon = getIcon('measure')\nconst DimensionIcon = getIcon('dimension')\nconst TimeDimensionIcon = getIcon('timeDimension')\n\ninterface AnalysisChartConfigPanelProps {\n chartType: ChartType\n chartConfig: ChartAxisConfig\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n /** Schema metadata for resolving field titles */\n schema?: MetaResponse | null\n /** Map of chart type availability for disabling unavailable chart types */\n chartAvailability?: ChartAvailabilityMap\n onChartTypeChange: (type: ChartType) => void\n onChartConfigChange: (config: ChartAxisConfig) => void\n}\n\nexport default function AnalysisChartConfigPanel({\n chartType,\n chartConfig,\n metrics,\n breakdowns,\n schema,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange\n}: AnalysisChartConfigPanelProps) {\n // Track currently dragging item for immediate state updates\n const [draggedItem, setDraggedItem] = useState<{\n field: string\n fromAxis: string\n fromIndex?: number\n } | null>(null)\n\n // Derive available fields from metrics and breakdowns\n const availableFields = useMemo(\n () => ({\n measures: metrics.map((m) => m.field),\n dimensions: breakdowns.filter((b) => !b.isTimeDimension).map((b) => b.field),\n timeDimensions: breakdowns.filter((b) => b.isTimeDimension).map((b) => b.field)\n }),\n [metrics, breakdowns]\n )\n\n // Get configuration for current chart type\n const { config: chartTypeConfig, loaded: chartConfigLoaded } = useChartConfig(chartType)\n\n // Check if this chart type skips queries\n const shouldSkipQuery = chartTypeConfig.skipQuery === true\n\n // Get fields for each drop zone\n const getFieldsForDropZone = useCallback((key: string): string[] => {\n const value = chartConfig[key as keyof ChartAxisConfig]\n const result = Array.isArray(value)\n ? value\n : typeof value === 'string'\n ? [value]\n : []\n return result\n }, [chartConfig])\n\n // Clean up chart config when available fields change\n useEffect(() => {\n if (!chartConfigLoaded) return\n const allAvailableFields = [\n ...availableFields.dimensions,\n ...availableFields.timeDimensions,\n ...availableFields.measures\n ]\n\n let hasChanges = false\n const newConfig = { ...chartConfig }\n\n // Check each axis and remove fields that are no longer available\n chartTypeConfig.dropZones.forEach((dropZone) => {\n const currentFields = getFieldsForDropZone(dropZone.key)\n const validFields = currentFields.filter((field) => allAvailableFields.includes(field))\n\n if (validFields.length !== currentFields.length) {\n hasChanges = true\n if (validFields.length === 0) {\n // Remove the axis property entirely if no valid fields remain\n delete newConfig[dropZone.key as keyof ChartAxisConfig]\n } else if (dropZone.maxItems === 1) {\n // Single field axis - always store as string\n newConfig[dropZone.key as keyof ChartAxisConfig] = validFields[0] as any\n } else {\n // Multi-field axis - always store as array\n newConfig[dropZone.key as keyof ChartAxisConfig] = validFields as any\n }\n }\n })\n\n if (hasChanges) {\n onChartConfigChange(newConfig)\n }\n }, [availableFields, chartConfig, chartTypeConfig.dropZones, onChartConfigChange, getFieldsForDropZone, chartConfigLoaded])\n\n // Helper to determine field type and styling\n const getFieldType = (field: string): 'dimension' | 'timeDimension' | 'measure' => {\n if (availableFields.measures.includes(field)) return 'measure'\n if (availableFields.timeDimensions.includes(field)) return 'timeDimension'\n return 'dimension'\n }\n\n // Helper to find field metadata from schema\n const findFieldMeta = (fieldName: string) => {\n if (!schema?.cubes) return null\n\n const [cubeName] = fieldName.split('.')\n const cube = schema.cubes.find((c) => c.name === cubeName)\n if (!cube) return null\n\n // Check measures first, then dimensions\n const measure = cube.measures?.find((m) => m.name === fieldName)\n if (measure) return { ...measure, fieldType: 'measure' as const }\n\n const dimension = cube.dimensions?.find((d) => d.name === fieldName)\n if (dimension) return { ...dimension, fieldType: dimension.type === 'time' ? 'timeDimension' as const : 'dimension' as const }\n\n return null\n }\n\n // Get field metadata for display in AnalysisAxisDropZone\n const getFieldMeta = (field: string) => {\n const fieldType = getFieldType(field)\n const parts = field.split('.')\n const cubeName = parts[0] || field\n const fieldName = parts[1] || field\n\n // Look up field metadata from schema\n const schemaMeta = findFieldMeta(field)\n\n // Try to find the field in breakdowns for isTimeDimension flag\n const breakdownItem = breakdowns.find((b) => b.field === field)\n\n if (schemaMeta) {\n return {\n title: schemaMeta.title || fieldName,\n shortTitle: schemaMeta.shortTitle || schemaMeta.title || fieldName,\n cubeName,\n type: schemaMeta.fieldType,\n measureType: schemaMeta.fieldType === 'measure' ? schemaMeta.type : undefined\n }\n }\n\n // Fallback when schema lookup fails\n if (breakdownItem) {\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: breakdownItem.isTimeDimension ? ('timeDimension' as const) : ('dimension' as const)\n }\n }\n\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: fieldType\n }\n }\n\n // Drag and drop handlers\n const handleDragStart = (\n e: DragEvent<HTMLDivElement>,\n field: string,\n fromAxis: string,\n fromIndex?: number\n ) => {\n e.dataTransfer.setData('text/plain', JSON.stringify({ field, fromAxis, fromIndex }))\n setDraggedItem({ field, fromAxis, fromIndex })\n }\n\n const handleDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n }\n\n const handleDragEnd = () => {\n setDraggedItem(null)\n }\n\n const handleDrop = (e: DragEvent<HTMLDivElement>, toAxis: string) => {\n e.preventDefault()\n const data = JSON.parse(e.dataTransfer.getData('text/plain'))\n const { field, fromAxis } = data\n\n const newConfig = { ...chartConfig }\n\n // Remove from old location if moving between axes\n if (fromAxis !== 'available' && fromAxis !== toAxis) {\n const fromValue = newConfig[fromAxis as keyof ChartAxisConfig]\n if (Array.isArray(fromValue)) {\n const filteredValue = fromValue.filter((f) => f !== field)\n if (filteredValue.length === 0) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n } else {\n newConfig[fromAxis as keyof ChartAxisConfig] = filteredValue as any\n }\n } else if (fromValue === field) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n }\n }\n\n // Add to new location\n const toValue = newConfig[toAxis as keyof ChartAxisConfig]\n const dropZoneConfig = chartTypeConfig.dropZones.find((dz) => dz.key === toAxis)\n\n if (dropZoneConfig?.maxItems === 1) {\n // Single field - always store as string\n newConfig[toAxis as keyof ChartAxisConfig] = field as any\n } else {\n // Multiple fields - always store as array\n if (Array.isArray(toValue)) {\n if (!toValue.includes(field)) {\n newConfig[toAxis as keyof ChartAxisConfig] = [...toValue, field] as any\n }\n } else {\n newConfig[toAxis as keyof ChartAxisConfig] = [field] as any\n }\n }\n\n // Apply default yAxisAssignment when adding to yAxis with dual axis enabled\n if (toAxis === 'yAxis' && dropZoneConfig?.enableDualAxis) {\n const currentYAxisFields = Array.isArray(newConfig.yAxis) ? newConfig.yAxis : [field]\n const fieldIndex = currentYAxisFields.indexOf(field)\n // Default: 1st field = left, 2nd field = right, 3rd+ = left\n if (!newConfig.yAxisAssignment?.[field]) {\n newConfig.yAxisAssignment = {\n ...newConfig.yAxisAssignment,\n [field]: fieldIndex === 1 ? 'right' : 'left'\n }\n }\n }\n\n setDraggedItem(null)\n onChartConfigChange(newConfig)\n }\n\n const handleRemoveFromAxis = (field: string, fromAxis: string) => {\n const newConfig = { ...chartConfig }\n const value = newConfig[fromAxis as keyof ChartAxisConfig]\n\n if (Array.isArray(value)) {\n const filteredValue = value.filter((f) => f !== field)\n if (filteredValue.length === 0) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n } else {\n newConfig[fromAxis as keyof ChartAxisConfig] = filteredValue as any\n }\n } else if (value === field) {\n delete newConfig[fromAxis as keyof ChartAxisConfig]\n }\n\n // Clean up yAxisAssignment when removing from yAxis\n if (fromAxis === 'yAxis' && newConfig.yAxisAssignment?.[field]) {\n const { [field]: _removed, ...rest } = newConfig.yAxisAssignment\n newConfig.yAxisAssignment = Object.keys(rest).length > 0 ? rest : undefined\n }\n\n onChartConfigChange(newConfig)\n }\n\n const handleReorder = (fromIndex: number, toIndex: number, axisKey: string) => {\n const newConfig = { ...chartConfig }\n const value = newConfig[axisKey as keyof ChartAxisConfig]\n\n // Only reorder if we have an array with multiple items\n if (Array.isArray(value) && value.length > 1 && fromIndex !== toIndex) {\n const newArray = [...value]\n const [movedItem] = newArray.splice(fromIndex, 1)\n newArray.splice(toIndex, 0, movedItem)\n newConfig[axisKey as keyof ChartAxisConfig] = newArray as any\n\n setDraggedItem(null)\n onChartConfigChange(newConfig)\n }\n }\n\n // Handler for Y-axis assignment changes (dual Y-axis support)\n const handleYAxisAssignmentChange = useCallback(\n (field: string, axis: 'left' | 'right') => {\n onChartConfigChange({\n ...chartConfig,\n yAxisAssignment: {\n ...chartConfig.yAxisAssignment,\n [field]: axis\n }\n })\n },\n [chartConfig, onChartConfigChange]\n )\n\n if (!chartConfigLoaded) {\n return (\n <div className=\"space-y-6\">\n <div>\n <SectionHeading className=\"mb-2\">Chart Type</SectionHeading>\n <ChartTypeSelector\n selectedType={chartType}\n onTypeChange={onChartTypeChange}\n availability={chartAvailability}\n excludeTypes={['funnel', 'sankey', 'sunburst', 'retentionHeatmap', 'retentionCombined']}\n compact\n />\n </div>\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n Loading chart configuration...\n </div>\n </div>\n )\n }\n\n // Get unassigned fields (fields selected in Query tab but not yet assigned to chart axes)\n const getUnassignedFields = () => {\n const assignedFields = new Set<string>()\n chartTypeConfig.dropZones.forEach((dz) => {\n getFieldsForDropZone(dz.key).forEach((field) => assignedFields.add(field))\n })\n\n // Exclude the currently dragged field only if it's being dragged FROM a configured axis\n if (draggedItem && draggedItem.fromAxis !== 'available') {\n assignedFields.add(draggedItem.field)\n }\n\n return {\n dimensions: availableFields.dimensions.filter((f) => !assignedFields.has(f)),\n timeDimensions: availableFields.timeDimensions.filter((f) => !assignedFields.has(f)),\n measures: availableFields.measures.filter((f) => !assignedFields.has(f))\n }\n }\n\n const unassignedFields = getUnassignedFields()\n const hasUnassignedFields =\n unassignedFields.dimensions.length > 0 ||\n unassignedFields.timeDimensions.length > 0 ||\n unassignedFields.measures.length > 0\n\n return (\n <div className=\"space-y-6\">\n {/* Chart Type Selector */}\n <div>\n <SectionHeading className=\"mb-2\">Chart Type</SectionHeading>\n <ChartTypeSelector\n selectedType={chartType}\n onTypeChange={onChartTypeChange}\n availability={chartAvailability}\n excludeTypes={['funnel', 'sankey', 'sunburst', 'retentionHeatmap', 'retentionCombined']}\n compact\n />\n </div>\n\n {/* Chart Axis Configuration - Dynamic Drop Zones */}\n {!shouldSkipQuery && chartTypeConfig.dropZones.length > 0 && (\n <div>\n <SectionHeading className=\"mb-2\">\n Chart Configuration\n </SectionHeading>\n <div className=\"space-y-1\">\n {chartTypeConfig.dropZones.map((dropZone) => (\n <AnalysisAxisDropZone\n key={dropZone.key}\n config={dropZone}\n fields={getFieldsForDropZone(dropZone.key)}\n onDrop={handleDrop}\n onRemove={handleRemoveFromAxis}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onReorder={handleReorder}\n draggedItem={draggedItem}\n getFieldMeta={getFieldMeta}\n yAxisAssignment={chartConfig.yAxisAssignment}\n onYAxisAssignmentChange={\n dropZone.enableDualAxis ? handleYAxisAssignmentChange : undefined\n }\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Unassigned Fields - Show fields from Query tab that haven't been assigned yet */}\n {!shouldSkipQuery && hasUnassignedFields && (\n <div>\n <div className=\"mb-2\">\n <SectionHeading>Unassigned Fields</SectionHeading>\n <div className=\"text-xs text-dc-text-muted mt-0.5\">\n Drag fields to chart axes above\n </div>\n </div>\n <div className=\"border-2 border-dashed border-dc-border rounded-lg p-2 bg-dc-surface-secondary\">\n <div className=\"space-y-2\">\n {/* Measures */}\n {unassignedFields.measures.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-measure text-dc-measure-text flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Dimensions */}\n {unassignedFields.dimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-dimension text-dc-dimension-text flex-shrink-0\">\n <DimensionIcon className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Time Dimensions */}\n {unassignedFields.timeDimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-dc-time-dimension text-dc-time-dimension-text flex-shrink-0\">\n <TimeDimensionIcon className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )}\n\n {/* Help text when no fields are available */}\n {!shouldSkipQuery &&\n availableFields.measures.length === 0 &&\n availableFields.dimensions.length === 0 &&\n availableFields.timeDimensions.length === 0 && (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n <p>Add metrics and breakdowns in the Query tab to configure your chart.</p>\n </div>\n )}\n </div>\n )\n}\n","/**\n * AnalysisDisplayConfigPanel Component\n *\n * A panel for configuring chart display options (legend, grid, tooltip, etc.)\n * Extracted from AnalysisChartConfigPanel to be shown in its own tab.\n */\n\nimport { useState, useCallback, useEffect } from 'react'\nimport SectionHeading from './SectionHeading'\nimport { useChartConfig } from '../../charts/lazyChartConfigRegistry'\nimport type { ChartType, ChartDisplayConfig, ColorPalette, AxisFormatConfig } from '../../types'\nimport { AxisFormatControls } from '../charts/AxisFormatControls'\n\ninterface AnalysisDisplayConfigPanelProps {\n chartType: ChartType\n displayConfig: ChartDisplayConfig\n colorPalette?: ColorPalette\n onDisplayConfigChange: (config: ChartDisplayConfig) => void\n}\n\n/**\n * StringArrayInput - A textarea that edits an array of strings\n * Uses local state while editing and only updates on blur\n */\nfunction StringArrayInput({\n label,\n value,\n onChange,\n placeholder,\n description,\n}: {\n label: string\n value: string[]\n onChange: (value: string[]) => void\n placeholder?: string\n description?: string\n}) {\n // Local state for textarea editing\n const [localText, setLocalText] = useState(() => value.join('\\n'))\n\n // Sync local state when external value changes (e.g., from undo/redo or load)\n useEffect(() => {\n const externalText = value.join('\\n')\n setLocalText(externalText)\n }, [value])\n\n const handleBlur = useCallback(() => {\n // Convert text to array, filtering empty strings\n const arrayValue = localText\n .split('\\n')\n .map(s => s.trim())\n .filter(s => s.length > 0)\n onChange(arrayValue)\n }, [localText, onChange])\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{label}</label>\n <textarea\n value={localText}\n onChange={(e) => setLocalText(e.target.value)}\n onBlur={handleBlur}\n placeholder={placeholder}\n rows={4}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text resize-y\"\n />\n {description && (\n <p className=\"text-xs text-dc-text-muted\">{description}</p>\n )}\n </div>\n )\n}\n\nexport default function AnalysisDisplayConfigPanel({\n chartType,\n displayConfig,\n colorPalette,\n onDisplayConfigChange\n}: AnalysisDisplayConfigPanelProps) {\n // Get configuration for current chart type\n const { config: chartTypeConfig, loaded: chartConfigLoaded } = useChartConfig(chartType)\n\n if (!chartConfigLoaded) {\n return (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n Loading display options...\n </div>\n )\n }\n\n // Check if we have any display options to show\n const hasDisplayOptions =\n (chartTypeConfig.displayOptions && chartTypeConfig.displayOptions.length > 0) ||\n (chartTypeConfig.displayOptionsConfig && chartTypeConfig.displayOptionsConfig.length > 0)\n\n if (!hasDisplayOptions) {\n return (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n <p>No display options available for this chart type.</p>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-6\">\n <div>\n <SectionHeading className=\"mb-2\">Display Options</SectionHeading>\n <div className=\"space-y-2\">\n {/* Backward compatibility: Simple boolean display options */}\n {chartTypeConfig.displayOptions?.includes('showLegend') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showLegend ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showLegend: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Legend</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showGrid') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showGrid ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showGrid: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Grid</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showTooltip') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showTooltip ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showTooltip: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Tooltip</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('stacked') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.stacked ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n stacked: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Stacked</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('hideHeader') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.hideHeader ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n hideHeader: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Hide Header</span>\n </label>\n )}\n\n {/* New structured display options */}\n {chartTypeConfig.displayOptionsConfig?.map((option) => (\n <div key={option.key} className={`space-y-1 ${option.type === 'axisFormat' ? 'mt-6 pt-2' : ''}`}>\n {option.type === 'boolean' && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={\n (displayConfig[option.key as keyof ChartDisplayConfig] as boolean) ??\n option.defaultValue ??\n false\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-dc-accent\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">{option.label}</span>\n </label>\n )}\n\n {option.type === 'string' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">\n {option.label}\n {option.key === 'content' && (\n <span className=\"text-xs text-dc-text-muted ml-1\">\n (only headers, lists and links)\n </span>\n )}\n </label>\n {option.key === 'content' ? (\n <textarea\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n rows={8}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent font-mono resize-y bg-dc-surface text-dc-text\"\n />\n ) : (\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n )}\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'paletteColor' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex flex-wrap gap-2\">\n {colorPalette?.colors.map((color, index) => {\n const isSelected =\n ((displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0) === index\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: index\n })\n }\n className={`w-8 h-8 rounded border-2 transition-all duration-200 hover:scale-110 focus:outline-hidden focus:ring-2 focus:ring-dc-accent focus:ring-offset-1 ${\n isSelected\n ? 'ring-2 ring-offset-1 scale-110'\n : 'hover:border-dc-text-muted'\n }`}\n style={{\n backgroundColor: color,\n borderColor: isSelected ? 'var(--dc-primary)' : 'var(--dc-border)'\n }}\n title={`Color ${index + 1}: ${color}`}\n />\n )\n }) || [\n // Fallback if no palette available\n <button\n key={0}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: 0\n })\n }\n className=\"w-8 h-8 rounded-sm border-2 ring-2 ring-offset-1\"\n style={{\n backgroundColor: '#8884d8',\n borderColor: 'var(--dc-primary)',\n boxShadow: '0 0 0 2px var(--dc-primary)'\n }}\n title=\"Default Color\"\n />\n ]}\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'number' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <input\n type=\"number\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value === '' ? undefined : Number(e.target.value)\n })\n }\n placeholder={option.placeholder}\n min={option.min}\n max={option.max}\n step={option.step}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'select' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <select\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n >\n {option.options?.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'color' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"color\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-12 h-8 border border-dc-border rounded-sm cursor-pointer\"\n />\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder || '#8884d8'}\n className=\"flex-1 px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-dc-accent focus:border-dc-accent bg-dc-surface text-dc-text\"\n />\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'axisFormat' && (\n <AxisFormatControls\n axisLabel={option.label}\n value={(displayConfig[option.key as keyof ChartDisplayConfig] as AxisFormatConfig) || {}}\n onChange={(config) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: Object.keys(config).length > 0 ? config : undefined\n })\n }\n />\n )}\n\n {option.type === 'stringArray' && (\n <StringArrayInput\n label={option.label}\n value={(displayConfig[option.key as keyof ChartDisplayConfig] as string[]) ?? []}\n onChange={(arrayValue) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: arrayValue.length > 0 ? arrayValue : undefined\n })\n }\n placeholder={option.placeholder}\n description={option.description}\n />\n )}\n\n {option.type === 'buttonGroup' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex border border-dc-border rounded-sm overflow-hidden\">\n {option.options?.map((opt) => {\n const isSelected = (displayConfig[option.key as keyof ChartDisplayConfig] ?? option.defaultValue) === opt.value\n return (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: opt.value\n })\n }\n className={`flex-1 px-3 py-1.5 text-sm font-medium transition-colors ${\n isSelected\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface text-dc-text hover:bg-dc-border'\n }`}\n >\n {opt.label}\n </button>\n )\n })}\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n}\n","/**\n * FunnelBindingKeySelector Component\n *\n * Dimension picker for selecting the binding key that links funnel steps together.\n * The binding key is typically a user ID, session ID, or order ID that exists\n * across all cubes in the funnel.\n */\n\nimport React, { memo, useMemo, useCallback, useState, useRef, useEffect } from 'react'\nimport type { CubeMeta, FunnelBindingKey } from '../../types'\nimport { getIcon } from '../../icons'\nimport { getAvailableBindingKeyDimensions, getBindingKeyLabel } from '../../utils/funnelValidation'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst CheckIcon = getIcon('check')\nconst SearchIcon = getIcon('search')\n\nexport interface FunnelBindingKeySelectorProps {\n /** Current binding key value */\n bindingKey: FunnelBindingKey | null\n /** Callback when binding key changes */\n onChange: (bindingKey: FunnelBindingKey | null) => void\n /** Cube metadata for available dimensions */\n schema: CubeMeta | null\n /** Whether the selector is disabled */\n disabled?: boolean\n /** Optional class name */\n className?: string\n}\n\n/**\n * FunnelBindingKeySelector allows users to select a dimension that links\n * funnel steps together. It shows available dimensions from all cubes\n * and supports search filtering.\n */\nconst FunnelBindingKeySelector = memo(function FunnelBindingKeySelector({\n bindingKey,\n onChange,\n schema,\n disabled = false,\n className = '',\n}: FunnelBindingKeySelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [searchQuery, setSearchQuery] = useState('')\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Get available dimensions\n const availableDimensions = useMemo(() => {\n return getAvailableBindingKeyDimensions(schema)\n }, [schema])\n\n // Group dimensions by cube\n const groupedDimensions = useMemo(() => {\n const groups: Record<string, typeof availableDimensions> = {}\n for (const dim of availableDimensions) {\n if (!groups[dim.cube]) {\n groups[dim.cube] = []\n }\n groups[dim.cube].push(dim)\n }\n return groups\n }, [availableDimensions])\n\n // Filter dimensions based on search\n const filteredGroups = useMemo(() => {\n if (!searchQuery.trim()) return groupedDimensions\n\n const query = searchQuery.toLowerCase()\n const filtered: Record<string, typeof availableDimensions> = {}\n\n for (const [cube, dims] of Object.entries(groupedDimensions)) {\n const matchingDims = dims.filter(\n (d) =>\n d.label.toLowerCase().includes(query) ||\n d.dimension.toLowerCase().includes(query) ||\n cube.toLowerCase().includes(query)\n )\n if (matchingDims.length > 0) {\n filtered[cube] = matchingDims\n }\n }\n\n return filtered\n }, [groupedDimensions, searchQuery])\n\n // Handle selecting a dimension\n const handleSelect = useCallback(\n (dimension: string) => {\n onChange({ dimension })\n setIsOpen(false)\n setSearchQuery('')\n },\n [onChange]\n )\n\n // Handle clearing the binding key\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n onChange(null)\n },\n [onChange]\n )\n\n // Close dropdown on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n setSearchQuery('')\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n // Focus search input when dropdown opens\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n // Check if a dimension is currently selected\n const isSelected = useCallback(\n (dimension: string) => {\n if (!bindingKey) return false\n if (typeof bindingKey.dimension === 'string') {\n return bindingKey.dimension === dimension\n }\n return bindingKey.dimension.some((m) => m.dimension === dimension)\n },\n [bindingKey]\n )\n\n const label = getBindingKeyLabel(bindingKey)\n const hasSelection = bindingKey?.dimension !== null && bindingKey?.dimension !== undefined\n\n return (\n <div className={className}>\n <div ref={dropdownRef} className=\"relative\">\n {/* Trigger Button - compact to match select dropdown */}\n <button\n type=\"button\"\n onClick={() => !disabled && setIsOpen(!isOpen)}\n disabled={disabled}\n className={`\n flex items-center justify-between w-full px-2 py-1 text-xs\n bg-dc-surface border border-dc-border rounded\n transition-colors\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-dc-primary cursor-pointer'}\n ${isOpen ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`truncate ${hasSelection ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {label}\n </span>\n <span className=\"flex items-center gap-1\">\n {hasSelection && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={handleClear}\n onKeyDown={(e) => e.key === 'Enter' && handleClear(e as unknown as React.MouseEvent)}\n className=\"p-0.5 rounded hover:bg-dc-surface-hover text-dc-text-muted hover:text-dc-text\"\n title=\"Clear binding key\"\n >\n ×\n </span>\n )}\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${isOpen ? 'rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"absolute z-50 mt-1 right-0 w-[280px] bg-dc-surface border border-dc-border rounded-md shadow-lg\">\n {/* Search Input */}\n <div className=\"p-2 border-b border-dc-border\">\n <div className=\"relative\">\n {SearchIcon && (\n <SearchIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-dc-text-muted\" />\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search dimensions...\"\n className=\"w-full pl-8 pr-3 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text placeholder:text-dc-text-muted focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Dimension List */}\n <div className=\"max-h-64 overflow-y-auto p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"px-3 py-4 text-sm text-dc-text-muted text-center\">\n No matching dimensions found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"mb-2 last:mb-0\">\n {/* Cube Header */}\n <div className=\"px-2 py-1 text-xs font-medium text-dc-text-muted uppercase tracking-wide\">\n {cubeName}\n </div>\n {/* Dimensions */}\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n rounded transition-colors\n ${isSelected(dim.dimension)\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{dim.label}</span>\n {isSelected(dim.dimension) && CheckIcon && (\n <CheckIcon className=\"w-4 h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n Select a dimension that identifies entities across funnel steps (e.g., user ID, order ID)\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\nexport default FunnelBindingKeySelector\n","/**\n * AnalysisTypeSelector Component\n *\n * Displays a horizontal button group for selecting analysis type:\n * - Query: Single query analysis\n * - Multi: Multiple queries with merge/concat\n * - Funnel: Funnel analysis with sequential steps\n */\n\nimport React, { memo, useMemo } from 'react'\nimport type { AnalysisType, CubeMeta } from '../../types'\nimport { getIcon } from '../../icons'\n\nconst ChartBarIcon = getIcon('chartBar')\nconst ChartFunnelIcon = getIcon('chartFunnel')\nconst ChartSankeyIcon = getIcon('chartSankey')\nconst ChartRetentionIcon = getIcon('chartRetention')\n\ninterface AnalysisTypeSelectorProps {\n /** Currently selected analysis type */\n value: AnalysisType\n /** Called when analysis type changes */\n onChange: (type: AnalysisType) => void\n /** Disable the selector */\n disabled?: boolean\n /** Cube metadata for eventStream detection */\n schema?: CubeMeta | null\n}\n\ninterface TypeOption {\n type: AnalysisType\n label: string\n description: string\n icon: React.ComponentType<{ className?: string }>\n}\n\nconst typeOptions: TypeOption[] = [\n {\n type: 'query',\n label: 'Query',\n description: 'Standard analysis (single or multi-query)',\n icon: ChartBarIcon,\n },\n {\n type: 'funnel',\n label: 'Funnel',\n description: 'Sequential conversion analysis',\n icon: ChartFunnelIcon,\n },\n {\n type: 'flow',\n label: 'Flow',\n description: 'Bidirectional path analysis with Sankey visualization',\n icon: ChartSankeyIcon,\n },\n {\n type: 'retention',\n label: 'Retention',\n description: 'Cohort-based retention analysis over time periods',\n icon: ChartRetentionIcon,\n },\n]\n\n/**\n * AnalysisTypeSelector - Horizontal tabs for analysis type selection\n */\nconst AnalysisTypeSelector = memo(function AnalysisTypeSelector({\n value,\n onChange,\n disabled = false,\n schema,\n}: AnalysisTypeSelectorProps) {\n // Check if any cubes have eventStream metadata\n const hasEventStreamCubes = useMemo(() => {\n return schema?.cubes?.some((cube) => cube.meta?.eventStream) ?? false\n }, [schema])\n\n // Filter type options - event-based modes require eventStream cubes\n const availableOptions = useMemo(() => {\n return typeOptions.filter((option) => {\n // Query mode is always available\n if (option.type === 'query') return true\n // Event-based modes (funnel, flow, retention) require eventStream cubes\n return hasEventStreamCubes\n })\n }, [hasEventStreamCubes])\n\n return (\n <div className=\"flex items-center gap-0.5 p-1.5 border-b border-dc-border bg-dc-surface\">\n {availableOptions.map((option) => {\n const isSelected = value === option.type\n const Icon = option.icon\n\n return (\n <button\n key={option.type}\n onClick={() => !disabled && onChange(option.type)}\n disabled={disabled}\n title={option.description}\n className={`\n flex items-center gap-1 px-2 py-1.5 rounded-md text-sm font-medium\n transition-colors duration-150\n ${\n isSelected\n ? 'bg-dc-primary/10 text-dc-primary border border-dc-primary/30'\n : 'text-dc-text-secondary hover:bg-dc-bg-secondary hover:text-dc-text border border-transparent'\n }\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}\n `}\n >\n <Icon className=\"h-4 w-4 flex-shrink-0\" />\n <span className=\"truncate\">{option.label}</span>\n </button>\n )\n })}\n </div>\n )\n})\n\nexport default AnalysisTypeSelector\n","/**\n * FunnelConfigPanel Component\n *\n * Configuration panel for funnel settings:\n * - Cube selector (only cubes with eventStream metadata)\n * - Binding key selector (filtered by selected cube)\n * - Time dimension selector (filtered by selected cube)\n *\n * The config section is collapsible and auto-collapses once all fields are set.\n */\n\nimport React, { memo, useMemo, useCallback, useState, useRef, useEffect } from 'react'\nimport type { CubeMeta, FunnelBindingKey } from '../../types'\nimport { getIcon } from '../../icons'\nimport { getAvailableBindingKeyDimensions } from '../../utils/funnelValidation'\nimport SectionHeading from './SectionHeading'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst ChevronRightIcon = getIcon('chevronRight')\nconst CheckIcon = getIcon('check')\nconst SearchIcon = getIcon('search')\nconst CubeIcon = getIcon('dimension') // Used for cube selector (no dedicated cube icon)\nconst LinkIcon = getIcon('link') // Used as key icon\nconst TimeDimensionIcon = getIcon('timeDimension') // Used as clock icon\n\nexport interface FunnelConfigPanelProps {\n /** Currently selected cube for this funnel */\n selectedCube: string | null\n /** Current binding key */\n bindingKey: FunnelBindingKey | null\n /** Current time dimension */\n timeDimension: string | null\n /** Cube metadata */\n schema: CubeMeta | null\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Callback when binding key changes */\n onBindingKeyChange: (bindingKey: FunnelBindingKey | null) => void\n /** Callback when time dimension changes */\n onTimeDimensionChange: (dimension: string | null) => void\n}\n\n/**\n * Get available funnel cubes from schema (only those with eventStream metadata)\n */\nfunction getAvailableFunnelCubes(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string // Use cube name as \"dimension\" for DropdownSelector compatibility\n label: string\n eventStream?: { bindingKey: string; timeDimension: string }\n}> {\n if (!schema?.cubes) return []\n\n return schema.cubes\n .filter((cube) => cube.meta?.eventStream) // Only eventStream cubes\n .map((cube) => ({\n cube: cube.name,\n dimension: cube.name, // DropdownSelector uses dimension as value\n label: cube.title || cube.name,\n eventStream: cube.meta?.eventStream as { bindingKey: string; timeDimension: string } | undefined,\n }))\n}\n\n/**\n * Get available time dimensions from schema\n */\nfunction getAvailableTimeDimensions(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n}> {\n if (!schema?.cubes) return []\n\n const timeDimensions: Array<{ cube: string; dimension: string; label: string }> = []\n\n for (const cube of schema.cubes) {\n for (const dim of cube.dimensions || []) {\n if (dim.type === 'time') {\n timeDimensions.push({\n cube: cube.name,\n dimension: dim.name,\n label: dim.shortTitle || dim.title || dim.name.split('.').pop() || dim.name,\n })\n }\n }\n }\n\n return timeDimensions\n}\n\n/**\n * Dropdown selector component for both binding key and time dimension\n */\ninterface DropdownSelectorProps {\n value: string | null\n label: string\n placeholder: string\n icon: React.ComponentType<{ className?: string }> | null\n options: Array<{ cube: string; dimension: string; label: string }>\n onChange: (value: string | null) => void\n helpText: string\n}\n\nconst DropdownSelector = memo(function DropdownSelector({\n value,\n label,\n placeholder,\n icon: Icon,\n options,\n onChange,\n helpText,\n}: DropdownSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [searchQuery, setSearchQuery] = useState('')\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Group options by cube\n const groupedOptions = useMemo(() => {\n const groups: Record<string, typeof options> = {}\n for (const opt of options) {\n if (!groups[opt.cube]) {\n groups[opt.cube] = []\n }\n groups[opt.cube].push(opt)\n }\n return groups\n }, [options])\n\n // Filter based on search\n const filteredGroups = useMemo(() => {\n if (!searchQuery.trim()) return groupedOptions\n\n const query = searchQuery.toLowerCase()\n const filtered: Record<string, typeof options> = {}\n\n for (const [cube, dims] of Object.entries(groupedOptions)) {\n const matchingDims = dims.filter(\n (d) =>\n d.label.toLowerCase().includes(query) ||\n d.dimension.toLowerCase().includes(query) ||\n cube.toLowerCase().includes(query)\n )\n if (matchingDims.length > 0) {\n filtered[cube] = matchingDims\n }\n }\n\n return filtered\n }, [groupedOptions, searchQuery])\n\n // Handle selection\n const handleSelect = useCallback(\n (dimension: string) => {\n onChange(dimension)\n setIsOpen(false)\n setSearchQuery('')\n },\n [onChange]\n )\n\n // Handle clear\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n onChange(null)\n },\n [onChange]\n )\n\n // Close on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n setSearchQuery('')\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n // Focus search when opened\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n const hasValue = value !== null\n\n return (\n <div className=\"flex-1 min-w-0\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium text-dc-text-muted mb-1\">\n {Icon && <Icon className=\"w-3.5 h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n flex items-center justify-between w-full px-2.5 py-1.5 text-sm\n bg-dc-surface border border-dc-border rounded\n transition-colors hover:border-dc-primary cursor-pointer\n ${isOpen ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`truncate ${hasValue ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {hasValue ? options.find((o) => o.dimension === value)?.label || value : placeholder}\n </span>\n <span className=\"flex items-center gap-1 ml-2\">\n {hasValue && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={handleClear}\n onKeyDown={(e) => e.key === 'Enter' && handleClear(e as unknown as React.MouseEvent)}\n className=\"p-0.5 rounded hover:bg-dc-surface-hover text-dc-text-muted hover:text-dc-text\"\n title=\"Clear\"\n >\n ×\n </span>\n )}\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${isOpen ? 'rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"absolute z-50 mt-1 left-0 right-0 min-w-[200px] bg-dc-surface border border-dc-border rounded-md shadow-lg\">\n {/* Search Input */}\n <div className=\"p-2 border-b border-dc-border\">\n <div className=\"relative\">\n {SearchIcon && (\n <SearchIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-dc-text-muted\" />\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full pl-8 pr-3 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text placeholder:text-dc-text-muted focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"max-h-48 overflow-y-auto p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"px-3 py-4 text-sm text-dc-text-muted text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"mb-2 last:mb-0\">\n <div className=\"px-2 py-1 text-xs font-medium text-dc-text-muted uppercase tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n rounded transition-colors\n ${value === dim.dimension\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{dim.label}</span>\n {value === dim.dimension && CheckIcon && (\n <CheckIcon className=\"w-4 h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n {helpText}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\n/**\n * FunnelConfigPanel displays selectors for cube, binding key and time dimension\n * in a collapsible section that auto-collapses once all fields are configured.\n */\nconst FunnelConfigPanel = memo(function FunnelConfigPanel({\n selectedCube,\n bindingKey,\n timeDimension,\n schema,\n onCubeChange,\n onBindingKeyChange,\n onTimeDimensionChange,\n}: FunnelConfigPanelProps) {\n // Get available cubes (only those with eventStream metadata)\n const availableCubes = useMemo(() => getAvailableFunnelCubes(schema), [schema])\n\n // Filter binding keys by selected cube\n const availableBindingKeys = useMemo(() => {\n const allKeys = getAvailableBindingKeyDimensions(schema)\n if (!selectedCube) return []\n return allKeys.filter((key) => key.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Filter time dimensions by selected cube\n const availableTimeDimensions = useMemo(() => {\n const allTimeDims = getAvailableTimeDimensions(schema)\n if (!selectedCube) return []\n return allTimeDims.filter((dim) => dim.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Check if all config is complete\n const isConfigComplete = Boolean(selectedCube && bindingKey && timeDimension)\n\n // Collapsed state - start expanded if config is incomplete\n const [isCollapsed, setIsCollapsed] = useState(false)\n\n // Auto-collapse when config becomes complete (only once)\n const hasAutoCollapsedRef = useRef(false)\n useEffect(() => {\n if (isConfigComplete && !hasAutoCollapsedRef.current) {\n hasAutoCollapsedRef.current = true\n setIsCollapsed(true)\n }\n }, [isConfigComplete])\n\n // Auto-populate binding key and time dimension from eventStream when cube is selected\n useEffect(() => {\n if (!selectedCube || !schema) return\n\n const cube = schema.cubes?.find((c) => c.name === selectedCube)\n if (cube?.meta?.eventStream) {\n const eventStream = cube.meta.eventStream as { bindingKey?: string; timeDimension?: string }\n\n // Auto-set binding key from eventStream\n if (!bindingKey && eventStream.bindingKey) {\n onBindingKeyChange({ dimension: eventStream.bindingKey })\n }\n // Auto-set time dimension from eventStream\n if (!timeDimension && eventStream.timeDimension) {\n onTimeDimensionChange(eventStream.timeDimension)\n }\n }\n }, [selectedCube, schema, bindingKey, timeDimension, onBindingKeyChange, onTimeDimensionChange])\n\n // Convert FunnelBindingKey to string for simpler handling\n const bindingKeyValue = bindingKey?.dimension\n ? typeof bindingKey.dimension === 'string'\n ? bindingKey.dimension\n : bindingKey.dimension[0]?.dimension || null\n : null\n\n const handleBindingKeyChange = useCallback(\n (value: string | null) => {\n onBindingKeyChange(value ? { dimension: value } : null)\n },\n [onBindingKeyChange]\n )\n\n // Get display label for the collapsed summary\n const cubeLabel = availableCubes.find((c) => c.dimension === selectedCube)?.label || selectedCube\n\n return (\n <div className=\"bg-dc-surface-secondary border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"flex items-center justify-between w-full px-4 py-2.5 hover:bg-dc-surface-hover transition-colors\"\n >\n <div className=\"flex items-center gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"w-4 h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"flex items-center gap-1 text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"w-3.5 h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"text-xs text-dc-text-muted truncate max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"flex flex-col gap-3 px-4 pb-3\">\n {/* Cube Selector - Only cubes with eventStream metadata */}\n <DropdownSelector\n value={selectedCube}\n label=\"Cube\"\n placeholder=\"Select event stream cube\"\n icon={CubeIcon}\n options={availableCubes}\n onChange={onCubeChange}\n helpText=\"Select a cube configured for funnel analysis\"\n />\n\n {/* Binding Key Selector - filtered by selected cube */}\n <DropdownSelector\n value={bindingKeyValue}\n label=\"Binding Key\"\n placeholder={selectedCube ? 'Select binding key' : 'Select cube first'}\n icon={LinkIcon}\n options={availableBindingKeys}\n onChange={handleBindingKeyChange}\n helpText=\"Entity that connects steps (e.g., user ID, order ID)\"\n />\n\n {/* Time Dimension Selector - filtered by selected cube */}\n <DropdownSelector\n value={timeDimension}\n label=\"Time Dimension\"\n placeholder={selectedCube ? 'Select time dimension' : 'Select cube first'}\n icon={TimeDimensionIcon}\n options={availableTimeDimensions}\n onChange={onTimeDimensionChange}\n helpText=\"Timestamp field for step ordering\"\n />\n </div>\n )}\n </div>\n )\n})\n\nexport default FunnelConfigPanel\n","/**\n * FunnelStepCard Component\n *\n * Individual funnel step card with:\n * - Editable step name\n * - Filter configuration\n * - Time-to-convert selector (optional)\n * - Drag handle and remove button\n *\n * Note: Cube is inherited from the top-level funnel configuration\n */\n\nimport React, { memo, useCallback, useState, useRef, useEffect, useMemo } from 'react'\nimport type { CubeMeta, Filter, FunnelStepState } from '../../types'\nimport type { MetaResponse } from '../../shared/types'\nimport { getIcon } from '../../icons'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport { getRelatedCubesSchema } from './utils/fieldUtils'\n\nconst DragHandleIcon = getIcon('menu')\nconst CloseIcon = getIcon('close')\nconst ChevronDownIcon = getIcon('chevronDown')\nconst CheckIcon = getIcon('check')\nconst TimeDimensionIcon = getIcon('timeDimension')\n\n// Common time-to-convert durations\nconst TIME_TO_CONVERT_OPTIONS = [\n { value: null, label: 'No limit' },\n { value: 'PT1H', label: '1 hour' },\n { value: 'PT6H', label: '6 hours' },\n { value: 'PT12H', label: '12 hours' },\n { value: 'P1D', label: '1 day' },\n { value: 'P3D', label: '3 days' },\n { value: 'P7D', label: '7 days' },\n { value: 'P14D', label: '14 days' },\n { value: 'P30D', label: '30 days' },\n { value: 'P90D', label: '90 days' },\n]\n\nexport interface FunnelStepCardProps {\n /** The step state */\n step: FunnelStepState\n /** Index of this step (0-based) */\n stepIndex: number\n /** Whether this step is currently active/selected */\n isActive: boolean\n /** Whether this step can be removed (false if only 1 step) */\n canRemove: boolean\n /** Cube metadata for filter field selection */\n schema: CubeMeta | null\n\n // Actions\n /** Select this step */\n onSelect: () => void\n /** Remove this step */\n onRemove: () => void\n /** Update this step */\n onUpdate: (updates: Partial<FunnelStepState>) => void\n}\n\n/**\n * FunnelStepCard displays a single funnel step with inline editing\n */\nconst FunnelStepCard = memo(function FunnelStepCard({\n step,\n stepIndex,\n isActive,\n canRemove,\n schema,\n onSelect,\n onRemove,\n onUpdate,\n}: FunnelStepCardProps) {\n const [isEditingName, setIsEditingName] = useState(false)\n const [showTimeDropdown, setShowTimeDropdown] = useState(false)\n // Local state for name editing - only syncs to store on blur/Enter\n const [localName, setLocalName] = useState(step.name)\n const nameInputRef = useRef<HTMLInputElement>(null)\n const timeDropdownRef = useRef<HTMLDivElement>(null)\n\n // Sync localName when step.name changes externally (e.g., undo/redo, load from URL)\n useEffect(() => {\n setLocalName(step.name)\n }, [step.name])\n\n // Focus name input when editing starts\n useEffect(() => {\n if (isEditingName && nameInputRef.current) {\n nameInputRef.current.focus()\n nameInputRef.current.select()\n }\n }, [isEditingName])\n\n // Close time dropdown on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (timeDropdownRef.current && !timeDropdownRef.current.contains(event.target as Node)) {\n setShowTimeDropdown(false)\n }\n }\n if (showTimeDropdown) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [showTimeDropdown])\n\n // Handle name change - local state only, no store update\n const handleNameChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setLocalName(e.target.value)\n },\n []\n )\n\n // Handle name key events - blur on Enter (triggers save), revert on Escape\n const handleNameKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n // Blur triggers handleNameBlur which saves the name\n e.currentTarget.blur()\n } else if (e.key === 'Escape') {\n // Revert to original name and exit editing\n setLocalName(step.name)\n setIsEditingName(false)\n }\n },\n [step.name]\n )\n\n // Handle name blur - save to store only if changed\n const handleNameBlur = useCallback(() => {\n const trimmedName = localName.trim()\n if (trimmedName !== step.name) {\n // Use trimmed name or default to \"Step N\" if empty\n onUpdate({ name: trimmedName || `Step ${stepIndex + 1}` })\n }\n setIsEditingName(false)\n }, [localName, step.name, onUpdate, stepIndex])\n\n // Handle time-to-convert selection\n const handleTimeSelect = useCallback(\n (value: string | null) => {\n onUpdate({ timeToConvert: value || undefined })\n setShowTimeDropdown(false)\n },\n [onUpdate]\n )\n\n // Handle filter changes\n const handleFiltersChange = useCallback(\n (filters: Filter[]) => {\n onUpdate({ filters })\n },\n [onUpdate]\n )\n\n // Get display label for time-to-convert\n const timeToConvertLabel = step.timeToConvert\n ? TIME_TO_CONVERT_OPTIONS.find((o) => o.value === step.timeToConvert)?.label || step.timeToConvert\n : 'No limit'\n\n // Get schema for filters - includes related cubes for cross-cube filtering\n // When a cube is selected, include the cube itself plus all related cubes via join relationships\n // This enables filtering by dimensions from related cubes (e.g., filter Events by Users.active)\n const cubeSchema: MetaResponse | null = useMemo(() => {\n if (!schema) return null\n\n // Cast schema to MetaResponse format for compatibility\n const metaSchema: MetaResponse = {\n cubes: schema.cubes.map((c) => ({\n ...c,\n description: c.description || '',\n })),\n }\n\n // If a specific cube is selected, include it and all related cubes\n if (step.cube) {\n return getRelatedCubesSchema(step.cube, metaSchema)\n }\n\n // No specific cube selected - show all cubes\n return metaSchema\n }, [schema, step.cube])\n\n return (\n <div\n className={`\n bg-dc-surface border rounded-lg transition-all cursor-pointer\n ${isActive\n ? 'border-dc-primary ring-1 ring-dc-primary'\n : 'border-dc-border hover:border-dc-text-muted'\n }\n `}\n onClick={onSelect}\n >\n {/* Header Row */}\n <div className=\"flex items-center gap-2 px-3 py-2 border-b border-dc-border\">\n {/* Drag Handle */}\n <div className=\"cursor-grab active:cursor-grabbing text-dc-text-muted hover:text-dc-text\">\n {DragHandleIcon && <DragHandleIcon className=\"w-4 h-4\" />}\n </div>\n\n {/* Step Number */}\n <span className=\"flex-shrink-0 w-6 h-6 flex items-center justify-center rounded-full bg-dc-primary/10 text-dc-primary text-xs font-medium\">\n {stepIndex + 1}\n </span>\n\n {/* Step Name */}\n {isEditingName ? (\n <input\n ref={nameInputRef}\n type=\"text\"\n value={localName}\n onChange={handleNameChange}\n onKeyDown={handleNameKeyDown}\n onBlur={handleNameBlur}\n onClick={(e) => e.stopPropagation()}\n className=\"flex-1 px-1.5 py-0.5 text-sm font-medium bg-dc-surface border border-dc-primary rounded text-dc-text focus:outline-none\"\n placeholder=\"Step name\"\n />\n ) : (\n <button\n onClick={(e) => {\n e.stopPropagation()\n setIsEditingName(true)\n }}\n className=\"flex-1 text-left text-sm font-medium text-dc-text hover:text-dc-primary truncate\"\n title=\"Click to edit name\"\n >\n {step.name || `Step ${stepIndex + 1}`}\n </button>\n )}\n\n {/* Remove Button */}\n {canRemove && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n onRemove()\n }}\n className=\"p-1 rounded hover:bg-dc-danger-bg text-dc-text-muted hover:text-dc-error transition-colors\"\n title=\"Remove step\"\n >\n {CloseIcon && <CloseIcon className=\"w-4 h-4\" />}\n </button>\n )}\n </div>\n\n {/* Body - Only visible when active */}\n {isActive && (\n <div className=\"px-3 py-3 space-y-4\" onClick={(e) => e.stopPropagation()}>\n {/* Filters - only dimensions allowed for funnel step filters */}\n <AnalysisFilterSection\n filters={step.filters}\n schema={cubeSchema}\n onFiltersChange={handleFiltersChange}\n dimensionsOnly\n />\n\n {/* Time to Convert (only for steps after the first) */}\n {stepIndex > 0 && (\n <div>\n <label className=\"flex items-center gap-1.5 text-xs font-medium text-dc-text-muted mb-1\">\n {TimeDimensionIcon && <TimeDimensionIcon className=\"w-3.5 h-3.5\" />}\n Time Window\n </label>\n <div ref={timeDropdownRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowTimeDropdown(!showTimeDropdown)}\n className={`\n flex items-center justify-between w-full px-2.5 py-1.5 text-sm\n bg-dc-surface border border-dc-border rounded\n transition-colors hover:border-dc-primary cursor-pointer\n ${showTimeDropdown ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={step.timeToConvert ? 'text-dc-text' : 'text-dc-text-muted'}>\n {timeToConvertLabel}\n </span>\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${showTimeDropdown ? 'rotate-180' : ''}`}\n />\n )}\n </button>\n\n {showTimeDropdown && (\n <div className=\"absolute z-50 mt-1 left-0 right-0 bg-dc-surface border border-dc-border rounded-md shadow-lg max-h-48 overflow-y-auto\">\n {TIME_TO_CONVERT_OPTIONS.map((option) => (\n <button\n key={option.value || 'none'}\n onClick={() => handleTimeSelect(option.value)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n transition-colors\n ${step.timeToConvert === option.value ||\n (!step.timeToConvert && option.value === null)\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{option.label}</span>\n {(step.timeToConvert === option.value ||\n (!step.timeToConvert && option.value === null)) &&\n CheckIcon && <CheckIcon className=\"w-4 h-4\" />}\n </button>\n ))}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n Max time from previous step to qualify\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Collapsed view - show filter count when not active */}\n {!isActive && (\n <div className=\"px-3 py-2 text-xs text-dc-text-muted\">\n {step.filters.length > 0 && (\n <span>{step.filters.length} filter{step.filters.length !== 1 ? 's' : ''}</span>\n )}\n {step.timeToConvert && stepIndex > 0 && (\n <span className={step.filters.length > 0 ? 'ml-2' : ''}>\n {step.filters.length > 0 ? '• ' : ''}within {timeToConvertLabel.toLowerCase()}\n </span>\n )}\n {step.filters.length === 0 && !step.timeToConvert && (\n <span className=\"italic\">No filters configured</span>\n )}\n </div>\n )}\n </div>\n )\n})\n\nexport default FunnelStepCard\n","/**\n * FunnelStepList Component\n *\n * Vertical list of funnel steps with drag-and-drop reordering.\n * Each step can be configured with a name, cube, and filters.\n */\n\nimport React, { memo, useCallback, useState } from 'react'\nimport type { CubeMeta, FunnelStepState } from '../../types'\nimport { getIcon } from '../../icons'\nimport FunnelStepCard from './FunnelStepCard'\nimport SectionHeading from './SectionHeading'\n\nconst AddIcon = getIcon('add')\n\nexport interface FunnelStepListProps {\n /** Array of funnel steps */\n steps: FunnelStepState[]\n /** Index of currently active step */\n activeStepIndex: number\n /** Cube metadata for cube/field selection */\n schema: CubeMeta | null\n\n // Actions\n /** Add a new step */\n onAddStep: () => void\n /** Remove a step by index */\n onRemoveStep: (index: number) => void\n /** Update a step */\n onUpdateStep: (index: number, updates: Partial<FunnelStepState>) => void\n /** Select a step */\n onSelectStep: (index: number) => void\n /** Reorder steps (drag and drop) */\n onReorderSteps: (fromIndex: number, toIndex: number) => void\n}\n\n/**\n * FunnelStepList displays a vertical list of funnel steps\n * with drag-and-drop reordering support.\n */\nconst FunnelStepList = memo(function FunnelStepList({\n steps,\n activeStepIndex,\n schema,\n onAddStep,\n onRemoveStep,\n onUpdateStep,\n onSelectStep,\n onReorderSteps,\n}: FunnelStepListProps) {\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null)\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null)\n\n // Drag handlers\n const handleDragStart = useCallback((index: number) => {\n setDraggedIndex(index)\n }, [])\n\n const handleDragOver = useCallback((e: React.DragEvent, index: number) => {\n e.preventDefault()\n if (draggedIndex !== null && draggedIndex !== index) {\n setDragOverIndex(index)\n }\n }, [draggedIndex])\n\n const handleDragLeave = useCallback(() => {\n setDragOverIndex(null)\n }, [])\n\n const handleDrop = useCallback((e: React.DragEvent, index: number) => {\n e.preventDefault()\n if (draggedIndex !== null && draggedIndex !== index) {\n onReorderSteps(draggedIndex, index)\n }\n setDraggedIndex(null)\n setDragOverIndex(null)\n }, [draggedIndex, onReorderSteps])\n\n const handleDragEnd = useCallback(() => {\n setDraggedIndex(null)\n setDragOverIndex(null)\n }, [])\n\n return (\n <div className=\"space-y-4\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <SectionHeading>\n Funnel Steps\n {steps.length > 0 && (\n <span className=\"ml-1.5 text-xs font-normal text-dc-text-muted normal-case tracking-normal\">\n ({steps.length})\n </span>\n )}\n </SectionHeading>\n </div>\n\n {/* Step List */}\n {steps.length === 0 ? (\n <div className=\"text-center py-8\">\n <p className=\"text-sm text-dc-text-muted mb-3\">\n No steps defined. Add at least 2 steps to create a funnel.\n </p>\n <button\n onClick={onAddStep}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-dc-primary bg-dc-primary/10 rounded-md hover:bg-dc-primary/20 transition-colors\"\n >\n <AddIcon className=\"w-4 h-4\" />\n Add First Step\n </button>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {steps.map((step, index) => (\n <div\n key={step.id}\n draggable\n onDragStart={() => handleDragStart(index)}\n onDragOver={(e) => handleDragOver(e, index)}\n onDragLeave={handleDragLeave}\n onDrop={(e) => handleDrop(e, index)}\n onDragEnd={handleDragEnd}\n className={`transition-all ${\n draggedIndex === index ? 'opacity-50' : ''\n } ${\n dragOverIndex === index\n ? 'border-t-2 border-dc-primary pt-1'\n : ''\n }`}\n >\n <FunnelStepCard\n step={step}\n stepIndex={index}\n isActive={index === activeStepIndex}\n canRemove={steps.length > 1}\n schema={schema}\n onSelect={() => onSelectStep(index)}\n onRemove={() => onRemoveStep(index)}\n onUpdate={(updates) => onUpdateStep(index, updates)}\n />\n </div>\n ))}\n </div>\n )}\n\n {/* Add Step Button */}\n {steps.length > 0 && (\n <button\n onClick={onAddStep}\n className=\"flex items-center justify-center gap-1.5 w-full py-2 text-sm font-medium text-dc-text-secondary bg-dc-surface border-2 border-dashed border-dc-border rounded-lg hover:border-dc-primary hover:text-dc-primary hover:bg-dc-primary/5 transition-colors\"\n >\n <AddIcon className=\"w-4 h-4\" />\n Add Step\n </button>\n )}\n\n {/* Validation Hint */}\n {steps.length === 1 && (\n <p className=\"text-xs text-dc-warning text-center\">\n Add at least one more step to create a valid funnel\n </p>\n )}\n </div>\n )\n})\n\nexport default FunnelStepList\n","/**\n * FunnelModeContent Component\n *\n * Container for all funnel mode UI in AnalysisBuilder.\n * Displays tabs for Steps and Display configuration.\n */\n\nimport { memo, useState } from 'react'\nimport type { CubeMeta, FunnelBindingKey, FunnelStepState, ChartType, ChartDisplayConfig } from '../../types'\nimport type { FunnelPanelTab } from './types'\nimport type { ColorPalette } from '../../utils/colorPalettes'\nimport FunnelConfigPanel from './FunnelConfigPanel'\nimport FunnelStepList from './FunnelStepList'\nimport AnalysisDisplayConfigPanel from './AnalysisDisplayConfigPanel'\n\nexport interface FunnelModeContentProps {\n /** Currently selected cube for funnel */\n funnelCube: string | null\n /** Current funnel steps */\n funnelSteps: FunnelStepState[]\n /** Index of the currently active step */\n activeFunnelStepIndex: number\n /** Time dimension for funnel temporal ordering */\n funnelTimeDimension: string | null\n /** Binding key that links steps together */\n funnelBindingKey: FunnelBindingKey | null\n /** Cube metadata for field selection */\n schema: CubeMeta | null\n\n // Actions - Steps\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Add a new funnel step */\n onAddStep: () => void\n /** Remove a funnel step by index */\n onRemoveStep: (index: number) => void\n /** Update a funnel step */\n onUpdateStep: (index: number, updates: Partial<FunnelStepState>) => void\n /** Set the active step index */\n onSelectStep: (index: number) => void\n /** Reorder funnel steps */\n onReorderSteps: (fromIndex: number, toIndex: number) => void\n /** Set the time dimension */\n onTimeDimensionChange: (dimension: string | null) => void\n /** Set the binding key */\n onBindingKeyChange: (bindingKey: FunnelBindingKey | null) => void\n\n // Display configuration (optional - for Display tab)\n /** Chart type for funnel display */\n chartType?: ChartType\n /** Display configuration */\n displayConfig?: ChartDisplayConfig\n /** Color palette */\n colorPalette?: ColorPalette\n /** Callback when display config changes */\n onDisplayConfigChange?: (config: ChartDisplayConfig) => void\n}\n\n/**\n * FunnelModeContent displays the complete funnel configuration interface:\n * - Tabs: Steps | Display\n * - Steps tab: Config panel (binding key + time dimension) + step list\n * - Display tab: Funnel chart display options\n */\nconst FunnelModeContent = memo(function FunnelModeContent({\n funnelCube,\n funnelSteps,\n activeFunnelStepIndex,\n funnelTimeDimension,\n funnelBindingKey,\n schema,\n onCubeChange,\n onAddStep,\n onRemoveStep,\n onUpdateStep,\n onSelectStep,\n onReorderSteps,\n onTimeDimensionChange,\n onBindingKeyChange,\n // Display props\n chartType = 'funnel',\n displayConfig,\n colorPalette,\n onDisplayConfigChange,\n}: FunnelModeContentProps) {\n const [activeTab, setActiveTab] = useState<FunnelPanelTab>('steps')\n\n // Check if display tab is available\n const hasDisplayTab = displayConfig && onDisplayConfigChange\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Tab Bar */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n <button\n onClick={() => setActiveTab('steps')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'steps'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Steps\n </button>\n <button\n onClick={() => hasDisplayTab && setActiveTab('display')}\n disabled={!hasDisplayTab}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={!hasDisplayTab ? 'Display options not available' : 'Display options'}\n >\n Display\n </button>\n </div>\n\n {/* Tab Content */}\n {activeTab === 'steps' ? (\n <div className=\"flex flex-col flex-1 min-h-0\">\n {/* Configuration Panel - Cube + Binding Key + Time Dimension */}\n <FunnelConfigPanel\n selectedCube={funnelCube}\n bindingKey={funnelBindingKey}\n timeDimension={funnelTimeDimension}\n schema={schema}\n onCubeChange={onCubeChange}\n onBindingKeyChange={onBindingKeyChange}\n onTimeDimensionChange={onTimeDimensionChange}\n />\n\n {/* Step List - scrollable with extra bottom padding for \"Add step\" button */}\n <div className=\"flex-1 min-h-0 overflow-auto p-4 pb-24\">\n <FunnelStepList\n steps={funnelSteps}\n activeStepIndex={activeFunnelStepIndex}\n schema={schema}\n onAddStep={onAddStep}\n onRemoveStep={onRemoveStep}\n onUpdateStep={onUpdateStep}\n onSelectStep={onSelectStep}\n onReorderSteps={onReorderSteps}\n />\n </div>\n </div>\n ) : activeTab === 'display' && displayConfig && onDisplayConfigChange ? (\n <div className=\"flex-1 min-h-0 overflow-auto p-4\">\n <AnalysisDisplayConfigPanel\n chartType={chartType}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n </div>\n ) : null}\n </div>\n )\n})\n\nexport default FunnelModeContent\n","/**\n * FlowConfigPanel Component\n *\n * Configuration panel for flow analysis settings:\n * - Cube selector (only cubes with eventStream metadata)\n * - Binding key selector (entity linking)\n * - Time dimension selector (event ordering)\n * - Event dimension selector (node labels in Sankey)\n *\n * The config section is collapsible and auto-collapses once all fields are set.\n */\n\nimport React, { memo, useMemo, useCallback, useState, useRef, useEffect } from 'react'\nimport type { CubeMeta, FunnelBindingKey } from '../../types'\nimport { getIcon } from '../../icons'\nimport { getAvailableBindingKeyDimensions } from '../../utils/funnelValidation'\nimport SectionHeading from './SectionHeading'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst ChevronRightIcon = getIcon('chevronRight')\nconst CheckIcon = getIcon('check')\nconst SearchIcon = getIcon('search')\nconst CubeIcon = getIcon('dimension')\nconst LinkIcon = getIcon('link')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst TagIcon = getIcon('dimension') // Used for event dimension\n\nexport interface FlowConfigPanelProps {\n /** Currently selected cube for flow analysis */\n selectedCube: string | null\n /** Current binding key */\n bindingKey: FunnelBindingKey | null\n /** Current time dimension */\n timeDimension: string | null\n /** Current event dimension */\n eventDimension: string | null\n /** Cube metadata */\n schema: CubeMeta | null\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Callback when binding key changes */\n onBindingKeyChange: (bindingKey: FunnelBindingKey | null) => void\n /** Callback when time dimension changes */\n onTimeDimensionChange: (dimension: string | null) => void\n /** Callback when event dimension changes */\n onEventDimensionChange: (dimension: string | null) => void\n}\n\n/**\n * Get available flow cubes from schema (only those with eventStream metadata)\n */\nfunction getAvailableFlowCubes(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n eventStream?: { bindingKey: string; timeDimension: string }\n}> {\n if (!schema?.cubes) return []\n\n return schema.cubes\n .filter((cube) => cube.meta?.eventStream)\n .map((cube) => ({\n cube: cube.name,\n dimension: cube.name,\n label: cube.title || cube.name,\n eventStream: cube.meta?.eventStream as { bindingKey: string; timeDimension: string } | undefined,\n }))\n}\n\n/**\n * Get available time dimensions from schema\n */\nfunction getAvailableTimeDimensions(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n}> {\n if (!schema?.cubes) return []\n\n const timeDimensions: Array<{ cube: string; dimension: string; label: string }> = []\n\n for (const cube of schema.cubes) {\n for (const dim of cube.dimensions || []) {\n if (dim.type === 'time') {\n timeDimensions.push({\n cube: cube.name,\n dimension: dim.name,\n label: dim.shortTitle || dim.title || dim.name.split('.').pop() || dim.name,\n })\n }\n }\n }\n\n return timeDimensions\n}\n\n/**\n * Get available string dimensions from schema (for event categorization)\n */\nfunction getAvailableStringDimensions(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n}> {\n if (!schema?.cubes) return []\n\n const stringDimensions: Array<{ cube: string; dimension: string; label: string }> = []\n\n for (const cube of schema.cubes) {\n for (const dim of cube.dimensions || []) {\n if (dim.type === 'string') {\n stringDimensions.push({\n cube: cube.name,\n dimension: dim.name,\n label: dim.shortTitle || dim.title || dim.name.split('.').pop() || dim.name,\n })\n }\n }\n }\n\n return stringDimensions\n}\n\n/**\n * Dropdown selector component\n */\ninterface DropdownSelectorProps {\n value: string | null\n label: string\n placeholder: string\n icon: React.ComponentType<{ className?: string }> | null\n options: Array<{ cube: string; dimension: string; label: string }>\n onChange: (value: string | null) => void\n helpText: string\n}\n\nconst DropdownSelector = memo(function DropdownSelector({\n value,\n label,\n placeholder,\n icon: Icon,\n options,\n onChange,\n helpText,\n}: DropdownSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [searchQuery, setSearchQuery] = useState('')\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Group options by cube\n const groupedOptions = useMemo(() => {\n const groups: Record<string, typeof options> = {}\n for (const opt of options) {\n if (!groups[opt.cube]) {\n groups[opt.cube] = []\n }\n groups[opt.cube].push(opt)\n }\n return groups\n }, [options])\n\n // Filter based on search\n const filteredGroups = useMemo(() => {\n if (!searchQuery.trim()) return groupedOptions\n\n const query = searchQuery.toLowerCase()\n const filtered: Record<string, typeof options> = {}\n\n for (const [cube, dims] of Object.entries(groupedOptions)) {\n const matchingDims = dims.filter(\n (d) =>\n d.label.toLowerCase().includes(query) ||\n d.dimension.toLowerCase().includes(query) ||\n cube.toLowerCase().includes(query)\n )\n if (matchingDims.length > 0) {\n filtered[cube] = matchingDims\n }\n }\n\n return filtered\n }, [groupedOptions, searchQuery])\n\n // Handle selection\n const handleSelect = useCallback(\n (dimension: string) => {\n onChange(dimension)\n setIsOpen(false)\n setSearchQuery('')\n },\n [onChange]\n )\n\n // Handle clear\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n onChange(null)\n },\n [onChange]\n )\n\n // Close on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n setSearchQuery('')\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n // Focus search when opened\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n const hasValue = value !== null\n\n return (\n <div className=\"flex-1 min-w-0\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium text-dc-text-muted mb-1\">\n {Icon && <Icon className=\"w-3.5 h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n flex items-center justify-between w-full px-2.5 py-1.5 text-sm\n bg-dc-surface border border-dc-border rounded\n transition-colors hover:border-dc-primary cursor-pointer\n ${isOpen ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`truncate ${hasValue ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {hasValue ? options.find((o) => o.dimension === value)?.label || value : placeholder}\n </span>\n <span className=\"flex items-center gap-1 ml-2\">\n {hasValue && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={handleClear}\n onKeyDown={(e) => e.key === 'Enter' && handleClear(e as unknown as React.MouseEvent)}\n className=\"p-0.5 rounded hover:bg-dc-surface-hover text-dc-text-muted hover:text-dc-text\"\n title=\"Clear\"\n >\n x\n </span>\n )}\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${isOpen ? 'rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"absolute z-50 mt-1 left-0 right-0 min-w-[200px] bg-dc-surface border border-dc-border rounded-md shadow-lg\">\n {/* Search Input */}\n <div className=\"p-2 border-b border-dc-border\">\n <div className=\"relative\">\n {SearchIcon && (\n <SearchIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-dc-text-muted\" />\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full pl-8 pr-3 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text placeholder:text-dc-text-muted focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"max-h-48 overflow-y-auto p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"px-3 py-4 text-sm text-dc-text-muted text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"mb-2 last:mb-0\">\n <div className=\"px-2 py-1 text-xs font-medium text-dc-text-muted uppercase tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n rounded transition-colors\n ${value === dim.dimension\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{dim.label}</span>\n {value === dim.dimension && CheckIcon && (\n <CheckIcon className=\"w-4 h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n {helpText}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\n/**\n * FlowConfigPanel displays selectors for cube, binding key, time dimension,\n * and event dimension in a collapsible section.\n */\nconst FlowConfigPanel = memo(function FlowConfigPanel({\n selectedCube,\n bindingKey,\n timeDimension,\n eventDimension,\n schema,\n onCubeChange,\n onBindingKeyChange,\n onTimeDimensionChange,\n onEventDimensionChange,\n}: FlowConfigPanelProps) {\n // Get available cubes (only those with eventStream metadata)\n const availableCubes = useMemo(() => getAvailableFlowCubes(schema), [schema])\n\n // Filter binding keys by selected cube\n const availableBindingKeys = useMemo(() => {\n const allKeys = getAvailableBindingKeyDimensions(schema)\n if (!selectedCube) return []\n return allKeys.filter((key) => key.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Filter time dimensions by selected cube\n const availableTimeDimensions = useMemo(() => {\n const allTimeDims = getAvailableTimeDimensions(schema)\n if (!selectedCube) return []\n return allTimeDims.filter((dim) => dim.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Filter string dimensions by selected cube (for event categorization)\n const availableEventDimensions = useMemo(() => {\n const allStringDims = getAvailableStringDimensions(schema)\n if (!selectedCube) return []\n return allStringDims.filter((dim) => dim.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Check if all config is complete\n const isConfigComplete = Boolean(selectedCube && bindingKey && timeDimension && eventDimension)\n\n // Collapsed state - start expanded if config is incomplete\n const [isCollapsed, setIsCollapsed] = useState(false)\n\n // Auto-collapse when config becomes complete (only once)\n const hasAutoCollapsedRef = useRef(false)\n useEffect(() => {\n if (isConfigComplete && !hasAutoCollapsedRef.current) {\n hasAutoCollapsedRef.current = true\n setIsCollapsed(true)\n }\n }, [isConfigComplete])\n\n // Auto-populate binding key and time dimension from eventStream when cube is selected\n useEffect(() => {\n if (!selectedCube || !schema) return\n\n const cube = schema.cubes?.find((c) => c.name === selectedCube)\n if (cube?.meta?.eventStream) {\n const eventStream = cube.meta.eventStream as { bindingKey?: string; timeDimension?: string }\n\n // Auto-set binding key from eventStream\n if (!bindingKey && eventStream.bindingKey) {\n onBindingKeyChange({ dimension: eventStream.bindingKey })\n }\n // Auto-set time dimension from eventStream\n if (!timeDimension && eventStream.timeDimension) {\n onTimeDimensionChange(eventStream.timeDimension)\n }\n }\n }, [selectedCube, schema, bindingKey, timeDimension, onBindingKeyChange, onTimeDimensionChange])\n\n // Convert FunnelBindingKey to string for simpler handling\n const bindingKeyValue = bindingKey?.dimension\n ? typeof bindingKey.dimension === 'string'\n ? bindingKey.dimension\n : bindingKey.dimension[0]?.dimension || null\n : null\n\n const handleBindingKeyChange = useCallback(\n (value: string | null) => {\n onBindingKeyChange(value ? { dimension: value } : null)\n },\n [onBindingKeyChange]\n )\n\n // Get display label for the collapsed summary\n const cubeLabel = availableCubes.find((c) => c.dimension === selectedCube)?.label || selectedCube\n\n return (\n <div className=\"bg-dc-surface-secondary border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"flex items-center justify-between w-full px-4 py-2.5 hover:bg-dc-surface-hover transition-colors\"\n >\n <div className=\"flex items-center gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"w-4 h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"flex items-center gap-1 text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"w-3.5 h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"text-xs text-dc-text-muted truncate max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"flex flex-col gap-3 px-4 pb-3\">\n {/* Cube Selector */}\n <DropdownSelector\n value={selectedCube}\n label=\"Cube\"\n placeholder=\"Select event stream cube\"\n icon={CubeIcon}\n options={availableCubes}\n onChange={onCubeChange}\n helpText=\"Select a cube configured for flow analysis\"\n />\n\n {/* Binding Key Selector */}\n <DropdownSelector\n value={bindingKeyValue}\n label=\"Binding Key\"\n placeholder={selectedCube ? 'Select binding key' : 'Select cube first'}\n icon={LinkIcon}\n options={availableBindingKeys}\n onChange={handleBindingKeyChange}\n helpText=\"Entity that links events together (e.g., user ID)\"\n />\n\n {/* Time Dimension Selector */}\n <DropdownSelector\n value={timeDimension}\n label=\"Time Dimension\"\n placeholder={selectedCube ? 'Select time dimension' : 'Select cube first'}\n icon={TimeDimensionIcon}\n options={availableTimeDimensions}\n onChange={onTimeDimensionChange}\n helpText=\"Timestamp field for event ordering\"\n />\n\n {/* Event Dimension Selector */}\n <DropdownSelector\n value={eventDimension}\n label=\"Event Dimension\"\n placeholder={selectedCube ? 'Select event dimension' : 'Select cube first'}\n icon={TagIcon}\n options={availableEventDimensions}\n onChange={onEventDimensionChange}\n helpText=\"Dimension that categorizes events (node labels in Sankey)\"\n />\n </div>\n )}\n </div>\n )\n})\n\nexport default FlowConfigPanel\n","/**\n * FlowModeContent Component\n *\n * Container for all flow mode UI in AnalysisBuilder.\n * Displays tabs for Flow Configuration and Display options.\n */\n\nimport { memo, useState, useCallback } from 'react'\nimport type { CubeMeta, FunnelBindingKey, ChartType, ChartDisplayConfig, Filter } from '../../types'\nimport type { ColorPalette } from '../../utils/colorPalettes'\nimport type { FlowStartingStep } from '../../types/flow'\nimport { FLOW_MIN_DEPTH, FLOW_MAX_DEPTH } from '../../types/flow'\nimport FlowConfigPanel from './FlowConfigPanel'\nimport AnalysisDisplayConfigPanel from './AnalysisDisplayConfigPanel'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport SectionHeading from './SectionHeading'\n\ntype FlowPanelTab = 'config' | 'display'\n\nexport interface FlowModeContentProps {\n /** Currently selected cube for flow analysis */\n flowCube: string | null\n /** Binding key that links events to entities */\n flowBindingKey: FunnelBindingKey | null\n /** Time dimension for event ordering */\n flowTimeDimension: string | null\n /** Event dimension that categorizes events */\n eventDimension: string | null\n /** Starting step configuration */\n startingStep: FlowStartingStep\n /** Number of steps to explore before starting step */\n stepsBefore: number\n /** Number of steps to explore after starting step */\n stepsAfter: number\n /** Join strategy for server execution */\n joinStrategy: 'auto' | 'lateral' | 'window'\n /** Cube metadata for field selection */\n schema: CubeMeta | null\n\n // Actions - Configuration\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Callback when binding key changes */\n onBindingKeyChange: (key: FunnelBindingKey | null) => void\n /** Callback when time dimension changes */\n onTimeDimensionChange: (dim: string | null) => void\n /** Callback when event dimension changes */\n onEventDimensionChange: (dim: string | null) => void\n /** Callback when starting step filters change */\n onStartingStepFiltersChange: (filters: Filter[]) => void\n /** Callback when steps before changes */\n onStepsBeforeChange: (count: number) => void\n /** Callback when steps after changes */\n onStepsAfterChange: (count: number) => void\n /** Callback when join strategy changes */\n onJoinStrategyChange?: (strategy: 'auto' | 'lateral' | 'window') => void\n\n // Chart type (core - affects query behavior)\n /** Chart type for flow display */\n chartType?: ChartType\n /** Callback when chart type changes (affects query!) */\n onChartTypeChange?: (type: ChartType) => void\n\n // Display configuration (optional - for Display tab)\n /** Display configuration */\n displayConfig?: ChartDisplayConfig\n /** Color palette */\n colorPalette?: ColorPalette\n /** Callback when display config changes */\n onDisplayConfigChange?: (config: ChartDisplayConfig) => void\n}\n\n/**\n * FlowModeContent displays the complete flow configuration interface:\n * - Tabs: Flow | Display\n * - Flow tab: Config panel + starting step + depth controls\n * - Display tab: Sankey chart display options\n */\nconst FlowModeContent = memo(function FlowModeContent({\n flowCube,\n flowBindingKey,\n flowTimeDimension,\n eventDimension,\n startingStep,\n stepsBefore,\n stepsAfter,\n joinStrategy = 'auto',\n schema,\n onCubeChange,\n onBindingKeyChange,\n onTimeDimensionChange,\n onEventDimensionChange,\n onStartingStepFiltersChange,\n onStepsBeforeChange,\n onStepsAfterChange,\n onJoinStrategyChange,\n // Chart type (affects query!)\n chartType = 'sankey',\n onChartTypeChange,\n // Display props\n displayConfig,\n colorPalette,\n onDisplayConfigChange,\n}: FlowModeContentProps) {\n const [activeTab, setActiveTab] = useState<FlowPanelTab>('config')\n\n // Check if display tab is available\n const hasDisplayTab = displayConfig && onDisplayConfigChange\n\n // Handler for filter changes from AnalysisFilterSection\n const handleFiltersChange = useCallback(\n (filters: Filter[]) => {\n onStartingStepFiltersChange(filters)\n },\n [onStartingStepFiltersChange]\n )\n\n return (\n <div className=\"flex flex-col h-full min-h-0 overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Flow\n </button>\n <button\n onClick={() => hasDisplayTab && setActiveTab('display')}\n disabled={!hasDisplayTab}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={!hasDisplayTab ? 'Display options not available' : 'Display options'}\n >\n Display\n </button>\n </div>\n\n {/* Tab Content */}\n {activeTab === 'config' ? (\n <div className=\"flex flex-col flex-1 min-h-0\">\n {/* Configuration Panel - Cube + Binding Key + Time Dimension + Event Dimension */}\n <FlowConfigPanel\n selectedCube={flowCube}\n bindingKey={flowBindingKey}\n timeDimension={flowTimeDimension}\n eventDimension={eventDimension}\n schema={schema}\n onCubeChange={onCubeChange}\n onBindingKeyChange={onBindingKeyChange}\n onTimeDimensionChange={onTimeDimensionChange}\n onEventDimensionChange={onEventDimensionChange}\n />\n\n {/* Flow Configuration - scrollable */}\n <div className=\"flex-1 min-h-0 overflow-auto p-4 space-y-6\">\n {/* Visualization Type - now in main config since it affects query */}\n {onChartTypeChange && (\n <div>\n <SectionHeading>Visualization</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Choose how to visualize the flow data. This affects how data is aggregated.\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => onChartTypeChange('sankey')}\n className={`flex-1 px-3 py-2 rounded-md border text-sm font-medium transition-colors ${\n chartType === 'sankey'\n ? 'border-dc-primary bg-dc-primary/10 text-dc-primary'\n : 'border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text'\n }`}\n >\n <div className=\"flex flex-col items-center gap-1\">\n <span>Sankey</span>\n <span className=\"text-[10px] font-normal text-dc-text-muted\">\n Paths can converge\n </span>\n </div>\n </button>\n <button\n type=\"button\"\n onClick={() => onChartTypeChange('sunburst')}\n className={`flex-1 px-3 py-2 rounded-md border text-sm font-medium transition-colors ${\n chartType === 'sunburst'\n ? 'border-dc-primary bg-dc-primary/10 text-dc-primary'\n : 'border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text'\n }`}\n >\n <div className=\"flex flex-col items-center gap-1\">\n <span>Sunburst</span>\n <span className=\"text-[10px] font-normal text-dc-text-muted\">\n Unique paths only\n </span>\n </div>\n </button>\n </div>\n </div>\n )}\n\n {/* Starting Step Section */}\n <div>\n <SectionHeading>Starting Step</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Define the anchor event from which paths will be explored in both directions.\n </p>\n\n {/* Starting Step Filters */}\n <div>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-2\">\n Filter Conditions\n </label>\n <AnalysisFilterSection\n filters={startingStep.filters}\n schema={schema as unknown as import('../../shared/types').MetaResponse | null}\n onFiltersChange={handleFiltersChange}\n />\n </div>\n </div>\n\n {/* Depth Configuration */}\n <div>\n <SectionHeading>Exploration Depth</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n {chartType === 'sunburst'\n ? 'How many steps to explore after the starting step.'\n : 'How many steps to explore before and after the starting step.'}\n </p>\n\n <div className=\"grid grid-cols-2 gap-4\">\n {/* Steps Before - disabled for sunburst */}\n <div className={chartType === 'sunburst' ? 'opacity-50' : ''}>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-1\">\n Steps Before\n {chartType === 'sunburst' && (\n <span className=\"ml-1 text-dc-text-muted\">(N/A)</span>\n )}\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"range\"\n min={FLOW_MIN_DEPTH}\n max={FLOW_MAX_DEPTH}\n value={stepsBefore}\n onChange={(e) => onStepsBeforeChange(parseInt(e.target.value, 10))}\n disabled={chartType === 'sunburst'}\n className=\"flex-1 disabled:cursor-not-allowed\"\n />\n <span className=\"w-6 text-sm font-medium text-dc-text text-center\">\n {chartType === 'sunburst' ? '-' : stepsBefore}\n </span>\n </div>\n </div>\n\n {/* Steps After */}\n <div>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-1\">\n Steps After\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"range\"\n min={FLOW_MIN_DEPTH}\n max={FLOW_MAX_DEPTH}\n value={stepsAfter}\n onChange={(e) => onStepsAfterChange(parseInt(e.target.value, 10))}\n className=\"flex-1\"\n />\n <span className=\"w-6 text-sm font-medium text-dc-text text-center\">\n {stepsAfter}\n </span>\n </div>\n </div>\n </div>\n\n {/* Performance warning for high depth */}\n {((chartType !== 'sunburst' && stepsBefore >= 4) || stepsAfter >= 4) && (\n <div className=\"mt-3 px-3 py-2 bg-dc-warning-bg rounded border border-dc-warning text-xs text-dc-warning\">\n High step depth (4-5) may impact query performance on large datasets.\n </div>\n )}\n\n </div>\n\n {/* Join strategy selection */}\n <div>\n <SectionHeading>Join Strategy</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Control how before/after steps are fetched. Switch to window if lateral is slower on your DB.\n </p>\n <select\n className=\"w-full border border-dc-border rounded px-2 py-2 text-sm bg-dc-surface text-dc-text\"\n value={joinStrategy}\n onChange={(e) =>\n onJoinStrategyChange?.(e.target.value as 'auto' | 'lateral' | 'window')\n }\n >\n <option value=\"auto\">Auto (prefer lateral if available)</option>\n <option value=\"lateral\">Lateral (index seeks)</option>\n <option value=\"window\">Window (ROW_NUMBER)</option>\n </select>\n </div>\n </div>\n </div>\n ) : activeTab === 'display' && displayConfig && onDisplayConfigChange ? (\n <div className=\"flex-1 min-h-0 overflow-auto p-4\">\n <AnalysisDisplayConfigPanel\n chartType={chartType}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n </div>\n ) : null}\n </div>\n )\n})\n\nexport default FlowModeContent\n","/**\n * RetentionConfigPanel Component\n *\n * Collapsible configuration panel for retention analysis settings:\n * - Cube selector\n * - Binding key (user ID) selector\n * - Timestamp dimension selector\n * - Date Range picker\n *\n * The config section is collapsible and auto-collapses once all fields are set.\n * Pattern matches FlowConfigPanel for consistency.\n */\n\nimport React, { memo, useMemo, useCallback, useState, useRef, useEffect } from 'react'\nimport type { CubeMeta, FunnelBindingKey } from '../../types'\nimport type { DateRange, DateRangePreset } from '../../types/retention'\nimport {\n RETENTION_DATE_RANGE_PRESETS,\n getDateRangeFromPreset,\n detectDateRangePreset,\n} from '../../types/retention'\nimport { getIcon } from '../../icons'\nimport { getAvailableBindingKeyDimensions } from '../../utils/funnelValidation'\nimport SectionHeading from './SectionHeading'\n\nconst ChevronDownIcon = getIcon('chevronDown')\nconst ChevronRightIcon = getIcon('chevronRight')\nconst CheckIcon = getIcon('check')\nconst SearchIcon = getIcon('search')\nconst CubeIcon = getIcon('dimension')\nconst LinkIcon = getIcon('link')\nconst TimeDimensionIcon = getIcon('timeDimension')\nconst CalendarIcon = getIcon('timeDimension')\n\nexport interface RetentionConfigPanelProps {\n /** Currently selected cube */\n selectedCube: string | null\n /** Binding key that identifies entities */\n bindingKey: FunnelBindingKey | null\n /** Timestamp dimension for the analysis */\n timeDimension: string | null\n /** Date range for cohort analysis (for collapsed summary display) */\n dateRange: DateRange\n /** Cube metadata for field selection */\n schema: CubeMeta | null\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Callback when binding key changes */\n onBindingKeyChange: (bindingKey: FunnelBindingKey | null) => void\n /** Callback when timestamp dimension changes */\n onTimeDimensionChange: (dimension: string | null) => void\n}\n\n/**\n * Get available cubes from schema (only those with eventStream metadata)\n * Matches FunnelConfigPanel pattern - retention requires eventStream for proper analysis\n */\nfunction getAvailableCubes(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n eventStream?: { bindingKey: string; timeDimension: string }\n}> {\n if (!schema?.cubes) return []\n\n return schema.cubes\n .filter((cube) => cube.meta?.eventStream) // Only eventStream cubes\n .map((cube) => ({\n cube: cube.name,\n dimension: cube.name,\n label: cube.title || cube.name,\n eventStream: cube.meta?.eventStream as { bindingKey: string; timeDimension: string } | undefined,\n }))\n}\n\n/**\n * Get available time dimensions from schema\n */\nfunction getAvailableTimeDimensions(schema: CubeMeta | null): Array<{\n cube: string\n dimension: string\n label: string\n}> {\n if (!schema?.cubes) return []\n\n const timeDimensions: Array<{ cube: string; dimension: string; label: string }> = []\n\n for (const cube of schema.cubes) {\n for (const dim of cube.dimensions || []) {\n if (dim.type === 'time') {\n timeDimensions.push({\n cube: cube.name,\n dimension: dim.name,\n label: dim.shortTitle || dim.title || dim.name.split('.').pop() || dim.name,\n })\n }\n }\n }\n\n return timeDimensions\n}\n\n/**\n * Format date for display (short format)\n */\nfunction formatDateDisplay(date: string): string {\n if (!date) return ''\n const d = new Date(date)\n return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })\n}\n\n/**\n * Dropdown selector component (same pattern as FlowConfigPanel)\n */\ninterface DropdownSelectorProps {\n value: string | null\n label: string\n placeholder: string\n icon: React.ComponentType<{ className?: string }> | null\n options: Array<{ cube: string; dimension: string; label: string }>\n onChange: (value: string | null) => void\n helpText: string\n}\n\nconst DropdownSelector = memo(function DropdownSelector({\n value,\n label,\n placeholder,\n icon: Icon,\n options,\n onChange,\n helpText,\n}: DropdownSelectorProps) {\n const [isOpen, setIsOpen] = useState(false)\n const [searchQuery, setSearchQuery] = useState('')\n const dropdownRef = useRef<HTMLDivElement>(null)\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n // Group options by cube\n const groupedOptions = useMemo(() => {\n const groups: Record<string, typeof options> = {}\n for (const opt of options) {\n if (!groups[opt.cube]) {\n groups[opt.cube] = []\n }\n groups[opt.cube].push(opt)\n }\n return groups\n }, [options])\n\n // Filter based on search\n const filteredGroups = useMemo(() => {\n if (!searchQuery.trim()) return groupedOptions\n\n const query = searchQuery.toLowerCase()\n const filtered: Record<string, typeof options> = {}\n\n for (const [cube, dims] of Object.entries(groupedOptions)) {\n const matchingDims = dims.filter(\n (d) =>\n d.label.toLowerCase().includes(query) ||\n d.dimension.toLowerCase().includes(query) ||\n cube.toLowerCase().includes(query)\n )\n if (matchingDims.length > 0) {\n filtered[cube] = matchingDims\n }\n }\n\n return filtered\n }, [groupedOptions, searchQuery])\n\n // Handle selection\n const handleSelect = useCallback(\n (dimension: string) => {\n onChange(dimension)\n setIsOpen(false)\n setSearchQuery('')\n },\n [onChange]\n )\n\n // Handle clear\n const handleClear = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n onChange(null)\n },\n [onChange]\n )\n\n // Close on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n setSearchQuery('')\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n // Focus search when opened\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n const hasValue = value !== null\n\n return (\n <div className=\"flex-1 min-w-0\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium text-dc-text-muted mb-1\">\n {Icon && <Icon className=\"w-3.5 h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n flex items-center justify-between w-full px-2.5 py-1.5 text-sm\n bg-dc-surface border border-dc-border rounded\n transition-colors hover:border-dc-primary cursor-pointer\n ${isOpen ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`truncate ${hasValue ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {hasValue ? options.find((o) => o.dimension === value)?.label || value : placeholder}\n </span>\n <span className=\"flex items-center gap-1 ml-2\">\n {hasValue && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={handleClear}\n onKeyDown={(e) => e.key === 'Enter' && handleClear(e as unknown as React.MouseEvent)}\n className=\"p-0.5 rounded hover:bg-dc-surface-hover text-dc-text-muted hover:text-dc-text\"\n title=\"Clear\"\n >\n ×\n </span>\n )}\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ${isOpen ? 'rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"absolute z-50 mt-1 left-0 right-0 min-w-[200px] bg-dc-surface border border-dc-border rounded-md shadow-lg\">\n {/* Search Input */}\n <div className=\"p-2 border-b border-dc-border\">\n <div className=\"relative\">\n {SearchIcon && (\n <SearchIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 w-4 h-4 text-dc-text-muted\" />\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full pl-8 pr-3 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text placeholder:text-dc-text-muted focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"max-h-48 overflow-y-auto p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"px-3 py-4 text-sm text-dc-text-muted text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"mb-2 last:mb-0\">\n <div className=\"px-2 py-1 text-xs font-medium text-dc-text-muted uppercase tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n flex items-center justify-between w-full px-3 py-1.5 text-sm\n rounded transition-colors\n ${value === dim.dimension\n ? 'bg-dc-primary-bg text-dc-primary'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }\n `}\n >\n <span>{dim.label}</span>\n {value === dim.dimension && CheckIcon && (\n <CheckIcon className=\"w-4 h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"px-3 py-2 border-t border-dc-border text-xs text-dc-text-muted\">\n {helpText}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\n/**\n * Date range selector component\n * Exported for use in RetentionModeContent\n */\nexport interface DateRangeSelectorProps {\n dateRange: DateRange\n onDateRangeChange: (range: DateRange) => void\n}\n\nexport const DateRangeSelector = memo(function DateRangeSelector({\n dateRange,\n onDateRangeChange,\n}: DateRangeSelectorProps) {\n // Safe defaults if dateRange is undefined\n const safeDateRange = dateRange ?? { start: '', end: '' }\n const safeStart = safeDateRange.start ?? ''\n const safeEnd = safeDateRange.end ?? ''\n\n const [showDatePicker, setShowDatePicker] = useState(false)\n const [selectedPreset, setSelectedPreset] = useState<DateRangePreset>(() =>\n safeStart && safeEnd ? detectDateRangePreset(safeDateRange) : 'last_3_months'\n )\n const [customStart, setCustomStart] = useState(safeStart)\n const [customEnd, setCustomEnd] = useState(safeEnd)\n const dropdownRef = useRef<HTMLDivElement>(null)\n\n // Update custom inputs when date range changes externally\n useEffect(() => {\n const start = dateRange?.start ?? ''\n const end = dateRange?.end ?? ''\n setCustomStart(start)\n setCustomEnd(end)\n if (start && end) {\n setSelectedPreset(detectDateRangePreset({ start, end }))\n }\n }, [dateRange?.start, dateRange?.end])\n\n // Handle preset selection\n const handlePresetSelect = useCallback(\n (preset: DateRangePreset) => {\n setSelectedPreset(preset)\n if (preset !== 'custom') {\n const range = getDateRangeFromPreset(preset)\n onDateRangeChange(range)\n setCustomStart(range.start)\n setCustomEnd(range.end)\n setShowDatePicker(false)\n }\n },\n [onDateRangeChange]\n )\n\n // Handle custom date apply\n const handleCustomDateApply = useCallback(() => {\n if (customStart && customEnd) {\n onDateRangeChange({ start: customStart, end: customEnd })\n setSelectedPreset('custom')\n setShowDatePicker(false)\n }\n }, [customStart, customEnd, onDateRangeChange])\n\n // Close on outside click\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setShowDatePicker(false)\n }\n }\n\n if (showDatePicker) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [showDatePicker])\n\n // Get display text for date range\n const dateRangeDisplay = useMemo(() => {\n const preset = RETENTION_DATE_RANGE_PRESETS.find((p) => p.value === selectedPreset)\n if (preset && selectedPreset !== 'custom') {\n return preset.label\n }\n const start = dateRange?.start ?? ''\n const end = dateRange?.end ?? ''\n if (!start || !end) return 'Select date range'\n return `${formatDateDisplay(start)} - ${formatDateDisplay(end)}`\n }, [selectedPreset, dateRange])\n\n return (\n <div className=\"flex-1 min-w-0\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium text-dc-text-muted mb-1\">\n {CalendarIcon && <CalendarIcon className=\"w-3.5 h-3.5\" />}\n Date Range\n </label>\n\n <div ref={dropdownRef} className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setShowDatePicker(!showDatePicker)}\n className={`\n flex items-center justify-between w-full px-2.5 py-1.5 text-sm\n bg-dc-surface border border-dc-border rounded\n hover:border-dc-primary cursor-pointer transition-colors\n ${showDatePicker ? 'border-dc-primary ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className=\"text-dc-text truncate\">{dateRangeDisplay}</span>\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`w-4 h-4 text-dc-text-muted transition-transform ml-2 ${showDatePicker ? 'rotate-180' : ''}`}\n />\n )}\n </button>\n\n {/* Date Range Dropdown */}\n {showDatePicker && (\n <div className=\"absolute z-50 mt-1 left-0 right-0 min-w-[280px] bg-dc-surface border border-dc-border rounded-lg shadow-lg p-3\">\n {/* Presets */}\n <div className=\"grid grid-cols-2 gap-2 mb-3\">\n {RETENTION_DATE_RANGE_PRESETS.filter((p) => p.value !== 'custom').map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n onClick={() => handlePresetSelect(preset.value)}\n className={`px-3 py-1.5 text-xs rounded transition-colors ${\n selectedPreset === preset.value\n ? 'bg-dc-primary text-white'\n : 'bg-dc-surface-secondary text-dc-text hover:bg-dc-surface-hover'\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n\n {/* Custom Range */}\n <div className=\"border-t border-dc-border pt-3\">\n <div className=\"text-xs font-medium text-dc-text-muted mb-2\">Custom Range</div>\n <div className=\"flex gap-2 items-center mb-2\">\n <input\n type=\"date\"\n value={customStart}\n onChange={(e) => {\n setCustomStart(e.target.value)\n setSelectedPreset('custom')\n }}\n className=\"flex-1 px-2 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n <span className=\"text-dc-text-muted text-xs\">to</span>\n <input\n type=\"date\"\n value={customEnd}\n onChange={(e) => {\n setCustomEnd(e.target.value)\n setSelectedPreset('custom')\n }}\n className=\"flex-1 px-2 py-1.5 text-sm bg-dc-surface-secondary border border-dc-border rounded text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleCustomDateApply}\n disabled={!customStart || !customEnd}\n className=\"w-full px-3 py-1.5 text-xs bg-dc-primary text-white rounded hover:bg-dc-primary-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n Apply Custom Range\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n})\n\n/**\n * RetentionConfigPanel displays selectors for cube, binding key, time dimension,\n * and date range in a collapsible section.\n */\nconst RetentionConfigPanel = memo(function RetentionConfigPanel({\n selectedCube = null,\n bindingKey = null,\n timeDimension = null,\n dateRange = { start: '', end: '' },\n schema = null,\n onCubeChange = () => {},\n onBindingKeyChange = () => {},\n onTimeDimensionChange = () => {},\n}: RetentionConfigPanelProps) {\n // Get available options\n const availableCubes = useMemo(() => getAvailableCubes(schema), [schema])\n\n // Filter binding keys by selected cube\n const availableBindingKeys = useMemo(() => {\n const allKeys = getAvailableBindingKeyDimensions(schema)\n if (!selectedCube) return []\n return allKeys.filter((key) => key.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Filter time dimensions by selected cube\n const availableTimeDimensions = useMemo(() => {\n const allTimeDims = getAvailableTimeDimensions(schema)\n if (!selectedCube) return []\n return allTimeDims.filter((dim) => dim.cube === selectedCube)\n }, [schema, selectedCube])\n\n // Check if all config is complete\n const isConfigComplete = Boolean(\n selectedCube && bindingKey?.dimension && timeDimension && dateRange?.start && dateRange?.end\n )\n\n // Collapsed state - start expanded if config is incomplete\n const [isCollapsed, setIsCollapsed] = useState(false)\n\n // Auto-collapse when config becomes complete (only once)\n const hasAutoCollapsedRef = useRef(false)\n useEffect(() => {\n if (isConfigComplete && !hasAutoCollapsedRef.current) {\n hasAutoCollapsedRef.current = true\n setIsCollapsed(true)\n }\n }, [isConfigComplete])\n\n // Convert FunnelBindingKey to string for simpler handling\n const bindingKeyValue = bindingKey?.dimension\n ? typeof bindingKey.dimension === 'string'\n ? bindingKey.dimension\n : bindingKey.dimension[0]?.dimension || null\n : null\n\n const handleBindingKeyChange = useCallback(\n (value: string | null) => {\n onBindingKeyChange(value ? { dimension: value } : null)\n },\n [onBindingKeyChange]\n )\n\n // Get display label for the collapsed summary\n const cubeLabel = availableCubes.find((c) => c.dimension === selectedCube)?.label || selectedCube\n const dateLabel = dateRange?.start\n ? `${formatDateDisplay(dateRange.start)} - ${formatDateDisplay(dateRange.end)}`\n : ''\n\n return (\n <div className=\"bg-dc-surface-secondary border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"flex items-center justify-between w-full px-4 py-2.5 hover:bg-dc-surface-hover transition-colors\"\n >\n <div className=\"flex items-center gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"w-4 h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"flex items-center gap-1 text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"w-3.5 h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"text-xs text-dc-text-muted truncate max-w-[200px]\">\n {cubeLabel} • {dateLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"flex flex-col gap-3 px-4 pb-3\">\n {/* Cube Selector */}\n <DropdownSelector\n value={selectedCube}\n label=\"Cube\"\n placeholder=\"Select cube\"\n icon={CubeIcon}\n options={availableCubes}\n onChange={onCubeChange}\n helpText=\"Select the cube containing your user events\"\n />\n\n {/* Binding Key Selector */}\n <DropdownSelector\n value={bindingKeyValue}\n label=\"Binding Key\"\n placeholder={selectedCube ? 'Select user identifier' : 'Select cube first'}\n icon={LinkIcon}\n options={availableBindingKeys}\n onChange={handleBindingKeyChange}\n helpText=\"Dimension that identifies entities across events (e.g., user ID, customer ID)\"\n />\n\n {/* Time Dimension Selector */}\n <DropdownSelector\n value={timeDimension}\n label=\"Timestamp\"\n placeholder={selectedCube ? 'Select timestamp' : 'Select cube first'}\n icon={TimeDimensionIcon}\n options={availableTimeDimensions}\n onChange={onTimeDimensionChange}\n helpText=\"Timestamp field for cohort entry and activity\"\n />\n </div>\n )}\n </div>\n )\n})\n\nexport default RetentionConfigPanel\n","/**\n * RetentionModeContent Component\n *\n * Container for all retention mode UI in AnalysisBuilder.\n * Displays tabs for Retention Configuration and Display options.\n *\n * Pattern matches FlowModeContent for consistency:\n * - Collapsible config panel at top\n * - Flat sections for filters, breakdowns, settings\n * - Reuses existing components (AnalysisFilterSection, BreakdownSection)\n */\n\nimport { memo, useState, useCallback, useMemo } from 'react'\nimport type { CubeMeta, FunnelBindingKey, ChartType, ChartDisplayConfig, Filter } from '../../types'\nimport type { ColorPalette } from '../../utils/colorPalettes'\nimport type {\n DateRange,\n RetentionGranularity,\n RetentionType,\n RetentionBreakdownItem,\n} from '../../types/retention'\nimport {\n RETENTION_GRANULARITY_OPTIONS,\n RETENTION_TYPE_OPTIONS,\n RETENTION_MIN_PERIODS,\n RETENTION_MAX_PERIODS,\n} from '../../types/retention'\nimport type { MetaResponse } from '../../shared/types'\nimport type { BreakdownItem } from './types'\nimport RetentionConfigPanel, { DateRangeSelector } from './RetentionConfigPanel'\nimport AnalysisDisplayConfigPanel from './AnalysisDisplayConfigPanel'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport BreakdownSection from './BreakdownSection'\nimport SectionHeading from './SectionHeading'\n\ntype RetentionPanelTab = 'config' | 'display'\n\nexport interface RetentionModeContentProps {\n /** Currently selected cube for retention analysis */\n retentionCube: string | null\n /** Binding key that links events to entities */\n retentionBindingKey: FunnelBindingKey | null\n /** Time dimension for event ordering */\n retentionTimeDimension: string | null\n /** Date range for cohort analysis */\n retentionDateRange: DateRange\n /** Cohort filters - define who enters the cohort */\n retentionCohortFilters: Filter[]\n /** Activity filters - define what counts as a return */\n retentionActivityFilters: Filter[]\n /** Breakdown dimensions for segmentation */\n retentionBreakdowns: RetentionBreakdownItem[]\n /** Granularity for viewing retention periods */\n retentionViewGranularity: RetentionGranularity\n /** Number of periods to analyze */\n retentionPeriods: number\n /** Retention calculation type */\n retentionType: RetentionType\n /** Cube metadata for field selection */\n schema: CubeMeta | null\n\n // Actions - Configuration\n /** Callback when cube changes */\n onCubeChange: (cube: string | null) => void\n /** Callback when binding key changes */\n onBindingKeyChange: (key: FunnelBindingKey | null) => void\n /** Callback when time dimension changes */\n onTimeDimensionChange: (dim: string | null) => void\n /** Callback when date range changes */\n onDateRangeChange: (range: DateRange) => void\n /** Callback when cohort filters change */\n onCohortFiltersChange: (filters: Filter[]) => void\n /** Callback when activity filters change */\n onActivityFiltersChange: (filters: Filter[]) => void\n /** Callback when breakdowns change (set all) */\n onBreakdownsChange: (breakdowns: RetentionBreakdownItem[]) => void\n /** Callback to add a breakdown */\n onAddBreakdown: (breakdown: RetentionBreakdownItem) => void\n /** Callback to remove a breakdown */\n onRemoveBreakdown: (field: string) => void\n /** Callback when granularity changes */\n onGranularityChange: (granularity: RetentionGranularity) => void\n /** Callback when periods changes */\n onPeriodsChange: (periods: number) => void\n /** Callback when retention type changes */\n onRetentionTypeChange: (type: RetentionType) => void\n /** Callback to open field modal for adding breakdowns */\n onOpenFieldModal?: () => void\n\n // Display configuration (optional - for Display tab)\n /** Chart type for retention display */\n chartType?: ChartType\n /** Callback when chart type changes */\n onChartTypeChange?: (type: ChartType) => void\n /** Display configuration */\n displayConfig?: ChartDisplayConfig\n /** Color palette */\n colorPalette?: ColorPalette\n /** Callback when display config changes */\n onDisplayConfigChange?: (config: ChartDisplayConfig) => void\n}\n\n/**\n * Convert RetentionBreakdownItem[] to BreakdownItem[] for BreakdownSection\n */\nfunction convertToBreakdownItems(items: RetentionBreakdownItem[] | undefined | null): BreakdownItem[] {\n if (!items || !Array.isArray(items)) return []\n return items.map((item) => ({\n id: item.field, // Use field as id\n field: item.field,\n isTimeDimension: false, // Retention breakdowns are never time dimensions\n granularity: undefined,\n enableComparison: false,\n }))\n}\n\n/**\n * RetentionModeContent displays the complete retention configuration interface:\n * - Tabs: Retention | Display\n * - Retention tab: Config panel + cohort filter + activity filter + breakdown + settings\n * - Display tab: Heatmap/chart display options\n */\nconst RetentionModeContent = memo(function RetentionModeContent({\n retentionCube = null,\n retentionBindingKey = null,\n retentionTimeDimension = null,\n retentionDateRange = { start: '', end: '' },\n retentionCohortFilters = [],\n retentionActivityFilters = [],\n retentionBreakdowns = [],\n retentionViewGranularity = 'week',\n retentionPeriods = 12,\n retentionType = 'classic',\n schema = null,\n onCubeChange = () => {},\n onBindingKeyChange = () => {},\n onTimeDimensionChange = () => {},\n onDateRangeChange = () => {},\n onCohortFiltersChange = () => {},\n onActivityFiltersChange = () => {},\n onBreakdownsChange: _onBreakdownsChange = () => {},\n onAddBreakdown: _onAddBreakdown = () => {},\n onRemoveBreakdown = () => {},\n onGranularityChange = () => {},\n onPeriodsChange = () => {},\n onRetentionTypeChange = () => {},\n onOpenFieldModal = () => {},\n // Display props\n chartType = 'retentionCombined',\n onChartTypeChange: _onChartTypeChange,\n displayConfig,\n colorPalette,\n onDisplayConfigChange,\n}: RetentionModeContentProps) {\n const [activeTab, setActiveTab] = useState<RetentionPanelTab>('config')\n\n // Check if display tab is available\n const hasDisplayTab = displayConfig && onDisplayConfigChange\n\n // Filter schema to only include the selected cube\n // Cast to MetaResponse for compatibility with AnalysisFilterSection\n const filteredSchema = useMemo((): MetaResponse | null => {\n if (!schema || !retentionCube) return schema as MetaResponse | null\n return {\n ...schema,\n cubes: schema.cubes?.filter((c) => c.name === retentionCube) || [],\n } as MetaResponse\n }, [schema, retentionCube])\n\n // Convert breakdowns to BreakdownItem format for BreakdownSection\n const breakdownItems = useMemo(\n () => convertToBreakdownItems(retentionBreakdowns),\n [retentionBreakdowns]\n )\n\n // Handler for breakdown removal (converts id back to field)\n const handleRemoveBreakdown = useCallback(\n (id: string) => {\n onRemoveBreakdown(id) // id is the field name\n },\n [onRemoveBreakdown]\n )\n\n // Handler for adding breakdown via BreakdownSection (opens field modal)\n const handleAddBreakdown = useCallback(() => {\n if (onOpenFieldModal) {\n onOpenFieldModal()\n }\n }, [onOpenFieldModal])\n\n // No-op handlers for BreakdownSection (retention doesn't use granularity/comparison)\n const handleGranularityChange = useCallback(() => {\n // No-op - retention breakdowns don't have granularity\n }, [])\n\n return (\n <div className=\"flex flex-col h-full min-h-0 overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Retention\n </button>\n <button\n onClick={() => hasDisplayTab && setActiveTab('display')}\n disabled={!hasDisplayTab}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={!hasDisplayTab ? 'Display options not available' : 'Display options'}\n >\n Display\n </button>\n </div>\n\n {/* Tab Content */}\n {activeTab === 'config' ? (\n <div className=\"flex flex-col flex-1 min-h-0\">\n {/* Configuration Panel - Cube + Binding Key + Time Dimension */}\n <RetentionConfigPanel\n selectedCube={retentionCube}\n bindingKey={retentionBindingKey}\n timeDimension={retentionTimeDimension}\n dateRange={retentionDateRange}\n schema={schema}\n onCubeChange={onCubeChange}\n onBindingKeyChange={onBindingKeyChange}\n onTimeDimensionChange={onTimeDimensionChange}\n />\n\n {/* Retention Configuration - scrollable */}\n <div className=\"flex-1 min-h-0 overflow-auto p-4 space-y-6\">\n {/* Date Range Selector - at top for visibility */}\n <div>\n <SectionHeading>Date Range</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Select the date range for cohort entry. Users who first appear within this range will be analyzed.\n </p>\n <DateRangeSelector\n dateRange={retentionDateRange}\n onDateRangeChange={onDateRangeChange}\n />\n </div>\n\n {/* Cohort Filter Section */}\n <div>\n <SectionHeading>Cohort Filter</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Define who enters the cohort. Users whose first event matches these filters within the date range are included.\n </p>\n <AnalysisFilterSection\n filters={retentionCohortFilters}\n schema={filteredSchema}\n onFiltersChange={onCohortFiltersChange}\n dimensionsOnly={true}\n />\n </div>\n\n {/* Return Filter Section */}\n <div>\n <SectionHeading>Return Filter</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Define what counts as a return. Events matching these filters in subsequent periods count as retention.\n </p>\n <AnalysisFilterSection\n filters={retentionActivityFilters}\n schema={filteredSchema}\n onFiltersChange={onActivityFiltersChange}\n dimensionsOnly={true}\n />\n </div>\n\n {/* Breakdown Section */}\n <div>\n <SectionHeading>Breakdown</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Optionally segment retention by dimensions (e.g., country, plan type).\n </p>\n <BreakdownSection\n breakdowns={breakdownItems}\n schema={filteredSchema}\n onAdd={handleAddBreakdown}\n onRemove={handleRemoveBreakdown}\n onGranularityChange={handleGranularityChange}\n />\n </div>\n\n {/* Settings Section */}\n <div>\n <SectionHeading>Settings</SectionHeading>\n <p className=\"text-xs text-dc-text-muted mb-3\">\n Configure how retention is calculated and displayed.\n </p>\n\n <div className=\"space-y-4\">\n {/* Granularity */}\n <div>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-1\">\n Period Granularity\n </label>\n <div className=\"flex gap-2\">\n {RETENTION_GRANULARITY_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onGranularityChange(option.value)}\n className={`flex-1 px-3 py-2 rounded-md border text-sm font-medium transition-colors ${\n retentionViewGranularity === option.value\n ? 'border-dc-primary bg-dc-primary/10 text-dc-primary'\n : 'border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text'\n }`}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Number of Periods */}\n <div>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-1\">\n Number of Periods ({RETENTION_MIN_PERIODS}-{RETENTION_MAX_PERIODS})\n </label>\n <div className=\"flex items-center gap-4\">\n <input\n type=\"range\"\n min={RETENTION_MIN_PERIODS}\n max={RETENTION_MAX_PERIODS}\n value={retentionPeriods}\n onChange={(e) => onPeriodsChange(parseInt(e.target.value, 10))}\n className=\"flex-1\"\n />\n <span className=\"w-8 text-sm font-medium text-dc-text text-center\">\n {retentionPeriods}\n </span>\n </div>\n {retentionPeriods > 26 && (\n <p className=\"mt-1 text-xs text-dc-warning\">\n High period count may impact query performance.\n </p>\n )}\n </div>\n\n {/* Retention Type */}\n <div>\n <label className=\"block text-xs font-medium text-dc-text-muted mb-1\">\n Retention Type\n </label>\n <div className=\"flex gap-2\">\n {RETENTION_TYPE_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onRetentionTypeChange(option.value)}\n className={`flex-1 px-3 py-2 rounded-md border text-sm transition-colors ${\n retentionType === option.value\n ? 'border-dc-primary bg-dc-primary/10 text-dc-primary'\n : 'border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text'\n }`}\n >\n <div className=\"flex flex-col items-center gap-0.5\">\n <span className=\"font-medium\">{option.label}</span>\n <span className=\"text-[10px] font-normal text-dc-text-muted\">\n {option.description}\n </span>\n </div>\n </button>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n ) : activeTab === 'display' && displayConfig && onDisplayConfigChange ? (\n <div className=\"flex-1 min-h-0 overflow-auto p-4\">\n <AnalysisDisplayConfigPanel\n chartType={chartType}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n </div>\n ) : null}\n </div>\n )\n})\n\nexport default RetentionModeContent\n","/**\n * AnalysisQueryPanel Component\n *\n * Right-side panel containing Query and Chart tabs with sections for\n * Metrics, Filters, and Breakdowns.\n */\n\nimport React, { useEffect, memo, useCallback, useMemo } from 'react'\nimport type { AnalysisQueryPanelProps, BreakdownItem } from './types'\nimport type { MetaField } from '../../shared/types'\nimport type { QueryMergeStrategy, CubeMeta } from '../../types'\nimport { getIcon } from '../../icons'\nimport MetricsSection from './MetricsSection'\nimport BreakdownSection from './BreakdownSection'\nimport BreakdownItemCard from './BreakdownItemCard'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport AnalysisChartConfigPanel from './AnalysisChartConfigPanel'\nimport AnalysisDisplayConfigPanel from './AnalysisDisplayConfigPanel'\nimport FunnelBindingKeySelector from './FunnelBindingKeySelector'\nimport AnalysisTypeSelector from './AnalysisTypeSelector'\nimport FunnelModeContent from './FunnelModeContent'\nimport FlowModeContent from './FlowModeContent'\nimport RetentionModeContent from './RetentionModeContent'\n\nconst AddIcon = getIcon('add')\nconst CloseIcon = getIcon('close')\nconst InfoIcon = getIcon('info')\nconst WarningIcon = getIcon('warning')\nconst LinkIcon = getIcon('link')\n\n/**\n * AnalysisQueryPanel displays the right-side query builder with:\n * - Query/Chart tab switcher (with multi-query support)\n * - Metrics section (measures)\n * - Filter section\n * - Breakdown section (dimensions)\n * - Chart configuration (in Chart tab)\n */\nconst AnalysisQueryPanel = memo(function AnalysisQueryPanel({\n metrics,\n breakdowns,\n filters,\n schema,\n activeTab,\n onActiveTabChange,\n onAddMetric,\n onRemoveMetric,\n onReorderMetrics,\n onAddBreakdown,\n onRemoveBreakdown,\n onBreakdownGranularityChange,\n onBreakdownComparisonToggle,\n onReorderBreakdowns,\n onFiltersChange,\n onDropFieldToFilter,\n // Sorting\n order,\n onOrderChange,\n // Chart configuration\n chartType,\n chartConfig,\n displayConfig,\n colorPalette,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange,\n onDisplayConfigChange,\n // Validation\n validationStatus: _validationStatus,\n validationError: _validationError,\n // Multi-query props\n queryCount = 1,\n activeQueryIndex = 0,\n mergeStrategy = 'concat',\n onActiveQueryChange,\n onAddQuery,\n onRemoveQuery,\n onMergeStrategyChange,\n breakdownsLocked = false,\n combinedMetrics,\n combinedBreakdowns,\n multiQueryValidation,\n adapterValidation,\n // Funnel props (legacy - for merge strategy mode)\n funnelBindingKey,\n onFunnelBindingKeyChange,\n // Analysis Type props\n analysisType = 'query',\n onAnalysisTypeChange,\n // Funnel Mode props (new dedicated state)\n funnelCube = null,\n funnelSteps = [],\n activeFunnelStepIndex = 0,\n funnelTimeDimension,\n onFunnelCubeChange,\n onAddFunnelStep,\n onRemoveFunnelStep,\n onUpdateFunnelStep,\n onSelectFunnelStep,\n onReorderFunnelSteps,\n onFunnelTimeDimensionChange,\n // Funnel display config (for Display tab)\n funnelDisplayConfig,\n onFunnelDisplayConfigChange,\n // Flow Mode props\n flowCube,\n flowBindingKey,\n flowTimeDimension,\n eventDimension,\n startingStep,\n stepsBefore = 3,\n stepsAfter = 3,\n flowJoinStrategy = 'auto',\n onFlowCubeChange,\n onFlowBindingKeyChange,\n onFlowTimeDimensionChange,\n onEventDimensionChange,\n onStartingStepFiltersChange,\n onStepsBeforeChange,\n onStepsAfterChange,\n onFlowJoinStrategyChange,\n flowDisplayConfig,\n onFlowDisplayConfigChange,\n // Retention Mode props (simplified Mixpanel-style)\n retentionCube,\n retentionBindingKey,\n retentionTimeDimension,\n retentionDateRange,\n retentionCohortFilters = [],\n retentionActivityFilters = [],\n retentionBreakdowns = [],\n retentionViewGranularity = 'week',\n retentionPeriods = 12,\n retentionType = 'classic',\n onRetentionCubeChange,\n onRetentionBindingKeyChange,\n onRetentionTimeDimensionChange,\n onRetentionDateRangeChange,\n onRetentionCohortFiltersChange,\n onRetentionActivityFiltersChange,\n onRetentionBreakdownsChange,\n onAddRetentionBreakdown,\n onRemoveRetentionBreakdown,\n onRetentionViewGranularityChange,\n onRetentionPeriodsChange,\n onRetentionTypeChange,\n retentionDisplayConfig,\n onRetentionDisplayConfigChange,\n}: AnalysisQueryPanelProps) {\n // Mark unused props\n void _validationStatus\n void _validationError\n\n const isMultiQuery = queryCount > 1\n // Note: Legacy mergeStrategy === 'funnel' is no longer supported\n // Funnel mode is determined by analysisType === 'funnel'\n const isFunnelMode = analysisType === 'funnel'\n // Flow mode is determined by analysisType === 'flow'\n const isFlowMode = analysisType === 'flow'\n // Retention mode is determined by analysisType === 'retention'\n const isRetentionMode = analysisType === 'retention'\n\n // Alias for clarity - same as isFunnelMode now\n const isNewFunnelMode = analysisType === 'funnel'\n\n // Helper to find field metadata for a breakdown\n const getFieldMeta = useCallback((breakdown: BreakdownItem): MetaField | null => {\n if (!schema?.cubes) return null\n const [cubeName] = breakdown.field.split('.')\n const cube = schema.cubes.find(c => c.name === cubeName)\n if (!cube) return null\n // Check dimensions first, then time dimensions (which are in dimensions array)\n return cube.dimensions?.find(d => d.name === breakdown.field) || null\n }, [schema])\n\n // Check if another breakdown already has comparison enabled\n const comparisonEnabledBreakdown = useMemo(() => {\n return breakdowns.find(b => b.isTimeDimension && b.enableComparison)\n }, [breakdowns])\n\n // Force query tab when no metrics are selected\n useEffect(() => {\n if (metrics.length === 0 && (activeTab === 'chart' || activeTab === 'display')) {\n onActiveTabChange('query')\n }\n }, [metrics.length, activeTab, onActiveTabChange])\n\n // Handle query tab click\n const handleQueryTabClick = useCallback((index: number) => {\n onActiveQueryChange?.(index)\n // Ensure we're on the query tab when switching queries\n if (activeTab !== 'query') {\n onActiveTabChange('query')\n }\n }, [onActiveQueryChange, activeTab, onActiveTabChange])\n\n // Handle remove query\n const handleRemoveQuery = useCallback((e: React.MouseEvent, index: number) => {\n e.stopPropagation()\n onRemoveQuery?.(index)\n }, [onRemoveQuery])\n\n // Get tab label for query tabs\n const getQueryTabLabel = (index: number) => {\n if (!isMultiQuery) return 'Query'\n // In funnel mode, show \"S1\", \"S2\", etc.\n if (isFunnelMode) return `S${index + 1}`\n return `Q${index + 1}`\n }\n\n return (\n <div className=\"h-full flex flex-col bg-dc-surface\">\n {/* Analysis Type Selector - always visible */}\n {onAnalysisTypeChange && (\n <AnalysisTypeSelector\n value={analysisType}\n onChange={onAnalysisTypeChange}\n schema={schema as CubeMeta | null}\n />\n )}\n\n {/* Funnel Mode - dedicated UI when analysisType === 'funnel' */}\n {isNewFunnelMode && onFunnelCubeChange && onAddFunnelStep && onRemoveFunnelStep && onUpdateFunnelStep && onSelectFunnelStep && onReorderFunnelSteps && onFunnelTimeDimensionChange && onFunnelBindingKeyChange ? (\n <FunnelModeContent\n funnelCube={funnelCube}\n funnelSteps={funnelSteps}\n activeFunnelStepIndex={activeFunnelStepIndex}\n funnelTimeDimension={funnelTimeDimension ?? null}\n funnelBindingKey={funnelBindingKey ?? null}\n schema={schema as CubeMeta | null}\n onCubeChange={onFunnelCubeChange}\n onAddStep={onAddFunnelStep}\n onRemoveStep={onRemoveFunnelStep}\n onUpdateStep={onUpdateFunnelStep}\n onSelectStep={onSelectFunnelStep}\n onReorderSteps={onReorderFunnelSteps}\n onTimeDimensionChange={onFunnelTimeDimensionChange}\n onBindingKeyChange={onFunnelBindingKeyChange}\n // Display tab props\n chartType=\"funnel\"\n displayConfig={funnelDisplayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onFunnelDisplayConfigChange}\n />\n ) : isFlowMode && onFlowCubeChange && onFlowBindingKeyChange && onFlowTimeDimensionChange && onEventDimensionChange && onStartingStepFiltersChange && onStepsBeforeChange && onStepsAfterChange && startingStep ? (\n /* Flow Mode - dedicated UI when analysisType === 'flow' */\n <FlowModeContent\n flowCube={flowCube ?? null}\n flowBindingKey={flowBindingKey ?? null}\n flowTimeDimension={flowTimeDimension ?? null}\n eventDimension={eventDimension ?? null}\n startingStep={startingStep}\n stepsBefore={stepsBefore}\n stepsAfter={stepsAfter}\n joinStrategy={flowJoinStrategy}\n schema={schema as CubeMeta | null}\n onCubeChange={onFlowCubeChange}\n onBindingKeyChange={onFlowBindingKeyChange}\n onTimeDimensionChange={onFlowTimeDimensionChange}\n onEventDimensionChange={onEventDimensionChange}\n onStartingStepFiltersChange={onStartingStepFiltersChange}\n onStepsBeforeChange={onStepsBeforeChange}\n onStepsAfterChange={onStepsAfterChange}\n onJoinStrategyChange={onFlowJoinStrategyChange}\n // Chart type (now core - affects query aggregation)\n chartType={chartType}\n onChartTypeChange={onChartTypeChange}\n // Display tab props\n displayConfig={flowDisplayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onFlowDisplayConfigChange}\n />\n ) : isRetentionMode ? (\n /* Retention Mode - dedicated UI when analysisType === 'retention' (simplified Mixpanel-style) */\n <RetentionModeContent\n retentionCube={retentionCube ?? null}\n retentionBindingKey={retentionBindingKey ?? null}\n retentionTimeDimension={retentionTimeDimension ?? null}\n retentionDateRange={retentionDateRange ?? { start: '', end: '' }}\n retentionCohortFilters={retentionCohortFilters}\n retentionActivityFilters={retentionActivityFilters}\n retentionBreakdowns={retentionBreakdowns}\n retentionViewGranularity={retentionViewGranularity}\n retentionPeriods={retentionPeriods}\n retentionType={retentionType}\n schema={schema as CubeMeta | null}\n onCubeChange={onRetentionCubeChange ?? (() => {})}\n onBindingKeyChange={onRetentionBindingKeyChange ?? (() => {})}\n onTimeDimensionChange={onRetentionTimeDimensionChange ?? (() => {})}\n onDateRangeChange={onRetentionDateRangeChange ?? (() => {})}\n onCohortFiltersChange={onRetentionCohortFiltersChange ?? (() => {})}\n onActivityFiltersChange={onRetentionActivityFiltersChange ?? (() => {})}\n onBreakdownsChange={onRetentionBreakdownsChange ?? (() => {})}\n onAddBreakdown={onAddRetentionBreakdown ?? (() => {})}\n onRemoveBreakdown={onRemoveRetentionBreakdown ?? (() => {})}\n onGranularityChange={onRetentionViewGranularityChange ?? (() => {})}\n onPeriodsChange={onRetentionPeriodsChange ?? (() => {})}\n onRetentionTypeChange={onRetentionTypeChange ?? (() => {})}\n onOpenFieldModal={onAddBreakdown}\n // Display tab props\n chartType={chartType}\n displayConfig={retentionDisplayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onRetentionDisplayConfigChange}\n />\n ) : (\n <>\n {/* Tab Bar - only shown when not in new funnel mode */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n {/* Query Tabs - show Q1, Q2, etc. when multi-query, or single \"Query\" tab */}\n {isMultiQuery ? (\n <div className=\"flex min-w-0 overflow-x-auto scrollbar-thin\">\n {Array.from({ length: queryCount }).map((_, index) => {\n const isActiveQuery = index === activeQueryIndex && activeTab === 'query'\n return (\n <button\n key={`q${index}`}\n onClick={() => handleQueryTabClick(index)}\n className={`flex items-center gap-1 px-3 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isActiveQuery\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n {getQueryTabLabel(index)}\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => handleRemoveQuery(e, index)}\n onKeyDown={(e) => e.key === 'Enter' && handleRemoveQuery(e as unknown as React.MouseEvent, index)}\n className=\"p-0.5 rounded hover:bg-dc-danger-bg hover:text-dc-error transition-colors ml-0.5\"\n title=\"Remove query\"\n aria-label={`Remove ${getQueryTabLabel(index)}`}\n >\n <CloseIcon className=\"w-3 h-3\" />\n </span>\n </button>\n )\n })}\n {/* Add Query Button */}\n <button\n onClick={onAddQuery}\n className=\"flex items-center justify-center px-2 py-3 text-dc-text-secondary hover:text-dc-text transition-colors flex-shrink-0\"\n title=\"Add query\"\n aria-label=\"Add new query\"\n >\n <AddIcon className=\"w-4 h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onActiveTabChange('query')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'query'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Query\n {/* Add button to convert to multi-query */}\n {onAddQuery && (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation()\n onAddQuery()\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.stopPropagation()\n onAddQuery()\n }\n }}\n className=\"ml-2 p-0.5 rounded hover:bg-dc-surface-hover transition-colors inline-flex items-center\"\n title=\"Add another query\"\n aria-label=\"Add another query\"\n >\n <AddIcon className=\"w-3 h-3\" />\n </span>\n )}\n </button>\n )}\n\n <button\n onClick={() => metrics.length > 0 && onActiveTabChange('chart')}\n disabled={metrics.length === 0}\n className={`px-4 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isMultiQuery ? '' : 'flex-1'\n } ${\n activeTab === 'chart'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={metrics.length === 0 ? 'Add metrics to configure chart' : 'Chart configuration'}\n >\n Chart\n </button>\n <button\n onClick={() => metrics.length > 0 && onActiveTabChange('display')}\n disabled={metrics.length === 0}\n className={`px-4 py-3 text-sm font-medium transition-colors flex-shrink-0 ${\n isMultiQuery ? '' : 'flex-1'\n } ${\n activeTab === 'display'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={metrics.length === 0 ? 'Add metrics to configure display' : 'Display options'}\n >\n Display\n </button>\n </div>\n\n {/* Merge Strategy Controls (only shown when multiple queries and on query tab) */}\n {isMultiQuery && activeTab === 'query' && (\n <div className=\"flex items-center gap-2 px-4 py-1.5 text-sm bg-dc-surface-secondary border-b border-dc-border\">\n {LinkIcon && <LinkIcon className=\"w-3.5 h-3.5 text-dc-text-muted flex-shrink-0\" />}\n <select\n value={mergeStrategy}\n onChange={(e) => onMergeStrategyChange?.(e.target.value as QueryMergeStrategy)}\n className=\"px-2 py-1 text-xs bg-dc-surface border border-dc-border rounded text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n >\n <option value=\"concat\">Separate series</option>\n <option value=\"merge\">Merge by dimension</option>\n <option value=\"funnel\">Funnel</option>\n </select>\n\n {/* Funnel Binding Key Selector (inline, only shown in funnel mode) */}\n {isFunnelMode && onFunnelBindingKeyChange && (\n <FunnelBindingKeySelector\n bindingKey={funnelBindingKey ?? null}\n onChange={onFunnelBindingKeyChange}\n schema={schema}\n className=\"w-[180px] flex-shrink-0\"\n />\n )}\n </div>\n )}\n\n {/* Adapter Validation Errors/Warnings (NEW - Phase 5) */}\n {adapterValidation && (adapterValidation.errors.length > 0 || adapterValidation.warnings.length > 0) && activeTab === 'query' && (\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-warning-bg space-y-1\">\n {adapterValidation.errors.map((error, i) => (\n <div key={`adapter-error-${i}`} className=\"flex items-start gap-2 text-xs text-dc-error\">\n <WarningIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{error}</span>\n </div>\n ))}\n {adapterValidation.warnings.map((warning, i) => (\n <div key={`adapter-warning-${i}`} className=\"flex items-start gap-2 text-xs text-dc-warning\">\n <InfoIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{warning}</span>\n </div>\n ))}\n </div>\n )}\n\n {/* Multi-Query Validation Warnings (hidden in funnel mode - funnels can have same metrics) */}\n {multiQueryValidation && !isFunnelMode && (multiQueryValidation.warnings.length > 0 || multiQueryValidation.errors.length > 0) && activeTab === 'query' && (\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-warning-bg\">\n {multiQueryValidation.errors.map((error, i) => (\n <div key={`error-${i}`} className=\"flex items-start gap-2 text-xs text-dc-error\">\n <WarningIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{error.message}</span>\n </div>\n ))}\n {multiQueryValidation.warnings.map((warning, i) => (\n <div key={`warning-${i}`} className=\"flex items-start gap-2 text-xs text-dc-warning\">\n <WarningIcon className=\"w-3.5 h-3.5 mt-0.5 flex-shrink-0\" />\n <span>{warning.message}</span>\n </div>\n ))}\n </div>\n )}\n\n {/* Tab Content */}\n <div className=\"flex-1 overflow-auto p-4\">\n {activeTab === 'query' ? (\n <div className=\"space-y-6\">\n {/* Metrics Section */}\n <MetricsSection\n metrics={metrics}\n schema={schema}\n onAdd={onAddMetric}\n onRemove={onRemoveMetric}\n order={order}\n onOrderChange={onOrderChange}\n onReorder={onReorderMetrics}\n />\n\n {/* Breakdown Section */}\n {breakdownsLocked ? (\n <div className=\"mb-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text\">Dimensions</h4>\n </div>\n {/* Explanation with link to switch mode */}\n <div className=\"flex items-start gap-2 px-3 py-2 mb-3 bg-dc-surface-secondary rounded border border-dc-border text-xs\">\n {InfoIcon && <InfoIcon className=\"w-4 h-4 text-dc-text-muted flex-shrink-0 mt-0.5\" />}\n <span className=\"text-dc-text-muted\">\n In merge mode, dimensions are shared from Q1.\n {onMergeStrategyChange && (\n <button\n onClick={() => onMergeStrategyChange('concat')}\n className=\"text-dc-primary hover:underline ml-1\"\n >\n Switch to separate series\n </button>\n )}\n </span>\n </div>\n {/* Show breakdown cards with granularity controls (but no remove) */}\n {breakdowns.length > 0 && (\n <div className=\"space-y-1\">\n {breakdowns.map((breakdown) => (\n <BreakdownItemCard\n key={breakdown.id}\n breakdown={breakdown}\n fieldMeta={getFieldMeta(breakdown)}\n onRemove={() => {}} // No-op - can't remove in locked mode\n onGranularityChange={breakdown.isTimeDimension ? (granularity) => onBreakdownGranularityChange(breakdown.id, granularity) : undefined}\n onComparisonToggle={breakdown.isTimeDimension && onBreakdownComparisonToggle ? () => onBreakdownComparisonToggle(breakdown.id) : undefined}\n comparisonDisabled={!!comparisonEnabledBreakdown && comparisonEnabledBreakdown.id !== breakdown.id}\n />\n ))}\n </div>\n )}\n </div>\n ) : (\n <BreakdownSection\n breakdowns={breakdowns}\n schema={schema}\n onAdd={onAddBreakdown}\n onRemove={onRemoveBreakdown}\n onGranularityChange={onBreakdownGranularityChange}\n onComparisonToggle={onBreakdownComparisonToggle}\n order={order}\n onOrderChange={onOrderChange}\n onReorder={onReorderBreakdowns}\n />\n )}\n\n {/* Filter Section */}\n <AnalysisFilterSection\n filters={filters}\n schema={schema}\n onFiltersChange={onFiltersChange}\n onFieldDropped={onDropFieldToFilter}\n />\n </div>\n ) : activeTab === 'chart' ? (\n /* Chart Tab Content - use combined metrics/breakdowns in multi-query mode */\n <AnalysisChartConfigPanel\n chartType={chartType}\n chartConfig={chartConfig}\n metrics={isMultiQuery && combinedMetrics ? combinedMetrics : metrics}\n breakdowns={isMultiQuery && combinedBreakdowns ? combinedBreakdowns : breakdowns}\n schema={schema}\n chartAvailability={chartAvailability}\n onChartTypeChange={onChartTypeChange}\n onChartConfigChange={onChartConfigChange}\n />\n ) : activeTab === 'display' ? (\n /* Display Tab Content */\n <AnalysisDisplayConfigPanel\n chartType={chartType}\n displayConfig={displayConfig}\n colorPalette={colorPalette}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n ) : null}\n </div>\n </>\n )}\n </div>\n )\n})\n\nexport default AnalysisQueryPanel\n","/**\n * AnalysisAIPanel Component\n *\n * A collapsible panel for AI-powered query generation.\n * Appears above the results panel when activated.\n */\n\nimport { useCallback, KeyboardEvent } from 'react'\nimport { getIcon } from '../../icons'\n\nconst SparklesIcon = getIcon('sparkles')\nconst ErrorIcon = getIcon('error')\n\nexport interface AnalysisAIPanelProps {\n /** User's natural language prompt */\n userPrompt: string\n /** Callback when prompt changes */\n onPromptChange: (prompt: string) => void\n /** Whether a query is being generated */\n isGenerating: boolean\n /** Error message from generation */\n error: string | null\n /** Whether the AI has generated a query */\n hasGeneratedQuery: boolean\n /** Callback to generate query */\n onGenerate: () => void\n /** Callback to accept the generated query */\n onAccept: () => void\n /** Callback to cancel and restore previous state */\n onCancel: () => void\n}\n\nexport default function AnalysisAIPanel({\n userPrompt,\n onPromptChange,\n isGenerating,\n error,\n hasGeneratedQuery,\n onGenerate,\n onAccept,\n onCancel\n}: AnalysisAIPanelProps) {\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n onGenerate()\n }\n },\n [onGenerate]\n )\n\n return (\n <div\n className=\"border-b border-dc-border\"\n style={{ background: 'linear-gradient(to right, var(--dc-ai-gradient-start), var(--dc-ai-gradient-end))' }}\n >\n {/* Header */}\n <div className=\"px-4 py-2 flex items-center justify-between border-b border-dc-border bg-dc-surface-secondary\">\n <div className=\"flex items-center gap-2\">\n <SparklesIcon className=\"w-4 h-4 text-dc-accent\" />\n <span className=\"text-sm font-medium text-dc-text\">AI Query Generator</span>\n {isGenerating && (\n <span className=\"text-xs text-dc-accent animate-pulse\">\n Generating...\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {hasGeneratedQuery && (\n <button\n onClick={onAccept}\n className=\"px-3 py-1 text-xs font-medium text-white bg-dc-success hover:opacity-80 rounded transition-colors\"\n >\n Accept\n </button>\n )}\n <button\n onClick={onCancel}\n className=\"px-3 py-1 text-xs font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover border border-dc-border rounded transition-colors\"\n >\n {hasGeneratedQuery ? 'Cancel' : 'Close'}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n <div className=\"flex gap-3\">\n {/* Prompt input */}\n <div className=\"flex-1\">\n <textarea\n value={userPrompt}\n onChange={(e) => onPromptChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Describe your query in natural language... (e.g., 'Show total sales by month for the last year')\"\n className=\"w-full px-3 py-2 text-sm border border-dc-border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-dc-accent focus:border-dc-accent resize-none bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n rows={2}\n disabled={isGenerating}\n />\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n Press Enter to generate, Shift+Enter for new line\n </div>\n </div>\n\n {/* Generate button */}\n <div className=\"flex-shrink-0\">\n <button\n onClick={onGenerate}\n disabled={isGenerating || !userPrompt.trim()}\n className={`px-4 py-2 text-sm font-medium rounded-md transition-colors flex items-center gap-2 ${\n isGenerating || !userPrompt.trim()\n ? 'bg-dc-surface-tertiary text-dc-text-disabled cursor-not-allowed'\n : 'bg-dc-accent hover:bg-dc-accent-hover text-white'\n }`}\n >\n {isGenerating ? (\n <>\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin\" />\n <span>Generating...</span>\n </>\n ) : (\n <>\n <SparklesIcon className=\"w-4 h-4\" />\n <span>Generate</span>\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"mt-3 flex items-start gap-2 p-3 bg-dc-error-bg border border-dc-error-border rounded-md\">\n <ErrorIcon className=\"w-4 h-4 text-dc-error mt-0.5 flex-shrink-0\" />\n <div className=\"text-sm text-dc-error\">{error}</div>\n </div>\n )}\n\n {/* Success message */}\n {hasGeneratedQuery && !error && (\n <div className=\"mt-3 p-3 bg-dc-success-bg border border-dc-success-border rounded-md\">\n <div className=\"text-sm text-dc-success\">\n Query generated and loaded! Check the results below, then click{' '}\n <strong>Accept</strong> to keep or <strong>Cancel</strong> to revert.\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * AnalysisModeErrorBoundary Component (NEW - Phase 5)\n *\n * Error boundary specifically for mode switching in AnalysisBuilder.\n * Catches errors from adapter loading/validation and provides a recovery option.\n * This prevents a broken mode from crashing the entire AnalysisBuilder.\n */\n\nimport React, { Component, ReactNode } from 'react'\nimport { getIcon } from '../../icons'\nimport type { AnalysisType } from '../../types'\n\nconst WarningIcon = getIcon('warning')\nconst RefreshIcon = getIcon('refresh')\n\ninterface Props {\n children: ReactNode\n /** Current analysis type (for error messages) */\n analysisType: AnalysisType\n /** Callback to switch to a safe mode (query) on error */\n onSwitchToSafeMode?: () => void\n}\n\ninterface State {\n hasError: boolean\n error: Error | null\n errorInfo: string | null\n}\n\n/**\n * Error boundary for mode switching in AnalysisBuilder.\n * If an adapter throws during load/validate/save, this catches it\n * and offers to switch back to query mode.\n */\nexport class AnalysisModeErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props)\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n }\n }\n\n static getDerivedStateFromError(error: Error): State {\n return {\n hasError: true,\n error,\n errorInfo: null,\n }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n this.setState({\n error,\n errorInfo: errorInfo.componentStack || null,\n })\n\n console.error(\n `[AnalysisModeErrorBoundary] Error in ${this.props.analysisType} mode:`,\n error,\n errorInfo\n )\n }\n\n handleReset = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null,\n })\n }\n\n handleSwitchToSafeMode = () => {\n this.handleReset()\n this.props.onSwitchToSafeMode?.()\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div className=\"flex flex-col items-center justify-center w-full h-full p-6 text-center bg-dc-surface\">\n <div className=\"h-10 w-10 mb-3 text-dc-warning\">\n {WarningIcon && <WarningIcon className=\"w-10 h-10\" />}\n </div>\n <h3 className=\"text-base font-semibold mb-2 text-dc-text\">\n Mode Error\n </h3>\n <p className=\"text-sm text-dc-text-secondary mb-3 max-w-sm\">\n There was a problem with the <strong>{this.props.analysisType}</strong> mode.\n This might be due to invalid configuration data.\n </p>\n\n {/* Error details (collapsible) */}\n <details className=\"w-full max-w-md mb-4 text-left\">\n <summary className=\"cursor-pointer text-xs text-dc-text-muted hover:text-dc-text\">\n Show error details\n </summary>\n <div className=\"mt-2 p-2 bg-dc-surface-secondary rounded text-xs font-mono text-dc-text-secondary overflow-auto max-h-32\">\n {this.state.error?.message || 'Unknown error'}\n </div>\n </details>\n\n <div className=\"flex gap-2\">\n <button\n onClick={this.handleReset}\n className=\"px-3 py-1.5 border border-dc-border rounded text-sm text-dc-text hover:bg-dc-surface-hover transition-colors flex items-center gap-1\"\n >\n {RefreshIcon && <RefreshIcon className=\"w-4 h-4\" />}\n Try Again\n </button>\n {this.props.onSwitchToSafeMode && (\n <button\n onClick={this.handleSwitchToSafeMode}\n className=\"px-3 py-1.5 bg-dc-primary text-white rounded text-sm hover:opacity-90 transition-opacity\"\n >\n Switch to Query Mode\n </button>\n )}\n </div>\n </div>\n )\n }\n\n return this.props.children\n }\n}\n\nexport default AnalysisModeErrorBoundary\n","/**\n * AnalysisBuilder Component (Refactored)\n *\n * A redesigned query builder with a modern UX:\n * - Results panel on the left (large)\n * - Query builder panel on the right\n * - Search-based field selection via modal\n * - Sections: Metrics (measures), Breakdown (dimensions), Filters\n * - Auto-execute queries on field changes\n *\n * This refactored version uses:\n * - `useAnalysisBuilder` master hook for all state and data fetching\n * - `useAnalysisShare` for share URL functionality\n * - `useAnalysisAI` for AI query generation\n * - Zustand store (via Context) for state management\n * - TanStack Query (via the master hook) for data fetching\n *\n * ARCHITECTURE: Instance-based stores\n * - Each AnalysisBuilder gets its own Zustand store instance\n * - Standalone mode: Uses localStorage persistence\n * - Modal/portlet editing: No persistence, initializes from props\n */\n\nimport { forwardRef, useImperativeHandle, useMemo } from 'react'\nimport { useCubeFeatures, useCubeMeta } from '../../providers/CubeProvider'\nimport { AnalysisBuilderStoreProvider } from '../../stores/analysisBuilderStore'\nimport { useAnalysisBuilder } from '../../hooks/useAnalysisBuilderHook'\nimport { useAnalysisBuilderStoreApi } from '../../stores/analysisBuilderStore'\nimport { useAnalysisAI } from '../../hooks/useAnalysisAI'\nimport { useAnalysisShare } from '../../hooks/useAnalysisShare'\nimport { parseShareHash, decodeAndDecompress } from '../../utils/shareUtils'\nimport type {\n AnalysisBuilderProps,\n AnalysisBuilderRef,\n} from './types'\nimport FieldSearchModal from './FieldSearchModal'\nimport AnalysisResultsPanel from './AnalysisResultsPanel'\nimport AnalysisQueryPanel from './AnalysisQueryPanel'\nimport AnalysisAIPanel from './AnalysisAIPanel'\nimport AnalysisModeErrorBoundary from './AnalysisModeErrorBoundary'\nimport type { MetaResponse } from '../../shared/types'\n\n/**\n * Inner component that uses the store (must be inside provider)\n */\ninterface AnalysisBuilderInnerProps extends Omit<AnalysisBuilderProps, 'initialQuery' | 'initialChartConfig' | 'disableLocalStorage'> {\n hideShare?: boolean\n}\n\nconst AnalysisBuilderInner = forwardRef<AnalysisBuilderRef, AnalysisBuilderInnerProps>(\n (\n {\n className = '',\n maxHeight,\n initialData,\n colorPalette: externalColorPalette,\n hideSettings: _hideSettings = false,\n hideShare = false,\n onQueryChange,\n onChartConfigChange\n },\n ref\n ) => {\n // Mark unused props for future use\n void _hideSettings\n\n // Get context\n const { meta } = useCubeMeta()\n const { features } = useCubeFeatures()\n\n // ========================================================================\n // Master Hook - Provides all state, data fetching, and actions\n // ========================================================================\n const analysis = useAnalysisBuilder({\n initialData,\n externalColorPalette,\n onQueryChange,\n onChartConfigChange,\n })\n\n // ========================================================================\n // AI Hook - Provides AI query generation functionality\n // ========================================================================\n\n // Get the store API for AI integration\n const storeApi = useAnalysisBuilderStoreApi()\n\n const {\n aiState,\n handleOpenAI,\n handleCloseAI,\n handleAIPromptChange,\n handleGenerateAI,\n handleAcceptAI,\n handleCancelAI\n } = useAnalysisAI({\n state: analysis.queryState,\n setState: (updater) => {\n // AI hook needs to update metrics, breakdowns, and filters all at once\n // Use the store's updateQueryState to apply the full state update\n const state = storeApi.getState()\n state.updateQueryState(analysis.activeQueryIndex, (prev) => {\n const newState = typeof updater === 'function' ? updater(prev) : updater\n return {\n ...prev,\n metrics: newState.metrics,\n breakdowns: newState.breakdowns,\n filters: newState.filters,\n }\n })\n },\n chartType: analysis.chartType,\n setChartType: analysis.actions.setChartType,\n chartConfig: analysis.chartConfig,\n setChartConfig: analysis.actions.setChartConfig,\n displayConfig: analysis.displayConfig,\n setDisplayConfig: analysis.actions.setDisplayConfig,\n setUserManuallySelectedChart: () => {\n // The store handles this internally via setChartTypeManual\n },\n setActiveView: analysis.actions.setActiveView,\n aiEndpoint: features?.aiEndpoint,\n // Funnel mode support\n analysisType: analysis.analysisType,\n setAnalysisType: analysis.actions.setAnalysisType,\n loadFunnelFromServerQuery: (serverQuery) => {\n // Create a FunnelAnalysisConfig and load it via the store\n const funnelConfig = {\n version: 1 as const,\n analysisType: 'funnel' as const,\n activeView: 'chart' as const,\n charts: {\n funnel: {\n chartType: 'funnel' as const,\n chartConfig: {},\n displayConfig: {},\n },\n },\n query: serverQuery,\n }\n storeApi.getState().load(funnelConfig)\n },\n // Full config snapshot/restore for complete undo (handles funnel mode properly)\n getFullConfig: () => storeApi.getState().save(),\n loadFullConfig: (config) => storeApi.getState().load(config),\n })\n\n // ========================================================================\n // Share Hook - Provides share URL functionality\n // Uses store.save() to get AnalysisConfig directly (Phase 3)\n // ========================================================================\n const {\n shareButtonState,\n handleShare\n } = useAnalysisShare({\n isValidQuery: analysis.isValidQuery,\n getAnalysisConfig: () => storeApi.getState().save(),\n })\n\n // ========================================================================\n // Derived Values\n // ========================================================================\n\n // Check if current mode can be cleared\n const canClear = useMemo(() => {\n if (analysis.analysisType === 'funnel') {\n // Funnel mode: can clear if there are steps, cube selected, or configuration\n return (\n analysis.funnelSteps.length > 0 ||\n analysis.funnelCube !== null ||\n analysis.funnelBindingKey !== null ||\n analysis.funnelTimeDimension !== null\n )\n }\n // Query mode: can clear if there are metrics, breakdowns, or filters\n return (\n analysis.queryState.metrics.length > 0 ||\n analysis.queryState.breakdowns.length > 0 ||\n analysis.queryState.filters.length > 0\n )\n }, [\n analysis.analysisType,\n analysis.funnelSteps.length,\n analysis.funnelCube,\n analysis.funnelBindingKey,\n analysis.funnelTimeDimension,\n analysis.queryState.metrics.length,\n analysis.queryState.breakdowns.length,\n analysis.queryState.filters.length\n ])\n\n // ========================================================================\n // Expose API via ref\n // ========================================================================\n useImperativeHandle(\n ref,\n () => ({\n getQueryConfig: analysis.getQueryConfig,\n getChartConfig: analysis.getChartConfig,\n getAnalysisType: analysis.getAnalysisType,\n getFunnelState: () => {\n // Read directly from store to ensure fresh values (same pattern as getQueryConfig/getChartConfig)\n const state = storeApi.getState()\n // Get funnel chart config from charts map (Phase 4 - use charts map)\n const funnelConfig = state.charts.funnel || {\n chartType: 'funnel' as const,\n chartConfig: {},\n displayConfig: { showLegend: true, showGrid: true, showTooltip: true },\n }\n return {\n funnelCube: state.funnelCube,\n funnelSteps: state.funnelSteps,\n funnelTimeDimension: state.funnelTimeDimension,\n funnelBindingKey: state.funnelBindingKey,\n funnelChartType: funnelConfig.chartType,\n funnelChartConfig: funnelConfig.chartConfig,\n funnelDisplayConfig: funnelConfig.displayConfig,\n activeFunnelStepIndex: state.activeFunnelStepIndex,\n }\n },\n // Phase 3: Complete AnalysisConfig from store.save()\n getAnalysisConfig: () => storeApi.getState().save(),\n executeQuery: () => {\n // Manual execute would refetch - for now just invalidate cache\n // This could be enhanced to trigger a refetch\n },\n clearQuery: analysis.actions.clearQuery\n }),\n [\n analysis.getQueryConfig,\n analysis.getChartConfig,\n analysis.getAnalysisType,\n analysis.actions.clearQuery,\n storeApi\n ]\n )\n\n // ========================================================================\n // Render\n // ========================================================================\n return (\n <div\n className={`flex flex-col lg:flex-row bg-dc-surface border-x border-b border-dc-border ${maxHeight ? 'lg:h-[var(--dc-max-h)] lg:max-h-[var(--dc-max-h)] lg:overflow-hidden' : 'lg:h-full'} ${className}`}\n style={maxHeight ? { ['--dc-max-h' as string]: maxHeight } : undefined}\n >\n {/* Top/Left Panel - Results */}\n <div className=\"h-[60vh] lg:h-auto lg:flex-1 min-w-0 border-b lg:border-b-0 lg:border-r border-dc-border overflow-auto flex flex-col\">\n {/* AI Panel - expands above results when open */}\n {aiState.isOpen && (\n <AnalysisAIPanel\n userPrompt={aiState.userPrompt}\n onPromptChange={handleAIPromptChange}\n isGenerating={aiState.isGenerating}\n error={aiState.error}\n hasGeneratedQuery={aiState.hasGeneratedQuery}\n onGenerate={handleGenerateAI}\n onAccept={handleAcceptAI}\n onCancel={handleCancelAI}\n />\n )}\n\n {/* Results Panel */}\n <div className=\"flex-1 overflow-auto\">\n <AnalysisResultsPanel\n executionStatus={analysis.executionStatus}\n executionResults={analysis.executionResults}\n executionError={analysis.error?.message || null}\n totalRowCount={null}\n resultsStale={analysis.isLoading && analysis.executionResults !== null}\n chartType={analysis.chartType}\n chartConfig={analysis.chartConfig}\n displayConfig={\n analysis.analysisType === 'flow'\n ? analysis.flowDisplayConfig\n : analysis.analysisType === 'funnel'\n ? analysis.funnelDisplayConfig\n : analysis.displayConfig\n }\n colorPalette={analysis.colorPalette}\n // Only show palette selector in standalone mode (not when editing portlet)\n currentPaletteName={!externalColorPalette ? analysis.localPaletteName : undefined}\n onColorPaletteChange={!externalColorPalette ? analysis.actions.setLocalPaletteName : undefined}\n allQueries={analysis.allQueries}\n funnelExecutedQueries={analysis.funnelExecutedQueries ?? undefined}\n schema={meta as MetaResponse | null}\n activeView={analysis.activeView}\n onActiveViewChange={analysis.actions.setActiveView}\n displayLimit={analysis.displayLimit}\n onDisplayLimitChange={analysis.actions.setDisplayLimit}\n hasMetrics={analysis.analysisType === 'funnel' ? (analysis.funnelSteps.length >= 2 && !!analysis.funnelBindingKey && !!analysis.funnelTimeDimension) : analysis.queryState.metrics.length > 0}\n // Debug props - per-query debug data for multi-query mode\n debugDataPerQuery={analysis.debugDataPerQuery}\n // Share props (hidden when viewing shared analysis with initialQuery)\n onShareClick={hideShare ? undefined : handleShare}\n canShare={hideShare ? false : analysis.isValidQuery}\n shareButtonState={shareButtonState}\n // Refresh props\n onRefreshClick={analysis.actions.refetch}\n canRefresh={analysis.isValidQuery}\n isRefreshing={analysis.isFetching}\n needsRefresh={analysis.needsRefresh}\n // Clear props - use clearCurrentMode to handle both query and funnel modes\n onClearClick={analysis.actions.clearCurrentMode}\n canClear={canClear}\n // AI props\n enableAI={features?.enableAI !== false}\n isAIOpen={aiState.isOpen}\n onAIToggle={aiState.isOpen ? handleCloseAI : handleOpenAI}\n // Multi-query props\n queryCount={analysis.queryStates.length}\n perQueryResults={analysis.perQueryResults ?? undefined}\n activeTableIndex={analysis.activeTableIndex}\n onActiveTableChange={analysis.actions.setActiveTableIndex}\n // Analysis type (new) - primary way to detect mode\n analysisType={analysis.analysisType}\n // Legacy funnel mode prop (deprecated)\n isFunnelMode={analysis.isFunnelModeEnabled}\n // Funnel debug props\n funnelServerQuery={analysis.funnelServerQuery}\n funnelDebugData={analysis.funnelDebugData}\n // Flow debug props\n flowServerQuery={analysis.flowServerQuery}\n flowDebugData={analysis.flowDebugData}\n // Retention debug props\n retentionServerQuery={analysis.retentionServerQuery}\n retentionDebugData={analysis.retentionDebugData}\n retentionChartData={analysis.retentionChartData}\n retentionValidation={analysis.retentionValidation}\n />\n </div>\n </div>\n\n {/* Bottom/Right Panel - Query Builder */}\n <div className=\"w-full lg:w-96 flex-shrink-0 lg:h-full overflow-auto lg:overflow-hidden\">\n <AnalysisModeErrorBoundary\n analysisType={analysis.analysisType}\n onSwitchToSafeMode={() => analysis.actions.setAnalysisType('query')}\n >\n <AnalysisQueryPanel\n metrics={analysis.queryState.metrics}\n breakdowns={analysis.effectiveBreakdowns}\n filters={analysis.queryState.filters}\n schema={meta as MetaResponse | null}\n activeTab={analysis.activeTab}\n onActiveTabChange={analysis.actions.setActiveTab}\n onAddMetric={analysis.actions.openMetricsModal}\n onRemoveMetric={analysis.actions.removeMetric}\n onReorderMetrics={analysis.actions.reorderMetrics}\n onAddBreakdown={analysis.actions.openBreakdownsModal}\n onRemoveBreakdown={analysis.actions.removeBreakdown}\n onBreakdownGranularityChange={analysis.actions.setBreakdownGranularity}\n onBreakdownComparisonToggle={analysis.actions.toggleBreakdownComparison}\n onReorderBreakdowns={analysis.actions.reorderBreakdowns}\n onFiltersChange={analysis.actions.setFilters}\n onDropFieldToFilter={analysis.actions.dropFieldToFilter}\n order={analysis.queryState.order}\n onOrderChange={analysis.actions.setOrder}\n chartType={analysis.chartType}\n chartConfig={analysis.chartConfig}\n displayConfig={analysis.displayConfig}\n colorPalette={analysis.colorPalette}\n chartAvailability={analysis.chartAvailability}\n onChartTypeChange={analysis.actions.setChartType}\n onChartConfigChange={analysis.actions.setChartConfig}\n onDisplayConfigChange={analysis.actions.setDisplayConfig}\n validationStatus={analysis.queryState.validationStatus}\n validationError={analysis.queryState.validationError}\n // Multi-query props\n queryCount={analysis.queryStates.length}\n activeQueryIndex={analysis.activeQueryIndex}\n mergeStrategy={analysis.mergeStrategy}\n onActiveQueryChange={analysis.actions.setActiveQueryIndex}\n onAddQuery={analysis.actions.addQuery}\n onRemoveQuery={analysis.actions.removeQuery}\n onMergeStrategyChange={analysis.actions.setMergeStrategy}\n breakdownsLocked={analysis.mergeStrategy === 'merge' && analysis.activeQueryIndex > 0}\n combinedMetrics={analysis.combinedMetrics}\n combinedBreakdowns={analysis.combinedBreakdowns}\n multiQueryValidation={analysis.multiQueryValidation}\n adapterValidation={analysis.adapterValidation}\n // Funnel props (legacy - merge strategy mode)\n funnelBindingKey={analysis.funnelBindingKey}\n onFunnelBindingKeyChange={analysis.actions.setFunnelBindingKey}\n // Analysis Type props (new)\n analysisType={analysis.analysisType}\n onAnalysisTypeChange={analysis.actions.setAnalysisType}\n // Funnel Mode props (new dedicated state)\n funnelCube={analysis.funnelCube}\n funnelSteps={analysis.funnelSteps}\n activeFunnelStepIndex={analysis.activeFunnelStepIndex}\n funnelTimeDimension={analysis.funnelTimeDimension}\n onFunnelCubeChange={analysis.actions.setFunnelCube}\n onAddFunnelStep={analysis.actions.addFunnelStep}\n onRemoveFunnelStep={analysis.actions.removeFunnelStep}\n onUpdateFunnelStep={analysis.actions.updateFunnelStep}\n onSelectFunnelStep={analysis.actions.setActiveFunnelStepIndex}\n onReorderFunnelSteps={analysis.actions.reorderFunnelSteps}\n onFunnelTimeDimensionChange={analysis.actions.setFunnelTimeDimension}\n // Funnel display config (for Display tab in funnel mode)\n funnelDisplayConfig={analysis.funnelDisplayConfig}\n onFunnelDisplayConfigChange={analysis.actions.setFunnelDisplayConfig}\n // Flow Mode props\n flowCube={analysis.flowCube}\n flowBindingKey={analysis.flowBindingKey}\n flowTimeDimension={analysis.flowTimeDimension}\n eventDimension={analysis.eventDimension}\n startingStep={analysis.startingStep}\n stepsBefore={analysis.stepsBefore}\n stepsAfter={analysis.stepsAfter}\n flowJoinStrategy={analysis.joinStrategy}\n onFlowCubeChange={analysis.actions.setFlowCube}\n onFlowBindingKeyChange={analysis.actions.setFlowBindingKey}\n onFlowTimeDimensionChange={analysis.actions.setFlowTimeDimension}\n onEventDimensionChange={analysis.actions.setEventDimension}\n onStartingStepFiltersChange={analysis.actions.setStartingStepFilters}\n onStepsBeforeChange={analysis.actions.setStepsBefore}\n onStepsAfterChange={analysis.actions.setStepsAfter}\n onFlowJoinStrategyChange={analysis.actions.setJoinStrategy}\n flowDisplayConfig={analysis.flowDisplayConfig}\n onFlowDisplayConfigChange={analysis.actions.setFlowDisplayConfig}\n // Retention Mode props (simplified Mixpanel-style)\n retentionCube={analysis.retentionCube}\n retentionBindingKey={analysis.retentionBindingKey}\n retentionTimeDimension={analysis.retentionTimeDimension}\n retentionDateRange={analysis.retentionDateRange}\n retentionCohortFilters={analysis.retentionCohortFilters}\n retentionActivityFilters={analysis.retentionActivityFilters}\n retentionBreakdowns={analysis.retentionBreakdowns}\n retentionViewGranularity={analysis.retentionViewGranularity}\n retentionPeriods={analysis.retentionPeriods}\n retentionType={analysis.retentionType}\n onRetentionCubeChange={analysis.actions.setRetentionCube}\n onRetentionBindingKeyChange={analysis.actions.setRetentionBindingKey}\n onRetentionTimeDimensionChange={analysis.actions.setRetentionTimeDimension}\n onRetentionDateRangeChange={analysis.actions.setRetentionDateRange}\n onRetentionCohortFiltersChange={analysis.actions.setRetentionCohortFilters}\n onRetentionActivityFiltersChange={analysis.actions.setRetentionActivityFilters}\n onRetentionBreakdownsChange={analysis.actions.setRetentionBreakdowns}\n onAddRetentionBreakdown={analysis.actions.addRetentionBreakdown}\n onRemoveRetentionBreakdown={analysis.actions.removeRetentionBreakdown}\n onRetentionViewGranularityChange={analysis.actions.setRetentionViewGranularity}\n onRetentionPeriodsChange={analysis.actions.setRetentionPeriods}\n onRetentionTypeChange={analysis.actions.setRetentionType}\n retentionDisplayConfig={analysis.retentionDisplayConfig}\n onRetentionDisplayConfigChange={analysis.actions.setRetentionDisplayConfig}\n />\n </AnalysisModeErrorBoundary>\n </div>\n\n {/* Field Search Modal */}\n <FieldSearchModal\n isOpen={analysis.showFieldModal}\n onClose={analysis.actions.closeFieldModal}\n onSelect={analysis.actions.handleFieldSelected}\n mode={analysis.fieldModalMode}\n schema={\n // In retention mode, filter schema to only show the selected cube's fields\n analysis.analysisType === 'retention' && analysis.retentionCube && meta\n ? {\n ...meta,\n cubes: meta.cubes?.filter((c) => c.name === analysis.retentionCube) || [],\n } as MetaResponse\n : meta as MetaResponse | null\n }\n selectedFields={[\n ...analysis.queryState.metrics.map((m) => m.field),\n ...analysis.effectiveBreakdowns.map((b) => b.field),\n // Include retention breakdowns in selected fields to show checkmarks\n ...(analysis.analysisType === 'retention' ? analysis.retentionBreakdowns.map((b) => b.field) : [])\n ]}\n />\n </div>\n )\n }\n)\n\nAnalysisBuilderInner.displayName = 'AnalysisBuilderInner'\n\n/**\n * AnalysisBuilder - Main exported component\n *\n * Wraps the inner component with the store provider to ensure\n * each AnalysisBuilder instance has its own isolated state.\n */\nconst AnalysisBuilder = forwardRef<AnalysisBuilderRef, AnalysisBuilderProps>(\n (props, ref) => {\n const {\n initialQuery,\n initialChartConfig,\n initialAnalysisType,\n initialFunnelState,\n initialFlowState,\n initialRetentionState,\n disableLocalStorage = false,\n ...innerProps\n } = props\n\n // Parse share URL synchronously to extract initial state before store creation\n // This prevents the flash of wrong view (e.g., chart when share specifies table)\n // and ensures analysisType is correct from the start (prevents useEffect race conditions)\n const shareHash = parseShareHash()\n const sharedState = shareHash ? decodeAndDecompress(shareHash) : null\n const initialActiveViewFromShare = sharedState?.activeView\n const initialAnalysisTypeFromShare = sharedState?.analysisType\n\n // Phase 3: Extract funnel state from AnalysisConfig format\n // For funnel mode, funnel config is in query.funnel, chart config is in charts.funnel\n const initialFunnelStateFromShare = (() => {\n if (!sharedState || sharedState.analysisType !== 'funnel') return undefined\n const funnelQuery = 'funnel' in sharedState.query ? sharedState.query.funnel : null\n if (!funnelQuery) return undefined\n\n const funnelChartConfig = sharedState.charts?.funnel\n\n return {\n funnelCube: null, // Not stored in AnalysisConfig directly - will be derived from steps\n funnelSteps: [], // Steps need to be reconstructed from ServerFunnelQuery format\n funnelTimeDimension: typeof funnelQuery.timeDimension === 'string' ? funnelQuery.timeDimension : null,\n funnelBindingKey: funnelQuery.bindingKey\n ? { dimension: funnelQuery.bindingKey }\n : null,\n funnelChartType: funnelChartConfig?.chartType || 'funnel',\n funnelChartConfig: funnelChartConfig?.chartConfig || {},\n funnelDisplayConfig: funnelChartConfig?.displayConfig || {},\n }\n })()\n\n // Extract flow state from AnalysisConfig format (for share URLs)\n const initialFlowStateFromShare = (() => {\n if (!sharedState || sharedState.analysisType !== 'flow') return undefined\n const flowQuery = 'flow' in sharedState.query ? sharedState.query.flow : null\n if (!flowQuery) return undefined\n\n const flowChartConfig = sharedState.charts?.flow\n\n return {\n flowCube: null, // Not stored in AnalysisConfig directly\n flowBindingKey: flowQuery.bindingKey\n ? (typeof flowQuery.bindingKey === 'string'\n ? { dimension: flowQuery.bindingKey }\n : { dimension: flowQuery.bindingKey[0]?.dimension || '' })\n : null,\n flowTimeDimension: typeof flowQuery.timeDimension === 'string'\n ? flowQuery.timeDimension\n : flowQuery.timeDimension?.[0]?.dimension || null,\n startingStep: flowQuery.startingStep\n ? {\n name: flowQuery.startingStep.name || '',\n filters: Array.isArray(flowQuery.startingStep.filter)\n ? flowQuery.startingStep.filter\n : flowQuery.startingStep.filter\n ? [flowQuery.startingStep.filter]\n : [],\n }\n : { name: '', filters: [] },\n stepsBefore: flowQuery.stepsBefore ?? 3,\n stepsAfter: flowQuery.stepsAfter ?? 3,\n eventDimension: flowQuery.eventDimension || null,\n flowChartType: flowChartConfig?.chartType || 'sankey',\n flowChartConfig: flowChartConfig?.chartConfig || {},\n flowDisplayConfig: flowChartConfig?.displayConfig || {},\n }\n })()\n\n // Extract retention state from AnalysisConfig format (for share URLs)\n const initialRetentionStateFromShare = (() => {\n if (!sharedState || sharedState.analysisType !== 'retention') return undefined\n const retentionQuery = 'retention' in sharedState.query ? sharedState.query.retention : null\n if (!retentionQuery) return undefined\n\n const retentionChartConfig = sharedState.charts?.retention\n\n return {\n retentionCube: null, // Not stored directly - derived from timeDimension\n retentionBindingKey: retentionQuery.bindingKey\n ? (typeof retentionQuery.bindingKey === 'string'\n ? { dimension: retentionQuery.bindingKey }\n : { dimension: retentionQuery.bindingKey })\n : null,\n retentionTimeDimension: typeof retentionQuery.timeDimension === 'string'\n ? retentionQuery.timeDimension\n : null,\n retentionDateRange: retentionQuery.dateRange,\n retentionCohortFilters: Array.isArray(retentionQuery.cohortFilters)\n ? retentionQuery.cohortFilters\n : retentionQuery.cohortFilters\n ? [retentionQuery.cohortFilters]\n : [],\n retentionActivityFilters: Array.isArray(retentionQuery.activityFilters)\n ? retentionQuery.activityFilters\n : retentionQuery.activityFilters\n ? [retentionQuery.activityFilters]\n : [],\n retentionBreakdowns: retentionQuery.breakdownDimensions?.map((field: string) => ({\n field,\n label: field.split('.').pop() || field,\n })) || [],\n retentionViewGranularity: retentionQuery.granularity || 'week',\n retentionPeriods: retentionQuery.periods || 12,\n retentionType: retentionQuery.retentionType || 'classic',\n retentionChartType: retentionChartConfig?.chartType || 'retentionCombined',\n retentionChartConfig: retentionChartConfig?.chartConfig || {},\n retentionDisplayConfig: retentionChartConfig?.displayConfig || {},\n }\n })()\n\n // Hide share button when using initialQuery (e.g., viewing a shared analysis)\n const hideShare = !!initialQuery || !!initialFunnelState || !!initialFlowState || !!initialRetentionState\n\n return (\n <AnalysisBuilderStoreProvider\n initialQuery={initialQuery}\n initialChartConfig={initialChartConfig}\n initialAnalysisType={initialAnalysisType || initialAnalysisTypeFromShare}\n initialFunnelState={initialFunnelState || initialFunnelStateFromShare}\n initialFlowState={initialFlowState || initialFlowStateFromShare}\n initialRetentionState={initialRetentionState || initialRetentionStateFromShare}\n initialActiveView={initialActiveViewFromShare}\n disableLocalStorage={disableLocalStorage || !!initialQuery || !!initialFunnelState || !!initialFlowState || !!initialRetentionState || !!shareHash}\n >\n <AnalysisBuilderInner ref={ref} {...innerProps} hideShare={hideShare} />\n </AnalysisBuilderStoreProvider>\n )\n }\n)\n\nAnalysisBuilder.displayName = 'AnalysisBuilder'\n\nexport default AnalysisBuilder\n"],"names":["createExplainQueryKey","query","options","stableStringify","isFunnelQuery","isFlowQuery","isRetentionQuery","useExplainQuery","skip","cubeApi","useCubeApi","explainOptions","setExplainOptions","useState","hasTriggered","setHasTriggered","serverQuery","useMemo","cleanQueryForServer","queryEnabled","queryResult","useQuery","runExplain","useCallback","opts","clearExplain","EXPLAIN_AI_QUERY_KEY","useExplainAI","features","useCubeFeatures","enableAI","queryClient","useQueryClient","aiEndpoint","mutation","useMutation","explainResult","response","errorData","analyze","clearAnalysis","sendGeminiMessage","apiKey","userPrompt","endpoint","requestBody","headers","errorMessage","errorText","data","extractTextFromResponse","isServerFunnelQuery","useAnalysisAI","state","setState","chartType","setChartType","chartConfig","setChartConfig","displayConfig","setDisplayConfig","setUserManuallySelectedChart","setActiveView","analysisType","setAnalysisType","loadFunnelFromServerQuery","getFullConfig","loadFullConfig","aiState","setAIState","handleOpenAI","fullConfig","handleCloseAI","prev","handleAIPromptChange","prompt","handleGenerateAI","responseText","parsed","aiChartType","aiChartConfig","cubeQuery","field","index","generateId","generateMetricLabel","td","error","handleAcceptAI","handleCancelAI","useAnalysisShare","isValidQuery","getAnalysisConfig","shareButtonState","setShareButtonState","handleShare","config","encoded","queryOnly","compressWithFallback","url","textArea","formatReason","reason","getReasonBadgeClasses","QueryAnalysisPanel","analysis","InfoIcon","getIcon","ArrowRightIcon","WarningIcon","TableIcon","LinkIcon","SuccessIcon","ErrorIcon","jsxs","jsx","c","i","jp","idx","step","stepIdx","jc","pa","jk","w","CodeBlock","code","language","title","maxHeight","height","className","headerRight","copied","setCopied","codeRef","useRef","CopyIcon","CheckIcon","useEffect","element","isActive","loadSyntaxHighlighter","hljs","getSyntaxHighlighter","handleCopy","Fragment","safeText","value","assessmentColors","severityColors","issueSeverityColors","AssessmentBadge","assessment","labels","IssueItem","issue","CopyButton","text","React","err","RecommendationCard","rec","typeLabels","ExplainAIPanel","onClose","onClear","handleClose","handleKeyDown","e","ExecutionPlanPanel","memo","sql","sqlLoading","sqlError","sqlPlaceholder","explainLoading","explainHasRun","explainError","aiAnalysis","aiAnalysisLoading","aiAnalysisError","runAIAnalysis","_clearAIAnalysis","useAnalyze","setUseAnalyze","showAIModal","setShowAIModal","formattedSql","handleAIClick","handleCloseModal","aiButton","AnalysisResultsPanel","executionStatus","executionResults","executionError","totalRowCount","resultsStale","colorPalette","currentPaletteName","onColorPaletteChange","allQueries","funnelExecutedQueries","activeView","onActiveViewChange","displayLimit","onDisplayLimitChange","hasMetrics","debugDataPerQuery","onShareClick","canShare","onRefreshClick","canRefresh","isRefreshing","needsRefresh","onClearClick","canClear","isAIOpen","onAIToggle","queryCount","perQueryResults","activeTableIndex","onActiveTableChange","isFunnelModeProp","funnelServerQuery","funnelDebugData","flowServerQuery","flowDebugData","retentionServerQuery","retentionDebugData","retentionChartData","retentionValidation","isFunnelMode","isFlowMode","isRetentionMode","showDebug","setShowDebug","activeDebugIndex","setActiveDebugIndex","isClearConfirmOpen","setIsClearConfirmOpen","isShiftHeld","setIsShiftHeld","isHoveringRefresh","setIsHoveringRefresh","handleKeyUp","showCacheBustIndicator","currentDebugData","debugSql","debugAnalysis","debugLoading","debugError","debugQuery","isShowingFunnelQuery","funnelExplainResult","funnelExplainLoading","funnelExplainHasRun","funnelExplainError","runFunnelExplain","clearFunnelExplain","flowExplainResult","flowExplainLoading","flowExplainHasRun","flowExplainError","runFlowExplain","clearFlowExplain","retentionExplainResult","retentionExplainLoading","retentionExplainHasRun","retentionExplainError","runRetentionExplain","clearAIAnalysis","isFirstRunRef","combinedQueryForChart","allMeasures","q","ChartIcon","CodeIcon","ShareIcon","TrashIcon","SparklesIcon","RefreshIcon","renderLoading","renderError","renderHeader","hasQueryContent","hasModeSpecificContent","renderWaiting","renderNeedsRefreshEmpty","renderEmpty","emptyMessage","renderNoData","renderChart","effectiveChartType","isValidChartType","LazyChart","renderFunnelDebug","funnelSql","funnelLoading","funnelError","funnelMeta","renderFlowDebug","flowSql","flowLoading","flowError","flowMeta","renderRetentionDebug","retentionSql","retentionLoading","retentionError","retentionMeta","renderStandardDebug","renderDebug","isMultiQuery","renderFlowTable","nodes","links","firstResult","r","a","b","node","link","sourceId","targetId","sourceName","targetName","renderTable","tableIndex","tableData","tableQuery","limitedData","renderOverlaySpinner","hasResults","ColorPaletteSelector","d","renderNeedsRefreshBanner","renderSuccess","_","flowData","hasNodes","hasLinks","shouldShowResults","ConfirmModal","MetricItemCard","metric","fieldMeta","onRemove","sortDirection","sortPriority","onToggleSort","isDragging","onDragStart","onDragEnd","CloseIcon","ChevronUpIcon","ChevronDownIcon","ChevronUpDownIcon","measureType","MeasureIcon","getMeasureTypeIcon","displayTitle","cubeName","getSortIcon","getSortTooltip","isDraggable","AddIcon","findFieldMeta","fieldName","schema","cube","m","getNextSortDirection","current","MetricsSection","metrics","onAdd","order","onOrderChange","onReorder","draggedIndex","setDraggedIndex","dropTargetIndex","setDropTargetIndex","draggedIndexRef","dropTargetIndexRef","orderKeys","metricsWithMeta","dragCloneRef","handleDragStart","target","clone","rect","offsetX","offsetY","handleDragEnd","handleItemDragOver","itemIndex","currentDraggedIndex","targetIndex","handleItemDrop","currentDropTargetIndex","adjustedTarget","handleSectionDragLeave","relatedTarget","getItemTransform","gapSize","shouldShowGapIndicator","SectionHeading","transform","showGapBefore","nextDirection","lastIndex","TIME_GRANULARITIES","BreakdownItemCard","breakdown","onGranularityChange","onComparisonToggle","comparisonDisabled","DimensionIcon","TimeIcon","Icon","g","BreakdownSection","breakdowns","activeComparisonId","breakdownsWithMeta","granularity","TimeDimensionIcon","FilterConfigModal","initialFilter","onSave","onCancel","anchorElement","filter","setFilter","isOperatorDropdownOpen","setIsOperatorDropdownOpen","isValueDropdownOpen","setIsValueDropdownOpen","isDateRangeDropdownOpen","setIsDateRangeDropdownOpen","rangeType","setRangeType","numberValue","setNumberValue","searchText","setSearchText","modalPosition","setModalPosition","highlightedIndex","setHighlightedIndex","containerRef","valueListRef","debouncedSearchText","useDebounce","fieldInfo","findFieldInSchema","fieldType","isTimeField","isMeasureField","isDimensionField","fieldTitle","getFieldTitle","operatorMeta","FILTER_OPERATORS","availableOperators","getAvailableOperators","shouldShowDateRange","shouldShowComboBox","distinctValues","valuesLoading","valuesError","searchValues","useFilterValues","modalHeight","spaceAbove","spaceBelow","modalWidth","shouldAppearAbove","left","handleClickOutside","event","highlightedElement","flexMatch","singularMatch","num","unit","found","option","DATE_RANGE_OPTIONS","requiresNumberInput","convertDateRangeTypeToValue","handleOperatorChange","operator","handleValueSelect","values","v","handleValueRemove","valueToRemove","handleValueKeyDown","handleDirectInput","numValue","handleBetweenStartInput","currentValues","newValues","handleBetweenEndInput","handleDateInput","handleRangeTypeChange","newRangeType","dateRange","today","handleNumberValueChange","handleCustomStartDate","start","end","handleCustomEndDate","operatorLabel","op","dateRangeLabel","opt","FieldIcon","renderValueInput","isSelected","AnalysisFilterItem","onUpdate","isModalOpen","setIsModalOpen","buttonRef","valueDisplay","formatValueDisplay","updatedFilter","isSimpleFilter","isGroupFilter","AnalysisFilterGroup","group","onAddFilter","depth","hideRemoveButton","isAddMenuOpen","setIsAddMenuOpen","addMenuRef","handleToggleType","newType","handleUpdateFilter","newFilter","newFilters","handleRemoveFilter","handleAddNestedGroup","type","newGroup","handleAddFilterClick","createNestedAddFilterHandler","nestedIndex","relativePath","getBorderColor","getGroupBgColor","conditionCount","conditionLabel","countFilters","filters","count","getSelectedFields","fields","addFilterAtPath","path","firstIndex","restPath","targetFilter","AnalysisFilterSection","onFiltersChange","onFieldDropped","dimensionsOnly","showFieldModal","setShowFieldModal","isDragOver","setIsDragOver","pendingAddPath","totalFilterCount","handleDragOver","handleDragLeave","handleDrop","selectedFields","handleFieldSelected","_fieldType","_cubeName","isTime","defaultOperator","updatedFilters","handleUpdateTopLevelFilter","handleRemoveTopLevelFilter","handleClearAll","createAddFilterHandler","basePath","renderFilter","parentPath","currentPath","FieldSearchModal","AnalysisAxisDropZone","onDrop","onDragOver","draggedItem","getFieldMeta","yAxisAssignment","onYAxisAssignmentChange","key","label","description","mandatory","maxItems","emptyText","isDraggedOver","setIsDraggedOver","isReorderDraggedOver","setIsReorderDraggedOver","draggingFieldRef","fieldsRef","getCanAcceptMore","effectiveCount","getIsFull","canAcceptMore","isFull","handleGlobalDragEnd","isTopHalf","fromIndex","handleFieldDragEnd","container","getDefaultFieldMeta","parts","renderFieldIcon","meta","IconComponent","isLeavingContainer","isRelatedTargetOutside","isBeingDragged","currentAxis","chartTypeLabels","ChartTypeSelector","selectedType","onTypeChange","compact","availability","excludeTypes","isOpen","setIsOpen","configRegistry","setConfigRegistry","module","chartTypes","labelA","labelB","SelectedIcon","selectedLabel","useCase","chartAvailability","isAvailable","unavailableReason","tooltipText","AnalysisChartConfigPanel","onChartTypeChange","onChartConfigChange","setDraggedItem","availableFields","chartTypeConfig","chartConfigLoaded","useChartConfig","shouldSkipQuery","getFieldsForDropZone","allAvailableFields","hasChanges","newConfig","dropZone","currentFields","validFields","getFieldType","measure","dimension","schemaMeta","breakdownItem","fromAxis","toAxis","fromValue","filteredValue","f","toValue","dropZoneConfig","dz","fieldIndex","handleRemoveFromAxis","_removed","rest","handleReorder","toIndex","axisKey","newArray","movedItem","handleYAxisAssignmentChange","axis","unassignedFields","assignedFields","hasUnassignedFields","StringArrayInput","onChange","placeholder","localText","setLocalText","externalText","handleBlur","arrayValue","s","AnalysisDisplayConfigPanel","onDisplayConfigChange","color","AxisFormatControls","SearchIcon","FunnelBindingKeySelector","bindingKey","disabled","searchQuery","setSearchQuery","dropdownRef","searchInputRef","availableDimensions","getAvailableBindingKeyDimensions","groupedDimensions","groups","dim","filteredGroups","filtered","dims","matchingDims","handleSelect","handleClear","getBindingKeyLabel","hasSelection","ChartBarIcon","ChartFunnelIcon","ChartSankeyIcon","ChartRetentionIcon","typeOptions","AnalysisTypeSelector","hasEventStreamCubes","availableOptions","ChevronRightIcon","CubeIcon","getAvailableFunnelCubes","getAvailableTimeDimensions","timeDimensions","DropdownSelector","helpText","groupedOptions","hasValue","FunnelConfigPanel","selectedCube","timeDimension","onCubeChange","onBindingKeyChange","onTimeDimensionChange","availableCubes","availableBindingKeys","allKeys","availableTimeDimensions","allTimeDims","isConfigComplete","isCollapsed","setIsCollapsed","hasAutoCollapsedRef","eventStream","bindingKeyValue","handleBindingKeyChange","cubeLabel","DragHandleIcon","TIME_TO_CONVERT_OPTIONS","FunnelStepCard","stepIndex","canRemove","onSelect","isEditingName","setIsEditingName","showTimeDropdown","setShowTimeDropdown","localName","setLocalName","nameInputRef","timeDropdownRef","handleNameChange","handleNameKeyDown","handleNameBlur","trimmedName","handleTimeSelect","handleFiltersChange","timeToConvertLabel","o","cubeSchema","metaSchema","getRelatedCubesSchema","FunnelStepList","steps","activeStepIndex","onAddStep","onRemoveStep","onUpdateStep","onSelectStep","onReorderSteps","dragOverIndex","setDragOverIndex","updates","FunnelModeContent","funnelCube","funnelSteps","activeFunnelStepIndex","funnelTimeDimension","funnelBindingKey","activeTab","setActiveTab","hasDisplayTab","TagIcon","getAvailableFlowCubes","getAvailableStringDimensions","stringDimensions","FlowConfigPanel","eventDimension","onEventDimensionChange","availableEventDimensions","allStringDims","FlowModeContent","flowCube","flowBindingKey","flowTimeDimension","startingStep","stepsBefore","stepsAfter","joinStrategy","onStartingStepFiltersChange","onStepsBeforeChange","onStepsAfterChange","onJoinStrategyChange","FLOW_MIN_DEPTH","FLOW_MAX_DEPTH","CalendarIcon","getAvailableCubes","formatDateDisplay","date","DateRangeSelector","onDateRangeChange","safeDateRange","safeStart","safeEnd","showDatePicker","setShowDatePicker","selectedPreset","setSelectedPreset","detectDateRangePreset","customStart","setCustomStart","customEnd","setCustomEnd","handlePresetSelect","preset","range","getDateRangeFromPreset","handleCustomDateApply","dateRangeDisplay","RETENTION_DATE_RANGE_PRESETS","p","RetentionConfigPanel","dateLabel","convertToBreakdownItems","items","item","RetentionModeContent","retentionCube","retentionBindingKey","retentionTimeDimension","retentionDateRange","retentionCohortFilters","retentionActivityFilters","retentionBreakdowns","retentionViewGranularity","retentionPeriods","retentionType","onCohortFiltersChange","onActivityFiltersChange","_onBreakdownsChange","_onAddBreakdown","onRemoveBreakdown","onPeriodsChange","onRetentionTypeChange","onOpenFieldModal","_onChartTypeChange","filteredSchema","breakdownItems","handleRemoveBreakdown","id","handleAddBreakdown","handleGranularityChange","RETENTION_GRANULARITY_OPTIONS","RETENTION_MIN_PERIODS","RETENTION_MAX_PERIODS","RETENTION_TYPE_OPTIONS","AnalysisQueryPanel","onActiveTabChange","onAddMetric","onRemoveMetric","onReorderMetrics","onAddBreakdown","onBreakdownGranularityChange","onBreakdownComparisonToggle","onReorderBreakdowns","onDropFieldToFilter","_validationStatus","_validationError","activeQueryIndex","mergeStrategy","onActiveQueryChange","onAddQuery","onRemoveQuery","onMergeStrategyChange","breakdownsLocked","combinedMetrics","combinedBreakdowns","multiQueryValidation","adapterValidation","onFunnelBindingKeyChange","onAnalysisTypeChange","onFunnelCubeChange","onAddFunnelStep","onRemoveFunnelStep","onUpdateFunnelStep","onSelectFunnelStep","onReorderFunnelSteps","onFunnelTimeDimensionChange","funnelDisplayConfig","onFunnelDisplayConfigChange","flowJoinStrategy","onFlowCubeChange","onFlowBindingKeyChange","onFlowTimeDimensionChange","onFlowJoinStrategyChange","flowDisplayConfig","onFlowDisplayConfigChange","onRetentionCubeChange","onRetentionBindingKeyChange","onRetentionTimeDimensionChange","onRetentionDateRangeChange","onRetentionCohortFiltersChange","onRetentionActivityFiltersChange","onRetentionBreakdownsChange","onAddRetentionBreakdown","onRemoveRetentionBreakdown","onRetentionViewGranularityChange","onRetentionPeriodsChange","retentionDisplayConfig","onRetentionDisplayConfigChange","isNewFunnelMode","comparisonEnabledBreakdown","handleQueryTabClick","handleRemoveQuery","getQueryTabLabel","warning","AnalysisAIPanel","onPromptChange","isGenerating","hasGeneratedQuery","onGenerate","onAccept","AnalysisModeErrorBoundary","Component","props","errorInfo","AnalysisBuilderInner","forwardRef","initialData","externalColorPalette","_hideSettings","hideShare","onQueryChange","ref","useCubeMeta","useAnalysisBuilder","storeApi","useAnalysisBuilderStoreApi","updater","newState","funnelConfig","useImperativeHandle","AnalysisBuilder","initialQuery","initialChartConfig","initialAnalysisType","initialFunnelState","initialFlowState","initialRetentionState","disableLocalStorage","innerProps","shareHash","parseShareHash","sharedState","decodeAndDecompress","initialActiveViewFromShare","initialAnalysisTypeFromShare","initialFunnelStateFromShare","funnelQuery","funnelChartConfig","initialFlowStateFromShare","flowQuery","flowChartConfig","initialRetentionStateFromShare","retentionQuery","retentionChartConfig","AnalysisBuilderStoreProvider"],"mappings":"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"}
|