drizzle-cube 0.4.21 → 0.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/adapters/express/index.cjs +1 -1
  2. package/dist/adapters/express/index.js +2 -2
  3. package/dist/adapters/fastify/index.cjs +1 -1
  4. package/dist/adapters/fastify/index.js +2 -2
  5. package/dist/adapters/{handler-B-tEntiU.cjs → handler-C3hT7g2W.cjs} +1 -1
  6. package/dist/adapters/{handler-9Rdn7zM2.js → handler-t7Qd1IYi.js} +1 -1
  7. package/dist/adapters/hono/index.cjs +6 -6
  8. package/dist/adapters/hono/index.d.ts +13 -6
  9. package/dist/adapters/hono/index.js +65 -65
  10. package/dist/adapters/{mcp-transport-m1X1GtwG.js → mcp-transport-B6ZudTSk.js} +7 -0
  11. package/dist/adapters/{mcp-transport-8u9G5oNa.cjs → mcp-transport-DCiSGtp1.cjs} +1 -1
  12. package/dist/adapters/nextjs/index.cjs +2 -2
  13. package/dist/adapters/nextjs/index.js +2 -2
  14. package/dist/client/charts.js +12 -12
  15. package/dist/client/chunks/{RetentionCombinedChart-CLq89aOJ.js → RetentionCombinedChart-BK3NPsHP.js} +2 -2
  16. package/dist/client/chunks/{RetentionCombinedChart-CLq89aOJ.js.map → RetentionCombinedChart-BK3NPsHP.js.map} +1 -1
  17. package/dist/client/chunks/{analysis-builder-3z9fHE2F.js → analysis-builder-DVrv9Q4n.js} +9 -9
  18. package/dist/client/chunks/{analysis-builder-3z9fHE2F.js.map → analysis-builder-DVrv9Q4n.js.map} +1 -1
  19. package/dist/client/chunks/{analysis-builder-shared-Da-vlQa_.js → analysis-builder-shared-CrENEvEk.js} +6 -6
  20. package/dist/client/chunks/{analysis-builder-shared-Da-vlQa_.js.map → analysis-builder-shared-CrENEvEk.js.map} +1 -1
  21. package/dist/client/chunks/{chart-activity-grid-CPGcTSuh.js → chart-activity-grid-OG6he4YS.js} +2 -2
  22. package/dist/client/chunks/{chart-activity-grid-CPGcTSuh.js.map → chart-activity-grid-OG6he4YS.js.map} +1 -1
  23. package/dist/client/chunks/{chart-area-ByJQ7NZd.js → chart-area-TawAd2k9.js} +3 -3
  24. package/dist/client/chunks/{chart-area-ByJQ7NZd.js.map → chart-area-TawAd2k9.js.map} +1 -1
  25. package/dist/client/chunks/{chart-bar-dj14frMt.js → chart-bar-D3vtCNQG.js} +2 -2
  26. package/dist/client/chunks/{chart-bar-dj14frMt.js.map → chart-bar-D3vtCNQG.js.map} +1 -1
  27. package/dist/client/chunks/{chart-box-plot-ZatBpatq.js → chart-box-plot-BXwN2rO5.js} +2 -2
  28. package/dist/client/chunks/{chart-box-plot-ZatBpatq.js.map → chart-box-plot-BXwN2rO5.js.map} +1 -1
  29. package/dist/client/chunks/{chart-bubble-CemotLx-.js → chart-bubble-ZfNe8t5k.js} +2 -2
  30. package/dist/client/chunks/{chart-bubble-CemotLx-.js.map → chart-bubble-ZfNe8t5k.js.map} +1 -1
  31. package/dist/client/chunks/{chart-candlestick-BIR4uGGt.js → chart-candlestick-DmF3haFu.js} +2 -2
  32. package/dist/client/chunks/{chart-candlestick-BIR4uGGt.js.map → chart-candlestick-DmF3haFu.js.map} +1 -1
  33. package/dist/client/chunks/{chart-data-table-BsAjHe7o.js → chart-data-table-DJZPkArt.js} +4 -4
  34. package/dist/client/chunks/{chart-data-table-BsAjHe7o.js.map → chart-data-table-DJZPkArt.js.map} +1 -1
  35. package/dist/client/chunks/{chart-funnel-dofnhD24.js → chart-funnel-CE9x0Io9.js} +2 -2
  36. package/dist/client/chunks/{chart-funnel-dofnhD24.js.map → chart-funnel-CE9x0Io9.js.map} +1 -1
  37. package/dist/client/chunks/{chart-gauge-CKJJ8m3b.js → chart-gauge-Djs5FWxB.js} +2 -2
  38. package/dist/client/chunks/{chart-gauge-CKJJ8m3b.js.map → chart-gauge-Djs5FWxB.js.map} +1 -1
  39. package/dist/client/chunks/{chart-heat-map-BVuPUKHT.js → chart-heat-map-CqtMkdxd.js} +2 -2
  40. package/dist/client/chunks/{chart-heat-map-BVuPUKHT.js.map → chart-heat-map-CqtMkdxd.js.map} +1 -1
  41. package/dist/client/chunks/{chart-kpi-delta-DUD3f8vL.js → chart-kpi-delta-DEzA74cL.js} +4 -4
  42. package/dist/client/chunks/{chart-kpi-delta-DUD3f8vL.js.map → chart-kpi-delta-DEzA74cL.js.map} +1 -1
  43. package/dist/client/chunks/{chart-kpi-number-iJh-PzsM.js → chart-kpi-number-Bab-BZtX.js} +3 -3
  44. package/dist/client/chunks/{chart-kpi-number-iJh-PzsM.js.map → chart-kpi-number-Bab-BZtX.js.map} +1 -1
  45. package/dist/client/chunks/{chart-kpi-text-x6pV9v9Q.js → chart-kpi-text-BkTgckDJ.js} +3 -3
  46. package/dist/client/chunks/{chart-kpi-text-x6pV9v9Q.js.map → chart-kpi-text-BkTgckDJ.js.map} +1 -1
  47. package/dist/client/chunks/{chart-line-DzyZkugh.js → chart-line-DhM-Hvu0.js} +3 -3
  48. package/dist/client/chunks/{chart-line-DzyZkugh.js.map → chart-line-DhM-Hvu0.js.map} +1 -1
  49. package/dist/client/chunks/{chart-measure-profile-C2IkBG3V.js → chart-measure-profile-4vQxFm69.js} +3 -3
  50. package/dist/client/chunks/{chart-measure-profile-C2IkBG3V.js.map → chart-measure-profile-4vQxFm69.js.map} +1 -1
  51. package/dist/client/chunks/{chart-pie-akbfRfb9.js → chart-pie-B86KRcHI.js} +2 -2
  52. package/dist/client/chunks/{chart-pie-akbfRfb9.js.map → chart-pie-B86KRcHI.js.map} +1 -1
  53. package/dist/client/chunks/{chart-radar-BaN-Kjww.js → chart-radar-BhDBmJRh.js} +2 -2
  54. package/dist/client/chunks/{chart-radar-BaN-Kjww.js.map → chart-radar-BhDBmJRh.js.map} +1 -1
  55. package/dist/client/chunks/{chart-radial-bar-DpptEL3s.js → chart-radial-bar-Brugya8X.js} +2 -2
  56. package/dist/client/chunks/{chart-radial-bar-DpptEL3s.js.map → chart-radial-bar-Brugya8X.js.map} +1 -1
  57. package/dist/client/chunks/{chart-sankey-CG-3hHmX.js → chart-sankey-D2L8ympI.js} +2 -2
  58. package/dist/client/chunks/{chart-sankey-CG-3hHmX.js.map → chart-sankey-D2L8ympI.js.map} +1 -1
  59. package/dist/client/chunks/{chart-scatter-l_yTVxF3.js → chart-scatter-CAkbBDkK.js} +2 -2
  60. package/dist/client/chunks/{chart-scatter-l_yTVxF3.js.map → chart-scatter-CAkbBDkK.js.map} +1 -1
  61. package/dist/client/chunks/{chart-sunburst-KhDcKhmZ.js → chart-sunburst-DaxJ-cob.js} +2 -2
  62. package/dist/client/chunks/{chart-sunburst-KhDcKhmZ.js.map → chart-sunburst-DaxJ-cob.js.map} +1 -1
  63. package/dist/client/chunks/{chart-tree-map-CBbiaBXV.js → chart-tree-map-CrDJAvZU.js} +2 -2
  64. package/dist/client/chunks/{chart-tree-map-CBbiaBXV.js.map → chart-tree-map-CrDJAvZU.js.map} +1 -1
  65. package/dist/client/chunks/{chart-waterfall-CX3vx_lI.js → chart-waterfall-BBwSfEKT.js} +3 -3
  66. package/dist/client/chunks/{chart-waterfall-CX3vx_lI.js.map → chart-waterfall-BBwSfEKT.js.map} +1 -1
  67. package/dist/client/chunks/{charts-core-CU9u_HtL.js → charts-core-B4Rbfdcn.js} +2 -2
  68. package/dist/client/chunks/{charts-core-CU9u_HtL.js.map → charts-core-B4Rbfdcn.js.map} +1 -1
  69. package/dist/client/chunks/{charts-loader-B3tt5oKG.js → charts-loader-DbrwgvCK.js} +25 -25
  70. package/dist/client/chunks/{charts-loader-B3tt5oKG.js.map → charts-loader-DbrwgvCK.js.map} +1 -1
  71. package/dist/client/chunks/{components-CMGGxqOB.js → components-GzooQM5J.js} +9 -9
  72. package/dist/client/chunks/{components-CMGGxqOB.js.map → components-GzooQM5J.js.map} +1 -1
  73. package/dist/client/chunks/{core-D_8mkGpQ.js → core-Y9e-sNfb.js} +2 -2
  74. package/dist/client/chunks/{core-D_8mkGpQ.js.map → core-Y9e-sNfb.js.map} +1 -1
  75. package/dist/client/chunks/{icons-M7shurcH.js → icons-DFJw-2HU.js} +6 -6
  76. package/dist/client/chunks/{icons-M7shurcH.js.map → icons-DFJw-2HU.js.map} +1 -1
  77. package/dist/client/chunks/{providers-CgxXm6Ll.js → providers-CCw8Kjlc.js} +2 -2
  78. package/dist/client/chunks/{providers-CgxXm6Ll.js.map → providers-CCw8Kjlc.js.map} +1 -1
  79. package/dist/client/chunks/{syntaxHighlighting-BQfjio-i.js → syntaxHighlighting-DAMSW_A6.js} +2 -2
  80. package/dist/client/chunks/{syntaxHighlighting-BQfjio-i.js.map → syntaxHighlighting-DAMSW_A6.js.map} +1 -1
  81. package/dist/client/chunks/{useDirtyStateTracking-Cu1HSjmo.js → useDirtyStateTracking-CjhwBXRw.js} +20 -20
  82. package/dist/client/chunks/{useDirtyStateTracking-Cu1HSjmo.js.map → useDirtyStateTracking-CjhwBXRw.js.map} +1 -1
  83. package/dist/client/chunks/useExplainAI-IiW55BaQ.js +182 -0
  84. package/dist/client/chunks/useExplainAI-IiW55BaQ.js.map +1 -0
  85. package/dist/client/chunks/{vendor-AVsJ2ni0.js → vendor-B2EH3V58.js} +7 -7
  86. package/dist/client/chunks/{vendor-AVsJ2ni0.js.map → vendor-B2EH3V58.js.map} +1 -1
  87. package/dist/client/components.js +1 -1
  88. package/dist/client/hooks/useNotebookLayout.d.ts +8 -0
  89. package/dist/client/hooks.d.ts +2 -0
  90. package/dist/client/hooks.js +51 -190
  91. package/dist/client/hooks.js.map +1 -1
  92. package/dist/client/icons.js +1 -1
  93. package/dist/client/index.js +871 -742
  94. package/dist/client/index.js.map +1 -1
  95. package/dist/client/providers.js +1 -1
  96. package/dist/client/styles.css +1 -1
  97. package/dist/client/utils.js +7 -7
  98. package/dist/client-bundle-stats.html +1 -1
  99. package/dist/server/index.cjs +1 -1
  100. package/dist/server/index.d.ts +5 -0
  101. package/dist/server/index.js +7 -0
  102. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-builder-3z9fHE2F.js","sources":["../../../src/client/shared/components/QueryAnalysisPanel.tsx","../../../src/client/components/AIAssistant/utils.ts","../../../src/client/hooks/useAnalysisAI.ts","../../../src/client/hooks/useAnalysisShare.ts","../../../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/charts/chartConfigRegistry.ts","../../../src/client/components/ChartTypeSelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.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 * 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\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\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 const summaryCards = [\n {\n label: 'Type',\n value: formatReason(analysis.querySummary.queryType),\n },\n {\n label: 'Cubes',\n value: String(analysis.cubeCount),\n },\n {\n label: 'Joins',\n value: String(analysis.querySummary.joinCount),\n },\n {\n label: 'CTEs',\n value: String(analysis.querySummary.cteCount),\n },\n ...(analysis.querySummary.measureStrategy\n ? [\n {\n label: 'Strategy',\n value: formatReason(analysis.querySummary.measureStrategy),\n },\n ]\n : []),\n ]\n\n return (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded-lg dc:p-4 dc:space-y-4\">\n {/* Query Summary Section */}\n <div className=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <InfoIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Query Summary\n </h4>\n <div\n className=\"dc:grid dc:gap-2 dc:text-xs\"\n style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))' }}\n >\n {summaryCards.map(card => (\n <div key={card.label} className=\"bg-dc-surface dc:p-2 dc:rounded\">\n <span className=\"text-dc-text-muted\">{card.label}:</span>\n <span className=\"dc:ml-1 dc:font-medium text-dc-text\">{card.value}</span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Primary Cube Section */}\n <div className=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <TableIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Primary Cube (FROM table)\n </h4>\n <div className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-2 dc:flex-wrap\">\n <span className=\"dc:font-mono dc:font-medium text-dc-primary\">\n {analysis.primaryCube.selectedCube}\n </span>\n <span className={`dc:text-xs dc:px-2 dc:py-0.5 dc:rounded ${getReasonBadgeClasses(analysis.primaryCube.reason)}`}>\n {formatReason(analysis.primaryCube.reason)}\n </span>\n </div>\n <p className=\"text-dc-text-secondary dc:text-xs\">\n {analysis.primaryCube.explanation}\n </p>\n {analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1 && (\n <details className=\"dc:mt-2\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n Show candidates ({analysis.primaryCube.candidates.length})\n </summary>\n <div className=\"dc:mt-2 dc:space-y-1 dc:ml-2\">\n {analysis.primaryCube.candidates.map((c, i) => (\n <div key={i} className=\"dc:text-xs dc:flex dc:items-center dc:gap-2 dc:flex-wrap\">\n <span className={`dc:font-mono ${c.cubeName === analysis.primaryCube.selectedCube ? 'dc: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 dc:flex dc:items-center dc:gap-0.5\">\n <SuccessIcon className=\"dc:w-3 dc:h-3\" />\n reachable\n </span>\n ) : (\n <span className=\"text-dc-error dc:flex dc:items-center dc:gap-0.5\">\n <ErrorIcon className=\"dc:w-3 dc: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=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <LinkIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Join Paths\n </h4>\n <div className=\"dc:space-y-2\">\n {analysis.joinPaths.map((jp, idx) => (\n <div key={idx} className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-2 dc:flex-wrap\">\n <span className=\"dc:font-mono text-dc-text-secondary\">{analysis.primaryCube.selectedCube}</span>\n <ArrowRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n <span className=\"dc:font-mono dc:font-medium text-dc-text\">{jp.targetCube}</span>\n {jp.pathFound ? (\n <span className=\"dc:text-xs dc:px-2 dc:py-0.5 bg-dc-success-bg text-dc-success dc:rounded\">\n {jp.pathLength} step{jp.pathLength !== 1 ? 's' : ''}\n </span>\n ) : (\n <span className=\"dc:text-xs dc:px-2 dc:py-0.5 bg-dc-error-bg text-dc-error dc:rounded\">\n No path\n </span>\n )}\n </div>\n {jp.pathFound && jp.path && jp.path.length > 0 && (\n <div className=\"dc:space-y-1 dc:ml-2\">\n {jp.path.map((step, stepIdx) => (\n <div key={stepIdx} className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs dc:flex-wrap\">\n <span className=\"dc:font-mono text-dc-text-secondary\">{step.fromCube}</span>\n <ArrowRightIcon className=\"dc:w-3 dc:h-3 text-dc-text-muted\" />\n <span className=\"dc: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.selection && (\n <div className=\"dc:mt-2 dc:ml-2 dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium text-dc-text\">Selection:</span>\n <span>{` ${formatReason(jp.selection.strategy)}`}</span>\n {typeof jp.selection.selectedRank === 'number' && (\n <span>{`, selected #${jp.selection.selectedRank}`}</span>\n )}\n {typeof jp.selection.selectedScore === 'number' && (\n <span>{`, score ${jp.selection.selectedScore}`}</span>\n )}\n </div>\n )}\n {jp.selection?.candidates && jp.selection.candidates.length > 0 && (\n <details className=\"dc:mt-2\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n {`Path scoring candidates (${jp.selection.candidates.length})`}\n </summary>\n <div className=\"dc:mt-1 dc:ml-2 dc:space-y-1\">\n {jp.selection.preferredCubes && jp.selection.preferredCubes.length > 0 && (\n <div className=\"dc:text-xs text-dc-text-muted\">\n preferred cubes: {jp.selection.preferredCubes.join(', ')}\n </div>\n )}\n {jp.selection.candidates.slice(0, 5).map(candidate => (\n <div key={candidate.rank} className=\"dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium text-dc-text\">\n #{candidate.rank}\n </span>\n <span>{` score ${candidate.score}`}</span>\n <span>{` (preferred+${candidate.scoreBreakdown.preferredJoinBonus + candidate.scoreBreakdown.preferredCubeBonus}, penalty-${candidate.scoreBreakdown.lengthPenalty})`}</span>\n <span>{`: `}</span>\n <span>\n {candidate.path.length > 0\n ? `${candidate.path[0].fromCube} → ${candidate.path.map(step => step.toCube).join(' → ')}`\n : analysis.primaryCube.selectedCube}\n </span>\n </div>\n ))}\n </div>\n </details>\n )}\n {!jp.pathFound && jp.error && (\n <p className=\"dc:text-xs text-dc-error dc:mt-1\">{jp.error}</p>\n )}\n {jp.visitedCubes && jp.visitedCubes.length > 0 && !jp.pathFound && (\n <details className=\"dc:mt-1\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n Cubes visited during search ({jp.visitedCubes.length})\n </summary>\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted dc: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=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <TableIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Pre-Aggregation CTEs\n </h4>\n <div className=\"dc:space-y-2\">\n {analysis.preAggregations.map((pa, idx) => (\n <div key={idx} className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-1 dc:flex-wrap\">\n <span className=\"dc:font-mono dc:font-medium text-dc-text\">{pa.cubeName}</span>\n <span className=\"dc:text-xs text-dc-text-muted\">as</span>\n <code className=\"dc:text-xs bg-dc-surface-secondary dc:px-1 dc:rounded dc:font-mono\">{pa.cteAlias}</code>\n </div>\n <p className=\"dc:text-xs text-dc-text-secondary\">{pa.reason}</p>\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium\">Measures:</span> {pa.measures.join(', ')}\n </div>\n {pa.joinKeys.length > 0 && (\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted\">\n <span className=\"dc: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=\"dc:text-sm dc:font-semibold text-dc-warning dc:mb-2 dc:flex dc:items-center\">\n <WarningIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Warnings\n </h4>\n <ul className=\"list-disc dc:list-inside dc:text-xs text-dc-warning dc: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=\"dc:text-xs text-dc-text-muted dc:pt-2 dc:border-t border-dc-border\">\n <span className=\"dc:font-medium\">Cubes involved:</span> {analysis.cubesInvolved.join(', ')}\n </div>\n )}\n </div>\n )\n}\n\nexport default QueryAnalysisPanel\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 * AnalysisResultsPanel Component\n *\n * Displays query execution results with chart and table views.\n * Used in the left panel of AnalysisBuilder.\n */\n\nimport React, { useState, useEffect, useMemo, memo, useRef, useCallback } 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 type { QueryAnalysis } from '../../shared/types'\nimport { ExecutionPlanPanel } from './ExecutionPlanPanel'\n\n/**\n * Generate markdown representation of query execution plan\n */\nfunction generateExecutionPlanMarkdown(\n analysis: QueryAnalysis,\n query: CubeQuery | null,\n sql?: { sql: string } | null\n): string {\n const lines: string[] = []\n\n lines.push('# Query Execution Plan')\n lines.push('')\n\n // Original query\n if (query) {\n lines.push('## Cube Query')\n lines.push('')\n lines.push('```json')\n lines.push(JSON.stringify(query, null, 2))\n lines.push('```')\n lines.push('')\n }\n\n // Query summary\n lines.push('## Query Summary')\n lines.push('')\n lines.push(`- **Cubes:** ${analysis.cubesInvolved.join(', ')}`)\n lines.push(`- **Query Type:** ${analysis.querySummary.queryType.replace(/_/g, ' ')}`)\n lines.push(`- **Joins:** ${analysis.querySummary.joinCount}`)\n lines.push(`- **CTEs:** ${analysis.querySummary.cteCount}`)\n lines.push('')\n\n // Primary cube selection\n lines.push('## Primary Cube Selection')\n lines.push('')\n lines.push(`**Selected:** ${analysis.primaryCube.selectedCube}`)\n lines.push(`**Reason:** ${analysis.primaryCube.reason.replace(/_/g, ' ')}`)\n lines.push(`**Explanation:** ${analysis.primaryCube.explanation}`)\n lines.push('')\n\n // Candidates if available\n if (analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1) {\n lines.push('### Candidates Considered')\n lines.push('')\n lines.push('| Cube | Dimensions | Joins | Can Reach All |')\n lines.push('|------|------------|-------|---------------|')\n for (const c of analysis.primaryCube.candidates) {\n const selected = c.cubeName === analysis.primaryCube.selectedCube ? ' ✓' : ''\n lines.push(`| ${c.cubeName}${selected} | ${c.dimensionCount} | ${c.joinCount} | ${c.canReachAll ? 'Yes' : 'No'} |`)\n }\n lines.push('')\n }\n\n // Join paths\n if (analysis.joinPaths.length > 0) {\n lines.push('## Join Paths')\n lines.push('')\n for (const jp of analysis.joinPaths) {\n if (jp.pathFound && jp.path) {\n lines.push(`### ${analysis.primaryCube.selectedCube} → ${jp.targetCube} (${jp.pathLength} step${jp.pathLength !== 1 ? 's' : ''})`)\n lines.push('')\n if (jp.selection) {\n lines.push(`**Selection strategy:** ${jp.selection.strategy}`)\n if (typeof jp.selection.selectedRank === 'number') {\n lines.push(`**Selected rank:** #${jp.selection.selectedRank}`)\n }\n if (typeof jp.selection.selectedScore === 'number') {\n lines.push(`**Selected score:** ${jp.selection.selectedScore}`)\n }\n if (jp.selection.preferredCubes && jp.selection.preferredCubes.length > 0) {\n lines.push(`**Preferred cubes:** ${jp.selection.preferredCubes.join(', ')}`)\n }\n if (jp.selection.candidates && jp.selection.candidates.length > 0) {\n lines.push('**Path scoring candidates:**')\n for (const candidate of jp.selection.candidates.slice(0, 5)) {\n const candidatePath = candidate.path.length > 0\n ? `${candidate.path[0].fromCube} → ${candidate.path.map(step => step.toCube).join(' → ')}`\n : analysis.primaryCube.selectedCube\n lines.push(\n `- #${candidate.rank} score=${candidate.score} `\n + `(preferredJoin=${candidate.scoreBreakdown.preferredJoinBonus}, `\n + `preferredCube=${candidate.scoreBreakdown.preferredCubeBonus}, `\n + `lengthPenalty=${candidate.scoreBreakdown.lengthPenalty}) `\n + `${candidatePath}`\n )\n }\n }\n lines.push('')\n }\n for (const step of jp.path) {\n lines.push(`- **${step.fromCube}** → **${step.toCube}** (${step.relationship}, ${step.joinType.toUpperCase()} JOIN)`)\n for (const col of step.joinColumns) {\n lines.push(` - \\`${col.sourceColumn}\\` = \\`${col.targetColumn}\\``)\n }\n }\n lines.push('')\n } else if (!jp.pathFound) {\n lines.push(`### ${analysis.primaryCube.selectedCube} → ${jp.targetCube}`)\n lines.push('')\n lines.push(`❌ **No path found**${jp.error ? `: ${jp.error}` : ''}`)\n if (jp.visitedCubes && jp.visitedCubes.length > 0) {\n lines.push(`Cubes visited: ${jp.visitedCubes.join(' → ')}`)\n }\n lines.push('')\n }\n }\n }\n\n // Pre-aggregation CTEs\n if (analysis.preAggregations.length > 0) {\n lines.push('## Pre-Aggregation CTEs')\n lines.push('')\n for (const cte of analysis.preAggregations) {\n lines.push(`### ${cte.cubeName} (\\`${cte.cteAlias}\\`)`)\n lines.push('')\n lines.push(`**Reason:** ${cte.reason}`)\n lines.push(`**Measures:** ${cte.measures.join(', ')}`)\n if (cte.joinKeys.length > 0) {\n lines.push('**Join Keys:**')\n for (const jk of cte.joinKeys) {\n lines.push(`- \\`${jk.sourceColumn}\\` = \\`${jk.targetColumn}\\``)\n }\n }\n lines.push('')\n }\n }\n\n // Warnings\n if (analysis.warnings && analysis.warnings.length > 0) {\n lines.push('## ⚠️ Warnings')\n lines.push('')\n for (const warning of analysis.warnings) {\n lines.push(`- ${warning}`)\n }\n lines.push('')\n }\n\n // Generated SQL\n if (sql?.sql) {\n lines.push('## Generated SQL')\n lines.push('')\n lines.push('```sql')\n lines.push(sql.sql)\n lines.push('```')\n }\n\n return lines.join('\\n')\n}\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 // Query warnings from server\n warnings\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 // Copy as markdown state\n const [copyMarkdownState, setCopyMarkdownState] = useState<'idle' | 'copied'>('idle')\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 mode: null,\n queryType: null,\n joinType: null,\n cubesUsed: [],\n modeMetadata: undefined,\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 // Copy execution plan as markdown\n const handleCopyMarkdown = useCallback(() => {\n if (!debugAnalysis) return\n const markdown = generateExecutionPlanMarkdown(debugAnalysis, debugQuery, debugSql)\n navigator.clipboard.writeText(markdown).then(() => {\n setCopyMarkdownState('copied')\n setTimeout(() => setCopyMarkdownState('idle'), 2000)\n })\n }, [debugAnalysis, debugQuery, debugSql])\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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-12 dc:w-12 dc:border-b-2 dc:mx-auto dc:mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Executing Query...\n </div>\n <div className=\"dc: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=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n <div className=\"dc:flex-1 dc:flex dc:items-center dc:justify-center dc:p-4\">\n {showDebug ? (\n <div className=\"dc:w-full dc:h-full dc:overflow-auto\">\n {renderDebug()}\n </div>\n ) : (\n <div className=\"dc:text-center dc:max-w-md\">\n <ErrorIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-error dc:mb-4\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Query Execution Failed\n </div>\n <div className=\"dc:text-sm text-dc-text-secondary dc: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 dc:border border-dc-error dc:rounded-lg dc:p-3 dc:text-left\">\n <div className=\"dc:text-xs dc:font-mono text-dc-error dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-12 dc:w-12 dc:border-b-2 dc:mx-auto dc:mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Preparing Query...\n </div>\n <div className=\"dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <svg className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-warning dc: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=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Ready to Execute\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc:mb-4\">\n Click refresh to run your query\n </div>\n {onRefreshClick && (\n <button\n onClick={() => onRefreshClick()}\n className=\"dc:inline-flex dc:items-center dc:gap-2 dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-white bg-dc-accent dc:hover:opacity-90 dc:rounded-lg dc:transition-colors dc:shadow-sm\"\n >\n <svg className=\"dc:w-4 dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center dc:pt-6\">\n <div className=\"dc:text-center dc:mb-16\">\n <ChartIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-text-muted dc:mb-3\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n No Results Yet\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:inline-flex dc:items-center dc:gap-2 dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-white bg-dc-accent hover:bg-dc-accent dc:rounded-lg dc:transition-colors dc:shadow-sm\"\n >\n <SparklesIcon className=\"dc:w-4 dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <SuccessIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-success dc:mb-3\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-1\">\n Query Successful\n </div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <ChartIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <WarningIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Unsupported chart type</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full\">\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full\" />\n </div>\n }\n />\n )\n }\n\n interface FunnelMetadata {\n stepCount: number\n steps: Array<{\n index: number\n name: string\n timeToConvert?: string\n cube?: string\n }>\n }\n\n interface FlowMetadata {\n stepsBefore?: number\n stepsAfter?: number\n eventDimension?: string\n startingStep?: { name?: string; filter?: unknown }\n }\n\n interface RetentionMetadata {\n totalUsers?: number\n segmentCount?: number\n periods?: number\n granularity?: string\n retentionType?: string\n }\n\n interface ModeDebugConfig {\n label: string\n badgeText?: string\n serverQuery: unknown | null | undefined\n serverQueryTitle: string\n serverQueryMissing: React.ReactNode\n debugData: {\n sql: { sql: string; params: unknown[] } | null\n loading: boolean\n error: Error | null\n modeMetadata?: unknown\n } | null | undefined\n sqlPlaceholder: string\n explainResult: any\n explainLoading: boolean\n explainHasRun: boolean\n explainError: Error | null\n runExplain: () => void\n metadataTitle?: string\n metadataSection?: React.ReactNode\n extraSection?: React.ReactNode\n responseSection: React.ReactNode\n }\n\n const renderExecutionErrorBanner = () => {\n if (!executionError) return null\n return (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg dc:border border-dc-error dark:border-dc-error dc:rounded dc:p-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-error dark:text-dc-error dc:mb-1\">\n Execution Error\n </h4>\n <p className=\"dc:text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )\n }\n\n const renderSharedConfigBlocks = () => (\n <div className=\"dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc: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\n const renderStandardResponseBlock = (title?: string) => (\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={title || `Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n )\n\n const renderRetentionResponseBlock = () => (\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 ) : (\n renderStandardResponseBlock()\n )}\n </div>\n )\n\n const renderModeDebug = (config: ModeDebugConfig) => {\n const modeSql = config.debugData?.sql\n const modeLoading = config.debugData?.loading || false\n const modeError = config.debugData?.error || null\n\n return (\n <div className=\"dc:p-4 dc:space-y-4 dc:overflow-auto dc:h-full\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-4\">\n <span className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium bg-dc-accent text-white dc:rounded\">\n {config.label}\n </span>\n {config.badgeText && (\n <span className=\"dc:text-xs text-dc-text-muted\">{config.badgeText}</span>\n )}\n {modeLoading && (\n <span className=\"dc:text-xs text-dc-text-muted dc:animate-pulse\">Loading SQL...</span>\n )}\n </div>\n\n {renderExecutionErrorBanner()}\n\n <div>\n {config.serverQuery ? (\n <CodeBlock\n code={JSON.stringify(config.serverQuery, null, 2)}\n language=\"json\"\n title={config.serverQueryTitle}\n height=\"16rem\"\n />\n ) : (\n config.serverQueryMissing\n )}\n </div>\n\n <ExecutionPlanPanel\n sql={modeSql}\n sqlLoading={modeLoading}\n sqlError={modeError}\n sqlPlaceholder={config.sqlPlaceholder}\n explainResult={config.explainResult}\n explainLoading={config.explainLoading}\n explainHasRun={config.explainHasRun}\n explainError={config.explainError}\n runExplain={config.runExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={config.serverQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {config.metadataTitle && config.metadataSection && (\n <div>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">{config.metadataTitle}</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n {config.metadataSection}\n </div>\n </div>\n )}\n\n {config.extraSection}\n\n {renderSharedConfigBlocks()}\n\n {config.responseSection}\n </div>\n )\n }\n\n // Render debug view (multi-query or single query)\n const renderStandardDebug = () => (\n <div className=\"dc:p-4 dc:space-y-4 dc:overflow-auto dc:h-full\">\n {/* Query tabs for multi-query mode */}\n {debugDataPerQuery.length > 1 && (\n <div className=\"dc:flex dc:items-center dc:gap-1 dc:mb-4\">\n <span className=\"dc:text-xs dc:font-medium text-dc-text-muted dc:mr-2\">Query:</span>\n <div className=\"dc:flex dc:border border-dc-border dc:rounded-md dc:overflow-hidden\">\n {debugDataPerQuery.map((data, idx) => (\n <button\n key={idx}\n onClick={() => setActiveDebugIndex(idx)}\n className={`dc:px-3 dc:py-1 dc:text-xs dc:font-medium dc:transition-colors dc:border-r dc: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=\"dc:ml-1 dc:opacity-70\">•</span>\n )}\n {data.error && (\n <span className=\"dc: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 dc:border border-dc-error dark:border-dc-error dc:rounded dc:p-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-error dark:text-dc-error dc:mb-1\">\n Execution Error\n </h4>\n <p className=\"dc: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 <div className=\"dc:flex dc:items-center dc:justify-between dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text\">Query Analysis</h4>\n {debugAnalysis && (\n <button\n onClick={handleCopyMarkdown}\n className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium dc:rounded dc:border border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text-secondary hover:text-dc-text dc:transition-colors dc:flex dc:items-center dc:gap-1\"\n title=\"Copy query, analysis, and SQL as markdown\"\n >\n {copyMarkdownState === 'copied' ? (\n <>\n <span className=\"text-dc-success\">✓</span>\n Copied!\n </>\n ) : (\n <>📋 Copy as Markdown</>\n )}\n </button>\n )}\n </div>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm\">\n Loading...\n </div>\n ) : debugAnalysis ? (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n <QueryAnalysisPanel analysis={debugAnalysis} />\n </div>\n ) : (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc: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=\"dc:mt-1 dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Cube Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc: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=\"dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc: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 (isFunnelMode) {\n const metadata = funnelDebugData?.modeMetadata as FunnelMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:flex dc:flex-wrap dc:gap-2\">\n {metadata.steps.map((step, idx) => (\n <div key={idx} className=\"dc:flex dc:items-center dc:gap-2 dc:px-3 dc:py-1.5 bg-dc-bg dc:border border-dc-border dc:rounded dc:text-sm\">\n <span className=\"dc:w-5 dc:h-5 dc:flex dc:items-center dc:justify-center bg-dc-accent text-white dc:text-xs dc:rounded-full\">\n {idx + 1}\n </span>\n <span className=\"text-dc-text\">{step.name}</span>\n {step.timeToConvert && (\n <span className=\"dc:text-xs text-dc-text-muted\">({step.timeToConvert})</span>\n )}\n </div>\n ))}\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Funnel Query',\n badgeText: metadata?.stepCount ? `${metadata.stepCount} steps` : undefined,\n serverQuery: funnelServerQuery,\n serverQueryTitle: 'Funnel Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Funnel Server Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc:overflow-auto\">\n No funnel query configured\n </div>\n </>\n ),\n debugData: funnelDebugData,\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 metadataTitle: metadataSection ? 'Funnel Steps' : undefined,\n metadataSection,\n responseSection: renderStandardResponseBlock(),\n })\n }\n\n if (isRetentionMode) {\n const metadata = retentionDebugData?.modeMetadata as RetentionMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Retention Type:</span>{' '}\n <span className=\"text-dc-text\">{metadata.retentionType || 'Classic'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Periods:</span>{' '}\n <span className=\"text-dc-text\">{metadata.periods ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Granularity:</span>{' '}\n <span className=\"text-dc-text\">{metadata.granularity || 'Week'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Segments:</span>{' '}\n <span className=\"text-dc-text\">{metadata.segmentCount || 1}</span>\n </div>\n </div>\n ) : null\n\n const extraSection = retentionChartData?.summary ? (\n <div>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Retention Summary</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n <div className=\"dc:grid dc:grid-cols-3 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Avg Period 1:</span>{' '}\n <span className=\"text-dc-text dc: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 dc: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 dc:font-medium\">\n {(retentionChartData.summary.minPeriod1Retention * 100).toFixed(1)}%\n </span>\n </div>\n </div>\n </div>\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Retention Query',\n badgeText: metadata ? `${metadata.segmentCount || 1} segment(s), ${metadata.totalUsers} users` : undefined,\n serverQuery: retentionServerQuery,\n serverQueryTitle: 'Retention Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Retention Server Query</h4>\n <div className=\"bg-dc-warning-bg dc:border border-dc-warning dc:rounded dc:p-3 dc:text-sm dc:h-64 dc:overflow-auto\">\n <div className=\"text-dc-warning dc:font-medium dc:mb-2\">Configuration Incomplete</div>\n {retentionValidation && retentionValidation.errors.length > 0 ? (\n <ul className=\"list-disc dc:list-inside text-dc-text-secondary dc: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 debugData: retentionDebugData,\n sqlPlaceholder: 'Configure retention to generate SQL',\n explainResult: retentionExplainResult,\n explainLoading: retentionExplainLoading,\n explainHasRun: retentionExplainHasRun,\n explainError: retentionExplainError,\n runExplain: runRetentionExplain,\n metadataTitle: metadataSection ? 'Retention Configuration' : undefined,\n metadataSection,\n extraSection,\n responseSection: renderRetentionResponseBlock(),\n })\n }\n\n if (isFlowMode) {\n const metadata = flowDebugData?.modeMetadata as FlowMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Starting Step:</span>{' '}\n <span className=\"text-dc-text\">{metadata.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\">{metadata.eventDimension || 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps Before:</span>{' '}\n <span className=\"text-dc-text\">{metadata.stepsBefore ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps After:</span>{' '}\n <span className=\"text-dc-text\">{metadata.stepsAfter ?? 'Not set'}</span>\n </div>\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Flow Query',\n badgeText: metadata ? `${metadata.stepsBefore} before, ${metadata.stepsAfter} after` : undefined,\n serverQuery: flowServerQuery,\n serverQueryTitle: 'Flow Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Flow Server Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc:overflow-auto\">\n No flow query configured\n </div>\n </>\n ),\n debugData: flowDebugData,\n sqlPlaceholder: 'Configure flow to generate SQL',\n explainResult: flowExplainResult,\n explainLoading: flowExplainLoading,\n explainHasRun: flowExplainHasRun,\n explainError: flowExplainError,\n runExplain: runFlowExplain,\n metadataTitle: metadataSection ? 'Flow Configuration' : undefined,\n metadataSection,\n responseSection: renderStandardResponseBlock('Server Response (Sankey Data)'),\n })\n }\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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data to display</div>\n <div className=\"dc:text-xs\">Configure flow analysis to see results</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:overflow-auto dc:p-4 dc:space-y-6\">\n {/* Nodes Table */}\n <div>\n <h3 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Nodes ({nodes.length})\n </h3>\n <div className=\"dc:border border-dc-border dc:rounded dc:overflow-hidden\">\n <table className=\"dc:w-full dc:text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Layer</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Name</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-right dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"dc: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=\"dc:px-3 dc:py-2 dc:whitespace-nowrap\">\n <span className={`dc:inline-flex dc:items-center dc:justify-center dc:w-6 dc:h-6 dc:rounded dc:text-xs dc: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=\"dc:px-3 dc:py-2 text-dc-text\">{node.name as string}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-right text-dc-text dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Transitions ({links.length})\n </h3>\n <div className=\"dc:border border-dc-border dc:rounded dc:overflow-hidden\">\n <table className=\"dc:w-full dc:text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">From</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-center dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">→</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">To</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-right dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"dc: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=\"dc:px-3 dc:py-2 text-dc-text\">{sourceName}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-center text-dc-text-muted\">→</td>\n <td className=\"dc:px-3 dc:py-2 text-dc-text\">{targetName}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-right text-dc-text dc: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\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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full\">\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full\" />\n </div>\n }\n />\n )\n }\n\n // Overlay spinner for refreshing\n const renderOverlaySpinner = () => (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center bg-dc-surface bg-opacity-75 dc:z-10\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-10 dc:w-10 dc:border-b-2 dc:mx-auto dc:mb-2\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-surface-secondary dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n {/* Left side: Status and row count */}\n <div className=\"dc:flex dc:items-center\">\n {executionStatus === 'refreshing' ? (\n <div\n className=\"dc:w-4 dc:h-4 dc:mr-2 dc:rounded-full dc:border-b-2 dc:animate-spin\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n ) : hasResults ? (\n <SuccessIcon className=\"dc:w-4 dc:h-4 text-dc-success dc:mr-2\" />\n ) : executionStatus === 'error' ? (\n <ErrorIcon className=\"dc:w-4 dc:h-4 text-dc-error dc:mr-2\" />\n ) : (\n <WarningIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted dc:mr-2\" />\n )}\n <span className=\"dc: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 dc: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=\"dc:flex dc:items-center dc: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=\"dc:text-xs dc:border border-dc-border dc:rounded dc:px-2 dc:py-1 bg-dc-surface text-dc-text dc:focus:outline-none dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n isAIOpen\n ? 'text-white bg-dc-accent dc:border border-dc-accent'\n : 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg dc:border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n }`}\n title={isAIOpen ? 'Close AI assistant' : 'Analyse with AI'}\n >\n <SparklesIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n shareButtonState === 'idle' && canShare\n ? 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg dc:border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n : shareButtonState !== 'idle'\n ? 'text-dc-success dark:text-dc-success bg-dc-success-bg dark:bg-dc-success-bg dc:border border-dc-success dark:border-dc-success'\n : 'text-dc-text-muted bg-dc-surface-secondary dc:border border-dc-border dc: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=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Share</span>\n </>\n ) : shareButtonState === 'copied' ? (\n <>\n <CheckIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Copied!</span>\n </>\n ) : (\n <>\n <CheckIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Copied!</span>\n <span className=\"dc:hidden dc:lg:inline dc:text-[10px] dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n isRefreshing\n ? 'text-dc-text-muted bg-dc-surface-secondary dc:border border-dc-border dc:cursor-wait'\n : showCacheBustIndicator\n ? 'text-dc-warning bg-dc-warning-bg dc:border border-dc-warning dc:font-semibold'\n : 'text-dc-accent bg-dc-accent-bg dc: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={`dc:w-3 dc:h-3 ${isRefreshing ? 'dc:animate-spin' : ''}`} />\n <span className=\"dc:hidden dc:sm:inline\">{isRefreshing ? 'Refreshing' : 'Refresh'}</span>\n </button>\n )}\n\n {/* Clear Button */}\n {onClearClick && canClear && (\n <button\n onClick={() => setIsClearConfirmOpen(true)}\n className=\"dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover dc:border border-dc-border dc:rounded dc:transition-colors\"\n title={isFunnelMode ? 'Clear funnel' : 'Clear all query data'}\n >\n <TrashIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Clear</span>\n </button>\n )}\n\n {/* Debug Toggle Button */}\n <button\n onClick={() => setShowDebug(!showDebug)}\n className={`dc:p-1.5 dc:rounded dc:transition-colors dc: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=\"dc:w-4 dc:h-4\" />\n {/* Error indicator dot - show if ANY query has an error */}\n {(executionError || debugDataPerQuery.some(d => d.error)) && !showDebug && (\n <span className=\"dc:absolute dc:-top-0.5 dc:-right-0.5 dc:w-2 dc:h-2 bg-dc-danger-bg0 dc:rounded-full\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Performance Warning */}\n {hasResults && totalRowCount !== null && totalRowCount > 1000 && (\n <div className=\"dc:mt-2 bg-dc-warning-bg dc:border border-dc-warning dc:rounded-lg dc:p-2 dc:flex dc:items-start\">\n <WarningIcon className=\"dc:w-4 dc:h-4 text-dc-warning dc:mr-2 dc:shrink-0 dc:mt-0.5\" />\n <div className=\"dc:text-xs text-dc-warning\">\n <span className=\"dc: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=\"dc:px-4 dc:py-2 bg-dc-warning-bg dc:border-b border-dc-warning dc:flex dc:items-center dc:justify-between dc:gap-3 dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center dc:gap-2 text-dc-warning\">\n <svg className=\"dc:w-4 dc:h-4 dc: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=\"dc:text-sm dc:font-medium\">Query configuration changed. Results may be outdated.</span>\n </div>\n <button\n onClick={() => onRefreshClick()}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium bg-dc-warning text-white dc:rounded hover:bg-dc-warning/90 dc:transition-colors\"\n >\n Refresh Now\n </button>\n </div>\n )\n }\n\n // Query warnings banner (e.g., fan-out without dimensions)\n const renderWarningsBanner = () => {\n if (!warnings || warnings.length === 0) return null\n\n return (\n <>\n {warnings.map((warning, index) => {\n const WarningIcon = getIcon('warning')\n const isError = warning.severity === 'error'\n const bgClass = isError ? 'bg-dc-danger-bg' : 'bg-dc-warning-bg'\n const borderClass = isError ? 'border-dc-error' : 'border-dc-warning'\n const textClass = isError ? 'text-dc-error' : 'text-dc-warning'\n\n return (\n <div\n key={`${warning.code}-${index}`}\n className={`dc:px-4 dc:py-2 ${bgClass} dc:border-b ${borderClass} dc:flex dc:items-start dc:gap-3 dc:flex-shrink-0`}\n >\n <WarningIcon className={`dc:w-4 dc:h-4 dc:flex-shrink-0 dc:mt-0.5 ${textClass}`} />\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className={`dc:text-sm dc:font-medium ${textClass}`}>\n {warning.message}\n </div>\n {warning.suggestion && (\n <div className={`dc:text-xs dc:mt-1 ${textClass} dc:opacity-80`}>\n 💡 {warning.suggestion}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </>\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=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n <div className=\"dc:flex-1 dc:min-h-0 dc:relative dc:overflow-auto\">\n {showDebug ? renderDebug() : renderNoData()}\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n {renderNeedsRefreshBanner()}\n {renderWarningsBanner()}\n\n {/* Results Content */}\n <div className=\"dc:flex-1 dc:min-h-0 dc:relative dc:overflow-auto\">\n {showDebug ? (\n renderDebug()\n ) : activeView === 'chart' ? (\n <div className=\"dc:p-4 dc:h-full\">{renderChart()}</div>\n ) : isFlowMode ? (\n <div className=\"dc:h-full\" key=\"table-flow\">{renderFlowTable()}</div>\n ) : isMultiQuery ? (\n <div className=\"dc:h-full\" key={`table-${activeTableIndex}`}>{renderTable(activeTableIndex)}</div>\n ) : (\n <div className=\"dc:h-full\" key=\"table-single\">{renderTable()}</div>\n )}\n </div>\n\n {/* View Toggle - Below content, centered */}\n {!showDebug && (\n <div className=\"dc:px-4 dc:py-3 dc:border-t border-dc-border bg-dc-surface dc:flex dc:justify-center dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center bg-dc-surface-secondary dc:border border-dc-border dc:rounded-md dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-4 dc:py-1.5 dc:text-sm dc:font-medium dc: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 dc: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=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc:h-4\" />\n Merged\n </button>\n </>\n ) : (\n <button\n onClick={() => onActiveViewChange('table')}\n className={`dc:flex dc:items-center dc:gap-1.5 dc:px-4 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc: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=\"dc:h-full dc:min-h-[400px] dc:flex dc:flex-col bg-dc-surface dc:relative\">\n {renderNeedsRefreshEmpty()}\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:min-h-[400px] dc:flex dc:flex-col bg-dc-surface dc: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=\"dc:w-4 dc:h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"dc:w-4 dc:h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 ${\n isDraggable ? 'dc:cursor-grab dc:active:cursor-grabbing' : ''\n } ${isDragging ? 'dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n {MeasureIcon && <MeasureIcon className=\"dc:w-4 dc:h-4\" />}\n </span>\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={metric.field}>\n {displayTitle}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc:truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`dc:p-1 dc:transition-opacity dc:flex-shrink-0 dc:flex dc:items-center dc:gap-0.5 ${\n sortDirection\n ? 'dc:opacity-100 text-dc-primary'\n : 'dc:opacity-100 dc:sm:opacity-0 dc: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=\"dc:text-xs dc:font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title=\"Remove metric\"\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add metric\"\n >\n <SectionHeading>Metrics</SectionHeading>\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc:transition-colors\" />\n </button>\n\n {/* Metrics List */}\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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 * Uses common dry-run fields across all analysis modes.\n */\n funnelDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Uses common dry-run fields across all analysis modes.\n */\n flowDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Uses common dry-run fields across all analysis modes.\n */\n retentionDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Query warnings from server (e.g., fan-out without dimensions).\n * Displayed as a banner above results.\n */\n warnings?: import('../../shared/types').QueryWarning[]\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=\"dc:w-4 dc:h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"dc:w-4 dc:h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 ${\n isDraggable ? 'dc:cursor-grab dc:active:cursor-grabbing' : ''\n } ${isDragging ? 'dc: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={`dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n </span>\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={breakdown.field}>\n {displayTitle}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs bg-dc-surface dc:border border-dc-border dc:rounded dc:px-2 dc:py-1 text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary dc: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={`dc:text-xs dc:px-2 dc:py-1 dc:rounded dc:flex-shrink-0 dc:transition-colors ${\n breakdown.enableComparison\n ? 'bg-dc-accent text-white'\n : 'bg-dc-surface dc:border border-dc-border text-dc-text-muted hover:text-dc-text hover:bg-dc-surface-hover'\n } ${comparisonDisabled && !breakdown.enableComparison ? 'dc:opacity-50 dc: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={`dc:p-1 dc:transition-opacity dc:flex-shrink-0 dc:flex dc:items-center dc:gap-0.5 ${\n sortDirection\n ? 'dc:opacity-100 text-dc-primary'\n : 'dc:opacity-100 dc:sm:opacity-0 dc: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=\"dc:text-xs dc:font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title=\"Remove breakdown\"\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add breakdown\"\n >\n <SectionHeading>Breakdown</SectionHeading>\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc:transition-colors\" />\n </button>\n\n {/* Breakdowns List */}\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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=\"dc:text-sm text-dc-text-muted dc:italic dc: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=\"dc:space-y-2\">\n {/* Range type dropdown */}\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"dc:truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isDateRangeDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-48 dc:overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc: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=\"dc:flex dc:items-center dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text dc:w-20\"\n />\n <span className=\"dc: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=\"dc:flex dc:items-center dc:gap-2\">\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-2 dc:py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-2 dc: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=\"dc:flex dc:items-center dc:gap-2\">\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:space-y-2\">\n {/* Selected values as tags */}\n {filter.values && filter.values.length > 0 && (\n <div className=\"dc:flex dc:flex-wrap dc:gap-1.5\">\n {filter.values.map((value: unknown, index: number) => (\n <span\n key={index}\n className=\"dc:inline-flex dc:items-center dc:gap-1 bg-dc-primary/10 text-dc-primary dc:text-sm dc:px-2 dc:py-1 dc:rounded\"\n >\n <span className=\"dc:max-w-[150px] dc:truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-dc-danger\"\n >\n <CloseIcon className=\"dc:w-3.5 dc:h-3.5\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted dc:truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isValueDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-56 dc:overflow-hidden\">\n {/* Search input with keyboard navigation */}\n <div className=\"dc:p-2 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div ref={valueListRef} className=\"dc:max-h-40 dc:overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"dc:px-3 dc:py-2 dc:text-sm text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"dc:px-3 dc:py-2 dc:text-sm text-dc-error\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"dc:px-3 dc:py-2 dc: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={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc:text-sm dc: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=\"dc: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=\"dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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={`dc:fixed dc:inset-0 bg-dc-overlay dc:z-50 ${modalPosition ? '' : 'dc:flex dc:items-center dc:justify-center dc: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=\"dc:flex dc:items-center dc:justify-between dc:p-4 dc:border-b border-dc-border\">\n <h2 className=\"dc:text-lg dc:font-semibold text-dc-text\">Edit Filter</h2>\n <button\n onClick={onCancel}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-text dc:transition-colors\"\n >\n <CloseIcon className=\"dc:w-5 dc:h-5\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"dc:p-4 dc:space-y-4\">\n {/* Field display */}\n <div>\n <label className=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Field\n </label>\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:p-3 bg-dc-surface-secondary dc:rounded\">\n <FieldIcon className=\"dc:w-5 dc:h-5 text-dc-filter-text\" />\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">{fieldTitle}</span>\n </div>\n </div>\n\n {/* Operator selector */}\n <div>\n <label className=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Operator\n </label>\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"dc:truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isOperatorDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-48 dc:overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc: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=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Value\n </label>\n {renderValueInput()}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"dc:flex dc:items-center dc:justify-end dc:gap-2 dc:p-4 dc:border-t border-dc-border\">\n <button\n onClick={onCancel}\n className=\"dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-dc-text-secondary hover:text-dc-text dc:transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={() => onSave(filter)}\n className=\"dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-dc-primary-content bg-dc-primary hover:bg-dc-primary-hover dc:rounded dc: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=\"dc:flex dc:items-start dc:gap-2 dc:px-2 dc:py-1.5 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 dc:w-full\"\n >\n {/* Field type icon with appropriate background color */}\n <span className={`dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded ${iconBgClass} ${iconTextClass} dc:flex-shrink-0 dc:mt-0.5`}>\n {FieldIcon && <FieldIcon className=\"dc:w-4 dc:h-4\" />}\n </span>\n\n {/* Filter description - clickable to edit */}\n <button\n ref={buttonRef}\n onClick={() => setIsModalOpen(true)}\n className=\"dc:flex-1 dc:min-w-0 dc:text-left\"\n title={`${fieldTitle} ${operatorLabel} ${valueDisplay}`}\n >\n <div className=\"dc:text-sm text-dc-text dc:break-words\">\n <span className=\"dc:font-medium\">{fieldTitle}</span>\n <span className=\"text-dc-text-muted dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0 dc:mt-0.5\"\n title=\"Remove filter\"\n >\n {CloseIcon && <CloseIcon className=\"dc:w-4 dc: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={`dc:border ${getBorderColor()} dc:rounded-lg bg-dc-surface dc:w-full`}>\n {/* Group Header */}\n <div className={`dc:flex dc:items-center dc:justify-between dc:px-2 dc:py-1.5 dc:border-b border-dc-border/50 dc:rounded-t-lg ${getGroupBgColor()}`}>\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {/* AND/OR Toggle Button */}\n <button\n onClick={handleToggleType}\n className={`dc:px-2 dc:py-0.5 dc:text-xs dc:font-semibold dc:rounded dc:transition-colors ${\n group.type === 'and'\n ? 'bg-dc-info-bg text-dc-info dc:hover:opacity-80'\n : 'bg-dc-warning-bg text-dc-warning dc: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=\"dc:text-xs text-dc-text-muted\">\n {conditionCount} {conditionLabel}\n </span>\n </div>\n\n <div className=\"dc:flex dc:items-center dc:gap-1\">\n {/* Add Button with Dropdown */}\n <div className=\"dc:relative\" ref={addMenuRef}>\n <button\n onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}\n className=\"dc:p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-hover dc:rounded dc:transition-colors\"\n title=\"Add condition\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n\n {isAddMenuOpen && (\n <div className=\"dc:absolute dc:right-0 dc:mt-1 dc:z-40 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:py-1 dc:min-w-[120px]\">\n <button\n onClick={handleAddFilterClick}\n className=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc:text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add Filter\n </button>\n <button\n onClick={() => handleAddNestedGroup('and')}\n className=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc: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=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:transition-colors\"\n title=\"Remove group\"\n >\n <CloseIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Group Body - Filter List */}\n <div className=\"dc:p-1.5 dc:flex dc:flex-wrap dc:gap-2\">\n {group.filters.length === 0 ? (\n <div className=\"dc:text-center dc:py-3\">\n <p className=\"dc:text-xs text-dc-text-muted dc:mb-1\">No conditions in this group</p>\n <button\n onClick={() => onAddFilter([])}\n className=\"dc:text-xs text-dc-primary dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add filter\"\n >\n <SectionHeading>\n Filter\n {totalFilterCount > 0 && (\n <span className=\"dc:ml-1.5 dc:text-xs dc:font-normal text-dc-text-muted dc:normal-case dc:tracking-normal\">\n ({totalFilterCount})\n </span>\n )}\n </SectionHeading>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:text-xs text-dc-text-muted hover:text-dc-error dc:underline dc:cursor-pointer\"\n >\n Clear all\n </span>\n )}\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc: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={`dc:p-2 dc:-mx-2 dc:rounded-lg dc:border-2 dc:border-dashed dc: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={`dc:text-sm ${isDragOver ? 'text-dc-primary dc:font-medium' : 'text-dc-text-muted'}`}>\n {isDragOver ? 'Drop to add filter' : 'No filters applied'}\n </p>\n ) : (\n <div className=\"dc:flex dc:flex-wrap dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n <IconComponent className=\"dc:w-4 dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-time-dimension text-dc-time-dimension-text dc:flex-shrink-0\">\n <TimeDimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n )\n } else {\n // Regular dimensions get colored background matching field selector\n return (\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-dimension text-dc-dimension-text dc:flex-shrink-0\">\n <DimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n )\n }\n }\n\n return (\n <div className=\"dc:mb-3\">\n {/* Header */}\n <div className=\"dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-medium text-dc-text dc:flex dc:items-center\">\n {label}\n {mandatory && <span className=\"text-dc-error dc:ml-1\">*</span>}\n </h4>\n {description && <div className=\"dc:text-xs text-dc-text-muted dc:mt-0.5\">{description}</div>}\n </div>\n\n {/* Drop Zone Container */}\n <div\n ref={containerRef}\n data-axis-container={key}\n className={`dc:min-h-[48px] dc:border-2 dc:border-dashed dc:rounded-lg dc:p-2 dc:transition-all dc:duration-200 ${\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'dc:shadow-sm dc: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=\"dc:text-sm text-dc-text-muted dc:text-center dc:py-2\">\n {isFull ? 'Maximum items reached' : emptyText || `Drop fields here`}\n </div>\n ) : (\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${\n isBeingDragged ? 'dc:opacity-30 dc:cursor-grabbing' : ''\n }`}\n >\n {/* Icon */}\n {renderFieldIcon(meta)}\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={field}>\n {meta.shortTitle || meta.title || field.split('.').pop()}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:px-1.5 dc:py-0.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors dc:flex-shrink-0 ${\n (yAxisAssignment?.[field] || 'left') === 'left'\n ? 'bg-dc-info-bg text-dc-info dc:hover:opacity-80'\n : 'bg-dc-accent-bg text-dc-accent dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-0 dc:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title={`Remove from ${label}`}\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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=\"dc:text-xs text-dc-error dc:mt-1\">This field is required</div>\n )}\n </div>\n )\n}\n","import { barChartConfig } from '../components/charts/BarChart.config'\nimport { lineChartConfig } from '../components/charts/LineChart.config'\nimport { areaChartConfig } from '../components/charts/AreaChart.config'\nimport { pieChartConfig } from '../components/charts/PieChart.config'\nimport { scatterChartConfig } from '../components/charts/ScatterChart.config'\nimport { bubbleChartConfig } from '../components/charts/BubbleChart.config'\nimport { radarChartConfig } from '../components/charts/RadarChart.config'\nimport { radialBarChartConfig } from '../components/charts/RadialBarChart.config'\nimport { treemapChartConfig } from '../components/charts/TreeMapChart.config'\nimport { dataTableConfig } from '../components/charts/DataTable.config'\nimport { activityGridChartConfig } from '../components/charts/ActivityGridChart.config'\nimport { kpiNumberConfig } from '../components/charts/KpiNumber.config'\nimport { kpiDeltaConfig } from '../components/charts/KpiDelta.config'\nimport { kpiTextConfig } from '../components/charts/KpiText.config'\nimport { markdownConfig } from '../components/charts/MarkdownChart.config'\nimport { funnelChartConfig } from '../components/charts/FunnelChart.config'\nimport { sankeyChartConfig } from '../components/charts/SankeyChart.config'\nimport { sunburstChartConfig } from '../components/charts/SunburstChart.config'\nimport { heatmapChartConfig } from '../components/charts/HeatMapChart.config'\nimport { retentionHeatmapConfig } from '../components/charts/RetentionHeatmap.config'\nimport { retentionCombinedConfig } from '../components/charts/RetentionCombinedChart.config'\nimport { boxPlotChartConfig } from '../components/charts/BoxPlotChart.config'\nimport { waterfallChartConfig } from '../components/charts/WaterfallChart.config'\nimport { candlestickChartConfig } from '../components/charts/CandlestickChart.config'\nimport { measureProfileChartConfig } from '../components/charts/MeasureProfileChart.config'\nimport { gaugeChartConfig } from '../components/charts/GaugeChart.config'\nimport type { ChartConfigRegistry } from './chartConfigs'\n\n/**\n * Registry of all chart type configurations\n */\nexport const chartConfigRegistry: ChartConfigRegistry = {\n bar: barChartConfig,\n line: lineChartConfig,\n area: areaChartConfig,\n pie: pieChartConfig,\n scatter: scatterChartConfig,\n bubble: bubbleChartConfig,\n radar: radarChartConfig,\n radialBar: radialBarChartConfig,\n treemap: treemapChartConfig,\n table: dataTableConfig,\n activityGrid: activityGridChartConfig,\n kpiNumber: kpiNumberConfig,\n kpiDelta: kpiDeltaConfig,\n kpiText: kpiTextConfig,\n markdown: markdownConfig,\n funnel: funnelChartConfig,\n sankey: sankeyChartConfig,\n sunburst: sunburstChartConfig,\n heatmap: heatmapChartConfig,\n retentionHeatmap: retentionHeatmapConfig,\n retentionCombined: retentionCombinedConfig,\n boxPlot: boxPlotChartConfig,\n waterfall: waterfallChartConfig,\n candlestick: candlestickChartConfig,\n measureProfile: measureProfileChartConfig,\n gauge: gaugeChartConfig,\n}\n","import { useMemo, useState } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\nimport { chartConfigRegistry } from '../charts/chartConfigRegistry'\nimport { getChartTypeIcon } from '../icons'\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/** Get label for a chart type from the registry, falling back to the chart type key */\nfunction getLabel(type: ChartType): string {\n return chartConfigRegistry[type]?.label || type\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\n // Derive chart types from the registry, filter excluded ones, and sort alphabetically by label\n const chartTypes = useMemo(() =>\n (Object.keys(chartConfigRegistry) as ChartType[])\n .filter((type) => !excludeTypes.includes(type))\n .sort((a, b) => getLabel(a).localeCompare(getLabel(b)))\n , [excludeTypes])\n\n const SelectedIcon = getChartTypeIcon(selectedType)\n const selectedLabel = getLabel(selectedType)\n\n return (\n <div className={`${className} dc:relative`}>\n {/* Dropdown Button */}\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:px-3 dc:py-2 dc:border border-dc-border dc:rounded-md bg-dc-surface hover:bg-dc-surface-hover focus:outline-hidden dc:focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n >\n <div className=\"dc:flex dc:items-center dc:space-x-2\">\n {SelectedIcon && (\n <SelectedIcon className=\"dc:h-5 dc:w-5 text-dc-text-secondary\" />\n )}\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">{selectedLabel}</span>\n </div>\n <svg\n className={`dc:h-4 dc:w-4 text-dc-text-muted dc:transform dc:transition-transform ${isOpen ? 'dc: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={`dc:absolute dc:z-10 dc:mt-1 dc:w-full bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg dc:max-h-80 dc:overflow-auto ${compact ? '' : 'dc:min-w-max'}`}>\n <div className=\"dc:p-2\">\n <div className={`dc:grid dc:gap-1.5 ${compact ? 'dc:grid-cols-2' : 'dc:grid-cols-2 dc:sm:grid-cols-3 dc:lg:grid-cols-4'}`}>\n {chartTypes.map((type) => {\n const config = chartConfigRegistry[type]\n const IconComponent = getChartTypeIcon(type)\n const label = getLabel(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 dc:relative dc:p-1.5 dc:rounded dc:border dc:transition-colors dc:duration-150\n dc:text-left dc:group dc:min-h-[30px] dc:flex dc:items-center dc:justify-start\n ${!isAvailable\n ? 'dc:opacity-50 dc: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=\"dc:flex dc:items-center dc:space-x-1.5\">\n {/* Icon */}\n {IconComponent && (\n <IconComponent\n className={`dc:h-4 dc:w-4 dc: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={`dc:text-xs dc:font-medium dc:leading-tight dc: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=\"dc:absolute dc:top-0.5 dc:right-0.5\">\n <div className=\"dc:w-1.5 dc:h-1.5 dc: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=\"dc:space-y-6\">\n <div>\n <SectionHeading className=\"dc: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=\"dc:text-center text-dc-text-muted dc:text-sm dc: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=\"dc:space-y-6\">\n {/* Chart Type Selector */}\n <div>\n <SectionHeading className=\"dc: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=\"dc:mb-2\">\n Chart Configuration\n </SectionHeading>\n <div className=\"dc: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=\"dc:mb-2\">\n <SectionHeading>Unassigned Fields</SectionHeading>\n <div className=\"dc:text-xs text-dc-text-muted dc:mt-0.5\">\n Drag fields to chart axes above\n </div>\n </div>\n <div className=\"dc:border-2 dc:border-dashed border-dc-border dc:rounded-lg dc:p-2 bg-dc-surface-secondary\">\n <div className=\"dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n <IconComponent className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-dimension text-dc-dimension-text dc:flex-shrink-0\">\n <DimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-time-dimension text-dc-time-dimension-text dc:flex-shrink-0\">\n <TimeDimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-center text-dc-text-muted dc:text-sm dc: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 * 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=\"dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2 dc:py-1 dc:text-xs\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors\n ${disabled ? 'dc:opacity-50 dc:cursor-not-allowed' : 'hover:border-dc-primary dc:cursor-pointer'}\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc:truncate ${hasSelection ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {label}\n </span>\n <span className=\"dc:flex dc:items-center dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:right-0 dc:w-[280px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Dimension List */}\n <div className=\"dc:max-h-64 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching dimensions found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n {/* Cube Header */}\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:flex dc:items-center dc:gap-0.5 dc:p-1.5 dc: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 dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:rounded-md dc:text-sm dc:font-medium\n dc:transition-colors dc:duration-150\n ${\n isSelected\n ? 'bg-dc-primary/10 text-dc-primary dc:border border-dc-primary/30'\n : 'text-dc-text-secondary hover:bg-dc-bg-secondary hover:text-dc-text dc:border border-transparent'\n }\n ${disabled ? 'dc:opacity-50 dc:cursor-not-allowed' : 'dc:cursor-pointer'}\n `}\n >\n <Icon className=\"dc:h-4 dc:w-4 dc:flex-shrink-0\" />\n <span className=\"dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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 dc:border dc:rounded-lg dc:transition-all dc:cursor-pointer\n ${isActive\n ? 'border-dc-primary dc: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=\"dc:flex dc:items-center dc:gap-2 dc:px-3 dc:py-2 dc:border-b border-dc-border\">\n {/* Drag Handle */}\n <div className=\"dc:cursor-grab dc:active:cursor-grabbing text-dc-text-muted hover:text-dc-text\">\n {DragHandleIcon && <DragHandleIcon className=\"dc:w-4 dc:h-4\" />}\n </div>\n\n {/* Step Number */}\n <span className=\"dc:flex-shrink-0 dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded-full bg-dc-primary/10 text-dc-primary dc:text-xs dc:font-medium\">\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=\"dc:flex-1 dc:px-1.5 dc:py-0.5 dc:text-sm dc:font-medium bg-dc-surface dc:border border-dc-primary dc:rounded text-dc-text dc:focus:outline-none\"\n placeholder=\"Step name\"\n />\n ) : (\n <button\n onClick={(e) => {\n e.stopPropagation()\n setIsEditingName(true)\n }}\n className=\"dc:flex-1 dc:text-left dc:text-sm dc:font-medium text-dc-text hover:text-dc-primary dc: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=\"dc:p-1 dc:rounded hover:bg-dc-danger-bg text-dc-text-muted hover:text-dc-error dc:transition-colors\"\n title=\"Remove step\"\n >\n {CloseIcon && <CloseIcon className=\"dc:w-4 dc:h-4\" />}\n </button>\n )}\n </div>\n\n {/* Body - Only visible when active */}\n {isActive && (\n <div className=\"dc:px-3 dc:py-3 dc: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=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {TimeDimensionIcon && <TimeDimensionIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n Time Window\n </label>\n <div ref={timeDropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setShowTimeDropdown(!showTimeDropdown)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${showTimeDropdown ? 'border-dc-primary dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${showTimeDropdown ? 'dc:rotate-180' : ''}`}\n />\n )}\n </button>\n\n {showTimeDropdown && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg dc:max-h-48 dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc: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=\"dc:w-4 dc:h-4\" />}\n </button>\n ))}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:px-3 dc:py-2 dc: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 ? 'dc:ml-2' : ''}>\n {step.filters.length > 0 ? '• ' : ''}within {timeToConvertLabel.toLowerCase()}\n </span>\n )}\n {step.filters.length === 0 && !step.timeToConvert && (\n <span className=\"dc: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=\"dc:space-y-4\">\n {/* Header */}\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <SectionHeading>\n Funnel Steps\n {steps.length > 0 && (\n <span className=\"dc:ml-1.5 dc:text-xs dc:font-normal text-dc-text-muted dc:normal-case dc:tracking-normal\">\n ({steps.length})\n </span>\n )}\n </SectionHeading>\n </div>\n\n {/* Step List */}\n {steps.length === 0 ? (\n <div className=\"dc:text-center dc:py-8\">\n <p className=\"dc:text-sm text-dc-text-muted dc:mb-3\">\n No steps defined. Add at least 2 steps to create a funnel.\n </p>\n <button\n onClick={onAddStep}\n className=\"dc:inline-flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium text-dc-primary bg-dc-primary/10 dc:rounded-md hover:bg-dc-primary/20 dc:transition-colors\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n Add First Step\n </button>\n </div>\n ) : (\n <div className=\"dc: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={`dc:transition-all ${\n draggedIndex === index ? 'dc:opacity-50' : ''\n } ${\n dragOverIndex === index\n ? 'dc:border-t-2 border-dc-primary dc: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=\"dc:flex dc:items-center dc:justify-center dc:gap-1.5 dc:w-full dc:py-2 dc:text-sm dc:font-medium text-dc-text-secondary bg-dc-surface dc:border-2 dc:border-dashed border-dc-border dc:rounded-lg hover:border-dc-primary hover:text-dc-primary hover:bg-dc-primary/5 dc:transition-colors\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n Add Step\n </button>\n )}\n\n {/* Validation Hint */}\n {steps.length === 1 && (\n <p className=\"dc:text-xs text-dc-warning dc: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=\"dc:flex dc:flex-col dc:h-full\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('steps')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'steps'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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=\"dc:flex dc:flex-col dc:h-full dc:min-h-0 dc:overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc: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=\"dc:text-xs text-dc-text-muted dc:mb-3\">\n Choose how to visualize the flow data. This affects how data is aggregated.\n </p>\n <div className=\"dc:flex dc:gap-2\">\n <button\n type=\"button\"\n onClick={() => onChartTypeChange('sankey')}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-1\">\n <span>Sankey</span>\n <span className=\"dc:text-[10px] dc: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={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-1\">\n <span>Sunburst</span>\n <span className=\"dc:text-[10px] dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:grid dc:grid-cols-2 dc:gap-4\">\n {/* Steps Before - disabled for sunburst */}\n <div className={chartType === 'sunburst' ? 'dc:opacity-50' : ''}>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Steps Before\n {chartType === 'sunburst' && (\n <span className=\"dc:ml-1 text-dc-text-muted\">(N/A)</span>\n )}\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1 dc:disabled:cursor-not-allowed\"\n />\n <span className=\"dc:w-6 dc:text-sm dc:font-medium text-dc-text dc:text-center\">\n {chartType === 'sunburst' ? '-' : stepsBefore}\n </span>\n </div>\n </div>\n\n {/* Steps After */}\n <div>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Steps After\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1\"\n />\n <span className=\"dc:w-6 dc:text-sm dc:font-medium text-dc-text dc: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=\"dc:mt-3 dc:px-3 dc:py-2 bg-dc-warning-bg dc:rounded dc:border border-dc-warning dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:w-full dc:border border-dc-border dc:rounded dc:px-2 dc:py-2 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {CalendarIcon && <CalendarIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n Date Range\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setShowDatePicker(!showDatePicker)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n hover:border-dc-primary dc:cursor-pointer dc:transition-colors\n ${showDatePicker ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className=\"text-dc-text dc:truncate\">{dateRangeDisplay}</span>\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform dc:ml-2 ${showDatePicker ? 'dc:rotate-180' : ''}`}\n />\n )}\n </button>\n\n {/* Date Range Dropdown */}\n {showDatePicker && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[280px] bg-dc-surface dc:border border-dc-border dc:rounded-lg dc:shadow-lg dc:p-3\">\n {/* Presets */}\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-2 dc: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={`dc:px-3 dc:py-1.5 dc:text-xs dc:rounded dc: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=\"dc:border-t border-dc-border dc:pt-3\">\n <div className=\"dc:text-xs dc:font-medium text-dc-text-muted dc:mb-2\">Custom Range</div>\n <div className=\"dc:flex dc:gap-2 dc:items-center dc:mb-2\">\n <input\n type=\"date\"\n value={customStart}\n onChange={(e) => {\n setCustomStart(e.target.value)\n setSelectedPreset('custom')\n }}\n className=\"dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n <span className=\"text-dc-text-muted dc: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=\"dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleCustomDateApply}\n disabled={!customStart || !customEnd}\n className=\"dc:w-full dc:px-3 dc:py-1.5 dc:text-xs bg-dc-primary text-white dc:rounded hover:bg-dc-primary-hover dc:disabled:opacity-50 dc:disabled:cursor-not-allowed dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel} • {dateLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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=\"dc:flex dc:flex-col dc:h-full dc:min-h-0 dc:overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc:space-y-6\">\n {/* Date Range Selector - at top for visibility */}\n <div>\n <SectionHeading>Date Range</SectionHeading>\n <p className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc:mb-3\">\n Configure how retention is calculated and displayed.\n </p>\n\n <div className=\"dc:space-y-4\">\n {/* Granularity */}\n <div>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Period Granularity\n </label>\n <div className=\"dc:flex dc:gap-2\">\n {RETENTION_GRANULARITY_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onGranularityChange(option.value)}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Number of Periods ({RETENTION_MIN_PERIODS}-{RETENTION_MAX_PERIODS})\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1\"\n />\n <span className=\"dc:w-8 dc:text-sm dc:font-medium text-dc-text dc:text-center\">\n {retentionPeriods}\n </span>\n </div>\n {retentionPeriods > 26 && (\n <p className=\"dc:mt-1 dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Retention Type\n </label>\n <div className=\"dc:flex dc:gap-2\">\n {RETENTION_TYPE_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onRetentionTypeChange(option.value)}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-0.5\">\n <span className=\"dc:font-medium\">{option.label}</span>\n <span className=\"dc:text-[10px] dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:h-full dc:flex dc: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=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n {/* Query Tabs - show Q1, Q2, etc. when multi-query, or single \"Query\" tab */}\n {isMultiQuery ? (\n <div className=\"dc:flex dc:min-w-0 dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-3 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isActiveQuery\n ? 'text-dc-primary dc: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=\"dc:p-0.5 dc:rounded hover:bg-dc-danger-bg hover:text-dc-error dc:transition-colors dc:ml-0.5\"\n title=\"Remove query\"\n aria-label={`Remove ${getQueryTabLabel(index)}`}\n >\n <CloseIcon className=\"dc:w-3 dc:h-3\" />\n </span>\n </button>\n )\n })}\n {/* Add Query Button */}\n <button\n onClick={onAddQuery}\n className=\"dc:flex dc:items-center dc:justify-center dc:px-2 dc:py-3 text-dc-text-secondary hover:text-dc-text dc:transition-colors dc:flex-shrink-0\"\n title=\"Add query\"\n aria-label=\"Add new query\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onActiveTabChange('query')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'query'\n ? 'text-dc-primary dc: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=\"dc:ml-2 dc:p-0.5 dc:rounded hover:bg-dc-surface-hover dc:transition-colors dc:inline-flex dc:items-center\"\n title=\"Add another query\"\n aria-label=\"Add another query\"\n >\n <AddIcon className=\"dc:w-3 dc: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={`dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isMultiQuery ? '' : 'dc:flex-1'\n } ${\n activeTab === 'chart'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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={`dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isMultiQuery ? '' : 'dc:flex-1'\n } ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:items-center dc:gap-2 dc:px-4 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border-b border-dc-border\">\n {LinkIcon && <LinkIcon className=\"dc:w-3.5 dc:h-3.5 text-dc-text-muted dc:flex-shrink-0\" />}\n <select\n value={mergeStrategy}\n onChange={(e) => onMergeStrategyChange?.(e.target.value as QueryMergeStrategy)}\n className=\"dc:px-2 dc:py-1 dc:text-xs bg-dc-surface dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc: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=\"dc:w-[180px] dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-warning-bg dc:space-y-1\">\n {adapterValidation.errors.map((error, i) => (\n <div key={`adapter-error-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-error\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{error}</span>\n </div>\n ))}\n {adapterValidation.warnings.map((warning, i) => (\n <div key={`adapter-warning-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-warning\">\n <InfoIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-warning-bg\">\n {multiQueryValidation.errors.map((error, i) => (\n <div key={`error-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-error\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{error.message}</span>\n </div>\n ))}\n {multiQueryValidation.warnings.map((warning, i) => (\n <div key={`warning-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-warning\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{warning.message}</span>\n </div>\n ))}\n </div>\n )}\n\n {/* Tab Content */}\n <div className=\"dc:flex-1 dc:overflow-auto dc:p-4\">\n {activeTab === 'query' ? (\n <div className=\"dc: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=\"dc:mb-4\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-medium text-dc-text\">Dimensions</h4>\n </div>\n {/* Explanation with link to switch mode */}\n <div className=\"dc:flex dc:items-start dc:gap-2 dc:px-3 dc:py-2 dc:mb-3 bg-dc-surface-secondary dc:rounded dc:border border-dc-border dc:text-xs\">\n {InfoIcon && <InfoIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted dc:flex-shrink-0 dc: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 dc:hover:underline dc: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=\"dc: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=\"dc: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=\"dc:px-4 dc:py-2 dc:flex dc:items-center dc:justify-between dc:border-b border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n <SparklesIcon className=\"dc:w-4 dc:h-4 text-dc-accent\" />\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">AI Query Generator</span>\n {isGenerating && (\n <span className=\"dc:text-xs text-dc-accent dc:animate-pulse\">\n Generating...\n </span>\n )}\n </div>\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {hasGeneratedQuery && (\n <button\n onClick={onAccept}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium text-white bg-dc-success dc:hover:opacity-80 dc:rounded dc:transition-colors\"\n >\n Accept\n </button>\n )}\n <button\n onClick={onCancel}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover dc:border border-dc-border dc:rounded dc:transition-colors\"\n >\n {hasGeneratedQuery ? 'Cancel' : 'Close'}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"dc:p-4\">\n <div className=\"dc:flex dc:gap-3\">\n {/* Prompt input */}\n <div className=\"dc: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=\"dc:w-full dc:px-3 dc:py-2 dc:text-sm dc:border border-dc-border dc:rounded-md dc:shadow-sm dc:focus:outline-none dc:focus:ring-2 focus:ring-dc-accent focus:border-dc-accent dc:resize-none bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n rows={2}\n disabled={isGenerating}\n />\n <div className=\"dc:mt-1 dc: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=\"dc:flex-shrink-0\">\n <button\n onClick={onGenerate}\n disabled={isGenerating || !userPrompt.trim()}\n className={`dc:px-4 dc:py-2 dc:text-sm dc:font-medium dc:rounded-md dc:transition-colors dc:flex dc:items-center dc:gap-2 ${\n isGenerating || !userPrompt.trim()\n ? 'bg-dc-surface-tertiary text-dc-text-disabled dc:cursor-not-allowed'\n : 'bg-dc-accent hover:bg-dc-accent-hover text-white'\n }`}\n >\n {isGenerating ? (\n <>\n <div className=\"dc:w-4 dc:h-4 dc:border-2 border-white border-t-transparent dc:rounded-full dc:animate-spin\" />\n <span>Generating...</span>\n </>\n ) : (\n <>\n <SparklesIcon className=\"dc:w-4 dc:h-4\" />\n <span>Generate</span>\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"dc:mt-3 dc:flex dc:items-start dc:gap-2 dc:p-3 bg-dc-error-bg dc:border border-dc-error-border dc:rounded-md\">\n <ErrorIcon className=\"dc:w-4 dc:h-4 text-dc-error dc:mt-0.5 dc:flex-shrink-0\" />\n <div className=\"dc:text-sm text-dc-error\">{error}</div>\n </div>\n )}\n\n {/* Success message */}\n {hasGeneratedQuery && !error && (\n <div className=\"dc:mt-3 dc:p-3 bg-dc-success-bg dc:border border-dc-success-border dc:rounded-md\">\n <div className=\"dc: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=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-6 dc:text-center bg-dc-surface\">\n <div className=\"dc:h-10 dc:w-10 dc:mb-3 text-dc-warning\">\n {WarningIcon && <WarningIcon className=\"dc:w-10 dc:h-10\" />}\n </div>\n <h3 className=\"dc:text-base dc:font-semibold dc:mb-2 text-dc-text\">\n Mode Error\n </h3>\n <p className=\"dc:text-sm text-dc-text-secondary dc:mb-3 dc: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=\"dc:w-full dc:max-w-md dc:mb-4 dc:text-left\">\n <summary className=\"dc:cursor-pointer dc:text-xs text-dc-text-muted hover:text-dc-text\">\n Show error details\n </summary>\n <div className=\"dc:mt-2 dc:p-2 bg-dc-surface-secondary dc:rounded dc:text-xs dc:font-mono text-dc-text-secondary dc:overflow-auto dc:max-h-32\">\n {this.state.error?.message || 'Unknown error'}\n </div>\n </details>\n\n <div className=\"dc:flex dc:gap-2\">\n <button\n onClick={this.handleReset}\n className=\"dc:px-3 dc:py-1.5 dc:border border-dc-border dc:rounded dc:text-sm text-dc-text hover:bg-dc-surface-hover dc:transition-colors dc:flex dc:items-center dc:gap-1\"\n >\n {RefreshIcon && <RefreshIcon className=\"dc:w-4 dc:h-4\" />}\n Try Again\n </button>\n {this.props.onSwitchToSafeMode && (\n <button\n onClick={this.handleSwitchToSafeMode}\n className=\"dc:px-3 dc:py-1.5 bg-dc-primary text-white dc:rounded dc:text-sm dc:hover:opacity-90 dc: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={`dc:flex dc:flex-col dc:lg:flex-row bg-dc-surface dc:border-x dc:border-b border-dc-border ${maxHeight ? 'dc:lg:h-[var(--dc-max-h)] dc:lg:max-h-[var(--dc-max-h)] dc:lg:overflow-hidden' : 'dc:lg:h-full'} ${className}`}\n style={maxHeight ? { ['--dc-max-h' as string]: maxHeight } : undefined}\n >\n {/* Top/Left Panel - Results */}\n <div className=\"dc:h-[60vh] dc:lg:h-auto dc:lg:flex-1 dc:min-w-0 dc:border-b dc:lg:border-b-0 dc:lg:border-r border-dc-border dc:overflow-auto dc:flex dc: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=\"dc:flex-1 dc: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 warnings={analysis.warnings}\n />\n </div>\n </div>\n\n {/* Bottom/Right Panel - Query Builder */}\n <div className=\"dc:w-full dc:lg:w-96 dc:flex-shrink-0 dc:lg:h-full dc:overflow-auto dc: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":["formatReason","reason","c","getReasonBadgeClasses","QueryAnalysisPanel","analysis","InfoIcon","getIcon","ArrowRightIcon","WarningIcon","TableIcon","LinkIcon","SuccessIcon","ErrorIcon","summaryCards","jsxs","jsx","card","i","jp","idx","step","stepIdx","jc","candidate","pa","jk","w","sendGeminiMessage","apiKey","userPrompt","endpoint","requestBody","headers","response","errorMessage","errorData","errorText","data","extractTextFromResponse","isServerFunnelQuery","query","useAnalysisAI","state","setState","chartType","setChartType","chartConfig","setChartConfig","displayConfig","setDisplayConfig","setUserManuallySelectedChart","setActiveView","aiEndpoint","analysisType","setAnalysisType","loadFunnelFromServerQuery","getFullConfig","loadFullConfig","aiState","setAIState","useState","handleOpenAI","useCallback","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","generateExecutionPlanMarkdown","sql","lines","selected","candidatePath","col","cte","warning","AnalysisResultsPanel","memo","executionStatus","executionResults","executionError","totalRowCount","resultsStale","colorPalette","currentPaletteName","onColorPaletteChange","allQueries","funnelExecutedQueries","activeView","onActiveViewChange","displayLimit","onDisplayLimitChange","hasMetrics","debugDataPerQuery","onShareClick","canShare","onRefreshClick","canRefresh","isRefreshing","needsRefresh","onClearClick","canClear","enableAI","isAIOpen","onAIToggle","queryCount","perQueryResults","activeTableIndex","onActiveTableChange","isFunnelModeProp","funnelServerQuery","funnelDebugData","flowServerQuery","flowDebugData","retentionServerQuery","retentionDebugData","retentionChartData","retentionValidation","warnings","isFunnelMode","isFlowMode","isRetentionMode","showDebug","setShowDebug","activeDebugIndex","setActiveDebugIndex","isClearConfirmOpen","setIsClearConfirmOpen","isShiftHeld","setIsShiftHeld","isHoveringRefresh","setIsHoveringRefresh","copyMarkdownState","setCopyMarkdownState","useEffect","handleKeyDown","e","handleKeyUp","showCacheBustIndicator","currentDebugData","debugSql","debugAnalysis","debugLoading","debugError","debugQuery","isShowingFunnelQuery","handleCopyMarkdown","markdown","explainResult","explainLoading","explainHasRun","explainError","runExplain","clearExplain","useExplainQuery","funnelExplainResult","funnelExplainLoading","funnelExplainHasRun","funnelExplainError","runFunnelExplain","clearFunnelExplain","flowExplainResult","flowExplainLoading","flowExplainHasRun","flowExplainError","runFlowExplain","clearFlowExplain","retentionExplainResult","retentionExplainLoading","retentionExplainHasRun","retentionExplainError","runRetentionExplain","aiAnalysis","aiAnalysisLoading","aiAnalysisError","runAIAnalysis","clearAIAnalysis","useExplainAI","isFirstRunRef","useRef","combinedQueryForChart","useMemo","allMeasures","q","ChartIcon","CodeIcon","ShareIcon","CheckIcon","TrashIcon","SparklesIcon","RefreshIcon","renderLoading","renderError","renderHeader","hasQueryContent","hasModeSpecificContent","renderWaiting","renderNeedsRefreshEmpty","renderEmpty","emptyMessage","renderNoData","renderChart","effectiveChartType","isValidChartType","LazyChart","renderExecutionErrorBanner","renderSharedConfigBlocks","CodeBlock","renderStandardResponseBlock","title","Fragment","renderRetentionResponseBlock","renderModeDebug","modeSql","modeLoading","modeError","ExecutionPlanPanel","renderStandardDebug","renderDebug","metadata","metadataSection","extraSection","isMultiQuery","renderFlowTable","nodes","links","firstResult","r","a","b","node","link","sourceId","targetId","sourceName","targetName","renderTable","tableIndex","tableData","tableQuery","limitedData","renderOverlaySpinner","hasResults","ColorPaletteSelector","d","renderNeedsRefreshBanner","renderWarningsBanner","isError","bgClass","borderClass","textClass","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","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","value","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","chartConfigRegistry","barChartConfig","lineChartConfig","areaChartConfig","pieChartConfig","scatterChartConfig","bubbleChartConfig","radarChartConfig","radialBarChartConfig","treemapChartConfig","dataTableConfig","activityGridChartConfig","kpiNumberConfig","kpiDeltaConfig","kpiTextConfig","markdownConfig","funnelChartConfig","sankeyChartConfig","sunburstChartConfig","heatmapChartConfig","retentionHeatmapConfig","retentionCombinedConfig","boxPlotChartConfig","waterfallChartConfig","candlestickChartConfig","measureProfileChartConfig","gaugeChartConfig","getLabel","ChartTypeSelector","selectedType","onTypeChange","className","compact","availability","excludeTypes","isOpen","setIsOpen","chartTypes","SelectedIcon","getChartTypeIcon","selectedLabel","useCase","chartAvailability","isAvailable","unavailableReason","tooltipText","AnalysisChartConfigPanel","onChartTypeChange","onChartConfigChange","setDraggedItem","availableFields","m","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","SearchIcon","FunnelBindingKeySelector","bindingKey","onChange","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","placeholder","options","helpText","groupedOptions","hasValue","o","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","isActive","canRemove","onSelect","isEditingName","setIsEditingName","showTimeDropdown","setShowTimeDropdown","localName","setLocalName","nameInputRef","timeDropdownRef","handleNameChange","handleNameKeyDown","handleNameBlur","trimmedName","handleTimeSelect","handleFiltersChange","timeToConvertLabel","cubeSchema","metaSchema","getRelatedCubesSchema","FunnelStepList","steps","activeStepIndex","onAddStep","onRemoveStep","onUpdateStep","onSelectStep","onReorderSteps","dragOverIndex","setDragOverIndex","updates","FunnelModeContent","funnelCube","funnelSteps","activeFunnelStepIndex","funnelTimeDimension","funnelBindingKey","onDisplayConfigChange","activeTab","setActiveTab","hasDisplayTab","AnalysisDisplayConfigPanel","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","AnalysisAIPanel","onPromptChange","isGenerating","hasGeneratedQuery","onGenerate","onAccept","AnalysisModeErrorBoundary","Component","props","errorInfo","AnalysisBuilderInner","forwardRef","maxHeight","initialData","externalColorPalette","_hideSettings","hideShare","onQueryChange","ref","useCubeMeta","features","useCubeFeatures","useAnalysisBuilder","storeApi","useAnalysisBuilderStoreApi","updater","newState","serverQuery","funnelConfig","useImperativeHandle","AnalysisBuilder","initialQuery","initialChartConfig","initialAnalysisType","initialFunnelState","initialFlowState","initialRetentionState","disableLocalStorage","innerProps","shareHash","parseShareHash","sharedState","decodeAndDecompress","initialActiveViewFromShare","initialAnalysisTypeFromShare","initialFunnelStateFromShare","funnelQuery","initialFlowStateFromShare","flowQuery","flowChartConfig","initialRetentionStateFromShare","retentionQuery","retentionChartConfig","AnalysisBuilderStoreProvider"],"mappings":"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"}
1
+ {"version":3,"file":"analysis-builder-DVrv9Q4n.js","sources":["../../../src/client/shared/components/QueryAnalysisPanel.tsx","../../../src/client/components/AIAssistant/utils.ts","../../../src/client/hooks/useAnalysisAI.ts","../../../src/client/hooks/useAnalysisShare.ts","../../../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/charts/chartConfigRegistry.ts","../../../src/client/components/ChartTypeSelector.tsx","../../../src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.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 * 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\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\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 const summaryCards = [\n {\n label: 'Type',\n value: formatReason(analysis.querySummary.queryType),\n },\n {\n label: 'Cubes',\n value: String(analysis.cubeCount),\n },\n {\n label: 'Joins',\n value: String(analysis.querySummary.joinCount),\n },\n {\n label: 'CTEs',\n value: String(analysis.querySummary.cteCount),\n },\n ...(analysis.querySummary.measureStrategy\n ? [\n {\n label: 'Strategy',\n value: formatReason(analysis.querySummary.measureStrategy),\n },\n ]\n : []),\n ]\n\n return (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded-lg dc:p-4 dc:space-y-4\">\n {/* Query Summary Section */}\n <div className=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <InfoIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Query Summary\n </h4>\n <div\n className=\"dc:grid dc:gap-2 dc:text-xs\"\n style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))' }}\n >\n {summaryCards.map(card => (\n <div key={card.label} className=\"bg-dc-surface dc:p-2 dc:rounded\">\n <span className=\"text-dc-text-muted\">{card.label}:</span>\n <span className=\"dc:ml-1 dc:font-medium text-dc-text\">{card.value}</span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Primary Cube Section */}\n <div className=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <TableIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Primary Cube (FROM table)\n </h4>\n <div className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-2 dc:flex-wrap\">\n <span className=\"dc:font-mono dc:font-medium text-dc-primary\">\n {analysis.primaryCube.selectedCube}\n </span>\n <span className={`dc:text-xs dc:px-2 dc:py-0.5 dc:rounded ${getReasonBadgeClasses(analysis.primaryCube.reason)}`}>\n {formatReason(analysis.primaryCube.reason)}\n </span>\n </div>\n <p className=\"text-dc-text-secondary dc:text-xs\">\n {analysis.primaryCube.explanation}\n </p>\n {analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1 && (\n <details className=\"dc:mt-2\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n Show candidates ({analysis.primaryCube.candidates.length})\n </summary>\n <div className=\"dc:mt-2 dc:space-y-1 dc:ml-2\">\n {analysis.primaryCube.candidates.map((c, i) => (\n <div key={i} className=\"dc:text-xs dc:flex dc:items-center dc:gap-2 dc:flex-wrap\">\n <span className={`dc:font-mono ${c.cubeName === analysis.primaryCube.selectedCube ? 'dc: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 dc:flex dc:items-center dc:gap-0.5\">\n <SuccessIcon className=\"dc:w-3 dc:h-3\" />\n reachable\n </span>\n ) : (\n <span className=\"text-dc-error dc:flex dc:items-center dc:gap-0.5\">\n <ErrorIcon className=\"dc:w-3 dc: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=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <LinkIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Join Paths\n </h4>\n <div className=\"dc:space-y-2\">\n {analysis.joinPaths.map((jp, idx) => (\n <div key={idx} className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-2 dc:flex-wrap\">\n <span className=\"dc:font-mono text-dc-text-secondary\">{analysis.primaryCube.selectedCube}</span>\n <ArrowRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n <span className=\"dc:font-mono dc:font-medium text-dc-text\">{jp.targetCube}</span>\n {jp.pathFound ? (\n <span className=\"dc:text-xs dc:px-2 dc:py-0.5 bg-dc-success-bg text-dc-success dc:rounded\">\n {jp.pathLength} step{jp.pathLength !== 1 ? 's' : ''}\n </span>\n ) : (\n <span className=\"dc:text-xs dc:px-2 dc:py-0.5 bg-dc-error-bg text-dc-error dc:rounded\">\n No path\n </span>\n )}\n </div>\n {jp.pathFound && jp.path && jp.path.length > 0 && (\n <div className=\"dc:space-y-1 dc:ml-2\">\n {jp.path.map((step, stepIdx) => (\n <div key={stepIdx} className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs dc:flex-wrap\">\n <span className=\"dc:font-mono text-dc-text-secondary\">{step.fromCube}</span>\n <ArrowRightIcon className=\"dc:w-3 dc:h-3 text-dc-text-muted\" />\n <span className=\"dc: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.selection && (\n <div className=\"dc:mt-2 dc:ml-2 dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium text-dc-text\">Selection:</span>\n <span>{` ${formatReason(jp.selection.strategy)}`}</span>\n {typeof jp.selection.selectedRank === 'number' && (\n <span>{`, selected #${jp.selection.selectedRank}`}</span>\n )}\n {typeof jp.selection.selectedScore === 'number' && (\n <span>{`, score ${jp.selection.selectedScore}`}</span>\n )}\n </div>\n )}\n {jp.selection?.candidates && jp.selection.candidates.length > 0 && (\n <details className=\"dc:mt-2\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n {`Path scoring candidates (${jp.selection.candidates.length})`}\n </summary>\n <div className=\"dc:mt-1 dc:ml-2 dc:space-y-1\">\n {jp.selection.preferredCubes && jp.selection.preferredCubes.length > 0 && (\n <div className=\"dc:text-xs text-dc-text-muted\">\n preferred cubes: {jp.selection.preferredCubes.join(', ')}\n </div>\n )}\n {jp.selection.candidates.slice(0, 5).map(candidate => (\n <div key={candidate.rank} className=\"dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium text-dc-text\">\n #{candidate.rank}\n </span>\n <span>{` score ${candidate.score}`}</span>\n <span>{` (preferred+${candidate.scoreBreakdown.preferredJoinBonus + candidate.scoreBreakdown.preferredCubeBonus}, penalty-${candidate.scoreBreakdown.lengthPenalty})`}</span>\n <span>{`: `}</span>\n <span>\n {candidate.path.length > 0\n ? `${candidate.path[0].fromCube} → ${candidate.path.map(step => step.toCube).join(' → ')}`\n : analysis.primaryCube.selectedCube}\n </span>\n </div>\n ))}\n </div>\n </details>\n )}\n {!jp.pathFound && jp.error && (\n <p className=\"dc:text-xs text-dc-error dc:mt-1\">{jp.error}</p>\n )}\n {jp.visitedCubes && jp.visitedCubes.length > 0 && !jp.pathFound && (\n <details className=\"dc:mt-1\">\n <summary className=\"dc:text-xs text-dc-text-muted dc:cursor-pointer hover:text-dc-text\">\n Cubes visited during search ({jp.visitedCubes.length})\n </summary>\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted dc: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=\"dc:border-b border-dc-border dc:pb-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2 dc:flex dc:items-center\">\n <TableIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Pre-Aggregation CTEs\n </h4>\n <div className=\"dc:space-y-2\">\n {analysis.preAggregations.map((pa, idx) => (\n <div key={idx} className=\"bg-dc-surface dc:p-3 dc:rounded dc:text-sm\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-1 dc:flex-wrap\">\n <span className=\"dc:font-mono dc:font-medium text-dc-text\">{pa.cubeName}</span>\n <span className=\"dc:text-xs text-dc-text-muted\">as</span>\n <code className=\"dc:text-xs bg-dc-surface-secondary dc:px-1 dc:rounded dc:font-mono\">{pa.cteAlias}</code>\n </div>\n <p className=\"dc:text-xs text-dc-text-secondary\">{pa.reason}</p>\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted\">\n <span className=\"dc:font-medium\">Measures:</span> {pa.measures.join(', ')}\n </div>\n {pa.joinKeys.length > 0 && (\n <div className=\"dc:mt-1 dc:text-xs text-dc-text-muted\">\n <span className=\"dc: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=\"dc:text-sm dc:font-semibold text-dc-warning dc:mb-2 dc:flex dc:items-center\">\n <WarningIcon className=\"dc:w-4 dc:h-4 dc:mr-2\" />\n Warnings\n </h4>\n <ul className=\"list-disc dc:list-inside dc:text-xs text-dc-warning dc: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=\"dc:text-xs text-dc-text-muted dc:pt-2 dc:border-t border-dc-border\">\n <span className=\"dc:font-medium\">Cubes involved:</span> {analysis.cubesInvolved.join(', ')}\n </div>\n )}\n </div>\n )\n}\n\nexport default QueryAnalysisPanel\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 * AnalysisResultsPanel Component\n *\n * Displays query execution results with chart and table views.\n * Used in the left panel of AnalysisBuilder.\n */\n\nimport React, { useState, useEffect, useMemo, memo, useRef, useCallback } 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 type { QueryAnalysis } from '../../shared/types'\nimport { ExecutionPlanPanel } from './ExecutionPlanPanel'\n\n/**\n * Generate markdown representation of query execution plan\n */\nfunction generateExecutionPlanMarkdown(\n analysis: QueryAnalysis,\n query: CubeQuery | null,\n sql?: { sql: string } | null\n): string {\n const lines: string[] = []\n\n lines.push('# Query Execution Plan')\n lines.push('')\n\n // Original query\n if (query) {\n lines.push('## Cube Query')\n lines.push('')\n lines.push('```json')\n lines.push(JSON.stringify(query, null, 2))\n lines.push('```')\n lines.push('')\n }\n\n // Query summary\n lines.push('## Query Summary')\n lines.push('')\n lines.push(`- **Cubes:** ${analysis.cubesInvolved.join(', ')}`)\n lines.push(`- **Query Type:** ${analysis.querySummary.queryType.replace(/_/g, ' ')}`)\n lines.push(`- **Joins:** ${analysis.querySummary.joinCount}`)\n lines.push(`- **CTEs:** ${analysis.querySummary.cteCount}`)\n lines.push('')\n\n // Primary cube selection\n lines.push('## Primary Cube Selection')\n lines.push('')\n lines.push(`**Selected:** ${analysis.primaryCube.selectedCube}`)\n lines.push(`**Reason:** ${analysis.primaryCube.reason.replace(/_/g, ' ')}`)\n lines.push(`**Explanation:** ${analysis.primaryCube.explanation}`)\n lines.push('')\n\n // Candidates if available\n if (analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1) {\n lines.push('### Candidates Considered')\n lines.push('')\n lines.push('| Cube | Dimensions | Joins | Can Reach All |')\n lines.push('|------|------------|-------|---------------|')\n for (const c of analysis.primaryCube.candidates) {\n const selected = c.cubeName === analysis.primaryCube.selectedCube ? ' ✓' : ''\n lines.push(`| ${c.cubeName}${selected} | ${c.dimensionCount} | ${c.joinCount} | ${c.canReachAll ? 'Yes' : 'No'} |`)\n }\n lines.push('')\n }\n\n // Join paths\n if (analysis.joinPaths.length > 0) {\n lines.push('## Join Paths')\n lines.push('')\n for (const jp of analysis.joinPaths) {\n if (jp.pathFound && jp.path) {\n lines.push(`### ${analysis.primaryCube.selectedCube} → ${jp.targetCube} (${jp.pathLength} step${jp.pathLength !== 1 ? 's' : ''})`)\n lines.push('')\n if (jp.selection) {\n lines.push(`**Selection strategy:** ${jp.selection.strategy}`)\n if (typeof jp.selection.selectedRank === 'number') {\n lines.push(`**Selected rank:** #${jp.selection.selectedRank}`)\n }\n if (typeof jp.selection.selectedScore === 'number') {\n lines.push(`**Selected score:** ${jp.selection.selectedScore}`)\n }\n if (jp.selection.preferredCubes && jp.selection.preferredCubes.length > 0) {\n lines.push(`**Preferred cubes:** ${jp.selection.preferredCubes.join(', ')}`)\n }\n if (jp.selection.candidates && jp.selection.candidates.length > 0) {\n lines.push('**Path scoring candidates:**')\n for (const candidate of jp.selection.candidates.slice(0, 5)) {\n const candidatePath = candidate.path.length > 0\n ? `${candidate.path[0].fromCube} → ${candidate.path.map(step => step.toCube).join(' → ')}`\n : analysis.primaryCube.selectedCube\n lines.push(\n `- #${candidate.rank} score=${candidate.score} `\n + `(preferredJoin=${candidate.scoreBreakdown.preferredJoinBonus}, `\n + `preferredCube=${candidate.scoreBreakdown.preferredCubeBonus}, `\n + `lengthPenalty=${candidate.scoreBreakdown.lengthPenalty}) `\n + `${candidatePath}`\n )\n }\n }\n lines.push('')\n }\n for (const step of jp.path) {\n lines.push(`- **${step.fromCube}** → **${step.toCube}** (${step.relationship}, ${step.joinType.toUpperCase()} JOIN)`)\n for (const col of step.joinColumns) {\n lines.push(` - \\`${col.sourceColumn}\\` = \\`${col.targetColumn}\\``)\n }\n }\n lines.push('')\n } else if (!jp.pathFound) {\n lines.push(`### ${analysis.primaryCube.selectedCube} → ${jp.targetCube}`)\n lines.push('')\n lines.push(`❌ **No path found**${jp.error ? `: ${jp.error}` : ''}`)\n if (jp.visitedCubes && jp.visitedCubes.length > 0) {\n lines.push(`Cubes visited: ${jp.visitedCubes.join(' → ')}`)\n }\n lines.push('')\n }\n }\n }\n\n // Pre-aggregation CTEs\n if (analysis.preAggregations.length > 0) {\n lines.push('## Pre-Aggregation CTEs')\n lines.push('')\n for (const cte of analysis.preAggregations) {\n lines.push(`### ${cte.cubeName} (\\`${cte.cteAlias}\\`)`)\n lines.push('')\n lines.push(`**Reason:** ${cte.reason}`)\n lines.push(`**Measures:** ${cte.measures.join(', ')}`)\n if (cte.joinKeys.length > 0) {\n lines.push('**Join Keys:**')\n for (const jk of cte.joinKeys) {\n lines.push(`- \\`${jk.sourceColumn}\\` = \\`${jk.targetColumn}\\``)\n }\n }\n lines.push('')\n }\n }\n\n // Warnings\n if (analysis.warnings && analysis.warnings.length > 0) {\n lines.push('## ⚠️ Warnings')\n lines.push('')\n for (const warning of analysis.warnings) {\n lines.push(`- ${warning}`)\n }\n lines.push('')\n }\n\n // Generated SQL\n if (sql?.sql) {\n lines.push('## Generated SQL')\n lines.push('')\n lines.push('```sql')\n lines.push(sql.sql)\n lines.push('```')\n }\n\n return lines.join('\\n')\n}\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 // Query warnings from server\n warnings\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 // Copy as markdown state\n const [copyMarkdownState, setCopyMarkdownState] = useState<'idle' | 'copied'>('idle')\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 mode: null,\n queryType: null,\n joinType: null,\n cubesUsed: [],\n modeMetadata: undefined,\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 // Copy execution plan as markdown\n const handleCopyMarkdown = useCallback(() => {\n if (!debugAnalysis) return\n const markdown = generateExecutionPlanMarkdown(debugAnalysis, debugQuery, debugSql)\n navigator.clipboard.writeText(markdown).then(() => {\n setCopyMarkdownState('copied')\n setTimeout(() => setCopyMarkdownState('idle'), 2000)\n })\n }, [debugAnalysis, debugQuery, debugSql])\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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-12 dc:w-12 dc:border-b-2 dc:mx-auto dc:mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Executing Query...\n </div>\n <div className=\"dc: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=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n <div className=\"dc:flex-1 dc:flex dc:items-center dc:justify-center dc:p-4\">\n {showDebug ? (\n <div className=\"dc:w-full dc:h-full dc:overflow-auto\">\n {renderDebug()}\n </div>\n ) : (\n <div className=\"dc:text-center dc:max-w-md\">\n <ErrorIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-error dc:mb-4\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Query Execution Failed\n </div>\n <div className=\"dc:text-sm text-dc-text-secondary dc: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 dc:border border-dc-error dc:rounded-lg dc:p-3 dc:text-left\">\n <div className=\"dc:text-xs dc:font-mono text-dc-error dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-12 dc:w-12 dc:border-b-2 dc:mx-auto dc:mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Preparing Query...\n </div>\n <div className=\"dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <svg className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-warning dc: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=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n Ready to Execute\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc:mb-4\">\n Click refresh to run your query\n </div>\n {onRefreshClick && (\n <button\n onClick={() => onRefreshClick()}\n className=\"dc:inline-flex dc:items-center dc:gap-2 dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-white bg-dc-accent dc:hover:opacity-90 dc:rounded-lg dc:transition-colors dc:shadow-sm\"\n >\n <svg className=\"dc:w-4 dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center dc:pt-6\">\n <div className=\"dc:text-center dc:mb-16\">\n <ChartIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-text-muted dc:mb-3\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text-secondary dc:mb-1\">\n No Results Yet\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:inline-flex dc:items-center dc:gap-2 dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-white bg-dc-accent hover:bg-dc-accent dc:rounded-lg dc:transition-colors dc:shadow-sm\"\n >\n <SparklesIcon className=\"dc:w-4 dc: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=\"dc:h-full dc:flex dc:items-center dc:justify-center\">\n <div className=\"dc:text-center\">\n <SuccessIcon className=\"dc:w-12 dc:h-12 dc:mx-auto text-dc-success dc:mb-3\" />\n <div className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-1\">\n Query Successful\n </div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <ChartIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <WarningIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">Unsupported chart type</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full\">\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full\" />\n </div>\n }\n />\n )\n }\n\n interface FunnelMetadata {\n stepCount: number\n steps: Array<{\n index: number\n name: string\n timeToConvert?: string\n cube?: string\n }>\n }\n\n interface FlowMetadata {\n stepsBefore?: number\n stepsAfter?: number\n eventDimension?: string\n startingStep?: { name?: string; filter?: unknown }\n }\n\n interface RetentionMetadata {\n totalUsers?: number\n segmentCount?: number\n periods?: number\n granularity?: string\n retentionType?: string\n }\n\n interface ModeDebugConfig {\n label: string\n badgeText?: string\n serverQuery: unknown | null | undefined\n serverQueryTitle: string\n serverQueryMissing: React.ReactNode\n debugData: {\n sql: { sql: string; params: unknown[] } | null\n loading: boolean\n error: Error | null\n modeMetadata?: unknown\n } | null | undefined\n sqlPlaceholder: string\n explainResult: any\n explainLoading: boolean\n explainHasRun: boolean\n explainError: Error | null\n runExplain: () => void\n metadataTitle?: string\n metadataSection?: React.ReactNode\n extraSection?: React.ReactNode\n responseSection: React.ReactNode\n }\n\n const renderExecutionErrorBanner = () => {\n if (!executionError) return null\n return (\n <div className=\"bg-dc-danger-bg dark:bg-dc-danger-bg dc:border border-dc-error dark:border-dc-error dc:rounded dc:p-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-error dark:text-dc-error dc:mb-1\">\n Execution Error\n </h4>\n <p className=\"dc:text-sm text-dc-error dark:text-dc-error\">{executionError}</p>\n </div>\n )\n }\n\n const renderSharedConfigBlocks = () => (\n <div className=\"dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc: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\n const renderStandardResponseBlock = (title?: string) => (\n <div>\n {executionResults ? (\n <CodeBlock\n code={JSON.stringify(executionResults, null, 2)}\n language=\"json\"\n title={title || `Server Response (${executionResults.length} rows)`}\n maxHeight=\"24rem\"\n />\n ) : (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm\">\n No results yet\n </div>\n </>\n )}\n </div>\n )\n\n const renderRetentionResponseBlock = () => (\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 ) : (\n renderStandardResponseBlock()\n )}\n </div>\n )\n\n const renderModeDebug = (config: ModeDebugConfig) => {\n const modeSql = config.debugData?.sql\n const modeLoading = config.debugData?.loading || false\n const modeError = config.debugData?.error || null\n\n return (\n <div className=\"dc:p-4 dc:space-y-4 dc:overflow-auto dc:h-full\">\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:mb-4\">\n <span className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium bg-dc-accent text-white dc:rounded\">\n {config.label}\n </span>\n {config.badgeText && (\n <span className=\"dc:text-xs text-dc-text-muted\">{config.badgeText}</span>\n )}\n {modeLoading && (\n <span className=\"dc:text-xs text-dc-text-muted dc:animate-pulse\">Loading SQL...</span>\n )}\n </div>\n\n {renderExecutionErrorBanner()}\n\n <div>\n {config.serverQuery ? (\n <CodeBlock\n code={JSON.stringify(config.serverQuery, null, 2)}\n language=\"json\"\n title={config.serverQueryTitle}\n height=\"16rem\"\n />\n ) : (\n config.serverQueryMissing\n )}\n </div>\n\n <ExecutionPlanPanel\n sql={modeSql}\n sqlLoading={modeLoading}\n sqlError={modeError}\n sqlPlaceholder={config.sqlPlaceholder}\n explainResult={config.explainResult}\n explainLoading={config.explainLoading}\n explainHasRun={config.explainHasRun}\n explainError={config.explainError}\n runExplain={config.runExplain}\n aiAnalysis={aiAnalysis}\n aiAnalysisLoading={aiAnalysisLoading}\n aiAnalysisError={aiAnalysisError}\n runAIAnalysis={runAIAnalysis}\n clearAIAnalysis={clearAIAnalysis}\n enableAI={enableAI}\n query={config.serverQuery}\n title=\"Generated SQL\"\n height=\"16rem\"\n />\n\n {config.metadataTitle && config.metadataSection && (\n <div>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">{config.metadataTitle}</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n {config.metadataSection}\n </div>\n </div>\n )}\n\n {config.extraSection}\n\n {renderSharedConfigBlocks()}\n\n {config.responseSection}\n </div>\n )\n }\n\n // Render debug view (multi-query or single query)\n const renderStandardDebug = () => (\n <div className=\"dc:p-4 dc:space-y-4 dc:overflow-auto dc:h-full\">\n {/* Query tabs for multi-query mode */}\n {debugDataPerQuery.length > 1 && (\n <div className=\"dc:flex dc:items-center dc:gap-1 dc:mb-4\">\n <span className=\"dc:text-xs dc:font-medium text-dc-text-muted dc:mr-2\">Query:</span>\n <div className=\"dc:flex dc:border border-dc-border dc:rounded-md dc:overflow-hidden\">\n {debugDataPerQuery.map((data, idx) => (\n <button\n key={idx}\n onClick={() => setActiveDebugIndex(idx)}\n className={`dc:px-3 dc:py-1 dc:text-xs dc:font-medium dc:transition-colors dc:border-r dc: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=\"dc:ml-1 dc:opacity-70\">•</span>\n )}\n {data.error && (\n <span className=\"dc: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 dc:border border-dc-error dark:border-dc-error dc:rounded dc:p-3\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-error dark:text-dc-error dc:mb-1\">\n Execution Error\n </h4>\n <p className=\"dc: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 <div className=\"dc:flex dc:items-center dc:justify-between dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text\">Query Analysis</h4>\n {debugAnalysis && (\n <button\n onClick={handleCopyMarkdown}\n className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium dc:rounded dc:border border-dc-border bg-dc-surface hover:bg-dc-surface-hover text-dc-text-secondary hover:text-dc-text dc:transition-colors dc:flex dc:items-center dc:gap-1\"\n title=\"Copy query, analysis, and SQL as markdown\"\n >\n {copyMarkdownState === 'copied' ? (\n <>\n <span className=\"text-dc-success\">✓</span>\n Copied!\n </>\n ) : (\n <>📋 Copy as Markdown</>\n )}\n </button>\n )}\n </div>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm\">\n Loading...\n </div>\n ) : debugAnalysis ? (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n <QueryAnalysisPanel analysis={debugAnalysis} />\n </div>\n ) : (\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc: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=\"dc:mt-1 dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Cube Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc: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=\"dc:grid dc:grid-cols-1 dc:md:grid-cols-2 dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Server Response</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc: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 (isFunnelMode) {\n const metadata = funnelDebugData?.modeMetadata as FunnelMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:flex dc:flex-wrap dc:gap-2\">\n {metadata.steps.map((step, idx) => (\n <div key={idx} className=\"dc:flex dc:items-center dc:gap-2 dc:px-3 dc:py-1.5 bg-dc-bg dc:border border-dc-border dc:rounded dc:text-sm\">\n <span className=\"dc:w-5 dc:h-5 dc:flex dc:items-center dc:justify-center bg-dc-accent text-white dc:text-xs dc:rounded-full\">\n {idx + 1}\n </span>\n <span className=\"text-dc-text\">{step.name}</span>\n {step.timeToConvert && (\n <span className=\"dc:text-xs text-dc-text-muted\">({step.timeToConvert})</span>\n )}\n </div>\n ))}\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Funnel Query',\n badgeText: metadata?.stepCount ? `${metadata.stepCount} steps` : undefined,\n serverQuery: funnelServerQuery,\n serverQueryTitle: 'Funnel Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Funnel Server Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc:overflow-auto\">\n No funnel query configured\n </div>\n </>\n ),\n debugData: funnelDebugData,\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 metadataTitle: metadataSection ? 'Funnel Steps' : undefined,\n metadataSection,\n responseSection: renderStandardResponseBlock(),\n })\n }\n\n if (isRetentionMode) {\n const metadata = retentionDebugData?.modeMetadata as RetentionMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Retention Type:</span>{' '}\n <span className=\"text-dc-text\">{metadata.retentionType || 'Classic'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Periods:</span>{' '}\n <span className=\"text-dc-text\">{metadata.periods ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Granularity:</span>{' '}\n <span className=\"text-dc-text\">{metadata.granularity || 'Week'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Segments:</span>{' '}\n <span className=\"text-dc-text\">{metadata.segmentCount || 1}</span>\n </div>\n </div>\n ) : null\n\n const extraSection = retentionChartData?.summary ? (\n <div>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Retention Summary</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3\">\n <div className=\"dc:grid dc:grid-cols-3 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Avg Period 1:</span>{' '}\n <span className=\"text-dc-text dc: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 dc: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 dc:font-medium\">\n {(retentionChartData.summary.minPeriod1Retention * 100).toFixed(1)}%\n </span>\n </div>\n </div>\n </div>\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Retention Query',\n badgeText: metadata ? `${metadata.segmentCount || 1} segment(s), ${metadata.totalUsers} users` : undefined,\n serverQuery: retentionServerQuery,\n serverQueryTitle: 'Retention Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Retention Server Query</h4>\n <div className=\"bg-dc-warning-bg dc:border border-dc-warning dc:rounded dc:p-3 dc:text-sm dc:h-64 dc:overflow-auto\">\n <div className=\"text-dc-warning dc:font-medium dc:mb-2\">Configuration Incomplete</div>\n {retentionValidation && retentionValidation.errors.length > 0 ? (\n <ul className=\"list-disc dc:list-inside text-dc-text-secondary dc: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 debugData: retentionDebugData,\n sqlPlaceholder: 'Configure retention to generate SQL',\n explainResult: retentionExplainResult,\n explainLoading: retentionExplainLoading,\n explainHasRun: retentionExplainHasRun,\n explainError: retentionExplainError,\n runExplain: runRetentionExplain,\n metadataTitle: metadataSection ? 'Retention Configuration' : undefined,\n metadataSection,\n extraSection,\n responseSection: renderRetentionResponseBlock(),\n })\n }\n\n if (isFlowMode) {\n const metadata = flowDebugData?.modeMetadata as FlowMetadata | undefined\n const metadataSection = metadata ? (\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-4 dc:text-sm\">\n <div>\n <span className=\"text-dc-text-muted\">Starting Step:</span>{' '}\n <span className=\"text-dc-text\">{metadata.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\">{metadata.eventDimension || 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps Before:</span>{' '}\n <span className=\"text-dc-text\">{metadata.stepsBefore ?? 'Not set'}</span>\n </div>\n <div>\n <span className=\"text-dc-text-muted\">Steps After:</span>{' '}\n <span className=\"text-dc-text\">{metadata.stepsAfter ?? 'Not set'}</span>\n </div>\n </div>\n ) : null\n\n return renderModeDebug({\n label: 'Flow Query',\n badgeText: metadata ? `${metadata.stepsBefore} before, ${metadata.stepsAfter} after` : undefined,\n serverQuery: flowServerQuery,\n serverQueryTitle: 'Flow Server Query',\n serverQueryMissing: (\n <>\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">Flow Server Query</h4>\n <div className=\"bg-dc-surface-secondary dc:border border-dc-border dc:rounded dc:p-3 text-dc-text-muted dc:text-sm dc:h-64 dc:overflow-auto\">\n No flow query configured\n </div>\n </>\n ),\n debugData: flowDebugData,\n sqlPlaceholder: 'Configure flow to generate SQL',\n explainResult: flowExplainResult,\n explainLoading: flowExplainLoading,\n explainHasRun: flowExplainHasRun,\n explainError: flowExplainError,\n runExplain: runFlowExplain,\n metadataTitle: metadataSection ? 'Flow Configuration' : undefined,\n metadataSection,\n responseSection: renderStandardResponseBlock('Server Response (Sankey Data)'),\n })\n }\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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No flow data to display</div>\n <div className=\"dc:text-xs\">Configure flow analysis to see results</div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:overflow-auto dc:p-4 dc:space-y-6\">\n {/* Nodes Table */}\n <div>\n <h3 className=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Nodes ({nodes.length})\n </h3>\n <div className=\"dc:border border-dc-border dc:rounded dc:overflow-hidden\">\n <table className=\"dc:w-full dc:text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Layer</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Name</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-right dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"dc: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=\"dc:px-3 dc:py-2 dc:whitespace-nowrap\">\n <span className={`dc:inline-flex dc:items-center dc:justify-center dc:w-6 dc:h-6 dc:rounded dc:text-xs dc: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=\"dc:px-3 dc:py-2 text-dc-text\">{node.name as string}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-right text-dc-text dc: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=\"dc:text-sm dc:font-semibold text-dc-text dc:mb-2\">\n Transitions ({links.length})\n </h3>\n <div className=\"dc:border border-dc-border dc:rounded dc:overflow-hidden\">\n <table className=\"dc:w-full dc:text-sm\">\n <thead className=\"bg-dc-surface-secondary\">\n <tr>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">From</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-center dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">→</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-left dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">To</th>\n <th className=\"dc:px-3 dc:py-2 dc:text-right dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wider\">Count</th>\n </tr>\n </thead>\n <tbody className=\"dc: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=\"dc:px-3 dc:py-2 text-dc-text\">{sourceName}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-center text-dc-text-muted\">→</td>\n <td className=\"dc:px-3 dc:py-2 text-dc-text\">{targetName}</td>\n <td className=\"dc:px-3 dc:py-2 dc:text-right text-dc-text dc: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\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=\"dc:flex dc:items-center dc:justify-center dc:h-full text-dc-text-muted\">\n <div className=\"dc:text-center\">\n <TableIcon className=\"dc:w-12 dc:h-12 dc:mx-auto dc:mb-3 dc:opacity-50\" />\n <div className=\"dc:text-sm dc:font-semibold dc:mb-1\">No data to display</div>\n <div className=\"dc: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=\"dc:flex dc:items-center dc:justify-center dc:h-full\">\n <div className=\"dc:animate-pulse bg-dc-surface-secondary dc:rounded dc:w-full dc:h-full\" />\n </div>\n }\n />\n )\n }\n\n // Overlay spinner for refreshing\n const renderOverlaySpinner = () => (\n <div className=\"dc:absolute dc:inset-0 dc:flex dc:items-center dc:justify-center bg-dc-surface bg-opacity-75 dc:z-10\">\n <div className=\"dc:text-center\">\n <div\n className=\"dc:animate-spin dc:rounded-full dc:h-10 dc:w-10 dc:border-b-2 dc:mx-auto dc:mb-2\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-surface-secondary dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n {/* Left side: Status and row count */}\n <div className=\"dc:flex dc:items-center\">\n {executionStatus === 'refreshing' ? (\n <div\n className=\"dc:w-4 dc:h-4 dc:mr-2 dc:rounded-full dc:border-b-2 dc:animate-spin\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n ) : hasResults ? (\n <SuccessIcon className=\"dc:w-4 dc:h-4 text-dc-success dc:mr-2\" />\n ) : executionStatus === 'error' ? (\n <ErrorIcon className=\"dc:w-4 dc:h-4 text-dc-error dc:mr-2\" />\n ) : (\n <WarningIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted dc:mr-2\" />\n )}\n <span className=\"dc: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 dc: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=\"dc:flex dc:items-center dc: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=\"dc:text-xs dc:border border-dc-border dc:rounded dc:px-2 dc:py-1 bg-dc-surface text-dc-text dc:focus:outline-none dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n isAIOpen\n ? 'text-white bg-dc-accent dc:border border-dc-accent'\n : 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg dc:border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n }`}\n title={isAIOpen ? 'Close AI assistant' : 'Analyse with AI'}\n >\n <SparklesIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n shareButtonState === 'idle' && canShare\n ? 'text-dc-accent dark:text-dc-accent bg-dc-accent-bg dark:bg-dc-accent-bg dc:border border-dc-accent dark:border-dc-accent hover:bg-dc-accent-bg dark:hover:bg-dc-accent-bg'\n : shareButtonState !== 'idle'\n ? 'text-dc-success dark:text-dc-success bg-dc-success-bg dark:bg-dc-success-bg dc:border border-dc-success dark:border-dc-success'\n : 'text-dc-text-muted bg-dc-surface-secondary dc:border border-dc-border dc: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=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Share</span>\n </>\n ) : shareButtonState === 'copied' ? (\n <>\n <CheckIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Copied!</span>\n </>\n ) : (\n <>\n <CheckIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Copied!</span>\n <span className=\"dc:hidden dc:lg:inline dc:text-[10px] dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors ${\n isRefreshing\n ? 'text-dc-text-muted bg-dc-surface-secondary dc:border border-dc-border dc:cursor-wait'\n : showCacheBustIndicator\n ? 'text-dc-warning bg-dc-warning-bg dc:border border-dc-warning dc:font-semibold'\n : 'text-dc-accent bg-dc-accent-bg dc: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={`dc:w-3 dc:h-3 ${isRefreshing ? 'dc:animate-spin' : ''}`} />\n <span className=\"dc:hidden dc:sm:inline\">{isRefreshing ? 'Refreshing' : 'Refresh'}</span>\n </button>\n )}\n\n {/* Clear Button */}\n {onClearClick && canClear && (\n <button\n onClick={() => setIsClearConfirmOpen(true)}\n className=\"dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:text-xs dc:font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover dc:border border-dc-border dc:rounded dc:transition-colors\"\n title={isFunnelMode ? 'Clear funnel' : 'Clear all query data'}\n >\n <TrashIcon className=\"dc:w-3 dc:h-3\" />\n <span className=\"dc:hidden dc:sm:inline\">Clear</span>\n </button>\n )}\n\n {/* Debug Toggle Button */}\n <button\n onClick={() => setShowDebug(!showDebug)}\n className={`dc:p-1.5 dc:rounded dc:transition-colors dc: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=\"dc:w-4 dc:h-4\" />\n {/* Error indicator dot - show if ANY query has an error */}\n {(executionError || debugDataPerQuery.some(d => d.error)) && !showDebug && (\n <span className=\"dc:absolute dc:-top-0.5 dc:-right-0.5 dc:w-2 dc:h-2 bg-dc-danger-bg0 dc:rounded-full\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Performance Warning */}\n {hasResults && totalRowCount !== null && totalRowCount > 1000 && (\n <div className=\"dc:mt-2 bg-dc-warning-bg dc:border border-dc-warning dc:rounded-lg dc:p-2 dc:flex dc:items-start\">\n <WarningIcon className=\"dc:w-4 dc:h-4 text-dc-warning dc:mr-2 dc:shrink-0 dc:mt-0.5\" />\n <div className=\"dc:text-xs text-dc-warning\">\n <span className=\"dc: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=\"dc:px-4 dc:py-2 bg-dc-warning-bg dc:border-b border-dc-warning dc:flex dc:items-center dc:justify-between dc:gap-3 dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center dc:gap-2 text-dc-warning\">\n <svg className=\"dc:w-4 dc:h-4 dc: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=\"dc:text-sm dc:font-medium\">Query configuration changed. Results may be outdated.</span>\n </div>\n <button\n onClick={() => onRefreshClick()}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium bg-dc-warning text-white dc:rounded hover:bg-dc-warning/90 dc:transition-colors\"\n >\n Refresh Now\n </button>\n </div>\n )\n }\n\n // Query warnings banner (e.g., fan-out without dimensions)\n const renderWarningsBanner = () => {\n if (!warnings || warnings.length === 0) return null\n\n return (\n <>\n {warnings.map((warning, index) => {\n const WarningIcon = getIcon('warning')\n const isError = warning.severity === 'error'\n const bgClass = isError ? 'bg-dc-danger-bg' : 'bg-dc-warning-bg'\n const borderClass = isError ? 'border-dc-error' : 'border-dc-warning'\n const textClass = isError ? 'text-dc-error' : 'text-dc-warning'\n\n return (\n <div\n key={`${warning.code}-${index}`}\n className={`dc:px-4 dc:py-2 ${bgClass} dc:border-b ${borderClass} dc:flex dc:items-start dc:gap-3 dc:flex-shrink-0`}\n >\n <WarningIcon className={`dc:w-4 dc:h-4 dc:flex-shrink-0 dc:mt-0.5 ${textClass}`} />\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className={`dc:text-sm dc:font-medium ${textClass}`}>\n {warning.message}\n </div>\n {warning.suggestion && (\n <div className={`dc:text-xs dc:mt-1 ${textClass} dc:opacity-80`}>\n 💡 {warning.suggestion}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </>\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=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n <div className=\"dc:flex-1 dc:min-h-0 dc:relative dc:overflow-auto\">\n {showDebug ? renderDebug() : renderNoData()}\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:flex dc:flex-col\">\n {renderHeader()}\n {renderNeedsRefreshBanner()}\n {renderWarningsBanner()}\n\n {/* Results Content */}\n <div className=\"dc:flex-1 dc:min-h-0 dc:relative dc:overflow-auto\">\n {showDebug ? (\n renderDebug()\n ) : activeView === 'chart' ? (\n <div className=\"dc:p-4 dc:h-full\">{renderChart()}</div>\n ) : isFlowMode ? (\n <div className=\"dc:h-full\" key=\"table-flow\">{renderFlowTable()}</div>\n ) : isMultiQuery ? (\n <div className=\"dc:h-full\" key={`table-${activeTableIndex}`}>{renderTable(activeTableIndex)}</div>\n ) : (\n <div className=\"dc:h-full\" key=\"table-single\">{renderTable()}</div>\n )}\n </div>\n\n {/* View Toggle - Below content, centered */}\n {!showDebug && (\n <div className=\"dc:px-4 dc:py-3 dc:border-t border-dc-border bg-dc-surface dc:flex dc:justify-center dc:flex-shrink-0\">\n <div className=\"dc:flex dc:items-center bg-dc-surface-secondary dc:border border-dc-border dc:rounded-md dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-4 dc:py-1.5 dc:text-sm dc:font-medium dc: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 dc: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=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc:h-4\" />\n Merged\n </button>\n </>\n ) : (\n <button\n onClick={() => onActiveViewChange('table')}\n className={`dc:flex dc:items-center dc:gap-1.5 dc:px-4 dc:py-1.5 dc:text-sm dc:font-medium dc: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=\"dc:w-4 dc: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=\"dc:h-full dc:min-h-[400px] dc:flex dc:flex-col bg-dc-surface dc:relative\">\n {renderNeedsRefreshEmpty()}\n </div>\n )\n }\n\n return (\n <div className=\"dc:h-full dc:min-h-[400px] dc:flex dc:flex-col bg-dc-surface dc: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=\"dc:w-4 dc:h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"dc:w-4 dc:h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 ${\n isDraggable ? 'dc:cursor-grab dc:active:cursor-grabbing' : ''\n } ${isDragging ? 'dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n {MeasureIcon && <MeasureIcon className=\"dc:w-4 dc:h-4\" />}\n </span>\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={metric.field}>\n {displayTitle}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc:truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`dc:p-1 dc:transition-opacity dc:flex-shrink-0 dc:flex dc:items-center dc:gap-0.5 ${\n sortDirection\n ? 'dc:opacity-100 text-dc-primary'\n : 'dc:opacity-100 dc:sm:opacity-0 dc: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=\"dc:text-xs dc:font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title=\"Remove metric\"\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add metric\"\n >\n <SectionHeading>Metrics</SectionHeading>\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc:transition-colors\" />\n </button>\n\n {/* Metrics List */}\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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 * Uses common dry-run fields across all analysis modes.\n */\n funnelDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Uses common dry-run fields across all analysis modes.\n */\n flowDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Uses common dry-run fields across all analysis modes.\n */\n retentionDebugData?: {\n sql: { sql: string; params: unknown[] } | null\n analysis: unknown\n mode?: 'regular' | 'comparison' | 'funnel' | 'flow' | 'retention' | null\n queryType?: string | null\n joinType?: string | null\n cubesUsed?: string[]\n modeMetadata?: unknown\n loading: boolean\n error: Error | null\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 * Query warnings from server (e.g., fan-out without dimensions).\n * Displayed as a banner above results.\n */\n warnings?: import('../../shared/types').QueryWarning[]\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=\"dc:w-4 dc:h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"dc:w-4 dc:h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"dc:w-4 dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 ${\n isDraggable ? 'dc:cursor-grab dc:active:cursor-grabbing' : ''\n } ${isDragging ? 'dc: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={`dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n </span>\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={breakdown.field}>\n {displayTitle}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs bg-dc-surface dc:border border-dc-border dc:rounded dc:px-2 dc:py-1 text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary dc: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={`dc:text-xs dc:px-2 dc:py-1 dc:rounded dc:flex-shrink-0 dc:transition-colors ${\n breakdown.enableComparison\n ? 'bg-dc-accent text-white'\n : 'bg-dc-surface dc:border border-dc-border text-dc-text-muted hover:text-dc-text hover:bg-dc-surface-hover'\n } ${comparisonDisabled && !breakdown.enableComparison ? 'dc:opacity-50 dc: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={`dc:p-1 dc:transition-opacity dc:flex-shrink-0 dc:flex dc:items-center dc:gap-0.5 ${\n sortDirection\n ? 'dc:opacity-100 text-dc-primary'\n : 'dc:opacity-100 dc:sm:opacity-0 dc: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=\"dc:text-xs dc:font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title=\"Remove breakdown\"\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add breakdown\"\n >\n <SectionHeading>Breakdown</SectionHeading>\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc:transition-colors\" />\n </button>\n\n {/* Breakdowns List */}\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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=\"dc:text-sm text-dc-text-muted dc:italic dc: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=\"dc:space-y-2\">\n {/* Range type dropdown */}\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"dc:truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isDateRangeDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-48 dc:overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc: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=\"dc:flex dc:items-center dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text dc:w-20\"\n />\n <span className=\"dc: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=\"dc:flex dc:items-center dc:gap-2\">\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-2 dc:py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-2 dc: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=\"dc:flex dc:items-center dc:gap-2\">\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text\"\n />\n <span className=\"dc: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=\"dc:flex-1 dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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=\"dc:space-y-2\">\n {/* Selected values as tags */}\n {filter.values && filter.values.length > 0 && (\n <div className=\"dc:flex dc:flex-wrap dc:gap-1.5\">\n {filter.values.map((value: unknown, index: number) => (\n <span\n key={index}\n className=\"dc:inline-flex dc:items-center dc:gap-1 bg-dc-primary/10 text-dc-primary dc:text-sm dc:px-2 dc:py-1 dc:rounded\"\n >\n <span className=\"dc:max-w-[150px] dc:truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-dc-danger\"\n >\n <CloseIcon className=\"dc:w-3.5 dc:h-3.5\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted dc:truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isValueDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-56 dc:overflow-hidden\">\n {/* Search input with keyboard navigation */}\n <div className=\"dc:p-2 dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div ref={valueListRef} className=\"dc:max-h-40 dc:overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"dc:px-3 dc:py-2 dc:text-sm text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"dc:px-3 dc:py-2 dc:text-sm text-dc-error\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"dc:px-3 dc:py-2 dc: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={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc:text-sm dc: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=\"dc: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=\"dc: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=\"dc:w-full dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc: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={`dc:fixed dc:inset-0 bg-dc-overlay dc:z-50 ${modalPosition ? '' : 'dc:flex dc:items-center dc:justify-center dc: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=\"dc:flex dc:items-center dc:justify-between dc:p-4 dc:border-b border-dc-border\">\n <h2 className=\"dc:text-lg dc:font-semibold text-dc-text\">Edit Filter</h2>\n <button\n onClick={onCancel}\n className=\"dc:p-1 text-dc-text-muted hover:text-dc-text dc:transition-colors\"\n >\n <CloseIcon className=\"dc:w-5 dc:h-5\" />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"dc:p-4 dc:space-y-4\">\n {/* Field display */}\n <div>\n <label className=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Field\n </label>\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:p-3 bg-dc-surface-secondary dc:rounded\">\n <FieldIcon className=\"dc:w-5 dc:h-5 text-dc-filter-text\" />\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">{fieldTitle}</span>\n </div>\n </div>\n\n {/* Operator selector */}\n <div>\n <label className=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Operator\n </label>\n <div className=\"dc:relative\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:text-left dc:text-sm dc:border border-dc-border dc:rounded dc:px-3 dc:py-2 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"dc:truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`dc:w-4 dc:h-4 text-dc-text-muted dc:shrink-0 dc:ml-2 dc:transition-transform ${\n isOperatorDropdownOpen ? 'dc:rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"dc:absolute dc:z-[60] dc:left-0 dc:right-0 dc:mt-1 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:max-h-48 dc:overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`dc:w-full dc:text-left dc:px-3 dc:py-2 dc: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=\"dc:block dc:text-sm dc:font-medium text-dc-text-secondary dc:mb-2\">\n Value\n </label>\n {renderValueInput()}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"dc:flex dc:items-center dc:justify-end dc:gap-2 dc:p-4 dc:border-t border-dc-border\">\n <button\n onClick={onCancel}\n className=\"dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-dc-text-secondary hover:text-dc-text dc:transition-colors\"\n >\n Cancel\n </button>\n <button\n onClick={() => onSave(filter)}\n className=\"dc:px-4 dc:py-2 dc:text-sm dc:font-medium text-dc-primary-content bg-dc-primary hover:bg-dc-primary-hover dc:rounded dc: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=\"dc:flex dc:items-start dc:gap-2 dc:px-2 dc:py-1.5 bg-dc-surface-secondary dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-all dc:duration-150 dc:w-full\"\n >\n {/* Field type icon with appropriate background color */}\n <span className={`dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded ${iconBgClass} ${iconTextClass} dc:flex-shrink-0 dc:mt-0.5`}>\n {FieldIcon && <FieldIcon className=\"dc:w-4 dc:h-4\" />}\n </span>\n\n {/* Filter description - clickable to edit */}\n <button\n ref={buttonRef}\n onClick={() => setIsModalOpen(true)}\n className=\"dc:flex-1 dc:min-w-0 dc:text-left\"\n title={`${fieldTitle} ${operatorLabel} ${valueDisplay}`}\n >\n <div className=\"dc:text-sm text-dc-text dc:break-words\">\n <span className=\"dc:font-medium\">{fieldTitle}</span>\n <span className=\"text-dc-text-muted dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-100 dc:sm:opacity-0 dc:sm:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0 dc:mt-0.5\"\n title=\"Remove filter\"\n >\n {CloseIcon && <CloseIcon className=\"dc:w-4 dc: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={`dc:border ${getBorderColor()} dc:rounded-lg bg-dc-surface dc:w-full`}>\n {/* Group Header */}\n <div className={`dc:flex dc:items-center dc:justify-between dc:px-2 dc:py-1.5 dc:border-b border-dc-border/50 dc:rounded-t-lg ${getGroupBgColor()}`}>\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {/* AND/OR Toggle Button */}\n <button\n onClick={handleToggleType}\n className={`dc:px-2 dc:py-0.5 dc:text-xs dc:font-semibold dc:rounded dc:transition-colors ${\n group.type === 'and'\n ? 'bg-dc-info-bg text-dc-info dc:hover:opacity-80'\n : 'bg-dc-warning-bg text-dc-warning dc: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=\"dc:text-xs text-dc-text-muted\">\n {conditionCount} {conditionLabel}\n </span>\n </div>\n\n <div className=\"dc:flex dc:items-center dc:gap-1\">\n {/* Add Button with Dropdown */}\n <div className=\"dc:relative\" ref={addMenuRef}>\n <button\n onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}\n className=\"dc:p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-hover dc:rounded dc:transition-colors\"\n title=\"Add condition\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n\n {isAddMenuOpen && (\n <div className=\"dc:absolute dc:right-0 dc:mt-1 dc:z-40 bg-dc-surface dc:border border-dc-border dc:rounded dc:shadow-lg dc:py-1 dc:min-w-[120px]\">\n <button\n onClick={handleAddFilterClick}\n className=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc:text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add Filter\n </button>\n <button\n onClick={() => handleAddNestedGroup('and')}\n className=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc: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=\"dc:w-full dc:text-left dc:px-3 dc:py-1.5 dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:transition-colors\"\n title=\"Remove group\"\n >\n <CloseIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Group Body - Filter List */}\n <div className=\"dc:p-1.5 dc:flex dc:flex-wrap dc:gap-2\">\n {group.filters.length === 0 ? (\n <div className=\"dc:text-center dc:py-3\">\n <p className=\"dc:text-xs text-dc-text-muted dc:mb-1\">No conditions in this group</p>\n <button\n onClick={() => onAddFilter([])}\n className=\"dc:text-xs text-dc-primary dc: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=\"dc:flex dc:items-center dc:justify-between dc:mb-3 dc:w-full dc:py-1 dc:px-2 dc:-ml-2 dc:rounded-lg hover:bg-dc-primary/10 dc:transition-colors dc:group\"\n title=\"Add filter\"\n >\n <SectionHeading>\n Filter\n {totalFilterCount > 0 && (\n <span className=\"dc:ml-1.5 dc:text-xs dc:font-normal text-dc-text-muted dc:normal-case dc:tracking-normal\">\n ({totalFilterCount})\n </span>\n )}\n </SectionHeading>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:text-xs text-dc-text-muted hover:text-dc-error dc:underline dc:cursor-pointer\"\n >\n Clear all\n </span>\n )}\n <AddIcon className=\"dc:w-5 dc:h-5 text-dc-text-secondary group-hover:text-dc-primary dc: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={`dc:p-2 dc:-mx-2 dc:rounded-lg dc:border-2 dc:border-dashed dc: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={`dc:text-sm ${isDragOver ? 'text-dc-primary dc:font-medium' : 'text-dc-text-muted'}`}>\n {isDragOver ? 'Drop to add filter' : 'No filters applied'}\n </p>\n ) : (\n <div className=\"dc:flex dc:flex-wrap dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n <IconComponent className=\"dc:w-4 dc: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=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-time-dimension text-dc-time-dimension-text dc:flex-shrink-0\">\n <TimeDimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n )\n } else {\n // Regular dimensions get colored background matching field selector\n return (\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-dimension text-dc-dimension-text dc:flex-shrink-0\">\n <DimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n )\n }\n }\n\n return (\n <div className=\"dc:mb-3\">\n {/* Header */}\n <div className=\"dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-medium text-dc-text dc:flex dc:items-center\">\n {label}\n {mandatory && <span className=\"text-dc-error dc:ml-1\">*</span>}\n </h4>\n {description && <div className=\"dc:text-xs text-dc-text-muted dc:mt-0.5\">{description}</div>}\n </div>\n\n {/* Drop Zone Container */}\n <div\n ref={containerRef}\n data-axis-container={key}\n className={`dc:min-h-[48px] dc:border-2 dc:border-dashed dc:rounded-lg dc:p-2 dc:transition-all dc:duration-200 ${\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'dc:shadow-sm dc: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=\"dc:text-sm text-dc-text-muted dc:text-center dc:py-2\">\n {isFull ? 'Maximum items reached' : emptyText || `Drop fields here`}\n </div>\n ) : (\n <div\n className=\"dc: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=\"dc: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=\"dc:absolute dc:-top-5 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg dc:group hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${\n isBeingDragged ? 'dc:opacity-30 dc:cursor-grabbing' : ''\n }`}\n >\n {/* Icon */}\n {renderFieldIcon(meta)}\n\n {/* Field Info */}\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\" title={field}>\n {meta.shortTitle || meta.title || field.split('.').pop()}\n </div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:px-1.5 dc:py-0.5 dc:text-xs dc:font-medium dc:rounded dc:transition-colors dc:flex-shrink-0 ${\n (yAxisAssignment?.[field] || 'left') === 'left'\n ? 'bg-dc-info-bg text-dc-info dc:hover:opacity-80'\n : 'bg-dc-accent-bg text-dc-accent dc: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=\"dc:p-1 text-dc-text-muted hover:text-dc-danger dc:opacity-0 dc:group-hover:opacity-100 dc:transition-opacity dc:flex-shrink-0\"\n title={`Remove from ${label}`}\n >\n <CloseIcon className=\"dc:w-4 dc: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=\"dc:relative dc:h-2\">\n <div className=\"dc:absolute dc:top-0 dc:left-0 dc:right-0 dc:flex dc:items-center dc:justify-center dc:pointer-events-none dc:z-10\">\n <div className=\"dc:h-0.5 dc:w-full bg-dc-primary dc: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=\"dc: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=\"dc:text-xs text-dc-error dc:mt-1\">This field is required</div>\n )}\n </div>\n )\n}\n","import { barChartConfig } from '../components/charts/BarChart.config'\nimport { lineChartConfig } from '../components/charts/LineChart.config'\nimport { areaChartConfig } from '../components/charts/AreaChart.config'\nimport { pieChartConfig } from '../components/charts/PieChart.config'\nimport { scatterChartConfig } from '../components/charts/ScatterChart.config'\nimport { bubbleChartConfig } from '../components/charts/BubbleChart.config'\nimport { radarChartConfig } from '../components/charts/RadarChart.config'\nimport { radialBarChartConfig } from '../components/charts/RadialBarChart.config'\nimport { treemapChartConfig } from '../components/charts/TreeMapChart.config'\nimport { dataTableConfig } from '../components/charts/DataTable.config'\nimport { activityGridChartConfig } from '../components/charts/ActivityGridChart.config'\nimport { kpiNumberConfig } from '../components/charts/KpiNumber.config'\nimport { kpiDeltaConfig } from '../components/charts/KpiDelta.config'\nimport { kpiTextConfig } from '../components/charts/KpiText.config'\nimport { markdownConfig } from '../components/charts/MarkdownChart.config'\nimport { funnelChartConfig } from '../components/charts/FunnelChart.config'\nimport { sankeyChartConfig } from '../components/charts/SankeyChart.config'\nimport { sunburstChartConfig } from '../components/charts/SunburstChart.config'\nimport { heatmapChartConfig } from '../components/charts/HeatMapChart.config'\nimport { retentionHeatmapConfig } from '../components/charts/RetentionHeatmap.config'\nimport { retentionCombinedConfig } from '../components/charts/RetentionCombinedChart.config'\nimport { boxPlotChartConfig } from '../components/charts/BoxPlotChart.config'\nimport { waterfallChartConfig } from '../components/charts/WaterfallChart.config'\nimport { candlestickChartConfig } from '../components/charts/CandlestickChart.config'\nimport { measureProfileChartConfig } from '../components/charts/MeasureProfileChart.config'\nimport { gaugeChartConfig } from '../components/charts/GaugeChart.config'\nimport type { ChartConfigRegistry } from './chartConfigs'\n\n/**\n * Registry of all chart type configurations\n */\nexport const chartConfigRegistry: ChartConfigRegistry = {\n bar: barChartConfig,\n line: lineChartConfig,\n area: areaChartConfig,\n pie: pieChartConfig,\n scatter: scatterChartConfig,\n bubble: bubbleChartConfig,\n radar: radarChartConfig,\n radialBar: radialBarChartConfig,\n treemap: treemapChartConfig,\n table: dataTableConfig,\n activityGrid: activityGridChartConfig,\n kpiNumber: kpiNumberConfig,\n kpiDelta: kpiDeltaConfig,\n kpiText: kpiTextConfig,\n markdown: markdownConfig,\n funnel: funnelChartConfig,\n sankey: sankeyChartConfig,\n sunburst: sunburstChartConfig,\n heatmap: heatmapChartConfig,\n retentionHeatmap: retentionHeatmapConfig,\n retentionCombined: retentionCombinedConfig,\n boxPlot: boxPlotChartConfig,\n waterfall: waterfallChartConfig,\n candlestick: candlestickChartConfig,\n measureProfile: measureProfileChartConfig,\n gauge: gaugeChartConfig,\n}\n","import { useMemo, useState } from 'react'\nimport type { ChartType } from '../types'\nimport type { ChartAvailabilityMap } from '../shared/chartDefaults'\nimport { chartConfigRegistry } from '../charts/chartConfigRegistry'\nimport { getChartTypeIcon } from '../icons'\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/** Get label for a chart type from the registry, falling back to the chart type key */\nfunction getLabel(type: ChartType): string {\n return chartConfigRegistry[type]?.label || type\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\n // Derive chart types from the registry, filter excluded ones, and sort alphabetically by label\n const chartTypes = useMemo(() =>\n (Object.keys(chartConfigRegistry) as ChartType[])\n .filter((type) => !excludeTypes.includes(type))\n .sort((a, b) => getLabel(a).localeCompare(getLabel(b)))\n , [excludeTypes])\n\n const SelectedIcon = getChartTypeIcon(selectedType)\n const selectedLabel = getLabel(selectedType)\n\n return (\n <div className={`${className} dc:relative`}>\n {/* Dropdown Button */}\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className=\"dc:w-full dc:flex dc:items-center dc:justify-between dc:px-3 dc:py-2 dc:border border-dc-border dc:rounded-md bg-dc-surface hover:bg-dc-surface-hover focus:outline-hidden dc:focus:ring-2 focus:ring-dc-accent focus:border-dc-accent\"\n >\n <div className=\"dc:flex dc:items-center dc:space-x-2\">\n {SelectedIcon && (\n <SelectedIcon className=\"dc:h-5 dc:w-5 text-dc-text-secondary\" />\n )}\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">{selectedLabel}</span>\n </div>\n <svg\n className={`dc:h-4 dc:w-4 text-dc-text-muted dc:transform dc:transition-transform ${isOpen ? 'dc: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={`dc:absolute dc:z-10 dc:mt-1 dc:w-full bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg dc:max-h-80 dc:overflow-auto ${compact ? '' : 'dc:min-w-max'}`}>\n <div className=\"dc:p-2\">\n <div className={`dc:grid dc:gap-1.5 ${compact ? 'dc:grid-cols-2' : 'dc:grid-cols-2 dc:sm:grid-cols-3 dc:lg:grid-cols-4'}`}>\n {chartTypes.map((type) => {\n const config = chartConfigRegistry[type]\n const IconComponent = getChartTypeIcon(type)\n const label = getLabel(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 dc:relative dc:p-1.5 dc:rounded dc:border dc:transition-colors dc:duration-150\n dc:text-left dc:group dc:min-h-[30px] dc:flex dc:items-center dc:justify-start\n ${!isAvailable\n ? 'dc:opacity-50 dc: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=\"dc:flex dc:items-center dc:space-x-1.5\">\n {/* Icon */}\n {IconComponent && (\n <IconComponent\n className={`dc:h-4 dc:w-4 dc: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={`dc:text-xs dc:font-medium dc:leading-tight dc: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=\"dc:absolute dc:top-0.5 dc:right-0.5\">\n <div className=\"dc:w-1.5 dc:h-1.5 dc: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=\"dc:space-y-6\">\n <div>\n <SectionHeading className=\"dc: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=\"dc:text-center text-dc-text-muted dc:text-sm dc: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=\"dc:space-y-6\">\n {/* Chart Type Selector */}\n <div>\n <SectionHeading className=\"dc: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=\"dc:mb-2\">\n Chart Configuration\n </SectionHeading>\n <div className=\"dc: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=\"dc:mb-2\">\n <SectionHeading>Unassigned Fields</SectionHeading>\n <div className=\"dc:text-xs text-dc-text-muted dc:mt-0.5\">\n Drag fields to chart axes above\n </div>\n </div>\n <div className=\"dc:border-2 dc:border-dashed border-dc-border dc:rounded-lg dc:p-2 bg-dc-surface-secondary\">\n <div className=\"dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-measure text-dc-measure-text dc:flex-shrink-0\">\n <IconComponent className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-dimension text-dc-dimension-text dc:flex-shrink-0\">\n <DimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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={`dc:flex dc:items-center dc:gap-2 dc:p-2 bg-dc-surface dc:rounded-lg hover:bg-dc-surface-tertiary dc:transition-colors dc:cursor-move ${isBeingDragged ? 'dc:opacity-50 dc:cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded bg-dc-time-dimension text-dc-time-dimension-text dc:flex-shrink-0\">\n <TimeDimensionIcon className=\"dc:w-4 dc:h-4\" />\n </span>\n <div className=\"dc:flex-1 dc:min-w-0\">\n <div className=\"dc:text-sm text-dc-text dc:truncate\">{meta.shortTitle}</div>\n <div className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-center text-dc-text-muted dc:text-sm dc: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 * 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=\"dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2 dc:py-1 dc:text-xs\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors\n ${disabled ? 'dc:opacity-50 dc:cursor-not-allowed' : 'hover:border-dc-primary dc:cursor-pointer'}\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc:truncate ${hasSelection ? 'text-dc-text' : 'text-dc-text-muted'}`}>\n {label}\n </span>\n <span className=\"dc:flex dc:items-center dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:right-0 dc:w-[280px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Dimension List */}\n <div className=\"dc:max-h-64 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching dimensions found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n {/* Cube Header */}\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:flex dc:items-center dc:gap-0.5 dc:p-1.5 dc: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 dc:flex dc:items-center dc:gap-1 dc:px-2 dc:py-1.5 dc:rounded-md dc:text-sm dc:font-medium\n dc:transition-colors dc:duration-150\n ${\n isSelected\n ? 'bg-dc-primary/10 text-dc-primary dc:border border-dc-primary/30'\n : 'text-dc-text-secondary hover:bg-dc-bg-secondary hover:text-dc-text dc:border border-transparent'\n }\n ${disabled ? 'dc:opacity-50 dc:cursor-not-allowed' : 'dc:cursor-pointer'}\n `}\n >\n <Icon className=\"dc:h-4 dc:w-4 dc:flex-shrink-0\" />\n <span className=\"dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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 dc:border dc:rounded-lg dc:transition-all dc:cursor-pointer\n ${isActive\n ? 'border-dc-primary dc: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=\"dc:flex dc:items-center dc:gap-2 dc:px-3 dc:py-2 dc:border-b border-dc-border\">\n {/* Drag Handle */}\n <div className=\"dc:cursor-grab dc:active:cursor-grabbing text-dc-text-muted hover:text-dc-text\">\n {DragHandleIcon && <DragHandleIcon className=\"dc:w-4 dc:h-4\" />}\n </div>\n\n {/* Step Number */}\n <span className=\"dc:flex-shrink-0 dc:w-6 dc:h-6 dc:flex dc:items-center dc:justify-center dc:rounded-full bg-dc-primary/10 text-dc-primary dc:text-xs dc:font-medium\">\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=\"dc:flex-1 dc:px-1.5 dc:py-0.5 dc:text-sm dc:font-medium bg-dc-surface dc:border border-dc-primary dc:rounded text-dc-text dc:focus:outline-none\"\n placeholder=\"Step name\"\n />\n ) : (\n <button\n onClick={(e) => {\n e.stopPropagation()\n setIsEditingName(true)\n }}\n className=\"dc:flex-1 dc:text-left dc:text-sm dc:font-medium text-dc-text hover:text-dc-primary dc: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=\"dc:p-1 dc:rounded hover:bg-dc-danger-bg text-dc-text-muted hover:text-dc-error dc:transition-colors\"\n title=\"Remove step\"\n >\n {CloseIcon && <CloseIcon className=\"dc:w-4 dc:h-4\" />}\n </button>\n )}\n </div>\n\n {/* Body - Only visible when active */}\n {isActive && (\n <div className=\"dc:px-3 dc:py-3 dc: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=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {TimeDimensionIcon && <TimeDimensionIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n Time Window\n </label>\n <div ref={timeDropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setShowTimeDropdown(!showTimeDropdown)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${showTimeDropdown ? 'border-dc-primary dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${showTimeDropdown ? 'dc:rotate-180' : ''}`}\n />\n )}\n </button>\n\n {showTimeDropdown && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg dc:max-h-48 dc: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 dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc: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=\"dc:w-4 dc:h-4\" />}\n </button>\n ))}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:px-3 dc:py-2 dc: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 ? 'dc:ml-2' : ''}>\n {step.filters.length > 0 ? '• ' : ''}within {timeToConvertLabel.toLowerCase()}\n </span>\n )}\n {step.filters.length === 0 && !step.timeToConvert && (\n <span className=\"dc: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=\"dc:space-y-4\">\n {/* Header */}\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <SectionHeading>\n Funnel Steps\n {steps.length > 0 && (\n <span className=\"dc:ml-1.5 dc:text-xs dc:font-normal text-dc-text-muted dc:normal-case dc:tracking-normal\">\n ({steps.length})\n </span>\n )}\n </SectionHeading>\n </div>\n\n {/* Step List */}\n {steps.length === 0 ? (\n <div className=\"dc:text-center dc:py-8\">\n <p className=\"dc:text-sm text-dc-text-muted dc:mb-3\">\n No steps defined. Add at least 2 steps to create a funnel.\n </p>\n <button\n onClick={onAddStep}\n className=\"dc:inline-flex dc:items-center dc:gap-1.5 dc:px-3 dc:py-1.5 dc:text-sm dc:font-medium text-dc-primary bg-dc-primary/10 dc:rounded-md hover:bg-dc-primary/20 dc:transition-colors\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n Add First Step\n </button>\n </div>\n ) : (\n <div className=\"dc: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={`dc:transition-all ${\n draggedIndex === index ? 'dc:opacity-50' : ''\n } ${\n dragOverIndex === index\n ? 'dc:border-t-2 border-dc-primary dc: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=\"dc:flex dc:items-center dc:justify-center dc:gap-1.5 dc:w-full dc:py-2 dc:text-sm dc:font-medium text-dc-text-secondary bg-dc-surface dc:border-2 dc:border-dashed border-dc-border dc:rounded-lg hover:border-dc-primary hover:text-dc-primary hover:bg-dc-primary/5 dc:transition-colors\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n Add Step\n </button>\n )}\n\n {/* Validation Hint */}\n {steps.length === 1 && (\n <p className=\"dc:text-xs text-dc-warning dc: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=\"dc:flex dc:flex-col dc:h-full\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('steps')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'steps'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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=\"dc:flex dc:flex-col dc:h-full dc:min-h-0 dc:overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc: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=\"dc:text-xs text-dc-text-muted dc:mb-3\">\n Choose how to visualize the flow data. This affects how data is aggregated.\n </p>\n <div className=\"dc:flex dc:gap-2\">\n <button\n type=\"button\"\n onClick={() => onChartTypeChange('sankey')}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-1\">\n <span>Sankey</span>\n <span className=\"dc:text-[10px] dc: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={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-1\">\n <span>Sunburst</span>\n <span className=\"dc:text-[10px] dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:grid dc:grid-cols-2 dc:gap-4\">\n {/* Steps Before - disabled for sunburst */}\n <div className={chartType === 'sunburst' ? 'dc:opacity-50' : ''}>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Steps Before\n {chartType === 'sunburst' && (\n <span className=\"dc:ml-1 text-dc-text-muted\">(N/A)</span>\n )}\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1 dc:disabled:cursor-not-allowed\"\n />\n <span className=\"dc:w-6 dc:text-sm dc:font-medium text-dc-text dc:text-center\">\n {chartType === 'sunburst' ? '-' : stepsBefore}\n </span>\n </div>\n </div>\n\n {/* Steps After */}\n <div>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Steps After\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1\"\n />\n <span className=\"dc:w-6 dc:text-sm dc:font-medium text-dc-text dc: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=\"dc:mt-3 dc:px-3 dc:py-2 bg-dc-warning-bg dc:rounded dc:border border-dc-warning dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:w-full dc:border border-dc-border dc:rounded dc:px-2 dc:py-2 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {Icon && <Icon className=\"dc:w-3.5 dc:h-3.5\" />}\n {label}\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n dc:transition-colors hover:border-dc-primary dc:cursor-pointer\n ${isOpen ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className={`dc: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=\"dc:flex dc:items-center dc:gap-1 dc: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=\"dc:p-0.5 dc: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={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform ${isOpen ? 'dc:rotate-180' : ''}`}\n />\n )}\n </span>\n </button>\n\n {/* Dropdown */}\n {isOpen && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[200px] bg-dc-surface dc:border border-dc-border dc:rounded-md dc:shadow-lg\">\n {/* Search Input */}\n <div className=\"dc:p-2 dc:border-b border-dc-border\">\n <div className=\"dc:relative\">\n {SearchIcon && (\n <SearchIcon className=\"dc:absolute dc:left-2 dc:top-1/2 dc:-translate-y-1/2 dc:w-4 dc: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=\"dc:w-full dc:pl-8 dc:pr-3 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text placeholder:text-dc-text-muted dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n </div>\n\n {/* Options List */}\n <div className=\"dc:max-h-48 dc:overflow-y-auto dc:p-1\">\n {Object.entries(filteredGroups).length === 0 ? (\n <div className=\"dc:px-3 dc:py-4 dc:text-sm text-dc-text-muted dc:text-center\">\n No matching fields found\n </div>\n ) : (\n Object.entries(filteredGroups).map(([cubeName, dims]) => (\n <div key={cubeName} className=\"dc:mb-2 dc:last:mb-0\">\n <div className=\"dc:px-2 dc:py-1 dc:text-xs dc:font-medium text-dc-text-muted dc:uppercase dc:tracking-wide\">\n {cubeName}\n </div>\n {dims.map((dim) => (\n <button\n key={dim.dimension}\n onClick={() => handleSelect(dim.dimension)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-3 dc:py-1.5 dc:text-sm\n dc:rounded dc: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=\"dc:w-4 dc:h-4\" />\n )}\n </button>\n ))}\n </div>\n ))\n )}\n </div>\n\n {/* Help Text */}\n <div className=\"dc:px-3 dc:py-2 dc:border-t border-dc-border dc: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=\"dc:flex-1 dc:min-w-0\">\n <label className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n {CalendarIcon && <CalendarIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n Date Range\n </label>\n\n <div ref={dropdownRef} className=\"dc:relative\">\n <button\n type=\"button\"\n onClick={() => setShowDatePicker(!showDatePicker)}\n className={`\n dc:flex dc:items-center dc:justify-between dc:w-full dc:px-2.5 dc:py-1.5 dc:text-sm\n bg-dc-surface dc:border border-dc-border dc:rounded\n hover:border-dc-primary dc:cursor-pointer dc:transition-colors\n ${showDatePicker ? 'border-dc-primary dc:ring-1 ring-dc-primary' : ''}\n `}\n >\n <span className=\"text-dc-text dc:truncate\">{dateRangeDisplay}</span>\n {ChevronDownIcon && (\n <ChevronDownIcon\n className={`dc:w-4 dc:h-4 text-dc-text-muted dc:transition-transform dc:ml-2 ${showDatePicker ? 'dc:rotate-180' : ''}`}\n />\n )}\n </button>\n\n {/* Date Range Dropdown */}\n {showDatePicker && (\n <div className=\"dc:absolute dc:z-50 dc:mt-1 dc:left-0 dc:right-0 dc:min-w-[280px] bg-dc-surface dc:border border-dc-border dc:rounded-lg dc:shadow-lg dc:p-3\">\n {/* Presets */}\n <div className=\"dc:grid dc:grid-cols-2 dc:gap-2 dc: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={`dc:px-3 dc:py-1.5 dc:text-xs dc:rounded dc: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=\"dc:border-t border-dc-border dc:pt-3\">\n <div className=\"dc:text-xs dc:font-medium text-dc-text-muted dc:mb-2\">Custom Range</div>\n <div className=\"dc:flex dc:gap-2 dc:items-center dc:mb-2\">\n <input\n type=\"date\"\n value={customStart}\n onChange={(e) => {\n setCustomStart(e.target.value)\n setSelectedPreset('custom')\n }}\n className=\"dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n <span className=\"text-dc-text-muted dc: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=\"dc:flex-1 dc:px-2 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc:focus:ring-1 focus:ring-dc-primary\"\n />\n </div>\n <button\n type=\"button\"\n onClick={handleCustomDateApply}\n disabled={!customStart || !customEnd}\n className=\"dc:w-full dc:px-3 dc:py-1.5 dc:text-xs bg-dc-primary text-white dc:rounded hover:bg-dc-primary-hover dc:disabled:opacity-50 dc:disabled:cursor-not-allowed dc: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 dc:border-b border-dc-border\">\n {/* Collapsible Header */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className=\"dc:flex dc:items-center dc:justify-between dc:w-full dc:px-4 dc:py-2.5 hover:bg-dc-surface-hover dc:transition-colors\"\n >\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {isCollapsed ? (\n ChevronRightIcon && <ChevronRightIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n ) : (\n ChevronDownIcon && <ChevronDownIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n )}\n <SectionHeading className=\"dc:mb-0\">Configuration</SectionHeading>\n {isConfigComplete && (\n <span className=\"dc:flex dc:items-center dc:gap-1 dc:text-xs text-dc-success\">\n {CheckIcon && <CheckIcon className=\"dc:w-3.5 dc:h-3.5\" />}\n </span>\n )}\n </div>\n\n {/* Collapsed Summary */}\n {isCollapsed && isConfigComplete && (\n <span className=\"dc:text-xs text-dc-text-muted dc:truncate dc:max-w-[200px]\">\n {cubeLabel} • {dateLabel}\n </span>\n )}\n </button>\n\n {/* Collapsible Content */}\n {!isCollapsed && (\n <div className=\"dc:flex dc:flex-col dc:gap-3 dc:px-4 dc: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=\"dc:flex dc:flex-col dc:h-full dc:min-h-0 dc:overflow-hidden\">\n {/* Tab Bar */}\n <div className=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n <button\n onClick={() => setActiveTab('config')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'config'\n ? 'text-dc-primary dc: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={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : !hasDisplayTab\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:flex-col dc:flex-1 dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc:p-4 dc:space-y-6\">\n {/* Date Range Selector - at top for visibility */}\n <div>\n <SectionHeading>Date Range</SectionHeading>\n <p className=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc: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=\"dc:text-xs text-dc-text-muted dc:mb-3\">\n Configure how retention is calculated and displayed.\n </p>\n\n <div className=\"dc:space-y-4\">\n {/* Granularity */}\n <div>\n <label className=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Period Granularity\n </label>\n <div className=\"dc:flex dc:gap-2\">\n {RETENTION_GRANULARITY_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onGranularityChange(option.value)}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc:font-medium dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Number of Periods ({RETENTION_MIN_PERIODS}-{RETENTION_MAX_PERIODS})\n </label>\n <div className=\"dc:flex dc:items-center dc: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=\"dc:flex-1\"\n />\n <span className=\"dc:w-8 dc:text-sm dc:font-medium text-dc-text dc:text-center\">\n {retentionPeriods}\n </span>\n </div>\n {retentionPeriods > 26 && (\n <p className=\"dc:mt-1 dc: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=\"dc:block dc:text-xs dc:font-medium text-dc-text-muted dc:mb-1\">\n Retention Type\n </label>\n <div className=\"dc:flex dc:gap-2\">\n {RETENTION_TYPE_OPTIONS.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => onRetentionTypeChange(option.value)}\n className={`dc:flex-1 dc:px-3 dc:py-2 dc:rounded-md dc:border dc:text-sm dc: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=\"dc:flex dc:flex-col dc:items-center dc:gap-0.5\">\n <span className=\"dc:font-medium\">{option.label}</span>\n <span className=\"dc:text-[10px] dc: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=\"dc:flex-1 dc:min-h-0 dc:overflow-auto dc: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=\"dc:h-full dc:flex dc: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=\"dc:flex dc:border-b border-dc-border dc:flex-shrink-0\">\n {/* Query Tabs - show Q1, Q2, etc. when multi-query, or single \"Query\" tab */}\n {isMultiQuery ? (\n <div className=\"dc:flex dc:min-w-0 dc: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={`dc:flex dc:items-center dc:gap-1 dc:px-3 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isActiveQuery\n ? 'text-dc-primary dc: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=\"dc:p-0.5 dc:rounded hover:bg-dc-danger-bg hover:text-dc-error dc:transition-colors dc:ml-0.5\"\n title=\"Remove query\"\n aria-label={`Remove ${getQueryTabLabel(index)}`}\n >\n <CloseIcon className=\"dc:w-3 dc:h-3\" />\n </span>\n </button>\n )\n })}\n {/* Add Query Button */}\n <button\n onClick={onAddQuery}\n className=\"dc:flex dc:items-center dc:justify-center dc:px-2 dc:py-3 text-dc-text-secondary hover:text-dc-text dc:transition-colors dc:flex-shrink-0\"\n title=\"Add query\"\n aria-label=\"Add new query\"\n >\n <AddIcon className=\"dc:w-4 dc:h-4\" />\n </button>\n </div>\n ) : (\n <button\n onClick={() => onActiveTabChange('query')}\n className={`dc:flex-1 dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors ${\n activeTab === 'query'\n ? 'text-dc-primary dc: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=\"dc:ml-2 dc:p-0.5 dc:rounded hover:bg-dc-surface-hover dc:transition-colors dc:inline-flex dc:items-center\"\n title=\"Add another query\"\n aria-label=\"Add another query\"\n >\n <AddIcon className=\"dc:w-3 dc: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={`dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isMultiQuery ? '' : 'dc:flex-1'\n } ${\n activeTab === 'chart'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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={`dc:px-4 dc:py-3 dc:text-sm dc:font-medium dc:transition-colors dc:flex-shrink-0 ${\n isMultiQuery ? '' : 'dc:flex-1'\n } ${\n activeTab === 'display'\n ? 'text-dc-primary dc:border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted dc:cursor-not-allowed dc: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=\"dc:flex dc:items-center dc:gap-2 dc:px-4 dc:py-1.5 dc:text-sm bg-dc-surface-secondary dc:border-b border-dc-border\">\n {LinkIcon && <LinkIcon className=\"dc:w-3.5 dc:h-3.5 text-dc-text-muted dc:flex-shrink-0\" />}\n <select\n value={mergeStrategy}\n onChange={(e) => onMergeStrategyChange?.(e.target.value as QueryMergeStrategy)}\n className=\"dc:px-2 dc:py-1 dc:text-xs bg-dc-surface dc:border border-dc-border dc:rounded text-dc-text dc:focus:outline-none dc: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=\"dc:w-[180px] dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-warning-bg dc:space-y-1\">\n {adapterValidation.errors.map((error, i) => (\n <div key={`adapter-error-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-error\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{error}</span>\n </div>\n ))}\n {adapterValidation.warnings.map((warning, i) => (\n <div key={`adapter-warning-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-warning\">\n <InfoIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc: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=\"dc:px-4 dc:py-2 dc:border-b border-dc-border bg-dc-warning-bg\">\n {multiQueryValidation.errors.map((error, i) => (\n <div key={`error-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-error\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{error.message}</span>\n </div>\n ))}\n {multiQueryValidation.warnings.map((warning, i) => (\n <div key={`warning-${i}`} className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs text-dc-warning\">\n <WarningIcon className=\"dc:w-3.5 dc:h-3.5 dc:mt-0.5 dc:flex-shrink-0\" />\n <span>{warning.message}</span>\n </div>\n ))}\n </div>\n )}\n\n {/* Tab Content */}\n <div className=\"dc:flex-1 dc:overflow-auto dc:p-4\">\n {activeTab === 'query' ? (\n <div className=\"dc: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=\"dc:mb-4\">\n <div className=\"dc:flex dc:items-center dc:justify-between dc:mb-2\">\n <h4 className=\"dc:text-sm dc:font-medium text-dc-text\">Dimensions</h4>\n </div>\n {/* Explanation with link to switch mode */}\n <div className=\"dc:flex dc:items-start dc:gap-2 dc:px-3 dc:py-2 dc:mb-3 bg-dc-surface-secondary dc:rounded dc:border border-dc-border dc:text-xs\">\n {InfoIcon && <InfoIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted dc:flex-shrink-0 dc: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 dc:hover:underline dc: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=\"dc: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=\"dc: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=\"dc:px-4 dc:py-2 dc:flex dc:items-center dc:justify-between dc:border-b border-dc-border bg-dc-surface-secondary\">\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n <SparklesIcon className=\"dc:w-4 dc:h-4 text-dc-accent\" />\n <span className=\"dc:text-sm dc:font-medium text-dc-text\">AI Query Generator</span>\n {isGenerating && (\n <span className=\"dc:text-xs text-dc-accent dc:animate-pulse\">\n Generating...\n </span>\n )}\n </div>\n <div className=\"dc:flex dc:items-center dc:gap-2\">\n {hasGeneratedQuery && (\n <button\n onClick={onAccept}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium text-white bg-dc-success dc:hover:opacity-80 dc:rounded dc:transition-colors\"\n >\n Accept\n </button>\n )}\n <button\n onClick={onCancel}\n className=\"dc:px-3 dc:py-1 dc:text-xs dc:font-medium text-dc-text-secondary hover:text-dc-text bg-dc-surface hover:bg-dc-surface-hover dc:border border-dc-border dc:rounded dc:transition-colors\"\n >\n {hasGeneratedQuery ? 'Cancel' : 'Close'}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"dc:p-4\">\n <div className=\"dc:flex dc:gap-3\">\n {/* Prompt input */}\n <div className=\"dc: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=\"dc:w-full dc:px-3 dc:py-2 dc:text-sm dc:border border-dc-border dc:rounded-md dc:shadow-sm dc:focus:outline-none dc:focus:ring-2 focus:ring-dc-accent focus:border-dc-accent dc:resize-none bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n rows={2}\n disabled={isGenerating}\n />\n <div className=\"dc:mt-1 dc: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=\"dc:flex-shrink-0\">\n <button\n onClick={onGenerate}\n disabled={isGenerating || !userPrompt.trim()}\n className={`dc:px-4 dc:py-2 dc:text-sm dc:font-medium dc:rounded-md dc:transition-colors dc:flex dc:items-center dc:gap-2 ${\n isGenerating || !userPrompt.trim()\n ? 'bg-dc-surface-tertiary text-dc-text-disabled dc:cursor-not-allowed'\n : 'bg-dc-accent hover:bg-dc-accent-hover text-white'\n }`}\n >\n {isGenerating ? (\n <>\n <div className=\"dc:w-4 dc:h-4 dc:border-2 border-white border-t-transparent dc:rounded-full dc:animate-spin\" />\n <span>Generating...</span>\n </>\n ) : (\n <>\n <SparklesIcon className=\"dc:w-4 dc:h-4\" />\n <span>Generate</span>\n </>\n )}\n </button>\n </div>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"dc:mt-3 dc:flex dc:items-start dc:gap-2 dc:p-3 bg-dc-error-bg dc:border border-dc-error-border dc:rounded-md\">\n <ErrorIcon className=\"dc:w-4 dc:h-4 text-dc-error dc:mt-0.5 dc:flex-shrink-0\" />\n <div className=\"dc:text-sm text-dc-error\">{error}</div>\n </div>\n )}\n\n {/* Success message */}\n {hasGeneratedQuery && !error && (\n <div className=\"dc:mt-3 dc:p-3 bg-dc-success-bg dc:border border-dc-success-border dc:rounded-md\">\n <div className=\"dc: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=\"dc:flex dc:flex-col dc:items-center dc:justify-center dc:w-full dc:h-full dc:p-6 dc:text-center bg-dc-surface\">\n <div className=\"dc:h-10 dc:w-10 dc:mb-3 text-dc-warning\">\n {WarningIcon && <WarningIcon className=\"dc:w-10 dc:h-10\" />}\n </div>\n <h3 className=\"dc:text-base dc:font-semibold dc:mb-2 text-dc-text\">\n Mode Error\n </h3>\n <p className=\"dc:text-sm text-dc-text-secondary dc:mb-3 dc: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=\"dc:w-full dc:max-w-md dc:mb-4 dc:text-left\">\n <summary className=\"dc:cursor-pointer dc:text-xs text-dc-text-muted hover:text-dc-text\">\n Show error details\n </summary>\n <div className=\"dc:mt-2 dc:p-2 bg-dc-surface-secondary dc:rounded dc:text-xs dc:font-mono text-dc-text-secondary dc:overflow-auto dc:max-h-32\">\n {this.state.error?.message || 'Unknown error'}\n </div>\n </details>\n\n <div className=\"dc:flex dc:gap-2\">\n <button\n onClick={this.handleReset}\n className=\"dc:px-3 dc:py-1.5 dc:border border-dc-border dc:rounded dc:text-sm text-dc-text hover:bg-dc-surface-hover dc:transition-colors dc:flex dc:items-center dc:gap-1\"\n >\n {RefreshIcon && <RefreshIcon className=\"dc:w-4 dc:h-4\" />}\n Try Again\n </button>\n {this.props.onSwitchToSafeMode && (\n <button\n onClick={this.handleSwitchToSafeMode}\n className=\"dc:px-3 dc:py-1.5 bg-dc-primary text-white dc:rounded dc:text-sm dc:hover:opacity-90 dc: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={`dc:flex dc:flex-col dc:lg:flex-row bg-dc-surface dc:border-x dc:border-b border-dc-border ${maxHeight ? 'dc:lg:h-[var(--dc-max-h)] dc:lg:max-h-[var(--dc-max-h)] dc:lg:overflow-hidden' : 'dc:lg:h-full'} ${className}`}\n style={maxHeight ? { ['--dc-max-h' as string]: maxHeight } : undefined}\n >\n {/* Top/Left Panel - Results */}\n <div className=\"dc:h-[60vh] dc:lg:h-auto dc:lg:flex-1 dc:min-w-0 dc:border-b dc:lg:border-b-0 dc:lg:border-r border-dc-border dc:overflow-auto dc:flex dc: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=\"dc:flex-1 dc: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 warnings={analysis.warnings}\n />\n </div>\n </div>\n\n {/* Bottom/Right Panel - Query Builder */}\n <div className=\"dc:w-full dc:lg:w-96 dc:flex-shrink-0 dc:lg:h-full dc:overflow-auto dc: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":["formatReason","reason","c","getReasonBadgeClasses","QueryAnalysisPanel","analysis","InfoIcon","getIcon","ArrowRightIcon","WarningIcon","TableIcon","LinkIcon","SuccessIcon","ErrorIcon","summaryCards","jsxs","jsx","card","i","jp","idx","step","stepIdx","jc","candidate","pa","jk","w","sendGeminiMessage","apiKey","userPrompt","endpoint","requestBody","headers","response","errorMessage","errorData","errorText","data","extractTextFromResponse","isServerFunnelQuery","query","useAnalysisAI","state","setState","chartType","setChartType","chartConfig","setChartConfig","displayConfig","setDisplayConfig","setUserManuallySelectedChart","setActiveView","aiEndpoint","analysisType","setAnalysisType","loadFunnelFromServerQuery","getFullConfig","loadFullConfig","aiState","setAIState","useState","handleOpenAI","useCallback","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","generateExecutionPlanMarkdown","sql","lines","selected","candidatePath","col","cte","warning","AnalysisResultsPanel","memo","executionStatus","executionResults","executionError","totalRowCount","resultsStale","colorPalette","currentPaletteName","onColorPaletteChange","allQueries","funnelExecutedQueries","activeView","onActiveViewChange","displayLimit","onDisplayLimitChange","hasMetrics","debugDataPerQuery","onShareClick","canShare","onRefreshClick","canRefresh","isRefreshing","needsRefresh","onClearClick","canClear","enableAI","isAIOpen","onAIToggle","queryCount","perQueryResults","activeTableIndex","onActiveTableChange","isFunnelModeProp","funnelServerQuery","funnelDebugData","flowServerQuery","flowDebugData","retentionServerQuery","retentionDebugData","retentionChartData","retentionValidation","warnings","isFunnelMode","isFlowMode","isRetentionMode","showDebug","setShowDebug","activeDebugIndex","setActiveDebugIndex","isClearConfirmOpen","setIsClearConfirmOpen","isShiftHeld","setIsShiftHeld","isHoveringRefresh","setIsHoveringRefresh","copyMarkdownState","setCopyMarkdownState","useEffect","handleKeyDown","e","handleKeyUp","showCacheBustIndicator","currentDebugData","debugSql","debugAnalysis","debugLoading","debugError","debugQuery","isShowingFunnelQuery","handleCopyMarkdown","markdown","explainResult","explainLoading","explainHasRun","explainError","runExplain","clearExplain","useExplainQuery","funnelExplainResult","funnelExplainLoading","funnelExplainHasRun","funnelExplainError","runFunnelExplain","clearFunnelExplain","flowExplainResult","flowExplainLoading","flowExplainHasRun","flowExplainError","runFlowExplain","clearFlowExplain","retentionExplainResult","retentionExplainLoading","retentionExplainHasRun","retentionExplainError","runRetentionExplain","aiAnalysis","aiAnalysisLoading","aiAnalysisError","runAIAnalysis","clearAIAnalysis","useExplainAI","isFirstRunRef","useRef","combinedQueryForChart","useMemo","allMeasures","q","ChartIcon","CodeIcon","ShareIcon","CheckIcon","TrashIcon","SparklesIcon","RefreshIcon","renderLoading","renderError","renderHeader","hasQueryContent","hasModeSpecificContent","renderWaiting","renderNeedsRefreshEmpty","renderEmpty","emptyMessage","renderNoData","renderChart","effectiveChartType","isValidChartType","LazyChart","renderExecutionErrorBanner","renderSharedConfigBlocks","CodeBlock","renderStandardResponseBlock","title","Fragment","renderRetentionResponseBlock","renderModeDebug","modeSql","modeLoading","modeError","ExecutionPlanPanel","renderStandardDebug","renderDebug","metadata","metadataSection","extraSection","isMultiQuery","renderFlowTable","nodes","links","firstResult","r","a","b","node","link","sourceId","targetId","sourceName","targetName","renderTable","tableIndex","tableData","tableQuery","limitedData","renderOverlaySpinner","hasResults","ColorPaletteSelector","d","renderNeedsRefreshBanner","renderWarningsBanner","isError","bgClass","borderClass","textClass","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","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","value","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","chartConfigRegistry","barChartConfig","lineChartConfig","areaChartConfig","pieChartConfig","scatterChartConfig","bubbleChartConfig","radarChartConfig","radialBarChartConfig","treemapChartConfig","dataTableConfig","activityGridChartConfig","kpiNumberConfig","kpiDeltaConfig","kpiTextConfig","markdownConfig","funnelChartConfig","sankeyChartConfig","sunburstChartConfig","heatmapChartConfig","retentionHeatmapConfig","retentionCombinedConfig","boxPlotChartConfig","waterfallChartConfig","candlestickChartConfig","measureProfileChartConfig","gaugeChartConfig","getLabel","ChartTypeSelector","selectedType","onTypeChange","className","compact","availability","excludeTypes","isOpen","setIsOpen","chartTypes","SelectedIcon","getChartTypeIcon","selectedLabel","useCase","chartAvailability","isAvailable","unavailableReason","tooltipText","AnalysisChartConfigPanel","onChartTypeChange","onChartConfigChange","setDraggedItem","availableFields","m","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","SearchIcon","FunnelBindingKeySelector","bindingKey","onChange","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","placeholder","options","helpText","groupedOptions","hasValue","o","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","isActive","canRemove","onSelect","isEditingName","setIsEditingName","showTimeDropdown","setShowTimeDropdown","localName","setLocalName","nameInputRef","timeDropdownRef","handleNameChange","handleNameKeyDown","handleNameBlur","trimmedName","handleTimeSelect","handleFiltersChange","timeToConvertLabel","cubeSchema","metaSchema","getRelatedCubesSchema","FunnelStepList","steps","activeStepIndex","onAddStep","onRemoveStep","onUpdateStep","onSelectStep","onReorderSteps","dragOverIndex","setDragOverIndex","updates","FunnelModeContent","funnelCube","funnelSteps","activeFunnelStepIndex","funnelTimeDimension","funnelBindingKey","onDisplayConfigChange","activeTab","setActiveTab","hasDisplayTab","AnalysisDisplayConfigPanel","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","AnalysisAIPanel","onPromptChange","isGenerating","hasGeneratedQuery","onGenerate","onAccept","AnalysisModeErrorBoundary","Component","props","errorInfo","AnalysisBuilderInner","forwardRef","maxHeight","initialData","externalColorPalette","_hideSettings","hideShare","onQueryChange","ref","useCubeMeta","features","useCubeFeatures","useAnalysisBuilder","storeApi","useAnalysisBuilderStoreApi","updater","newState","serverQuery","funnelConfig","useImperativeHandle","AnalysisBuilder","initialQuery","initialChartConfig","initialAnalysisType","initialFunnelState","initialFlowState","initialRetentionState","disableLocalStorage","innerProps","shareHash","parseShareHash","sharedState","decodeAndDecompress","initialActiveViewFromShare","initialAnalysisTypeFromShare","initialFunnelStateFromShare","funnelQuery","initialFlowStateFromShare","flowQuery","flowChartConfig","initialRetentionStateFromShare","retentionQuery","retentionChartConfig","AnalysisBuilderStoreProvider"],"mappings":"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"}