drizzle-cube 0.2.5 → 0.2.8

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 (122) hide show
  1. package/dist/client/charts.js +15 -15
  2. package/dist/client/chunks/{chart-activitygridchart-BzL97Vnm.js → chart-activitygridchart-Cz4bEf3V.js} +219 -217
  3. package/dist/client/chunks/chart-activitygridchart-Cz4bEf3V.js.map +1 -0
  4. package/dist/client/chunks/{chart-activitygridchart-config-48WqIofo.js → chart-activitygridchart-config-BngZDVh_.js} +96 -90
  5. package/dist/client/chunks/chart-activitygridchart-config-BngZDVh_.js.map +1 -0
  6. package/dist/client/chunks/{chart-areachart-BtH3SvAM.js → chart-areachart-DLdolSnU.js} +3 -3
  7. package/dist/client/chunks/{chart-areachart-BtH3SvAM.js.map → chart-areachart-DLdolSnU.js.map} +1 -1
  8. package/dist/client/chunks/{chart-areachart-config-D8taXdn1.js → chart-areachart-config-DWN1E5ej.js} +2 -2
  9. package/dist/client/chunks/{chart-areachart-config-D8taXdn1.js.map → chart-areachart-config-DWN1E5ej.js.map} +1 -1
  10. package/dist/client/chunks/chart-barchart-Bdjz8DJp.js +171 -0
  11. package/dist/client/chunks/chart-barchart-Bdjz8DJp.js.map +1 -0
  12. package/dist/client/chunks/{chart-barchart-config-DjRZBtLb.js → chart-barchart-config-DZA0xTns.js} +2 -2
  13. package/dist/client/chunks/{chart-barchart-config-DjRZBtLb.js.map → chart-barchart-config-DZA0xTns.js.map} +1 -1
  14. package/dist/client/chunks/{chart-bubblechart-Lj_PnppP.js → chart-bubblechart-BlQkmqkI.js} +2 -2
  15. package/dist/client/chunks/{chart-bubblechart-Lj_PnppP.js.map → chart-bubblechart-BlQkmqkI.js.map} +1 -1
  16. package/dist/client/chunks/{chart-bubblechart-config-C6ck2qmg.js → chart-bubblechart-config-C79lfDSO.js} +2 -2
  17. package/dist/client/chunks/{chart-bubblechart-config-C6ck2qmg.js.map → chart-bubblechart-config-C79lfDSO.js.map} +1 -1
  18. package/dist/client/chunks/{chart-charttooltip-D9BKscsw.js → chart-charttooltip-k8soCd2n.js} +2 -2
  19. package/dist/client/chunks/{chart-charttooltip-D9BKscsw.js.map → chart-charttooltip-k8soCd2n.js.map} +1 -1
  20. package/dist/client/chunks/chart-datatable-Mo4gYCwa.js +249 -0
  21. package/dist/client/chunks/chart-datatable-Mo4gYCwa.js.map +1 -0
  22. package/dist/client/chunks/{chart-datatable-config-B5z0SlOJ.js → chart-datatable-config-DqGw99R3.js} +2 -2
  23. package/dist/client/chunks/{chart-datatable-config-B5z0SlOJ.js.map → chart-datatable-config-DqGw99R3.js.map} +1 -1
  24. package/dist/client/chunks/{chart-kpidelta-Bx-stIIk.js → chart-kpidelta-CTcuIO9G.js} +3 -3
  25. package/dist/client/chunks/{chart-kpidelta-Bx-stIIk.js.map → chart-kpidelta-CTcuIO9G.js.map} +1 -1
  26. package/dist/client/chunks/{chart-kpidelta-config-CnZfi_P2.js → chart-kpidelta-config-B-Y-LHmd.js} +2 -2
  27. package/dist/client/chunks/{chart-kpidelta-config-CnZfi_P2.js.map → chart-kpidelta-config-B-Y-LHmd.js.map} +1 -1
  28. package/dist/client/chunks/{chart-kpinumber-config-CVikHojM.js → chart-kpinumber-config-BaNaJMI6.js} +2 -2
  29. package/dist/client/chunks/{chart-kpinumber-config-CVikHojM.js.map → chart-kpinumber-config-BaNaJMI6.js.map} +1 -1
  30. package/dist/client/chunks/{chart-kpinumber-BrXgyKGP.js → chart-kpinumber-slEXt8C-.js} +5 -5
  31. package/dist/client/chunks/{chart-kpinumber-BrXgyKGP.js.map → chart-kpinumber-slEXt8C-.js.map} +1 -1
  32. package/dist/client/chunks/{chart-kpitext-config-B2MovXSw.js → chart-kpitext-config-BNywYqEW.js} +2 -2
  33. package/dist/client/chunks/{chart-kpitext-config-B2MovXSw.js.map → chart-kpitext-config-BNywYqEW.js.map} +1 -1
  34. package/dist/client/chunks/{chart-kpitext-_2tnYN_z.js → chart-kpitext-giq03TOK.js} +3 -3
  35. package/dist/client/chunks/{chart-kpitext-_2tnYN_z.js.map → chart-kpitext-giq03TOK.js.map} +1 -1
  36. package/dist/client/chunks/{chart-linechart-DBdIULsM.js → chart-linechart-BfnU6L-D.js} +4 -4
  37. package/dist/client/chunks/{chart-linechart-DBdIULsM.js.map → chart-linechart-BfnU6L-D.js.map} +1 -1
  38. package/dist/client/chunks/{chart-linechart-config-CVBVB7nS.js → chart-linechart-config-BL_1mjHF.js} +2 -2
  39. package/dist/client/chunks/{chart-linechart-config-CVBVB7nS.js.map → chart-linechart-config-BL_1mjHF.js.map} +1 -1
  40. package/dist/client/chunks/{chart-markdownchart-config-Cq5Sxrgq.js → chart-markdownchart-config-DtZOfYu4.js} +2 -2
  41. package/dist/client/chunks/{chart-markdownchart-config-Cq5Sxrgq.js.map → chart-markdownchart-config-DtZOfYu4.js.map} +1 -1
  42. package/dist/client/chunks/{chart-piechart-CzesCpZ_.js → chart-piechart-CZRDQxeB.js} +3 -3
  43. package/dist/client/chunks/{chart-piechart-CzesCpZ_.js.map → chart-piechart-CZRDQxeB.js.map} +1 -1
  44. package/dist/client/chunks/{chart-piechart-config-Bdd31Gdi.js → chart-piechart-config-Bg4jeIFo.js} +2 -2
  45. package/dist/client/chunks/{chart-piechart-config-Bdd31Gdi.js.map → chart-piechart-config-Bg4jeIFo.js.map} +1 -1
  46. package/dist/client/chunks/{chart-radarchart-B3WUEiTh.js → chart-radarchart-D5yRnY9j.js} +3 -3
  47. package/dist/client/chunks/{chart-radarchart-B3WUEiTh.js.map → chart-radarchart-D5yRnY9j.js.map} +1 -1
  48. package/dist/client/chunks/{chart-radarchart-config-BWyfn0ij.js → chart-radarchart-config-d6dLkI7B.js} +2 -2
  49. package/dist/client/chunks/{chart-radarchart-config-BWyfn0ij.js.map → chart-radarchart-config-d6dLkI7B.js.map} +1 -1
  50. package/dist/client/chunks/{chart-radialbarchart-DBiRcLd9.js → chart-radialbarchart-Djtcn7aH.js} +3 -3
  51. package/dist/client/chunks/{chart-radialbarchart-DBiRcLd9.js.map → chart-radialbarchart-Djtcn7aH.js.map} +1 -1
  52. package/dist/client/chunks/{chart-radialbarchart-config-lU2_NQCD.js → chart-radialbarchart-config-BGf97-BV.js} +2 -2
  53. package/dist/client/chunks/{chart-radialbarchart-config-lU2_NQCD.js.map → chart-radialbarchart-config-BGf97-BV.js.map} +1 -1
  54. package/dist/client/chunks/{chart-scatterchart-C_D9OqA1.js → chart-scatterchart-C83KgqYY.js} +2 -2
  55. package/dist/client/chunks/{chart-scatterchart-C_D9OqA1.js.map → chart-scatterchart-C83KgqYY.js.map} +1 -1
  56. package/dist/client/chunks/{chart-scatterchart-config-DtLnut1M.js → chart-scatterchart-config-DEIB74ot.js} +2 -2
  57. package/dist/client/chunks/{chart-scatterchart-config-DtLnut1M.js.map → chart-scatterchart-config-DEIB74ot.js.map} +1 -1
  58. package/dist/client/chunks/{chart-treemapchart-DJqy3Sy7.js → chart-treemapchart-BDKnKGTz.js} +3 -3
  59. package/dist/client/chunks/{chart-treemapchart-DJqy3Sy7.js.map → chart-treemapchart-BDKnKGTz.js.map} +1 -1
  60. package/dist/client/chunks/{chart-treemapchart-config-BEiIWQnR.js → chart-treemapchart-config-ppKPTB96.js} +2 -2
  61. package/dist/client/chunks/{chart-treemapchart-config-BEiIWQnR.js.map → chart-treemapchart-config-ppKPTB96.js.map} +1 -1
  62. package/dist/client/chunks/{charts-DFbr7EGW.js → charts-MJLpxe3r.js} +42 -42
  63. package/dist/client/chunks/{charts-DFbr7EGW.js.map → charts-MJLpxe3r.js.map} +1 -1
  64. package/dist/client/chunks/components-CXA6-jJq.js +9845 -0
  65. package/dist/client/chunks/components-CXA6-jJq.js.map +1 -0
  66. package/dist/client/chunks/{icons-D6z-_9sa.js → icons-B2XSxpVK.js} +213 -181
  67. package/dist/client/chunks/icons-B2XSxpVK.js.map +1 -0
  68. package/dist/client/chunks/{index-_pVwmFVW.js → index-CSeLP8gq.js} +2 -2
  69. package/dist/client/chunks/{index-_pVwmFVW.js.map → index-CSeLP8gq.js.map} +1 -1
  70. package/dist/client/components/AnalysisBuilder/AnalysisAxisDropZone.d.ts +27 -0
  71. package/dist/client/components/AnalysisBuilder/AnalysisChartConfigPanel.d.ts +21 -0
  72. package/dist/client/components/AnalysisBuilder/AnalysisFilterGroup.d.ts +20 -0
  73. package/dist/client/components/AnalysisBuilder/AnalysisFilterItem.d.ts +16 -0
  74. package/dist/client/components/AnalysisBuilder/AnalysisFilterSection.d.ts +12 -0
  75. package/dist/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +10 -0
  76. package/dist/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +12 -0
  77. package/dist/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +10 -0
  78. package/dist/client/components/AnalysisBuilder/BreakdownSection.d.ts +8 -0
  79. package/dist/client/components/AnalysisBuilder/FieldDetailPanel.d.ts +4 -0
  80. package/dist/client/components/AnalysisBuilder/FieldSearchItem.d.ts +6 -0
  81. package/dist/client/components/AnalysisBuilder/FieldSearchModal.d.ts +2 -0
  82. package/dist/client/components/AnalysisBuilder/MetricItemCard.d.ts +9 -0
  83. package/dist/client/components/AnalysisBuilder/MetricsSection.d.ts +8 -0
  84. package/dist/client/components/AnalysisBuilder/index.d.ts +3 -0
  85. package/dist/client/components/AnalysisBuilder/types.d.ts +366 -0
  86. package/dist/client/components/AnalysisBuilder/utils.d.ts +103 -0
  87. package/dist/client/components/ChartTypeSelector.d.ts +6 -1
  88. package/dist/client/components/DashboardGrid.d.ts +3 -2
  89. package/dist/client/components/DashboardPortletCard.d.ts +63 -0
  90. package/dist/client/components/QueryBuilder/CubeMetaExplorer.d.ts +2 -2
  91. package/dist/client/components/QueryBuilder/QueryPanel.d.ts +2 -2
  92. package/dist/client/components/QueryBuilder/types.d.ts +7 -138
  93. package/dist/client/components/RowManagedLayout.d.ts +19 -0
  94. package/dist/client/components/charts/DataTable.d.ts +1 -1
  95. package/dist/client/components.js +16 -9148
  96. package/dist/client/components.js.map +1 -1
  97. package/dist/client/hooks.js +2 -2
  98. package/dist/client/icons/types.d.ts +6 -0
  99. package/dist/client/icons.js +1 -1
  100. package/dist/client/index.d.ts +1 -0
  101. package/dist/client/index.js +3202 -49
  102. package/dist/client/index.js.map +1 -1
  103. package/dist/client/providers/CubeProvider.d.ts +4 -2
  104. package/dist/client/providers.js +1 -1
  105. package/dist/client/shared/chartDefaults.d.ts +64 -0
  106. package/dist/client/shared/components/QueryAnalysisPanel.d.ts +7 -0
  107. package/dist/client/shared/index.d.ts +10 -0
  108. package/dist/client/shared/types.d.ts +134 -0
  109. package/dist/client/shared/utils.d.ts +101 -0
  110. package/dist/client/styles.css +1 -1
  111. package/dist/client/types.d.ts +20 -0
  112. package/dist/client/utils/index.d.ts +1 -0
  113. package/dist/client/utils/pivotUtils.d.ts +78 -0
  114. package/dist/client-bundle-stats.html +1 -1
  115. package/package.json +1 -1
  116. package/dist/client/chunks/chart-activitygridchart-BzL97Vnm.js.map +0 -1
  117. package/dist/client/chunks/chart-activitygridchart-config-48WqIofo.js.map +0 -1
  118. package/dist/client/chunks/chart-barchart-DX6DIoIp.js +0 -177
  119. package/dist/client/chunks/chart-barchart-DX6DIoIp.js.map +0 -1
  120. package/dist/client/chunks/chart-datatable-BaECYDn2.js +0 -57
  121. package/dist/client/chunks/chart-datatable-BaECYDn2.js.map +0 -1
  122. package/dist/client/chunks/icons-D6z-_9sa.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/client/components/AnalysisBuilder/utils.ts","../../src/client/components/AnalysisBuilder/FieldSearchItem.tsx","../../src/client/components/AnalysisBuilder/FieldDetailPanel.tsx","../../src/client/components/AnalysisBuilder/FieldSearchModal.tsx","../../src/client/shared/utils.ts","../../src/client/shared/components/QueryAnalysisPanel.tsx","../../src/client/shared/chartDefaults.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/AnalysisFilterItem.tsx","../../src/client/components/AnalysisBuilder/AnalysisFilterGroup.tsx","../../src/client/components/AnalysisBuilder/AnalysisFilterSection.tsx","../../src/client/components/AnalysisBuilder/AnalysisAxisDropZone.tsx","../../src/client/components/AnalysisBuilder/AnalysisChartConfigPanel.tsx","../../src/client/components/AnalysisBuilder/AnalysisQueryPanel.tsx","../../src/client/components/AnalysisBuilder/index.tsx"],"sourcesContent":["/**\n * Utility functions for PortletBuilder component\n */\n\nimport type {\n MetricItem,\n BreakdownItem,\n FieldOption,\n FieldType,\n RecentFieldsStorage\n} from './types'\nimport type { MetaResponse, MetaField } from '../../shared/types'\nimport type { CubeQuery, Filter } from '../../types'\n\n// ============================================================================\n// ID Generation\n// ============================================================================\n\n/**\n * Generate a unique ID for items\n */\nexport function generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Generate letter label for metrics (A, B, C, ..., AA, AB, ...)\n */\nexport function generateMetricLabel(index: number): string {\n let label = ''\n let n = index\n do {\n label = String.fromCharCode(65 + (n % 26)) + label\n n = Math.floor(n / 26) - 1\n } while (n >= 0)\n return label\n}\n\n// ============================================================================\n// Query Building\n// ============================================================================\n\n/**\n * Convert metrics and breakdowns to CubeQuery format\n */\nexport function buildCubeQuery(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n filters: Filter[]\n): CubeQuery {\n const query: CubeQuery = {\n measures: metrics.map((m) => m.field),\n dimensions: breakdowns.filter((b) => !b.isTimeDimension).map((b) => b.field),\n timeDimensions: breakdowns\n .filter((b) => b.isTimeDimension)\n .map((b) => ({\n dimension: b.field,\n granularity: b.granularity || 'day'\n })),\n filters: filters.length > 0 ? filters : undefined\n }\n\n // Clean up empty arrays\n if (query.measures?.length === 0) delete query.measures\n if (query.dimensions?.length === 0) delete query.dimensions\n if (query.timeDimensions?.length === 0) delete query.timeDimensions\n\n return query\n}\n\n/**\n * Check if a query has any content\n */\nexport function hasQueryContent(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n filters: Filter[]\n): boolean {\n return metrics.length > 0 || breakdowns.length > 0 || filters.length > 0\n}\n\n// ============================================================================\n// Field Utilities\n// ============================================================================\n\n/**\n * Get cube name from a field name (e.g., \"Employees.count\" -> \"Employees\")\n */\nexport function getCubeNameFromField(fieldName: string): string {\n return fieldName.split('.')[0]\n}\n\n/**\n * Get field short name from full name (e.g., \"Employees.count\" -> \"count\")\n */\nexport function getFieldShortName(fieldName: string): string {\n const parts = fieldName.split('.')\n return parts.length > 1 ? parts.slice(1).join('.') : fieldName\n}\n\n/**\n * Find field metadata from schema\n */\nexport function findFieldInSchema(\n fieldName: string,\n schema: MetaResponse | null\n): { field: MetaField; cubeName: string; fieldType: FieldType } | null {\n if (!schema) return null\n\n for (const cube of schema.cubes) {\n // Check measures\n const measure = cube.measures.find((m) => m.name === fieldName)\n if (measure) {\n return { field: measure, cubeName: cube.name, fieldType: 'measure' }\n }\n\n // Check dimensions\n const dimension = cube.dimensions.find((d) => d.name === fieldName)\n if (dimension) {\n return {\n field: dimension,\n cubeName: cube.name,\n fieldType: dimension.type === 'time' ? 'timeDimension' : 'dimension'\n }\n }\n }\n\n return null\n}\n\n/**\n * Get display title for a field\n */\nexport function getFieldTitle(fieldName: string, schema: MetaResponse | null): string {\n const found = findFieldInSchema(fieldName, schema)\n if (found) {\n return found.field.title || found.field.shortTitle || fieldName\n }\n return fieldName\n}\n\n/**\n * Determine field type from metadata\n */\nexport function getFieldType(field: MetaField): FieldType {\n if (field.type === 'time') return 'timeDimension'\n // Measures typically have aggregation types\n if (['count', 'countDistinct', 'sum', 'avg', 'min', 'max', 'runningTotal', 'countDistinctApprox'].includes(field.type)) {\n return 'measure'\n }\n return 'dimension'\n}\n\n// ============================================================================\n// Field Search & Filtering\n// ============================================================================\n\n/**\n * Convert schema to flat list of field options\n */\nexport function schemaToFieldOptions(\n schema: MetaResponse | null,\n mode: 'metrics' | 'breakdown' | 'filter'\n): FieldOption[] {\n if (!schema) return []\n\n const options: FieldOption[] = []\n\n for (const cube of schema.cubes) {\n if (mode === 'metrics') {\n // Add measures only\n for (const measure of cube.measures) {\n options.push({\n name: measure.name,\n title: measure.title || measure.shortTitle || measure.name,\n shortTitle: measure.shortTitle || measure.title || measure.name,\n type: measure.type,\n description: measure.description,\n cubeName: cube.name,\n fieldType: 'measure'\n })\n }\n } else if (mode === 'breakdown') {\n // Add dimensions only (both regular and time)\n for (const dimension of cube.dimensions) {\n const isTime = dimension.type === 'time'\n options.push({\n name: dimension.name,\n title: dimension.title || dimension.shortTitle || dimension.name,\n shortTitle: dimension.shortTitle || dimension.title || dimension.name,\n type: dimension.type,\n description: dimension.description,\n cubeName: cube.name,\n fieldType: isTime ? 'timeDimension' : 'dimension'\n })\n }\n } else {\n // 'filter' mode - add BOTH measures AND dimensions\n // Add measures first\n for (const measure of cube.measures) {\n options.push({\n name: measure.name,\n title: measure.title || measure.shortTitle || measure.name,\n shortTitle: measure.shortTitle || measure.title || measure.name,\n type: measure.type,\n description: measure.description,\n cubeName: cube.name,\n fieldType: 'measure'\n })\n }\n // Add dimensions (both regular and time)\n for (const dimension of cube.dimensions) {\n const isTime = dimension.type === 'time'\n options.push({\n name: dimension.name,\n title: dimension.title || dimension.shortTitle || dimension.name,\n shortTitle: dimension.shortTitle || dimension.title || dimension.name,\n type: dimension.type,\n description: dimension.description,\n cubeName: cube.name,\n fieldType: isTime ? 'timeDimension' : 'dimension'\n })\n }\n }\n }\n\n return options\n}\n\n/**\n * Filter field options by search term\n */\nexport function filterFieldOptions(\n options: FieldOption[],\n searchTerm: string,\n selectedCube?: string | null\n): FieldOption[] {\n let filtered = options\n\n // Filter by cube if selected\n if (selectedCube && selectedCube !== 'all') {\n filtered = filtered.filter((opt) => opt.cubeName === selectedCube)\n }\n\n // Filter by search term\n if (searchTerm.trim()) {\n const term = searchTerm.toLowerCase()\n filtered = filtered.filter(\n (opt) =>\n opt.name.toLowerCase().includes(term) ||\n opt.title.toLowerCase().includes(term) ||\n (opt.description?.toLowerCase().includes(term) ?? false)\n )\n }\n\n return filtered\n}\n\n/**\n * Group field options by cube\n */\nexport function groupFieldsByCube(options: FieldOption[]): Map<string, FieldOption[]> {\n const grouped = new Map<string, FieldOption[]>()\n\n for (const option of options) {\n const existing = grouped.get(option.cubeName) || []\n existing.push(option)\n grouped.set(option.cubeName, existing)\n }\n\n return grouped\n}\n\n// ============================================================================\n// Recent Fields Storage\n// ============================================================================\n\nconst RECENT_FIELDS_KEY = 'drizzle-cube-recent-fields'\nconst MAX_RECENT_FIELDS = 10\n\n/**\n * Get recent fields from localStorage\n */\nexport function getRecentFields(): RecentFieldsStorage {\n try {\n const stored = localStorage.getItem(RECENT_FIELDS_KEY)\n if (stored) {\n return JSON.parse(stored)\n }\n } catch {\n // Ignore errors\n }\n return { metrics: [], breakdowns: [] }\n}\n\n/**\n * Add a field to recent fields\n */\nexport function addRecentField(fieldName: string, mode: 'metrics' | 'breakdowns'): void {\n try {\n const recent = getRecentFields()\n const list = recent[mode]\n\n // Remove if already exists\n const filtered = list.filter((f) => f !== fieldName)\n\n // Add to front\n filtered.unshift(fieldName)\n\n // Limit size\n recent[mode] = filtered.slice(0, MAX_RECENT_FIELDS)\n\n localStorage.setItem(RECENT_FIELDS_KEY, JSON.stringify(recent))\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Get recent field options from schema\n */\nexport function getRecentFieldOptions(\n schema: MetaResponse | null,\n mode: 'metrics' | 'breakdown' | 'filter',\n recentFieldNames: string[]\n): FieldOption[] {\n if (!schema || recentFieldNames.length === 0) return []\n\n const allOptions = schemaToFieldOptions(schema, mode)\n const recentOptions: FieldOption[] = []\n\n for (const fieldName of recentFieldNames) {\n const option = allOptions.find((opt) => opt.name === fieldName)\n if (option) {\n recentOptions.push(option)\n }\n }\n\n return recentOptions\n}\n\n// ============================================================================\n// Cube List Utilities\n// ============================================================================\n\n/**\n * Get list of cube names from schema\n */\nexport function getCubeNames(schema: MetaResponse | null): string[] {\n if (!schema) return []\n return schema.cubes.map((cube) => cube.name)\n}\n\n/**\n * Get cube title by name\n */\nexport function getCubeTitle(cubeName: string, schema: MetaResponse | null): string {\n if (!schema) return cubeName\n const cube = schema.cubes.find((c) => c.name === cubeName)\n return cube?.title || cubeName\n}\n\n// ============================================================================\n// State Persistence\n// ============================================================================\n\nconst STORAGE_KEY = 'drizzle-cube-portlet-builder-state'\n\n/**\n * Save state to localStorage\n */\nexport function saveStateToStorage(state: {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: string\n chartConfig: object\n displayConfig: object\n activeView: string\n}): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(state))\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Load state from localStorage\n */\nexport function loadStateFromStorage(): {\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n filters: Filter[]\n chartType: string\n chartConfig: object\n displayConfig: object\n activeView: string\n} | null {\n try {\n const stored = localStorage.getItem(STORAGE_KEY)\n if (stored) {\n return JSON.parse(stored)\n }\n } catch {\n // Ignore errors\n }\n return null\n}\n\n/**\n * Clear state from localStorage\n */\nexport function clearStateFromStorage(): void {\n try {\n localStorage.removeItem(STORAGE_KEY)\n } catch {\n // Ignore errors\n }\n}\n","/**\n * FieldSearchItem Component\n *\n * A single field item in the search results list.\n * Shows field icon, title, type badge, and selection state.\n */\n\nimport { memo } from 'react'\nimport { getIcon, getMeasureTypeIcon, getFieldTypeIcon } from '../../icons'\nimport type { FieldSearchItemProps } from './types'\n\nconst CheckIcon = getIcon('check')\n\nfunction FieldSearchItem({\n field,\n isSelected,\n isFocused,\n onClick,\n onMouseEnter,\n ...props\n}: FieldSearchItemProps & { 'data-field-index'?: number }) {\n // Get appropriate icon based on field type\n const getFieldIcon = () => {\n if (field.fieldType === 'measure') {\n const Icon = getMeasureTypeIcon(field.type)\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n } else if (field.fieldType === 'timeDimension') {\n const Icon = getFieldTypeIcon('time')\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n } else {\n const Icon = getFieldTypeIcon('dimension')\n return Icon ? <Icon className=\"w-4 h-4\" /> : null\n }\n }\n\n // Get badge color based on field type\n const getBadgeStyle = () => {\n if (field.fieldType === 'measure') {\n return 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300'\n } else if (field.fieldType === 'timeDimension') {\n return 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'\n } else {\n return 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'\n }\n }\n\n // Get short type label\n const getTypeLabel = () => {\n if (field.fieldType === 'measure') {\n return field.type.charAt(0).toUpperCase() + field.type.slice(1)\n } else if (field.fieldType === 'timeDimension') {\n return 'Time'\n } else {\n return 'Dim'\n }\n }\n\n return (\n <button\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n className={`w-full text-left px-3 py-2 rounded-lg flex items-center gap-3 transition-colors group ${\n isFocused\n ? 'bg-dc-primary/10 ring-1 ring-dc-primary'\n : isSelected\n ? 'bg-dc-success/10'\n : 'hover:bg-dc-surface-hover'\n }`}\n {...props}\n >\n {/* Icon */}\n <span\n className={`shrink-0 w-8 h-8 flex items-center justify-center rounded-md ${\n field.fieldType === 'measure'\n ? 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400'\n : field.fieldType === 'timeDimension'\n ? 'bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400'\n : 'bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400'\n }`}\n >\n {getFieldIcon()}\n </span>\n\n {/* Title and name */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium text-dc-text truncate\">\n {field.title}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">{field.name}</div>\n </div>\n\n {/* Type badge */}\n <span\n className={`shrink-0 px-2 py-0.5 rounded text-xs font-medium ${getBadgeStyle()}`}\n >\n {getTypeLabel()}\n </span>\n\n {/* Selection indicator */}\n {isSelected && (\n <span className=\"shrink-0 w-5 h-5 flex items-center justify-center rounded-full bg-dc-success text-white\">\n <CheckIcon className=\"w-3 h-3\" />\n </span>\n )}\n </button>\n )\n}\n\nexport default memo(FieldSearchItem)\n","/**\n * FieldDetailPanel Component\n *\n * Shows detailed information about the currently focused/hovered field.\n * Displays: icon, title, description, type, cube name, and technical name.\n */\n\nimport { memo } from 'react'\nimport { getMeasureTypeIcon, getFieldTypeIcon } from '../../icons'\nimport type { FieldDetailPanelProps } from './types'\n\nfunction FieldDetailPanel({ field }: FieldDetailPanelProps) {\n if (!field) {\n return (\n <div className=\"p-6 text-center text-dc-text-muted\">\n <p className=\"text-sm\">Hover over a field to see details</p>\n </div>\n )\n }\n\n // Get appropriate icon based on field type\n const getFieldIcon = () => {\n if (field.fieldType === 'measure') {\n const Icon = getMeasureTypeIcon(field.type)\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n } else if (field.fieldType === 'timeDimension') {\n const Icon = getFieldTypeIcon('time')\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n } else {\n const Icon = getFieldTypeIcon('dimension')\n return Icon ? <Icon className=\"w-6 h-6\" /> : null\n }\n }\n\n // Get icon background color\n const getIconBgStyle = () => {\n if (field.fieldType === 'measure') {\n return 'bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400'\n } else if (field.fieldType === 'timeDimension') {\n return 'bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400'\n } else {\n return 'bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400'\n }\n }\n\n // Get type display name\n const getTypeDisplay = () => {\n if (field.fieldType === 'measure') {\n const typeMap: Record<string, string> = {\n count: 'Count',\n countDistinct: 'Count Distinct',\n countDistinctApprox: 'Count Distinct (Approx)',\n sum: 'Sum',\n avg: 'Average',\n min: 'Minimum',\n max: 'Maximum',\n runningTotal: 'Running Total',\n number: 'Number'\n }\n return typeMap[field.type] || field.type\n } else if (field.fieldType === 'timeDimension') {\n return 'Time Dimension'\n } else {\n const typeMap: Record<string, string> = {\n string: 'Text',\n number: 'Number',\n boolean: 'Boolean',\n geo: 'Geographic'\n }\n return typeMap[field.type] || 'Dimension'\n }\n }\n\n return (\n <div className=\"p-4\">\n {/* Header with icon and title */}\n <div className=\"flex items-start gap-3 mb-4\">\n <span\n className={`shrink-0 w-12 h-12 flex items-center justify-center rounded-lg ${getIconBgStyle()}`}\n >\n {getFieldIcon()}\n </span>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold text-dc-text leading-tight\">\n {field.title}\n </h3>\n <p className=\"text-xs text-dc-text-muted mt-0.5 truncate\">\n {field.name}\n </p>\n </div>\n </div>\n\n {/* Description */}\n {field.description && (\n <div className=\"mb-4\">\n <p className=\"text-sm text-dc-text-secondary leading-relaxed\">\n {field.description}\n </p>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"space-y-3 pt-4 border-t border-dc-border\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Type</span>\n <span className=\"text-sm text-dc-text font-medium\">{getTypeDisplay()}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Cube</span>\n <span className=\"text-sm text-dc-text font-medium\">{field.cubeName}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-dc-text-muted\">Category</span>\n <span\n className={`text-xs px-2 py-0.5 rounded font-medium ${\n field.fieldType === 'measure'\n ? 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300'\n : field.fieldType === 'timeDimension'\n ? 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'\n : 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'\n }`}\n >\n {field.fieldType === 'measure'\n ? 'Measure'\n : field.fieldType === 'timeDimension'\n ? 'Time Dimension'\n : 'Dimension'}\n </span>\n </div>\n </div>\n\n {/* Usage hint */}\n <div className=\"mt-6 p-3 bg-dc-surface rounded-lg\">\n <p className=\"text-xs text-dc-text-muted\">\n Press <kbd className=\"px-1 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Enter</kbd> or click to add this field to your query.\n </p>\n </div>\n </div>\n )\n}\n\nexport default memo(FieldDetailPanel)\n","/**\n * FieldSearchModal Component\n *\n * A full-screen search modal for selecting cube fields (measures/dimensions).\n * Features:\n * - Real-time search filtering\n * - Cube-based category filtering\n * - Three-column layout: Categories | Results | Details\n * - Keyboard navigation support\n * - Recent fields tracking\n */\n\nimport { useState, useMemo, useCallback, useEffect, useRef } from 'react'\nimport { getIcon } from '../../icons'\nimport type { FieldSearchModalProps, FieldOption } from './types'\nimport type { MetaField } from '../../shared/types'\nimport {\n schemaToFieldOptions,\n filterFieldOptions,\n groupFieldsByCube,\n getCubeNames,\n getCubeTitle,\n getRecentFields,\n addRecentField,\n getRecentFieldOptions\n} from './utils'\nimport FieldSearchItem from './FieldSearchItem'\nimport FieldDetailPanel from './FieldDetailPanel'\n\nconst SearchIcon = getIcon('search')\nconst CloseIcon = getIcon('close')\n\nexport default function FieldSearchModal({\n isOpen,\n onClose,\n onSelect,\n mode,\n schema,\n selectedFields,\n recentFields: externalRecentFields\n}: FieldSearchModalProps) {\n // State\n const [searchTerm, setSearchTerm] = useState('')\n const [selectedCube, setSelectedCube] = useState<string | null>(null)\n const [focusedField, setFocusedField] = useState<FieldOption | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const [lastSelectedIndex, setLastSelectedIndex] = useState<number | null>(null)\n\n // Refs\n const searchInputRef = useRef<HTMLInputElement>(null)\n const resultsContainerRef = useRef<HTMLDivElement>(null)\n\n // Get recent fields from localStorage or props\n const recentFieldNames = useMemo(() => {\n if (externalRecentFields) return externalRecentFields\n const stored = getRecentFields()\n return mode === 'metrics' ? stored.metrics : stored.breakdowns\n }, [externalRecentFields, mode])\n\n // Map mode to field options mode\n const fieldOptionsMode = mode\n\n // Get all field options for current mode\n const allFieldOptions = useMemo(() => {\n return schemaToFieldOptions(schema, fieldOptionsMode)\n }, [schema, fieldOptionsMode])\n\n // Get cube names for category filter\n const cubeNames = useMemo(() => {\n return getCubeNames(schema)\n }, [schema])\n\n // Filter fields by search and cube\n const filteredFields = useMemo(() => {\n return filterFieldOptions(allFieldOptions, searchTerm, selectedCube)\n }, [allFieldOptions, searchTerm, selectedCube])\n\n // Group filtered fields by cube\n const groupedFields = useMemo(() => {\n return groupFieldsByCube(filteredFields)\n }, [filteredFields])\n\n // Get recent field options (only when not searching)\n const recentOptions = useMemo(() => {\n if (searchTerm.trim()) return []\n return getRecentFieldOptions(schema, fieldOptionsMode, recentFieldNames).filter(\n (f) => !selectedCube || f.cubeName === selectedCube\n )\n }, [schema, fieldOptionsMode, recentFieldNames, searchTerm, selectedCube])\n\n // Flat list of visible fields for keyboard navigation\n const flatFieldsList = useMemo(() => {\n const list: FieldOption[] = [...recentOptions]\n groupedFields.forEach((fields) => {\n list.push(...fields)\n })\n return list\n }, [recentOptions, groupedFields])\n\n // Focus search input when modal opens\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus()\n }\n }, [isOpen])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!isOpen) {\n setSearchTerm('')\n setSelectedCube(null)\n setFocusedField(null)\n setFocusedIndex(-1)\n setLastSelectedIndex(null)\n }\n }, [isOpen])\n\n // Handle single field selection\n const selectSingleField = useCallback(\n (field: FieldOption, keepOpen: boolean = false) => {\n // Add to recent fields\n addRecentField(field.name, mode === 'metrics' ? 'metrics' : 'breakdowns')\n\n // Create MetaField object for callback\n const metaField: MetaField = {\n name: field.name,\n title: field.title,\n shortTitle: field.shortTitle,\n type: field.type,\n description: field.description\n }\n\n onSelect(metaField, field.fieldType, field.cubeName, keepOpen)\n },\n [mode, onSelect]\n )\n\n // Handle field selection with shift-click support for range selection\n const handleSelectField = useCallback(\n (field: FieldOption, fieldIndex: number, shiftKey: boolean = false) => {\n // Shift-click for range selection - keep modal open\n if (shiftKey && lastSelectedIndex !== null && lastSelectedIndex !== fieldIndex) {\n const startIndex = Math.min(lastSelectedIndex, fieldIndex)\n const endIndex = Math.max(lastSelectedIndex, fieldIndex)\n\n // Select all fields in the range, keep modal open for all\n for (let i = startIndex; i <= endIndex; i++) {\n const rangeField = flatFieldsList[i]\n if (rangeField && !selectedFields.includes(rangeField.name)) {\n selectSingleField(rangeField, true) // Keep modal open\n }\n }\n } else if (shiftKey) {\n // Shift-click on single item - select but keep modal open\n selectSingleField(field, true)\n } else {\n // Normal single selection - close modal after\n selectSingleField(field, false)\n }\n\n // Update last selected index for next shift-click\n setLastSelectedIndex(fieldIndex)\n },\n [flatFieldsList, lastSelectedIndex, selectSingleField, selectedFields]\n )\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (flatFieldsList.length === 0) return\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setFocusedIndex((prev) => {\n const next = Math.min(prev + 1, flatFieldsList.length - 1)\n setFocusedField(flatFieldsList[next])\n return next\n })\n break\n\n case 'ArrowUp':\n e.preventDefault()\n setFocusedIndex((prev) => {\n const next = Math.max(prev - 1, 0)\n setFocusedField(flatFieldsList[next])\n return next\n })\n break\n\n case 'Enter':\n e.preventDefault()\n if (focusedIndex >= 0 && flatFieldsList[focusedIndex]) {\n handleSelectField(flatFieldsList[focusedIndex], focusedIndex, e.shiftKey)\n }\n break\n\n case 'Escape':\n e.preventDefault()\n onClose()\n break\n }\n },\n [flatFieldsList, focusedIndex, handleSelectField, onClose]\n )\n\n // Scroll focused item into view\n useEffect(() => {\n if (focusedIndex >= 0 && resultsContainerRef.current) {\n const focusedElement = resultsContainerRef.current.querySelector(\n `[data-field-index=\"${focusedIndex}\"]`\n )\n if (focusedElement) {\n focusedElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' })\n }\n }\n }, [focusedIndex])\n\n if (!isOpen) return null\n\n const searchPlaceholder =\n mode === 'metrics' ? 'Search metrics...' : mode === 'filter' ? 'Search fields to filter...' : 'Search dimensions...'\n\n const modalTitle = mode === 'metrics' ? 'Select a Metric' : mode === 'filter' ? 'Select a Field to Filter' : 'Select a Dimension'\n const focusedFieldId = focusedIndex >= 0 && flatFieldsList[focusedIndex]\n ? `field-option-${flatFieldsList[focusedIndex].name.replace(/\\./g, '-')}`\n : undefined\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n onClick={onClose}\n role=\"presentation\"\n >\n {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={modalTitle}\n className=\"bg-dc-surface shadow-xl w-full h-full md:rounded-lg md:w-auto md:max-w-5xl md:h-[80vh] md:max-h-[700px] flex flex-col overflow-hidden\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleKeyDown}\n >\n {/* Header with Search */}\n <div className=\"shrink-0 border-b border-dc-border\">\n <div className=\"flex items-center px-4 py-3 gap-3\">\n <SearchIcon className=\"w-5 h-5 text-dc-text-muted\" aria-hidden={true} />\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchTerm}\n onChange={(e) => {\n setSearchTerm(e.target.value)\n setFocusedIndex(-1)\n }}\n placeholder={searchPlaceholder}\n className=\"flex-1 bg-transparent border-none outline-none text-dc-text placeholder-dc-text-muted text-lg\"\n aria-label={searchPlaceholder}\n aria-controls=\"field-search-results\"\n aria-activedescendant={focusedFieldId}\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-autocomplete=\"list\"\n />\n <button\n onClick={onClose}\n className=\"p-1 text-dc-text-secondary hover:text-dc-text rounded\"\n aria-label=\"Close dialog\"\n >\n <CloseIcon className=\"w-5 h-5\" aria-hidden={true} />\n </button>\n </div>\n {/* Mobile cube filter - shown only on mobile */}\n {cubeNames.length > 1 && (\n <div className=\"md:hidden px-4 pb-3\">\n <select\n value={selectedCube || ''}\n onChange={(e) => setSelectedCube(e.target.value || null)}\n className=\"w-full px-3 py-2 bg-dc-surface border border-dc-border rounded-lg text-sm text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n aria-label=\"Filter by cube\"\n >\n <option value=\"\">All Cubes</option>\n {cubeNames.map((cubeName) => (\n <option key={cubeName} value={cubeName}>\n {getCubeTitle(cubeName, schema)}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n\n {/* Three Column Layout - Single column on mobile */}\n <div className=\"flex-1 flex overflow-hidden\">\n {/* Left Column - Categories (hidden on mobile) */}\n <nav\n className=\"hidden md:block w-48 shrink-0 border-r border-dc-border overflow-y-auto bg-dc-surface-secondary\"\n aria-label=\"Filter by cube\"\n >\n <div className=\"p-2\" role=\"group\" aria-label=\"Cube categories\">\n <button\n onClick={() => setSelectedCube(null)}\n className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${\n selectedCube === null\n ? 'bg-dc-primary/10 text-dc-primary font-medium'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }`}\n aria-pressed={selectedCube === null}\n >\n All\n </button>\n {cubeNames.map((cubeName) => (\n <button\n key={cubeName}\n onClick={() => setSelectedCube(cubeName)}\n className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors truncate ${\n selectedCube === cubeName\n ? 'bg-dc-primary/10 text-dc-primary font-medium'\n : 'text-dc-text hover:bg-dc-surface-hover'\n }`}\n title={getCubeTitle(cubeName, schema)}\n aria-pressed={selectedCube === cubeName}\n >\n {getCubeTitle(cubeName, schema)}\n </button>\n ))}\n </div>\n </nav>\n\n {/* Middle Column - Results */}\n <div\n id=\"field-search-results\"\n ref={resultsContainerRef}\n className=\"flex-1 overflow-y-auto p-4\"\n role=\"listbox\"\n aria-label=\"Available fields\"\n >\n {filteredFields.length === 0 && recentOptions.length === 0 ? (\n <div className=\"text-center py-12 text-dc-text-muted\">\n <p className=\"text-lg mb-2\">No fields found</p>\n <p className=\"text-sm\">\n {searchTerm\n ? `No ${mode === 'metrics' ? 'metrics' : 'dimensions'} match \"${searchTerm}\"`\n : `No ${mode === 'metrics' ? 'metrics' : 'dimensions'} available`}\n </p>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {/* Recent Fields */}\n {recentOptions.length > 0 && (\n <div>\n <h3 className=\"text-xs font-semibold text-dc-text-muted uppercase tracking-wider mb-2\">\n Recents\n </h3>\n <div className=\"space-y-1\">\n {recentOptions.map((field, idx) => (\n <FieldSearchItem\n key={`recent-${field.name}`}\n field={field}\n isSelected={selectedFields.includes(field.name)}\n isFocused={focusedIndex === idx}\n onClick={(e) => handleSelectField(field, idx, e.shiftKey)}\n onMouseEnter={() => {\n setFocusedField(field)\n setFocusedIndex(idx)\n }}\n data-field-index={idx}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Grouped by Cube */}\n {Array.from(groupedFields.entries()).map(([cubeName, fields]) => (\n <div key={cubeName}>\n <h3 className=\"text-xs font-semibold text-dc-text-muted uppercase tracking-wider mb-2\">\n {getCubeTitle(cubeName, schema)}\n </h3>\n <div className=\"space-y-1\">\n {fields.map((field) => {\n const fieldIndex =\n recentOptions.length +\n Array.from(groupedFields.entries())\n .slice(\n 0,\n Array.from(groupedFields.keys()).indexOf(cubeName)\n )\n .reduce((sum, [, f]) => sum + f.length, 0) +\n fields.indexOf(field)\n\n return (\n <FieldSearchItem\n key={field.name}\n field={field}\n isSelected={selectedFields.includes(field.name)}\n isFocused={focusedIndex === fieldIndex}\n onClick={(e) => handleSelectField(field, fieldIndex, e.shiftKey)}\n onMouseEnter={() => {\n setFocusedField(field)\n setFocusedIndex(fieldIndex)\n }}\n data-field-index={fieldIndex}\n />\n )\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Right Column - Field Details (hidden on mobile) */}\n <div className=\"hidden md:block w-72 shrink-0 border-l border-dc-border bg-dc-surface-secondary overflow-y-auto\">\n <FieldDetailPanel field={focusedField} />\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"shrink-0 border-t border-dc-border px-4 py-3 flex items-center justify-between text-sm text-dc-text-muted\">\n <div>\n <span className=\"text-dc-text-secondary\">{filteredFields.length}</span>{' '}\n {mode === 'metrics' ? 'metrics' : mode === 'filter' ? 'fields' : 'dimensions'} available\n </div>\n {/* Keyboard shortcuts - hidden on mobile */}\n <div className=\"hidden md:flex items-center gap-4\">\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">↑↓</kbd> Navigate\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Enter</kbd> Select\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Shift</kbd>+Click Multi-select\n </span>\n <span>\n <kbd className=\"px-1.5 py-0.5 bg-dc-surface-tertiary rounded text-xs\">Esc</kbd> Close\n </span>\n </div>\n </div>\n </div>\n </div>\n )\n}\n","/**\n * Shared utility functions used across QueryBuilder and AnalysisBuilder\n */\n\nimport type { CubeQuery, Filter, SimpleFilter, GroupFilter } from '../types'\nimport type { MetaField, MetaResponse } from './types'\nimport { FILTER_OPERATORS } from './types'\n\n// ============================================================================\n// Filter type guards\n// ============================================================================\n\n/**\n * Check if a filter is a simple filter\n */\nexport function isSimpleFilter(filter: Filter): filter is SimpleFilter {\n return 'member' in filter && 'operator' in filter && 'values' in filter\n}\n\n/**\n * Check if a filter is a group filter\n */\nexport function isGroupFilter(filter: Filter): filter is GroupFilter {\n return 'type' in filter && 'filters' in filter\n}\n\n/**\n * Check if a filter is an AND filter\n */\nexport function isAndFilter(filter: Filter): filter is GroupFilter {\n return isGroupFilter(filter) && filter.type === 'and'\n}\n\n/**\n * Check if a filter is an OR filter\n */\nexport function isOrFilter(filter: Filter): filter is GroupFilter {\n return isGroupFilter(filter) && filter.type === 'or'\n}\n\n// ============================================================================\n// Filter manipulation functions\n// ============================================================================\n\n/**\n * Flatten all simple filters from a hierarchical filter structure\n */\nexport function flattenFilters(filters: Filter[]): SimpleFilter[] {\n const simple: SimpleFilter[] = []\n\n const flatten = (filter: Filter) => {\n if (isSimpleFilter(filter)) {\n simple.push(filter)\n } else if (isGroupFilter(filter)) {\n filter.filters.forEach(flatten)\n }\n }\n\n filters.forEach(flatten)\n return simple\n}\n\n/**\n * Count total filters in hierarchical structure\n */\nexport function countFilters(filters: Filter[]): number {\n let count = 0\n\n const countFilter = (filter: Filter) => {\n if (isSimpleFilter(filter)) {\n count++\n } else if (isGroupFilter(filter)) {\n filter.filters.forEach(countFilter)\n }\n }\n\n filters.forEach(countFilter)\n return count\n}\n\n/**\n * Create a new simple filter\n */\nexport function createSimpleFilter(member: string, operator: string = 'equals', values: any[] = []): SimpleFilter {\n return {\n member,\n operator: operator as any,\n values\n }\n}\n\n/**\n * Create a new AND filter group\n */\nexport function createAndFilter(filters: Filter[] = []): GroupFilter {\n return {\n type: 'and',\n filters\n }\n}\n\n/**\n * Create a new OR filter group\n */\nexport function createOrFilter(filters: Filter[] = []): GroupFilter {\n return {\n type: 'or',\n filters\n }\n}\n\n// ============================================================================\n// Filter transformation functions\n// ============================================================================\n\n/**\n * Transform filters from new GroupFilter format to legacy server format\n * Server expects { and: [...] } and { or: [...] } instead of { type: 'and', filters: [...] }\n */\nexport function transformFiltersForServer(filters: Filter[]): any[] {\n const transformFilter = (filter: Filter): any => {\n if (isSimpleFilter(filter)) {\n return filter\n } else if (isGroupFilter(filter)) {\n const transformedSubFilters = filter.filters.map(transformFilter)\n\n if (filter.type === 'and') {\n return { and: transformedSubFilters }\n } else {\n return { or: transformedSubFilters }\n }\n }\n return filter\n }\n\n return filters.map(transformFilter)\n}\n\n/**\n * Transform filters from server/API format to UI format\n * Converts {and: [...]} and {or: [...]} to {type: 'and', filters: [...]} format\n */\nexport function transformFiltersFromServer(filters: any[]): Filter[] {\n return filters.map(filter => {\n if (!filter || typeof filter !== 'object') {\n return filter\n }\n\n // Handle legacy {and: [...]} format\n if ('and' in filter && Array.isArray(filter.and)) {\n return {\n type: 'and',\n filters: transformFiltersFromServer(filter.and)\n } as GroupFilter\n }\n\n // Handle legacy {or: [...]} format\n if ('or' in filter && Array.isArray(filter.or)) {\n return {\n type: 'or',\n filters: transformFiltersFromServer(filter.or)\n } as GroupFilter\n }\n\n // Handle new format {type: 'and', filters: [...]} - process recursively\n if ('type' in filter && 'filters' in filter && Array.isArray(filter.filters)) {\n return {\n type: filter.type,\n filters: transformFiltersFromServer(filter.filters)\n } as GroupFilter\n }\n\n // Simple filter - pass through\n return filter as SimpleFilter\n }).filter(Boolean) // Remove any null/undefined values\n}\n\n// ============================================================================\n// Query utility functions\n// ============================================================================\n\n/**\n * Check if query has any content (measures, dimensions, or timeDimensions)\n */\nexport function hasQueryContent(query: CubeQuery): boolean {\n return Boolean(\n (query.measures && query.measures.length > 0) ||\n (query.dimensions && query.dimensions.length > 0) ||\n (query.timeDimensions && query.timeDimensions.length > 0)\n )\n}\n\n/**\n * Clean query object by removing empty arrays\n */\nexport function cleanQuery(query: CubeQuery): CubeQuery {\n const cleanedQuery: CubeQuery = {}\n\n if (query.measures && query.measures.length > 0) {\n cleanedQuery.measures = query.measures\n }\n\n if (query.dimensions && query.dimensions.length > 0) {\n cleanedQuery.dimensions = query.dimensions\n }\n\n if (query.timeDimensions && query.timeDimensions.length > 0) {\n cleanedQuery.timeDimensions = query.timeDimensions\n }\n\n if (query.filters && query.filters.length > 0) {\n cleanedQuery.filters = query.filters\n }\n\n if (query.order) {\n cleanedQuery.order = query.order\n }\n\n if (query.limit) {\n cleanedQuery.limit = query.limit\n }\n\n if (query.offset) {\n cleanedQuery.offset = query.offset\n }\n\n if (query.segments && query.segments.length > 0) {\n cleanedQuery.segments = query.segments\n }\n\n return cleanedQuery\n}\n\n/**\n * Clean a query and transform filters for server compatibility\n * This version transforms GroupFilter to legacy and/or format\n */\nexport function cleanQueryForServer(query: CubeQuery): CubeQuery {\n const cleanedQuery = cleanQuery(query)\n\n // Apply server transformation to filters\n if (cleanedQuery.filters && cleanedQuery.filters.length > 0) {\n cleanedQuery.filters = transformFiltersForServer(cleanedQuery.filters) as any\n }\n\n return cleanedQuery\n}\n\n/**\n * Transform a Cube.js query from external format to UI internal format\n * This handles format differences between server/API queries and QueryBuilder state\n */\nexport function transformQueryForUI(query: any): CubeQuery {\n if (!query || typeof query !== 'object') {\n return {}\n }\n\n const transformed: CubeQuery = {}\n\n // Copy simple fields if they exist\n if (query.measures) transformed.measures = Array.isArray(query.measures) ? query.measures : []\n if (query.dimensions) transformed.dimensions = Array.isArray(query.dimensions) ? query.dimensions : []\n if (query.timeDimensions) transformed.timeDimensions = Array.isArray(query.timeDimensions) ? query.timeDimensions : []\n if (query.order) transformed.order = query.order\n if (query.limit) transformed.limit = query.limit\n if (query.offset) transformed.offset = query.offset\n if (query.segments) transformed.segments = Array.isArray(query.segments) ? query.segments : []\n\n // Transform filters from server format to UI format\n if (query.filters && Array.isArray(query.filters)) {\n transformed.filters = transformFiltersFromServer(query.filters)\n }\n\n return cleanQuery(transformed)\n}\n\n// ============================================================================\n// Schema utility functions\n// ============================================================================\n\n/**\n * Get cube name from field name (e.g., \"Employees.count\" -> \"Employees\")\n */\nexport function getCubeNameFromField(fieldName: string): string {\n return fieldName.split('.')[0]\n}\n\n/**\n * Get field type from schema\n */\nexport function getFieldType(fieldName: string, schema: MetaResponse): string {\n for (const cube of schema.cubes) {\n // Check measures\n const measure = cube.measures.find(m => m.name === fieldName)\n if (measure) return measure.type\n\n // Check dimensions\n const dimension = cube.dimensions.find(d => d.name === fieldName)\n if (dimension) return dimension.type\n }\n\n return 'string' // Default fallback\n}\n\n/**\n * Get field title from schema metadata, falling back to field name\n */\nexport function getFieldTitle(fieldName: string, schema: MetaResponse | null): string {\n if (!schema) return fieldName\n\n for (const cube of schema.cubes) {\n // Check measures\n const measure = cube.measures.find(m => m.name === fieldName)\n if (measure) return measure.title || measure.shortTitle || fieldName\n\n // Check dimensions\n const dimension = cube.dimensions.find(d => d.name === fieldName)\n if (dimension) return dimension.title || dimension.shortTitle || fieldName\n }\n\n return fieldName // Fallback to field name if not found\n}\n\n/**\n * Get available operators for a field type\n */\nexport function getAvailableOperators(fieldType: string): Array<{operator: string, label: string}> {\n const operators: Array<{operator: string, label: string}> = []\n\n for (const [operator, meta] of Object.entries(FILTER_OPERATORS)) {\n if (meta.fieldTypes.includes(fieldType)) {\n operators.push({\n operator,\n label: meta.label\n })\n }\n }\n\n return operators\n}\n\n/**\n * Get ALL filterable fields from schema\n */\nexport function getAllFilterableFields(schema: MetaResponse): MetaField[] {\n const allFields: MetaField[] = []\n\n schema.cubes.forEach(cube => {\n allFields.push(...cube.measures)\n allFields.push(...cube.dimensions)\n })\n\n return allFields.sort((a, b) => a.name.localeCompare(b.name))\n}\n\n// ============================================================================\n// Date range utility functions\n// ============================================================================\n\n/**\n * Convert DateRangeType to Cube.js compatible date range format\n */\nexport function convertDateRangeTypeToValue(rangeType: string, number?: number): string {\n const typeMap: Record<string, string> = {\n 'today': 'today',\n 'yesterday': 'yesterday',\n 'this_week': 'this week',\n 'this_month': 'this month',\n 'this_quarter': 'this quarter',\n 'this_year': 'this year',\n 'last_7_days': 'last 7 days',\n 'last_30_days': 'last 30 days',\n 'last_week': 'last week',\n 'last_month': 'last month',\n 'last_quarter': 'last quarter',\n 'last_year': 'last year',\n 'last_12_months': 'last 12 months'\n }\n\n // Handle dynamic ranges with number input\n if (rangeType.startsWith('last_n_') && number !== undefined && number > 0) {\n const unit = rangeType.replace('last_n_', '')\n const unitSingular = unit.slice(0, -1) // Remove 's' for singular form\n return number === 1 ? `last ${unitSingular}` : `last ${number} ${unit}`\n }\n\n return typeMap[rangeType] || rangeType\n}\n\n/**\n * Check if a date range type requires a number input\n */\nexport function requiresNumberInput(rangeType: string): boolean {\n return rangeType.startsWith('last_n_')\n}\n\n/**\n * Format date for Cube.js (YYYY-MM-DD)\n */\nexport function formatDateForCube(date: Date): string {\n return date.toISOString().split('T')[0]\n}\n","/**\n * QueryAnalysisPanel Component\n * Displays query planning analysis for debugging and transparency\n */\n\nimport React from 'react'\nimport { getIcon } from '../../icons'\nimport type { QueryAnalysis } from '../types'\n\ninterface QueryAnalysisPanelProps {\n analysis: QueryAnalysis\n}\n\n/**\n * Format reason string for display\n */\nfunction formatReason(reason: string): string {\n return reason.replace(/_/g, ' ')\n}\n\n/**\n * Get badge color based on reason\n */\nfunction getReasonBadgeClasses(reason: string): string {\n switch (reason) {\n case 'most_dimensions':\n return 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300'\n case 'most_connected':\n return 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300'\n case 'alphabetical_fallback':\n return 'bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300'\n case 'single_cube':\n return 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'\n default:\n return 'bg-gray-100 dark:bg-gray-900/30 text-gray-700 dark:text-gray-300'\n }\n}\n\nconst QueryAnalysisPanel: React.FC<QueryAnalysisPanelProps> = ({ analysis }) => {\n const InfoIcon = getIcon('info')\n const ArrowRightIcon = getIcon('chevronRight')\n const WarningIcon = getIcon('warning')\n const TableIcon = getIcon('table')\n const LinkIcon = getIcon('link')\n const SuccessIcon = getIcon('success')\n const ErrorIcon = getIcon('error')\n\n return (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded-lg p-4 space-y-4\">\n {/* Query Summary Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <InfoIcon className=\"w-4 h-4 mr-2\" />\n Query Summary\n </h4>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2 text-xs\">\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Type:</span>\n <span className=\"ml-1 font-medium text-dc-text\">\n {formatReason(analysis.querySummary.queryType)}\n </span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Cubes:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.cubeCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">Joins:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.joinCount}</span>\n </div>\n <div className=\"bg-dc-surface p-2 rounded\">\n <span className=\"text-dc-text-muted\">CTEs:</span>\n <span className=\"ml-1 font-medium text-dc-text\">{analysis.querySummary.cteCount}</span>\n </div>\n </div>\n </div>\n\n {/* Primary Cube Section */}\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Primary Cube (FROM table)\n </h4>\n <div className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-primary\">\n {analysis.primaryCube.selectedCube}\n </span>\n <span className={`text-xs px-2 py-0.5 rounded ${getReasonBadgeClasses(analysis.primaryCube.reason)}`}>\n {formatReason(analysis.primaryCube.reason)}\n </span>\n </div>\n <p className=\"text-dc-text-secondary text-xs\">\n {analysis.primaryCube.explanation}\n </p>\n {analysis.primaryCube.candidates && analysis.primaryCube.candidates.length > 1 && (\n <details className=\"mt-2\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Show candidates ({analysis.primaryCube.candidates.length})\n </summary>\n <div className=\"mt-2 space-y-1 ml-2\">\n {analysis.primaryCube.candidates.map((c, i) => (\n <div key={i} className=\"text-xs flex items-center gap-2 flex-wrap\">\n <span className={`font-mono ${c.cubeName === analysis.primaryCube.selectedCube ? 'font-bold text-dc-primary' : 'text-dc-text-muted'}`}>\n {c.cubeName}\n </span>\n <span className=\"text-dc-text-muted\">\n dims: {c.dimensionCount}, joins: {c.joinCount}\n </span>\n {c.canReachAll ? (\n <span className=\"text-green-600 dark:text-green-400 flex items-center gap-0.5\">\n <SuccessIcon className=\"w-3 h-3\" />\n reachable\n </span>\n ) : (\n <span className=\"text-red-600 dark:text-red-400 flex items-center gap-0.5\">\n <ErrorIcon className=\"w-3 h-3\" />\n cannot reach all\n </span>\n )}\n </div>\n ))}\n </div>\n </details>\n )}\n </div>\n </div>\n\n {/* Join Paths Section */}\n {analysis.joinPaths.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <LinkIcon className=\"w-4 h-4 mr-2\" />\n Join Paths\n </h4>\n <div className=\"space-y-2\">\n {analysis.joinPaths.map((jp, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-2 flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{analysis.primaryCube.selectedCube}</span>\n <ArrowRightIcon className=\"w-4 h-4 text-dc-text-muted\" />\n <span className=\"font-mono font-medium text-dc-text\">{jp.targetCube}</span>\n {jp.pathFound ? (\n <span className=\"text-xs px-2 py-0.5 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 rounded\">\n {jp.pathLength} step{jp.pathLength !== 1 ? 's' : ''}\n </span>\n ) : (\n <span className=\"text-xs px-2 py-0.5 bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300 rounded\">\n No path\n </span>\n )}\n </div>\n {jp.pathFound && jp.path && jp.path.length > 0 && (\n <div className=\"space-y-1 ml-2\">\n {jp.path.map((step, stepIdx) => (\n <div key={stepIdx} className=\"flex items-center gap-1 text-xs flex-wrap\">\n <span className=\"font-mono text-dc-text-secondary\">{step.fromCube}</span>\n <ArrowRightIcon className=\"w-3 h-3 text-dc-text-muted\" />\n <span className=\"font-mono text-dc-text\">{step.toCube}</span>\n <span className=\"text-dc-text-muted\">\n ({step.relationship}, {step.joinType} join)\n </span>\n {step.joinColumns.length > 0 && (\n <span className=\"text-dc-text-muted\">\n on {step.joinColumns.map(jc => `${jc.sourceColumn}=${jc.targetColumn}`).join(', ')}\n </span>\n )}\n </div>\n ))}\n </div>\n )}\n {!jp.pathFound && jp.error && (\n <p className=\"text-xs text-red-600 dark:text-red-400 mt-1\">{jp.error}</p>\n )}\n {jp.visitedCubes && jp.visitedCubes.length > 0 && !jp.pathFound && (\n <details className=\"mt-1\">\n <summary className=\"text-xs text-dc-text-muted cursor-pointer hover:text-dc-text\">\n Cubes visited during search ({jp.visitedCubes.length})\n </summary>\n <div className=\"mt-1 text-xs text-dc-text-muted ml-2\">\n {jp.visitedCubes.join(' → ')}\n </div>\n </details>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Pre-Aggregations Section */}\n {analysis.preAggregations.length > 0 && (\n <div className=\"border-b border-dc-border pb-3\">\n <h4 className=\"text-sm font-semibold text-dc-text mb-2 flex items-center\">\n <TableIcon className=\"w-4 h-4 mr-2\" />\n Pre-Aggregation CTEs\n </h4>\n <div className=\"space-y-2\">\n {analysis.preAggregations.map((pa, idx) => (\n <div key={idx} className=\"bg-dc-surface p-3 rounded text-sm\">\n <div className=\"flex items-center gap-2 mb-1 flex-wrap\">\n <span className=\"font-mono font-medium text-dc-text\">{pa.cubeName}</span>\n <span className=\"text-xs text-dc-text-muted\">as</span>\n <code className=\"text-xs bg-dc-surface-secondary px-1 rounded font-mono\">{pa.cteAlias}</code>\n </div>\n <p className=\"text-xs text-dc-text-secondary\">{pa.reason}</p>\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Measures:</span> {pa.measures.join(', ')}\n </div>\n {pa.joinKeys.length > 0 && (\n <div className=\"mt-1 text-xs text-dc-text-muted\">\n <span className=\"font-medium\">Join keys:</span> {pa.joinKeys.map(jk => `${jk.sourceColumn}=${jk.targetColumn}`).join(', ')}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Warnings Section */}\n {analysis.warnings && analysis.warnings.length > 0 && (\n <div>\n <h4 className=\"text-sm font-semibold text-amber-600 dark:text-amber-400 mb-2 flex items-center\">\n <WarningIcon className=\"w-4 h-4 mr-2\" />\n Warnings\n </h4>\n <ul className=\"list-disc list-inside text-xs text-amber-600 dark:text-amber-400 space-y-1\">\n {analysis.warnings.map((w, i) => (\n <li key={i}>{w}</li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Cubes Involved */}\n {analysis.cubesInvolved.length > 0 && (\n <div className=\"text-xs text-dc-text-muted pt-2 border-t border-dc-border\">\n <span className=\"font-medium\">Cubes involved:</span> {analysis.cubesInvolved.join(', ')}\n </div>\n )}\n </div>\n )\n}\n\nexport default QueryAnalysisPanel\n","/**\n * Smart Chart Defaulting System\n *\n * Provides intelligent chart type selection and configuration based on\n * the user's current metrics and breakdowns selection.\n */\n\nimport type { ChartType, ChartAxisConfig } from '../types'\nimport type { MetricItem, BreakdownItem } from '../components/AnalysisBuilder/types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Result of smart chart defaults calculation\n */\nexport interface SmartChartDefaults {\n /** The recommended chart type */\n chartType: ChartType\n /** The auto-configured chart axis settings */\n chartConfig: ChartAxisConfig\n}\n\n/**\n * Availability status for a chart type\n */\nexport interface ChartAvailability {\n /** Whether the chart type can be used with current selections */\n available: boolean\n /** Reason why the chart is unavailable (for tooltip) */\n reason?: string\n}\n\n/**\n * Map of chart type availability statuses\n */\nexport type ChartAvailabilityMap = Record<ChartType, ChartAvailability>\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if a breakdown is a time dimension\n */\nfunction isTimeDimension(breakdown: BreakdownItem): boolean {\n return breakdown.isTimeDimension\n}\n\n/**\n * Get the first time dimension from breakdowns, if any\n */\nfunction getFirstTimeDimension(breakdowns: BreakdownItem[]): BreakdownItem | undefined {\n return breakdowns.find(isTimeDimension)\n}\n\n/**\n * Get the first non-time dimension from breakdowns, if any\n */\nfunction getFirstDimension(breakdowns: BreakdownItem[]): BreakdownItem | undefined {\n return breakdowns.find((b) => !b.isTimeDimension)\n}\n\n/**\n * Get all non-time dimensions\n */\nfunction getDimensions(breakdowns: BreakdownItem[]): BreakdownItem[] {\n return breakdowns.filter((b) => !b.isTimeDimension)\n}\n\n/**\n * Get all time dimensions\n */\nfunction getTimeDimensions(breakdowns: BreakdownItem[]): BreakdownItem[] {\n return breakdowns.filter(isTimeDimension)\n}\n\n// ============================================================================\n// Chart Availability\n// ============================================================================\n\n/**\n * Check if a specific chart type is available given current selections\n */\nexport function getChartAvailability(\n chartType: ChartType,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAvailability {\n const measureCount = metrics.length\n const dimensionCount = getDimensions(breakdowns).length\n const timeDimensionCount = getTimeDimensions(breakdowns).length\n const totalBreakdowns = breakdowns.length\n\n switch (chartType) {\n // Always available charts\n case 'table':\n case 'markdown':\n return { available: true }\n\n // Measure-only charts (KPI Number, KPI Text)\n case 'kpiNumber':\n case 'kpiText':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n return { available: true }\n\n // Bar chart - needs dimension for categories + measure for values\n case 'bar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires at least 1 breakdown for categories' }\n }\n return { available: true }\n\n // KPI Delta - needs dimension for ordering + measure for values\n case 'kpiDelta':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires at least 1 breakdown for ordering' }\n }\n return { available: true }\n\n // Line and area charts - need dimension/time + measure\n case 'line':\n case 'area':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (totalBreakdowns < 1) {\n return { available: false, reason: 'Requires a breakdown (dimension or time)' }\n }\n return { available: true }\n\n // Pie chart - needs dimension (not time) + measure\n case 'pie':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires 1 dimension (not time dimension)' }\n }\n return { available: true }\n\n // Scatter - needs measure + any breakdown\n case 'scatter':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n // Scatter can work with just measures (x and y from different measures)\n // or with dimension + measure\n if (measureCount < 2 && totalBreakdowns < 1) {\n return { available: false, reason: 'Requires 2 measures or 1 measure + 1 breakdown' }\n }\n return { available: true }\n\n // Bubble - needs 2+ measures and 1+ dimension\n case 'bubble':\n if (measureCount < 2) {\n return { available: false, reason: 'Requires at least 2 measures' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Radar - needs dimension + measure\n case 'radar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Radial Bar - needs dimension + measure\n case 'radialBar':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Treemap - needs dimension + measure\n case 'treemap':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (dimensionCount < 1) {\n return { available: false, reason: 'Requires at least 1 dimension' }\n }\n return { available: true }\n\n // Activity Grid - needs time dimension + measure\n case 'activityGrid':\n if (measureCount < 1) {\n return { available: false, reason: 'Requires at least 1 measure' }\n }\n if (timeDimensionCount < 1) {\n return { available: false, reason: 'Requires a time dimension' }\n }\n return { available: true }\n\n default:\n // Unknown chart type - assume available\n return { available: true }\n }\n}\n\n/**\n * Get availability for all chart types\n */\nexport function getAllChartAvailability(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAvailabilityMap {\n // Chart types in alphabetical order (matching ChartTypeSelector display)\n const chartTypes: ChartType[] = [\n 'activityGrid',\n 'area',\n 'bar',\n 'bubble',\n 'kpiDelta',\n 'kpiNumber',\n 'kpiText',\n 'line',\n 'markdown',\n 'pie',\n 'radar',\n 'radialBar',\n 'scatter',\n 'table',\n 'treemap'\n ]\n\n const availability: Partial<ChartAvailabilityMap> = {}\n for (const chartType of chartTypes) {\n availability[chartType] = getChartAvailability(chartType, metrics, breakdowns)\n }\n\n return availability as ChartAvailabilityMap\n}\n\n// ============================================================================\n// Smart Chart Type Selection\n// ============================================================================\n\n/**\n * Select the best chart type based on current metrics and breakdowns\n *\n * Priority order:\n * 1. If current chart type is still valid, keep it (preserve user intent)\n * 2. If current chart becomes invalid, switch to best alternative:\n * - Has time dimension → line\n * - Has dimension + measure → bar\n * - Has measures only → bar (or kpiNumber if single measure + no breakdowns)\n * - No fields → keep current\n */\nexport function selectBestChartType(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType\n): ChartType {\n // Check if current chart type is still valid\n const currentAvailability = getChartAvailability(currentChartType, metrics, breakdowns)\n if (currentAvailability.available) {\n return currentChartType\n }\n\n // No fields selected - keep current\n if (metrics.length === 0 && breakdowns.length === 0) {\n return currentChartType\n }\n\n const hasTimeDimension = getTimeDimensions(breakdowns).length > 0\n const hasDimension = getDimensions(breakdowns).length > 0\n const hasMeasure = metrics.length > 0\n\n // Priority selection logic\n if (hasTimeDimension && hasMeasure) {\n // Time series data → line chart\n return 'line'\n }\n\n if (hasDimension && hasMeasure) {\n // Categorical data with measures → bar chart\n return 'bar'\n }\n\n if (hasMeasure && !hasDimension && !hasTimeDimension) {\n // Measures only, no breakdowns → KPI number (works with just measures)\n return 'kpiNumber'\n }\n\n // Fallback to table as most versatile (works with any combination)\n return 'table'\n}\n\n// ============================================================================\n// Smart Chart Config Defaults\n// ============================================================================\n\n/**\n * Get smart default chart configuration based on chart type and selections\n */\nexport function getSmartChartDefaults(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType\n): SmartChartDefaults {\n // First, determine the best chart type\n const chartType = selectBestChartType(metrics, breakdowns, currentChartType)\n\n // Then, auto-configure the chart axes based on chart type\n const chartConfig = buildChartConfig(chartType, metrics, breakdowns)\n\n return { chartType, chartConfig }\n}\n\n/**\n * Build optimal chart configuration for a given chart type\n */\nfunction buildChartConfig(\n chartType: ChartType,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAxisConfig {\n const timeDimension = getFirstTimeDimension(breakdowns)\n const dimension = getFirstDimension(breakdowns)\n const dimensions = getDimensions(breakdowns)\n const allBreakdowns = breakdowns\n\n switch (chartType) {\n case 'line':\n case 'area':\n // Line/Area: xAxis = first time dimension (prefer) or dimension\n // yAxis = all measures, series = optional second dimension\n return {\n xAxis: timeDimension\n ? [timeDimension.field]\n : dimension\n ? [dimension.field]\n : [],\n yAxis: metrics.map((m) => m.field),\n series:\n dimensions.length > 1\n ? [dimensions[1].field]\n : dimension && timeDimension\n ? [dimension.field]\n : []\n }\n\n case 'bar':\n // Bar: xAxis = first dimension (prefer non-time), yAxis = all measures\n return {\n xAxis: dimension\n ? [dimension.field]\n : timeDimension\n ? [timeDimension.field]\n : [],\n yAxis: metrics.map((m) => m.field),\n series:\n dimensions.length > 1\n ? [dimensions[1].field]\n : timeDimension && dimension\n ? [timeDimension.field]\n : []\n }\n\n case 'pie':\n // Pie: xAxis = first dimension (exactly 1), yAxis = first measure (exactly 1)\n return {\n xAxis: dimension ? [dimension.field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'scatter':\n // Scatter: xAxis = first dimension or measure, yAxis = first/second measure\n if (metrics.length >= 2) {\n return {\n xAxis: [metrics[0].field],\n yAxis: [metrics[1].field],\n series: dimension ? [dimension.field] : []\n }\n }\n return {\n xAxis: allBreakdowns.length > 0 ? [allBreakdowns[0].field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : [],\n series: dimensions.length > 1 ? [dimensions[1].field] : []\n }\n\n case 'bubble':\n // Bubble: xAxis = first measure, yAxis = second measure, sizeField = third measure (or second if only 2)\n // series = first dimension for grouping/coloring\n return {\n xAxis: metrics.length > 0 ? [metrics[0].field] : [],\n yAxis: metrics.length > 1 ? [metrics[1].field] : [],\n sizeField: metrics.length > 2 ? metrics[2].field : metrics.length > 1 ? metrics[1].field : undefined,\n series: dimension ? [dimension.field] : []\n }\n\n case 'radar':\n case 'radialBar':\n case 'treemap':\n // These all use dimension for categories and measure for values\n return {\n xAxis: dimension ? [dimension.field] : [],\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'activityGrid':\n // Activity Grid: dateField = time dimension, valueField = measure\n return {\n dateField: timeDimension ? [timeDimension.field] : [],\n valueField: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'kpiNumber':\n case 'kpiDelta':\n case 'kpiText':\n // KPI charts: just need the measure\n return {\n yAxis: metrics.length > 0 ? [metrics[0].field] : []\n }\n\n case 'table':\n // Table: include all fields\n return {\n xAxis: [\n ...breakdowns.map((b) => b.field),\n ...metrics.map((m) => m.field)\n ]\n }\n\n case 'markdown':\n // Markdown doesn't need chart config\n return {}\n\n default:\n // Default fallback - x = first breakdown, y = all measures\n return {\n xAxis: allBreakdowns.length > 0 ? [allBreakdowns[0].field] : [],\n yAxis: metrics.map((m) => m.field)\n }\n }\n}\n\n// ============================================================================\n// Update Logic for AnalysisBuilder\n// ============================================================================\n\n/**\n * Determine if chart type should be auto-switched based on selections change\n *\n * Returns the new chart type if a switch is recommended, or null if no change needed.\n *\n * @param metrics - Current metrics selection\n * @param breakdowns - Current breakdowns selection\n * @param currentChartType - Current chart type\n * @param userManuallySelected - Whether user manually selected the current chart type\n */\nexport function shouldAutoSwitchChartType(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n currentChartType: ChartType,\n userManuallySelected: boolean\n): ChartType | null {\n // If user manually selected this chart type, only switch if it becomes invalid\n if (userManuallySelected) {\n const availability = getChartAvailability(currentChartType, metrics, breakdowns)\n if (availability.available) {\n return null // Keep user's choice\n }\n }\n\n // Check if a better chart type should be used\n const recommendedType = selectBestChartType(metrics, breakdowns, currentChartType)\n\n // Only suggest switch if recommended type is different\n if (recommendedType !== currentChartType) {\n return recommendedType\n }\n\n return null\n}\n\n/**\n * Check if a chart config field references valid fields from metrics/breakdowns\n */\nfunction isValidConfigField(\n fieldValue: string | string[] | undefined,\n validFields: Set<string>\n): boolean {\n if (!fieldValue) return false\n if (Array.isArray(fieldValue)) {\n return fieldValue.length > 0 && fieldValue.every((f) => validFields.has(f))\n }\n return validFields.has(fieldValue)\n}\n\n/**\n * Merge existing chart config with smart defaults\n * Only fills in missing or invalid fields, preserves valid existing config\n */\nexport function mergeChartConfigWithDefaults(\n existingConfig: ChartAxisConfig,\n smartDefaults: ChartAxisConfig,\n metrics: MetricItem[],\n breakdowns: BreakdownItem[]\n): ChartAxisConfig {\n // Build set of valid field names\n const validFields = new Set<string>([\n ...metrics.map((m) => m.field),\n ...breakdowns.map((b) => b.field)\n ])\n\n const result: ChartAxisConfig = {}\n\n // For each key in smart defaults, use existing value if valid, otherwise use default\n const allKeys = new Set([\n ...Object.keys(existingConfig),\n ...Object.keys(smartDefaults)\n ]) as Set<keyof ChartAxisConfig>\n\n for (const key of allKeys) {\n const existingValue = existingConfig[key]\n const defaultValue = smartDefaults[key]\n\n // Check if existing value is valid\n if (isValidConfigField(existingValue as string | string[] | undefined, validFields)) {\n // Keep existing valid config\n result[key] = existingValue as any\n } else if (defaultValue !== undefined) {\n // Use smart default\n result[key] = defaultValue as any\n }\n // If neither exists or is valid, leave undefined\n }\n\n return result\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 { useState, useEffect } from 'react'\nimport type { AnalysisResultsPanelProps } from './types'\nimport { LazyChart, isValidChartType } from '../../charts/ChartLoader'\nimport { getIcon } from '../../icons'\nimport { QueryAnalysisPanel } from '../../shared'\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 */\nexport default function AnalysisResultsPanel({\n executionStatus,\n executionResults,\n executionError,\n totalRowCount,\n resultsStale = false,\n chartType = 'line',\n chartConfig = {},\n displayConfig = {},\n query,\n activeView = 'chart',\n onActiveViewChange,\n displayLimit = 100,\n onDisplayLimitChange,\n hasMetrics = false,\n // Debug props\n debugQuery,\n debugSql,\n debugAnalysis,\n debugLoading,\n debugError\n}: AnalysisResultsPanelProps) {\n // Debug view toggle state\n const [showDebug, setShowDebug] = useState(false)\n // Force table view when no metrics are selected\n useEffect(() => {\n if (!hasMetrics && activeView === 'chart') {\n onActiveViewChange('table')\n }\n }, [hasMetrics, activeView, onActiveViewChange])\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 TimeIcon = getIcon('timeDimension')\n const CodeIcon = getIcon('codeBracket')\n\n // Loading state - initial load\n const renderLoading = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Executing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Running your query against the cube API\n </div>\n </div>\n </div>\n )\n\n // Error state - no previous results\n const renderError = () => (\n <div className=\"h-full flex items-center justify-center p-4\">\n <div className=\"text-center max-w-md\">\n <ErrorIcon className=\"w-12 h-12 mx-auto text-red-500 mb-4\" />\n <div className=\"text-sm font-semibold text-dc-text mb-2\">\n Query Execution Failed\n </div>\n <div className=\"text-sm text-dc-text-secondary mb-4\">\n There was an error executing your query. Please check the query and try again.\n </div>\n {executionError && (\n <div className=\"bg-red-50 border border-red-200 rounded-lg p-3 text-left\">\n <div className=\"text-xs font-mono text-red-800 break-words\">\n {executionError}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n\n // Check if query has any content (pending execution)\n const hasQueryContent = !!(\n (query.measures && query.measures.length > 0) ||\n (query.dimensions && query.dimensions.length > 0) ||\n (query.timeDimensions && query.timeDimensions.length > 0)\n )\n\n // Waiting state - query built but not yet executed (debounce period)\n const renderWaiting = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-12 w-12 border-b-2 mx-auto mb-4\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n Preparing Query...\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Your query will execute shortly\n </div>\n </div>\n </div>\n )\n\n // Empty state - no query built yet\n const renderEmpty = () => (\n <div className=\"h-full flex items-center justify-center pt-6\">\n <div className=\"text-center mb-16\">\n <TimeIcon className=\"w-12 h-12 mx-auto text-dc-text-muted mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text-secondary mb-1\">\n No Results Yet\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n Add metrics or breakdowns from the panel on the right to see results\n </div>\n </div>\n </div>\n )\n\n // No data returned state\n const renderNoData = () => (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center\">\n <SuccessIcon className=\"w-12 h-12 mx-auto text-green-500 mb-3\" />\n <div className=\"text-sm font-semibold text-dc-text mb-1\">\n Query Successful\n </div>\n <div className=\"text-xs text-dc-text-muted\">\n No data returned from the query\n </div>\n </div>\n </div>\n )\n\n // Render chart\n const renderChart = () => {\n if (!executionResults || executionResults.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <ChartIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see chart visualization</div>\n </div>\n </div>\n )\n }\n\n if (!isValidChartType(chartType)) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <WarningIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">Unsupported chart type</div>\n <div className=\"text-xs\">{chartType}</div>\n </div>\n </div>\n )\n }\n\n return (\n <LazyChart\n chartType={chartType}\n data={executionResults}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n queryObject={query}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Render debug view\n const renderDebug = () => (\n <div className=\"p-4 space-y-4 overflow-auto h-full\">\n {/* Execution Error Banner (if any) */}\n {executionError && (\n <div className=\"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded p-3\">\n <h4 className=\"text-sm font-semibold text-red-700 dark:text-red-400 mb-1\">\n Execution Error\n </h4>\n <p className=\"text-sm text-red-600 dark:text-red-300\">{executionError}</p>\n </div>\n )}\n\n {/* JSON Query and SQL Query in 2 columns */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {/* JSON Query */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">JSON Query</h4>\n <pre className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-xs overflow-auto max-h-64 text-dc-text-secondary\">\n {debugQuery ? JSON.stringify(debugQuery, null, 2) : 'No query'}\n </pre>\n </div>\n\n {/* Generated SQL */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Generated SQL</h4>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n Loading...\n </div>\n ) : debugError ? (\n <div className=\"text-red-500 text-sm bg-red-50 dark:bg-red-900/20 p-3 rounded border border-red-200 dark:border-red-800\">\n {debugError}\n </div>\n ) : debugSql ? (\n <pre className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-xs overflow-auto max-h-64 text-dc-text-secondary font-mono whitespace-pre-wrap\">\n {debugSql.sql}\n {debugSql.params && debugSql.params.length > 0 && (\n <>\n {'\\n\\n-- Parameters:\\n'}\n {JSON.stringify(debugSql.params, null, 2)}\n </>\n )}\n </pre>\n ) : (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n Add metrics to generate SQL\n </div>\n )}\n </div>\n </div>\n\n {/* Query Analysis - full width */}\n <div>\n <h4 className=\"text-sm font-semibold text-dc-text mb-2\">Query Analysis</h4>\n {debugLoading ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n Loading...\n </div>\n ) : debugAnalysis ? (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3\">\n <QueryAnalysisPanel analysis={debugAnalysis} />\n </div>\n ) : (\n <div className=\"bg-dc-surface-secondary border border-dc-border rounded p-3 text-dc-text-muted text-sm\">\n {debugError ? 'Analysis unavailable due to error' : 'Add metrics to see analysis'}\n </div>\n )}\n </div>\n </div>\n )\n\n // Render table\n const renderTable = () => {\n if (!executionResults || executionResults.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full text-dc-text-muted\">\n <div className=\"text-center\">\n <TableIcon className=\"w-12 h-12 mx-auto mb-3 opacity-50\" />\n <div className=\"text-sm font-semibold mb-1\">No data to display</div>\n <div className=\"text-xs\">Run a query to see table data</div>\n </div>\n </div>\n )\n }\n\n // Apply display limit\n const limitedData = executionResults.slice(0, displayLimit)\n\n return (\n <LazyChart\n chartType=\"table\"\n data={limitedData}\n queryObject={query}\n height=\"100%\"\n fallback={\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"animate-pulse bg-dc-surface-secondary rounded w-full h-full\" />\n </div>\n }\n />\n )\n }\n\n // Overlay spinner for refreshing\n const renderOverlaySpinner = () => (\n <div className=\"absolute inset-0 flex items-center justify-center bg-dc-surface bg-opacity-75 z-10\">\n <div className=\"text-center\">\n <div\n className=\"animate-spin rounded-full h-10 w-10 border-b-2 mx-auto mb-2\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n <div className=\"text-xs text-dc-text-secondary\">Refreshing results...</div>\n </div>\n </div>\n )\n\n // Success state with data\n const renderSuccess = () => {\n if (!executionResults || executionResults.length === 0) {\n return renderNoData()\n }\n\n return (\n <div className=\"h-full flex flex-col\">\n {/* Results Header - Compact status bar */}\n <div className=\"px-4 py-2 border-b border-dc-border bg-dc-surface-secondary flex-shrink-0\">\n <div className=\"flex items-center justify-between\">\n {/* Left side: Status and row count */}\n <div className=\"flex items-center\">\n {executionStatus === 'refreshing' ? (\n <div\n className=\"w-4 h-4 mr-2 rounded-full border-b-2 animate-spin\"\n style={{ borderBottomColor: 'var(--dc-primary)' }}\n />\n ) : (\n <SuccessIcon className=\"w-4 h-4 text-green-500 mr-2\" />\n )}\n <span className=\"text-sm text-dc-text-secondary\">\n {executionResults.length} row{executionResults.length !== 1 ? 's' : ''}\n {totalRowCount !== null && totalRowCount > executionResults.length && (\n <span className=\"text-dc-text-muted\"> of {totalRowCount.toLocaleString()}</span>\n )}\n {resultsStale && (\n <span className=\"text-dc-warning ml-2\">• Results may be outdated</span>\n )}\n </span>\n </div>\n\n {/* Right side: Display limit (table only) and Debug toggle */}\n <div className=\"flex items-center gap-2\">\n {/* Display Limit (only for table view) */}\n {activeView === 'table' && !showDebug && onDisplayLimitChange && (\n <select\n value={displayLimit}\n onChange={(e) => onDisplayLimitChange(Number(e.target.value))}\n className=\"text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary\"\n >\n <option value={50}>50 rows</option>\n <option value={100}>100 rows</option>\n <option value={250}>250 rows</option>\n <option value={500}>500 rows</option>\n </select>\n )}\n\n {/* Debug Toggle Button */}\n <button\n onClick={() => setShowDebug(!showDebug)}\n className={`p-1.5 rounded transition-colors relative ${\n showDebug\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:text-dc-text hover:bg-dc-surface-hover'\n }`}\n title={showDebug ? 'Hide debug info' : 'Show debug info'}\n >\n <CodeIcon className=\"w-4 h-4\" />\n {/* Error indicator dot */}\n {(executionError || debugError) && !showDebug && (\n <span className=\"absolute -top-0.5 -right-0.5 w-2 h-2 bg-red-500 rounded-full\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Performance Warning */}\n {totalRowCount !== null && totalRowCount > 1000 && (\n <div className=\"mt-2 bg-yellow-50 border border-yellow-200 rounded-lg p-2 flex items-start\">\n <WarningIcon className=\"w-4 h-4 text-yellow-600 mr-2 shrink-0 mt-0.5\" />\n <div className=\"text-xs text-yellow-800\">\n <span className=\"font-semibold\">Large dataset:</span> {totalRowCount.toLocaleString()} rows.\n Consider adding filters to improve performance.\n </div>\n </div>\n )}\n </div>\n\n {/* Results Content */}\n <div className=\"flex-1 min-h-0 relative overflow-auto\">\n {showDebug ? (\n renderDebug()\n ) : activeView === 'chart' ? (\n <div className=\"p-4 h-full\">{renderChart()}</div>\n ) : (\n <div className=\"h-full\">{renderTable()}</div>\n )}\n </div>\n\n {/* View Toggle - Below content, centered */}\n {!showDebug && (\n <div className=\"px-4 py-3 border-t border-dc-border bg-dc-surface flex justify-center flex-shrink-0\">\n <div className=\"flex items-center bg-dc-surface-secondary border border-dc-border rounded-md overflow-hidden\">\n <button\n onClick={() => hasMetrics && onActiveViewChange('chart')}\n disabled={!hasMetrics}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'chart'\n ? 'bg-dc-primary text-white'\n : !hasMetrics\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title={hasMetrics ? 'Chart view' : 'Add metrics to enable chart view'}\n >\n <ChartIcon className=\"w-4 h-4\" />\n Chart\n </button>\n <button\n onClick={() => onActiveViewChange('table')}\n className={`flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium transition-colors ${\n activeView === 'table'\n ? 'bg-dc-primary text-white'\n : 'text-dc-text-secondary hover:bg-dc-surface-hover'\n }`}\n title=\"Table view\"\n >\n <TableIcon className=\"w-4 h-4\" />\n Table\n </button>\n </div>\n </div>\n )}\n </div>\n )\n }\n\n // Determine what to render based on execution status\n const hasResults = executionResults !== null\n\n return (\n <div className=\"h-full min-h-[400px] flex flex-col bg-dc-surface rounded-lg border border-dc-border relative\">\n {/* Main content */}\n {executionStatus === 'idle' && !hasQueryContent && renderEmpty()}\n {executionStatus === 'idle' && hasQueryContent && !hasResults && renderWaiting()}\n {executionStatus === 'loading' && !hasResults && renderLoading()}\n {executionStatus === 'error' && !hasResults && renderError()}\n {(executionStatus === 'success' || hasResults) && renderSuccess()}\n\n {/* Overlay states */}\n {(executionStatus === 'loading' || executionStatus === 'refreshing') && hasResults && renderOverlaySpinner()}\n </div>\n )\n}\n","/**\n * MetricItemCard Component\n *\n * Displays a single metric item with remove button.\n */\n\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 */\nexport default function MetricItemCard({\n metric,\n fieldMeta,\n onRemove,\n sortDirection,\n sortPriority,\n onToggleSort\n}: MetricItemCardProps) {\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get the appropriate icon based on measure type\n const measureType = fieldMeta?.type || 'count'\n const MeasureIcon = getMeasureTypeIcon(measureType) || getIcon('measure')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || metric.field.split('.').pop() || metric.field\n\n // Get the cube name from the field\n const cubeName = metric.field.split('.')[0]\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n return (\n <div className=\"flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-colors\">\n {/* Icon - colored background matching field selector */}\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex-shrink-0\">\n {MeasureIcon && <MeasureIcon className=\"w-4 h-4\" />}\n </span>\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={metric.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-0 group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove metric\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n}\n","/**\n * MetricsSection Component\n *\n * Displays the Metrics section in the query panel with expandable list of metrics.\n */\n\nimport { useMemo } from 'react'\nimport type { MetricsSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport MetricItemCard from './MetricItemCard'\nimport { getIcon } from '../../icons'\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 * - Empty state with add button\n */\nexport default function MetricsSection({\n metrics,\n schema,\n onAdd,\n onRemove,\n order,\n onOrderChange\n}: MetricsSectionProps) {\n const AddIcon = getIcon('add')\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) => {\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 }\n })\n }, [metrics, schema, order, orderKeys])\n\n return (\n <div>\n {/* Section Header */}\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-sm font-semibold text-dc-text\">Metrics</h3>\n <button\n onClick={onAdd}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-secondary rounded transition-colors\"\n title=\"Add metric\"\n >\n <AddIcon className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Metrics List or Empty State */}\n {metrics.length === 0 ? (\n <button\n onClick={onAdd}\n className=\"w-full p-3 border-2 border-dashed border-dc-border rounded-lg text-dc-text-muted hover:border-dc-primary hover:text-dc-primary transition-colors\"\n >\n + Add Metric\n </button>\n ) : (\n <div className=\"space-y-2\">\n {metricsWithMeta.map(({ metric, fieldMeta, sortDirection, sortPriority }) => (\n <MetricItemCard\n key={metric.id}\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 />\n ))}\n\n {/* Add Another Button */}\n <button\n onClick={onAdd}\n className=\"w-full p-2 text-sm text-dc-text-muted hover:text-dc-primary transition-colors\"\n >\n + Add Metric\n </button>\n </div>\n )}\n </div>\n )\n}\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 React from 'react'\nimport type {\n CubeQuery,\n Filter,\n ChartType,\n ChartAxisConfig,\n ChartDisplayConfig\n} from '../../types'\nimport type { MetaResponse, MetaField, MetaCube, QueryAnalysis } from '../../shared/types'\nimport type { ChartAvailabilityMap } from '../../shared/chartDefaults'\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}\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 */\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\n // Validation state\n validationStatus: ValidationStatus\n validationError: string | null\n\n // Execution state\n executionStatus: ExecutionStatus\n executionResults: any[] | null\n executionError: string | null\n totalRowCount: number | null\n\n // Stale indicator (query changed since last execution)\n resultsStale: boolean\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 */\nexport type FieldSearchMode = 'metrics' | 'breakdown' | 'filter'\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: React.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'\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\n // Breakdown actions\n onAddBreakdown: () => void\n onRemoveBreakdown: (id: string) => void\n onBreakdownGranularityChange: (id: string, granularity: string) => void\n\n // Filter actions\n onFiltersChange: (filters: Filter[]) => 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 /** 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\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\n /** Current query object (for annotation/metadata) */\n query: 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)\n debugQuery?: CubeQuery | null\n debugSql?: { sql: string; params: any[] } | null\n debugAnalysis?: QueryAnalysis | null\n debugLoading?: boolean\n debugError?: string | null\n}\n\n// ============================================================================\n// Section Component Props\n// ============================================================================\n\n/**\n * Props for the MetricsSection component\n */\nexport interface MetricsSectionProps {\n /** Selected metrics */\n metrics: MetricItem[]\n /** Schema for resolving field titles */\n schema: MetaResponse | null\n /** Add metric handler */\n onAdd: () => void\n /** Remove metric handler */\n onRemove: (id: string) => void\n /** Whether the section is expanded */\n isExpanded?: boolean\n /** Toggle expansion */\n onToggleExpanded?: () => void\n /** Current sort order */\n order?: Record<string, 'asc' | 'desc'>\n /** Callback when sort order changes */\n onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void\n}\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 /** 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}\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}\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 /** 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}\n\n// ============================================================================\n// Main Component Props\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 /** Initial query to load */\n initialQuery?: CubeQuery\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 * Ref interface for AnalysisBuilder (for external access)\n */\nexport interface AnalysisBuilderRef {\n /** Get the current query object */\n getCurrentQuery: () => CubeQuery\n /** Get current chart configuration */\n getChartConfig: () => { chartType: ChartType; chartConfig: ChartAxisConfig; displayConfig: ChartDisplayConfig }\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 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\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 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 */\nexport default function BreakdownItemCard({\n breakdown,\n fieldMeta,\n onRemove,\n onGranularityChange,\n sortDirection,\n sortPriority,\n onToggleSort\n}: BreakdownItemCardProps) {\n const DimensionIcon = getIcon('dimension')\n const TimeIcon = getIcon('timeDimension')\n const CloseIcon = getIcon('close')\n const ChevronUpIcon = getIcon('chevronUp')\n const ChevronDownIcon = getIcon('chevronDown')\n const ChevronUpDownIcon = getIcon('chevronUpDown')\n\n // Get display title - prefer shortTitle, then title, then field name\n const displayTitle = fieldMeta?.shortTitle || fieldMeta?.title || breakdown.field.split('.').pop() || breakdown.field\n\n // Get the cube name from the field\n const cubeName = breakdown.field.split('.')[0]\n\n // Choose icon based on dimension type\n const Icon = breakdown.isTimeDimension ? TimeIcon : DimensionIcon\n\n // Get sort icon based on direction\n const getSortIcon = () => {\n switch (sortDirection) {\n case 'asc':\n return ChevronUpIcon ? <ChevronUpIcon className=\"w-4 h-4\" /> : '↑'\n case 'desc':\n return ChevronDownIcon ? <ChevronDownIcon className=\"w-4 h-4\" /> : '↓'\n default:\n return ChevronUpDownIcon ? <ChevronUpDownIcon className=\"w-4 h-4\" /> : '⇅'\n }\n }\n\n // Get sort tooltip\n const getSortTooltip = () => {\n switch (sortDirection) {\n case 'asc':\n return 'Sorted ascending (click for descending)'\n case 'desc':\n return 'Sorted descending (click to remove)'\n default:\n return 'Click to sort ascending'\n }\n }\n\n return (\n <div className=\"flex items-center gap-2 p-2 bg-dc-surface-secondary rounded-lg group hover:bg-dc-surface-tertiary transition-colors\">\n {/* Icon */}\n <Icon className=\"w-4 h-4 text-dc-text-secondary flex-shrink-0\" />\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={breakdown.field}>\n {displayTitle}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">\n {cubeName}\n </div>\n </div>\n\n {/* Granularity Selector (for time dimensions) */}\n {breakdown.isTimeDimension && onGranularityChange && (\n <select\n value={breakdown.granularity || 'day'}\n onChange={(e) => onGranularityChange(e.target.value as TimeGranularity)}\n onClick={(e) => e.stopPropagation()}\n className=\"text-xs bg-dc-surface border border-dc-border rounded px-2 py-1 text-dc-text focus:outline-none focus:ring-1 focus:ring-dc-primary flex-shrink-0\"\n >\n {TIME_GRANULARITIES.map((g) => (\n <option key={g.value} value={g.value}>\n {g.label}\n </option>\n ))}\n </select>\n )}\n\n {/* Sort Button */}\n {onToggleSort && (\n <button\n onClick={onToggleSort}\n className={`p-1 transition-opacity flex-shrink-0 flex items-center gap-0.5 ${\n sortDirection\n ? 'opacity-100 text-dc-primary'\n : 'opacity-0 group-hover:opacity-100 text-dc-text-muted hover:text-dc-primary'\n }`}\n title={getSortTooltip()}\n >\n {getSortIcon()}\n {sortDirection && sortPriority && (\n <span className=\"text-xs font-medium\">({sortPriority})</span>\n )}\n </button>\n )}\n\n {/* Remove Button */}\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title=\"Remove breakdown\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n )\n}\n","/**\n * BreakdownSection Component\n *\n * Displays the Breakdown section in the query panel with expandable list of breakdowns.\n */\n\nimport { useMemo } from 'react'\nimport type { BreakdownSectionProps } from './types'\nimport type { MetaField } from '../../shared/types'\nimport BreakdownItemCard from './BreakdownItemCard'\nimport { getIcon } from '../../icons'\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 * - Empty state with add button\n */\nexport default function BreakdownSection({\n breakdowns,\n schema,\n onAdd,\n onRemove,\n onGranularityChange,\n order,\n onOrderChange\n}: BreakdownSectionProps) {\n const AddIcon = getIcon('add')\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 breakdowns with sort info\n const breakdownsWithMeta = useMemo(() => {\n return breakdowns.map((breakdown) => {\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 }\n })\n }, [breakdowns, schema, order, orderKeys])\n\n return (\n <div>\n {/* Section Header */}\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-sm font-semibold text-dc-text\">Breakdown</h3>\n <button\n onClick={onAdd}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-secondary rounded transition-colors\"\n title=\"Add breakdown\"\n >\n <AddIcon className=\"w-5 h-5\" />\n </button>\n </div>\n\n {/* Breakdowns List or Empty State */}\n {breakdowns.length === 0 ? (\n <button\n onClick={onAdd}\n className=\"w-full p-3 border-2 border-dashed border-dc-border rounded-lg text-dc-text-muted hover:border-dc-primary hover:text-dc-primary transition-colors\"\n >\n + Add Breakdown\n </button>\n ) : (\n <div className=\"space-y-2\">\n {breakdownsWithMeta.map(({ breakdown, fieldMeta, sortDirection, sortPriority }) => (\n <BreakdownItemCard\n key={breakdown.id}\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 sortDirection={sortDirection}\n sortPriority={sortPriority}\n onToggleSort={onOrderChange ? () => {\n const nextDirection = getNextSortDirection(sortDirection)\n onOrderChange(breakdown.field, nextDirection)\n } : undefined}\n />\n ))}\n\n {/* Add Another Button */}\n <button\n onClick={onAdd}\n className=\"w-full p-2 text-sm text-dc-text-muted hover:text-dc-primary transition-colors\"\n >\n + Add Breakdown\n </button>\n </div>\n )}\n </div>\n )\n}\n","/**\n * AnalysisFilterItem Component\n *\n * Compact filter item for the AnalysisBuilder's narrow column layout.\n * Features:\n * - Display name for field (not just shortName)\n * - Operator + value on same row\n * - API-fetched combo box with search for dimension values\n * - Multi-value support with tags for in/notIn operators\n * - Date range selector with predefined options\n */\n\nimport { useState, useRef, useEffect, useCallback, useMemo } 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 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 /** Optional depth for nested styling */\n depth?: number\n}\n\nexport default function AnalysisFilterItem({\n filter,\n schema,\n onRemove,\n onUpdate,\n depth = 0\n}: AnalysisFilterItemProps) {\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 containerRef = 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]\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 = useMemo(() => {\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 // 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 }, [isValueDropdownOpen, shouldShowComboBox, searchValues])\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\n const flexMatch = filter.dateRange.match(/^last (\\d+) (days|weeks|months|quarters|years)$/)\n if (flexMatch) {\n const [, num, unit] = flexMatch\n setRangeType(`last_n_${unit}` as DateRangeType)\n setNumberValue(parseInt(num) || 1)\n } else {\n // Check predefined ranges\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 const newFilter: SimpleFilter = {\n member: filter.member,\n operator,\n values: []\n }\n onUpdate(newFilter)\n setIsOperatorDropdownOpen(false)\n }, [filter.member, onUpdate])\n\n // Handle value selection from combo box\n const handleValueSelect = useCallback((value: unknown) => {\n const values = filter.values || []\n if (operatorMeta?.supportsMultipleValues) {\n if (!values.includes(value)) {\n onUpdate({ ...filter, values: [...values, value] })\n }\n } else {\n onUpdate({ ...filter, values: [value] })\n setIsValueDropdownOpen(false)\n }\n setSearchText('')\n }, [filter, operatorMeta?.supportsMultipleValues, onUpdate])\n\n // Handle value removal\n const handleValueRemove = useCallback((valueToRemove: unknown) => {\n const values = (filter.values || []).filter(v => v !== valueToRemove)\n onUpdate({ ...filter, values })\n }, [filter, onUpdate])\n\n // Handle direct text/number input\n const handleDirectInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n if (operatorMeta?.valueType === 'number') {\n const numValue = parseFloat(value)\n if (!isNaN(numValue)) {\n onUpdate({ ...filter, values: [numValue] })\n } else if (value === '' || value === '-') {\n onUpdate({ ...filter, values: [] })\n }\n } else {\n onUpdate({ ...filter, values: value ? [value] : [] })\n }\n }, [filter, operatorMeta?.valueType, onUpdate])\n\n // Handle between range inputs\n const handleBetweenStartInput = useCallback((e: React.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 onUpdate({ ...filter, values: newValues })\n }, [filter, onUpdate])\n\n const handleBetweenEndInput = useCallback((e: React.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 onUpdate({ ...filter, values: newValues })\n }, [filter, onUpdate])\n\n // Handle date input\n const handleDateInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n onUpdate({ ...filter, values: value ? [value] : [] })\n }, [filter, onUpdate])\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 onUpdate({ ...filter, dateRange } as SimpleFilter)\n }, [filter, numberValue, onUpdate])\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 onUpdate({ ...filter, dateRange } as SimpleFilter)\n }\n }, [filter, rangeType, onUpdate])\n\n // Handle custom date range inputs\n const handleCustomStartDate = useCallback((e: React.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 onUpdate({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter, onUpdate])\n\n const handleCustomEndDate = useCallback((e: React.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 onUpdate({ ...filter, dateRange: [start, end] } as SimpleFilter)\n }, [filter, onUpdate])\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 const iconColor = isTimeField ? 'text-blue-500' : isMeasureField ? 'text-amber-500' : 'text-green-500'\n\n // Render value input based on operator type\n const renderValueInput = () => {\n // No value required for set/notSet\n if (!operatorMeta?.requiresValues) {\n return (\n <div className=\"text-xs text-dc-text-muted italic py-1\">\n No value required\n </div>\n )\n }\n\n // Date range selector for inDateRange on time fields\n if (shouldShowDateRange) {\n return (\n <div className=\"space-y-1.5\">\n {/* Range type dropdown */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(!isDateRangeDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{dateRangeLabel}</span>\n <ChevronDownIcon className={`w-3 h-3 text-dc-text-muted shrink-0 ml-1 transition-transform ${\n isDateRangeDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isDateRangeDropdownOpen && (\n <div className=\"absolute z-30 left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-40 overflow-y-auto\">\n {DATE_RANGE_OPTIONS.map((option) => (\n <button\n key={option.value}\n onClick={() => handleRangeTypeChange(option.value)}\n className={`w-full text-left px-2 py-1.5 text-xs hover:bg-dc-surface-hover ${\n option.value === rangeType ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {option.label}\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Number input for \"last N\" ranges */}\n {requiresNumberInput(rangeType) && (\n <div className=\"flex items-center gap-1.5\">\n <input\n type=\"number\"\n min=\"1\"\n max=\"1000\"\n value={numberValue}\n onChange={(e) => handleNumberValueChange(Math.max(1, parseInt(e.target.value) || 1))}\n className=\"flex-1 text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text w-16\"\n />\n <span className=\"text-xs text-dc-text-muted\">\n {rangeType.replace('last_n_', '')}\n </span>\n </div>\n )}\n\n {/* Custom date inputs */}\n {rangeType === 'custom' && (\n <div className=\"flex items-center gap-1.5\">\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[0] : ''}\n onChange={handleCustomStartDate}\n className=\"flex-1 text-xs border border-dc-border rounded px-1.5 py-1 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-xs text-dc-text-muted\">to</span>\n <input\n type=\"date\"\n value={Array.isArray(filter.dateRange) ? filter.dateRange[1] : ''}\n onChange={handleCustomEndDate}\n className=\"flex-1 text-xs border border-dc-border rounded px-1.5 py-1 bg-dc-surface text-dc-text\"\n />\n </div>\n )}\n </div>\n )\n }\n\n // Between/notBetween range inputs\n if (filter.operator === 'between' || filter.operator === 'notBetween') {\n return (\n <div className=\"flex items-center gap-1.5\">\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleBetweenStartInput}\n placeholder=\"Min\"\n className=\"flex-1 text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text\"\n />\n <span className=\"text-xs text-dc-text-muted\">to</span>\n <input\n type=\"number\"\n value={filter.values?.[1] ?? ''}\n onChange={handleBetweenEndInput}\n placeholder=\"Max\"\n className=\"flex-1 text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text\"\n />\n </div>\n )\n }\n\n // Date picker for date operators\n if (operatorMeta?.valueType === 'date') {\n return (\n <input\n type=\"date\"\n value={filter.values?.[0] || ''}\n onChange={handleDateInput}\n className=\"w-full text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Number input\n if (operatorMeta?.valueType === 'number') {\n return (\n <input\n type=\"number\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter number\"\n className=\"w-full text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text\"\n />\n )\n }\n\n // Combo box for equals/notEquals/in/notIn on dimensions\n if (shouldShowComboBox) {\n return (\n <div className=\"space-y-1.5\">\n {/* Selected values as tags */}\n {filter.values && filter.values.length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {filter.values.map((value, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-0.5 bg-dc-primary/10 text-dc-primary text-xs px-1.5 py-0.5 rounded\"\n >\n <span className=\"max-w-[100px] truncate\">{String(value)}</span>\n <button\n onClick={() => handleValueRemove(value)}\n className=\"hover:text-red-600\"\n >\n <CloseIcon className=\"w-3 h-3\" />\n </button>\n </span>\n ))}\n </div>\n )}\n\n {/* Dropdown trigger */}\n <div className=\"relative\">\n <button\n onClick={() => {\n setIsOperatorDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsValueDropdownOpen(!isValueDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"text-dc-text-muted truncate\">\n {valuesLoading ? 'Loading...' : 'Select value...'}\n </span>\n <ChevronDownIcon className={`w-3 h-3 text-dc-text-muted shrink-0 ml-1 transition-transform ${\n isValueDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isValueDropdownOpen && (\n <div className=\"absolute z-30 left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-48 overflow-hidden\">\n {/* Search input */}\n <div className=\"p-1.5 border-b border-dc-border\">\n <input\n type=\"text\"\n value={searchText}\n onChange={(e) => setSearchText(e.target.value)}\n placeholder=\"Search...\"\n className=\"w-full text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text\"\n autoFocus\n />\n </div>\n\n {/* Values list */}\n <div className=\"max-h-36 overflow-y-auto\">\n {valuesLoading ? (\n <div className=\"px-2 py-2 text-xs text-dc-text-muted\">Loading...</div>\n ) : valuesError ? (\n <div className=\"px-2 py-2 text-xs text-red-600\">Error: {valuesError}</div>\n ) : distinctValues.length === 0 ? (\n <div className=\"px-2 py-2 text-xs text-dc-text-muted\">No values found</div>\n ) : (\n distinctValues.map((value, index) => {\n const isSelected = filter.values?.includes(value)\n return (\n <button\n key={`${value}-${index}`}\n onClick={() => handleValueSelect(value)}\n className={`w-full text-left px-2 py-1.5 text-xs hover:bg-dc-surface-hover ${\n isSelected ? 'bg-dc-primary/10 text-dc-primary' : 'text-dc-text'\n }`}\n >\n {String(value)}\n {isSelected && <span className=\"float-right\">✓</span>}\n </button>\n )\n })\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n }\n\n // Default: text input\n return (\n <input\n type=\"text\"\n value={filter.values?.[0] ?? ''}\n onChange={handleDirectInput}\n placeholder=\"Enter value...\"\n className=\"w-full text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text placeholder-dc-text-muted\"\n />\n )\n }\n\n return (\n <div\n ref={containerRef}\n className={`bg-dc-surface border border-dc-border rounded-lg p-2 ${depth > 0 ? 'ml-3' : ''}`}\n >\n {/* Header: Field name and remove button */}\n <div className=\"flex items-center justify-between mb-1.5\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n <FieldIcon className={`w-3.5 h-3.5 ${iconColor} shrink-0`} />\n <span className=\"text-xs font-medium text-dc-text truncate\" title={filter.member}>\n {fieldTitle}\n </span>\n </div>\n <button\n onClick={onRemove}\n className=\"text-dc-text-muted hover:text-red-600 transition-colors shrink-0 p-0.5\"\n title=\"Remove filter\"\n >\n <CloseIcon className=\"w-3.5 h-3.5\" />\n </button>\n </div>\n\n {/* Operator selector */}\n <div className=\"relative mb-1.5\">\n <button\n onClick={() => {\n setIsValueDropdownOpen(false)\n setIsDateRangeDropdownOpen(false)\n setIsOperatorDropdownOpen(!isOperatorDropdownOpen)\n }}\n className=\"w-full flex items-center justify-between text-left text-xs border border-dc-border rounded px-2 py-1 bg-dc-surface text-dc-text hover:bg-dc-surface-hover\"\n >\n <span className=\"truncate\">{operatorLabel}</span>\n <ChevronDownIcon className={`w-3 h-3 text-dc-text-muted shrink-0 ml-1 transition-transform ${\n isOperatorDropdownOpen ? 'rotate-180' : ''\n }`} />\n </button>\n\n {isOperatorDropdownOpen && (\n <div className=\"absolute z-30 left-0 right-0 mt-1 bg-dc-surface border border-dc-border rounded shadow-lg max-h-40 overflow-y-auto\">\n {availableOperators.map((op) => (\n <button\n key={op.operator}\n onClick={() => handleOperatorChange(op.operator as FilterOperator)}\n className={`w-full text-left px-2 py-1.5 text-xs 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\n {/* Value input */}\n {renderValueInput()}\n </div>\n )\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-slate-300 dark:border-slate-600'\n }\n\n // Get background color based on group type\n const getGroupBgColor = () => {\n return group.type === 'and' ? 'bg-blue-50/50 dark:bg-blue-900/10' : 'bg-amber-50/50 dark:bg-amber-900/10'\n }\n\n const conditionCount = group.filters.length\n const conditionLabel = conditionCount === 1 ? 'condition' : 'conditions'\n\n return (\n <div className={`border ${getBorderColor()} rounded-lg ${getGroupBgColor()} ${depth > 0 ? 'ml-3' : ''}`}>\n {/* Group Header */}\n <div className=\"flex items-center justify-between px-2 py-1.5 border-b border-dc-border/50\">\n <div className=\"flex items-center gap-2\">\n {/* AND/OR Toggle Button */}\n <button\n onClick={handleToggleType}\n className={`px-2 py-0.5 text-xs font-semibold rounded transition-colors ${\n group.type === 'and'\n ? 'bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-800/50 dark:text-blue-300'\n : 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-800/50 dark:text-amber-300'\n }`}\n title={`Click to switch to ${group.type === 'and' ? 'OR' : 'AND'}`}\n >\n {group.type.toUpperCase()}\n </button>\n\n {/* Condition Count */}\n <span className=\"text-xs text-dc-text-muted\">\n {conditionCount} {conditionLabel}\n </span>\n </div>\n\n <div className=\"flex items-center gap-1\">\n {/* Add Button with Dropdown */}\n <div className=\"relative\" ref={addMenuRef}>\n <button\n onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-hover rounded transition-colors\"\n title=\"Add condition\"\n >\n <AddIcon className=\"w-4 h-4\" />\n </button>\n\n {isAddMenuOpen && (\n <div className=\"absolute right-0 mt-1 z-40 bg-dc-surface border border-dc-border rounded shadow-lg py-1 min-w-[120px]\">\n <button\n onClick={handleAddFilterClick}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add Filter\n </button>\n <button\n onClick={() => handleAddNestedGroup('and')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add AND Group\n </button>\n <button\n onClick={() => handleAddNestedGroup('or')}\n className=\"w-full text-left px-3 py-1.5 text-xs text-dc-text hover:bg-dc-surface-hover\"\n >\n Add OR Group\n </button>\n </div>\n )}\n </div>\n\n {/* Remove Group Button */}\n {!hideRemoveButton && (\n <button\n onClick={onRemove}\n className=\"p-1 text-dc-text-muted hover:text-red-600 transition-colors\"\n title=\"Remove group\"\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </div>\n\n {/* Group Body - Filter List */}\n <div className=\"p-2 space-y-2\">\n {group.filters.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-dc-text-muted mb-1\">No conditions in this group</p>\n <button\n onClick={() => onAddFilter([])}\n className=\"text-xs text-dc-primary hover:underline\"\n >\n Add a filter\n </button>\n </div>\n ) : (\n group.filters.map((filter, index) => {\n if (isSimpleFilter(filter)) {\n return (\n <AnalysisFilterItem\n key={`filter-${index}`}\n filter={filter}\n schema={schema}\n onUpdate={(newFilter) => handleUpdateFilter(index, newFilter)}\n onRemove={() => handleRemoveFilter(index)}\n depth={depth + 1}\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 } from 'react'\nimport { getIcon } from '../../icons'\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'\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}\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}: AnalysisFilterSectionProps) {\n const [showFieldModal, setShowFieldModal] = 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 // 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\n const newFilter: SimpleFilter = {\n member: field.name,\n operator: defaultOperator,\n values: []\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 */}\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-sm font-semibold text-dc-text\">\n Filter\n {totalFilterCount > 0 && (\n <span className=\"ml-1.5 text-xs font-normal text-dc-text-muted\">\n ({totalFilterCount})\n </span>\n )}\n </h3>\n <div className=\"flex items-center gap-2\">\n {totalFilterCount > 0 && (\n <button\n onClick={handleClearAll}\n className=\"text-xs text-dc-text-muted hover:text-red-600 underline\"\n >\n Clear all\n </button>\n )}\n <button\n onClick={handleAddFilterClick}\n className=\"p-1 text-dc-text-secondary hover:text-dc-primary hover:bg-dc-surface-secondary rounded transition-colors\"\n title=\"Add filter\"\n >\n <AddIcon className=\"w-5 h-5\" />\n </button>\n </div>\n </div>\n\n {/* Filter List - Hierarchical Rendering */}\n {filters.length === 0 ? (\n <p className=\"text-sm text-dc-text-muted\">No filters applied</p>\n ) : (\n <div className=\"space-y-2\">\n {filters.map((filter, index) => renderFilter(filter, index))}\n </div>\n )}\n\n {/* Field Search Modal - mode 'filter' shows all fields (measures + dimensions) */}\n <FieldSearchModal\n isOpen={showFieldModal}\n onClose={() => {\n setShowFieldModal(false)\n pendingAddPath.current = []\n }}\n onSelect={handleFieldSelected}\n mode=\"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 React, { useState } 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: React.DragEvent<HTMLDivElement>, toKey: string) => void\n onRemove: (field: string, fromKey: string) => void\n onDragStart: (\n e: React.DragEvent<HTMLDivElement>,\n field: string,\n fromKey: string,\n fromIndex?: number\n ) => void\n onDragEnd?: (e: React.DragEvent<HTMLDivElement>) => void\n onDragOver: (e: React.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}\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}: AnalysisAxisDropZoneProps) {\n const { key, label, description, mandatory, maxItems, emptyText } = config\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null)\n const [isDraggedOver, setIsDraggedOver] = useState(false)\n const [isReorderDraggedOver, setIsReorderDraggedOver] = useState(false)\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 React.useEffect(() => {\n const handleGlobalDragEnd = () => {\n setDragOverIndex(null)\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\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 React.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 setDragOverIndex(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 setDragOverIndex(null)\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }, [draggedItem, key])\n\n const handleReorderDragOver = (e: React.DragEvent<HTMLDivElement>, targetIndex: number) => {\n // Check if this is a reorder operation (same axis) using the draggedItem prop\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n e.preventDefault()\n e.stopPropagation()\n setDragOverIndex(targetIndex)\n setIsReorderDraggedOver(true)\n }\n }\n\n const handleReorderDragLeave = () => {\n // Clear the individual item drag over index\n setDragOverIndex(null)\n }\n\n const handleReorderDrop = (e: React.DragEvent<HTMLDivElement>, targetIndex: number) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOverIndex(null)\n setIsReorderDraggedOver(false)\n\n // Handle reordering using either drag data or the draggedItem prop\n if (\n draggedItem &&\n draggedItem.fromAxis === key &&\n draggedItem.fromIndex !== undefined &&\n onReorder\n ) {\n onReorder(draggedItem.fromIndex, targetIndex, key)\n return\n }\n\n // Fallback to parsing drag data\n try {\n const data = JSON.parse(e.dataTransfer.getData('text/plain'))\n if (data.fromAxis === key && onReorder && data.fromIndex !== undefined) {\n onReorder(data.fromIndex, targetIndex, key)\n }\n } catch {\n // If we can't parse the data, ignore\n }\n }\n\n // Get default field meta from field name\n const getDefaultFieldMeta = (field: string): FieldMeta => {\n const parts = field.split('.')\n const cubeName = parts[0] || field\n const fieldName = parts[1] || field\n\n return {\n title: fieldName,\n shortTitle: fieldName,\n cubeName,\n type: 'dimension' // Default assumption\n }\n }\n\n // Render icon based on field type\n const renderFieldIcon = (meta: FieldMeta) => {\n if (meta.type === 'measure') {\n // Measures get colored icon box with type-specific icon\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n )\n } else if (meta.type === 'timeDimension') {\n // Time dimensions get plain icon\n return <TimeDimensionIcon className=\"w-4 h-4 text-dc-text-secondary flex-shrink-0\" />\n } else {\n // Regular dimensions get plain icon\n return <DimensionIcon className=\"w-4 h-4 text-dc-text-secondary flex-shrink-0\" />\n }\n }\n\n return (\n <div className=\"mb-3\">\n {/* Header */}\n <div className=\"mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text flex items-center\">\n {label}\n {mandatory && <span className=\"text-red-500 ml-1\">*</span>}\n </h4>\n {description && <div className=\"text-xs text-dc-text-muted mt-0.5\">{description}</div>}\n </div>\n\n {/* Drop Zone Container */}\n <div\n data-axis-container={key}\n className={`min-h-[48px] border-2 border-dashed rounded-lg p-2 transition-all duration-300 ${\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'shadow-lg border-solid animate-pulse'\n : isFull\n ? 'bg-dc-surface-secondary'\n : 'bg-dc-surface-secondary hover:bg-dc-surface-hover'\n }`}\n style={{\n borderColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'var(--dc-primary)'\n : 'var(--dc-border)',\n backgroundColor:\n (isDraggedOver && (canAcceptMore || maxItems === 1)) || isReorderDraggedOver\n ? 'rgba(var(--dc-primary-rgb), 0.1)'\n : undefined\n }}\n onDragOver={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const canAccept = canAcceptMore || maxItems === 1\n\n if (canAccept) {\n setIsDraggedOver(true)\n onDragOver(e)\n } else {\n e.preventDefault()\n e.dataTransfer.dropEffect = 'none'\n }\n }}\n onDragLeave={(e) => {\n // Check if we're truly leaving the container\n const rect = e.currentTarget.getBoundingClientRect()\n const isLeavingContainer =\n e.clientX < rect.left ||\n e.clientX > rect.right ||\n e.clientY < rect.top ||\n e.clientY > rect.bottom\n\n // Also check if the related target is outside this container\n const relatedTarget = e.relatedTarget as Element | null\n const isRelatedTargetOutside = relatedTarget && !e.currentTarget.contains(relatedTarget)\n\n if (isLeavingContainer || isRelatedTargetOutside || e.currentTarget === e.target) {\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }\n }}\n onDrop={(e) => {\n // Check if this is a reorder operation (same axis) - if so, don't interfere\n if (draggedItem && draggedItem.fromAxis === key && draggedItem.fromIndex !== undefined) {\n return\n }\n\n // Simple acceptance check - either we have space OR it's a single-item replacement\n const shouldAcceptDrop = canAcceptMore || maxItems === 1\n\n if (shouldAcceptDrop) {\n onDrop(e, key)\n } else {\n e.preventDefault()\n }\n\n // Reset drag state on drop\n setIsDraggedOver(false)\n setIsReorderDraggedOver(false)\n }}\n >\n {fields.length === 0 ? (\n <div className=\"text-sm text-dc-text-muted text-center py-2\">\n {isFull ? 'Maximum items reached' : emptyText || `Drop fields here`}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {fields.map((field, index) => {\n const meta = getFieldMeta ? getFieldMeta(field) : getDefaultFieldMeta(field)\n const isDragOver = dragOverIndex === index\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === key\n\n return (\n <div key={`${field}-${index}`} className={`relative ${isDragOver ? '' : ''}`}>\n {/* Drop indicator line for reordering */}\n {isDragOver && (\n <div\n className=\"absolute -top-1 left-0 right-0 h-0.5 rounded-full z-10\"\n style={{ backgroundColor: 'var(--dc-primary)' }}\n />\n )}\n\n <div\n draggable\n onDragStart={(e) => {\n onDragStart(e, field, key, index)\n }}\n onDragEnd={onDragEnd}\n onDragOver={(e) => handleReorderDragOver(e, index)}\n onDragLeave={handleReorderDragLeave}\n onDrop={(e) => handleReorderDrop(e, index)}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg group hover:bg-dc-surface-tertiary transition-colors cursor-move ${\n isBeingDragged ? 'opacity-50 cursor-grabbing' : ''\n } ${isDragOver ? 'mt-1' : ''}`}\n >\n {/* Icon */}\n {renderFieldIcon(meta)}\n\n {/* Field Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\" title={field}>\n {meta.shortTitle || meta.title || field.split('.').pop()}\n </div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n\n {/* Remove Button - hidden until hover */}\n <button\n type=\"button\"\n onClick={() => onRemove(field, key)}\n className=\"p-1 text-dc-text-muted hover:text-dc-danger opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n title={`Remove from ${label}`}\n >\n <CloseIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n )\n })}\n </div>\n )}\n </div>\n\n {mandatory && fields.length === 0 && (\n <div className=\"text-xs text-red-500 mt-1\">This field is required</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 React, { useMemo, useEffect, useState } from 'react'\nimport { getIcon, getMeasureTypeIcon } from '../../icons'\nimport AnalysisAxisDropZone from './AnalysisAxisDropZone'\nimport ChartTypeSelector from '../ChartTypeSelector'\nimport { chartConfigRegistry } from '../../charts/chartConfigRegistry'\nimport { getChartConfig } from '../../charts/chartConfigs'\nimport type { ChartType, ChartAxisConfig, ChartDisplayConfig, ColorPalette } 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 displayConfig: ChartDisplayConfig\n metrics: MetricItem[]\n breakdowns: BreakdownItem[]\n colorPalette?: ColorPalette\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 onDisplayConfigChange: (config: ChartDisplayConfig) => void\n}\n\nexport default function AnalysisChartConfigPanel({\n chartType,\n chartConfig,\n displayConfig,\n metrics,\n breakdowns,\n colorPalette,\n schema,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange,\n onDisplayConfigChange\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 chartTypeConfig = useMemo(\n () => getChartConfig(chartType, chartConfigRegistry),\n [chartType]\n )\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 = (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 }\n\n // Clean up chart config when available fields change\n useEffect(() => {\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])\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: React.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: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n }\n\n const handleDragEnd = () => {\n setDraggedItem(null)\n }\n\n const handleDrop = (e: React.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 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 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 // Get unassigned fields (fields selected in Query tab but not yet assigned to chart axes)\n const getUnassignedFields = () => {\n const assignedFields = new Set<string>()\n chartTypeConfig.dropZones.forEach((dz) => {\n getFieldsForDropZone(dz.key).forEach((field) => assignedFields.add(field))\n })\n\n // Exclude the currently dragged field only if it's being dragged FROM a configured axis\n if (draggedItem && draggedItem.fromAxis !== 'available') {\n assignedFields.add(draggedItem.field)\n }\n\n return {\n dimensions: availableFields.dimensions.filter((f) => !assignedFields.has(f)),\n timeDimensions: availableFields.timeDimensions.filter((f) => !assignedFields.has(f)),\n measures: availableFields.measures.filter((f) => !assignedFields.has(f))\n }\n }\n\n const unassignedFields = getUnassignedFields()\n const hasUnassignedFields =\n unassignedFields.dimensions.length > 0 ||\n unassignedFields.timeDimensions.length > 0 ||\n unassignedFields.measures.length > 0\n\n return (\n <div className=\"space-y-6\">\n {/* Chart Type Selector */}\n <div>\n <label className=\"block text-sm font-medium text-dc-text mb-2\">Chart Type</label>\n <ChartTypeSelector\n selectedType={chartType}\n onTypeChange={onChartTypeChange}\n availability={chartAvailability}\n compact\n />\n </div>\n\n {/* Unassigned Fields - Show fields from Query tab that haven't been assigned yet */}\n {!shouldSkipQuery && hasUnassignedFields && (\n <div>\n <div className=\"mb-2\">\n <h4 className=\"text-sm font-medium text-dc-text\">Unassigned Fields</h4>\n <div className=\"text-xs text-dc-text-muted mt-0.5\">\n Drag fields to chart axes below\n </div>\n </div>\n <div className=\"border-2 border-dashed border-dc-border rounded-lg p-2 bg-dc-surface-secondary\">\n <div className=\"space-y-2\">\n {/* Measures */}\n {unassignedFields.measures.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n const IconComponent = getMeasureTypeIcon(meta.measureType || 'count') || MeasureIcon\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <span className=\"w-6 h-6 flex items-center justify-center rounded bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex-shrink-0\">\n <IconComponent className=\"w-4 h-4\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Dimensions */}\n {unassignedFields.dimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <DimensionIcon className=\"w-4 h-4 text-dc-text-secondary flex-shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n\n {/* Time Dimensions */}\n {unassignedFields.timeDimensions.map((field) => {\n const meta = getFieldMeta(field)\n const isBeingDragged =\n draggedItem && draggedItem.field === field && draggedItem.fromAxis === 'available'\n return (\n <div\n key={field}\n draggable\n onDragStart={(e) => handleDragStart(e, field, 'available')}\n onDragEnd={handleDragEnd}\n className={`flex items-center gap-2 p-2 bg-dc-surface rounded-lg hover:bg-dc-surface-tertiary transition-colors cursor-move ${isBeingDragged ? 'opacity-50 cursor-grabbing' : ''}`}\n title={field}\n >\n <TimeDimensionIcon className=\"w-4 h-4 text-dc-text-secondary flex-shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm text-dc-text truncate\">{meta.shortTitle}</div>\n <div className=\"text-xs text-dc-text-muted truncate\">{meta.cubeName}</div>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )}\n\n {/* Chart Axis Configuration - Dynamic Drop Zones */}\n {!shouldSkipQuery && chartTypeConfig.dropZones.length > 0 && (\n <div>\n <h4 className=\"text-xs font-semibold text-dc-text-secondary mb-2\">\n Chart Configuration\n </h4>\n <div className=\"space-y-1\">\n {chartTypeConfig.dropZones.map((dropZone) => (\n <AnalysisAxisDropZone\n key={dropZone.key}\n config={dropZone}\n fields={getFieldsForDropZone(dropZone.key)}\n onDrop={handleDrop}\n onRemove={handleRemoveFromAxis}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onReorder={handleReorder}\n draggedItem={draggedItem}\n getFieldMeta={getFieldMeta}\n />\n ))}\n </div>\n </div>\n )}\n\n {/* Display Options */}\n {((chartTypeConfig.displayOptions && chartTypeConfig.displayOptions.length > 0) ||\n (chartTypeConfig.displayOptionsConfig &&\n chartTypeConfig.displayOptionsConfig.length > 0)) && (\n <div>\n <h4 className=\"text-xs font-semibold text-dc-text-secondary mb-2\">Display Options</h4>\n <div className=\"space-y-2\">\n {/* Backward compatibility: Simple boolean display options */}\n {chartTypeConfig.displayOptions?.includes('showLegend') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showLegend ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showLegend: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Legend</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showGrid') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showGrid ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showGrid: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Grid</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('showTooltip') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.showTooltip ?? true}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n showTooltip: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Show Tooltip</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('stacked') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.stacked ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n stacked: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Stacked</span>\n </label>\n )}\n\n {chartTypeConfig.displayOptions?.includes('hideHeader') && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={displayConfig.hideHeader ?? false}\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n hideHeader: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">Hide Header</span>\n </label>\n )}\n\n {/* New structured display options */}\n {chartTypeConfig.displayOptionsConfig?.map((option) => (\n <div key={option.key} className=\"space-y-1\">\n {option.type === 'boolean' && (\n <label className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n checked={\n (displayConfig[option.key as keyof ChartDisplayConfig] as boolean) ??\n option.defaultValue ??\n false\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.checked\n })\n }\n className=\"rounded border-dc-border focus:ring-blue-500\"\n style={{ color: 'var(--dc-primary)' }}\n />\n <span className=\"text-sm text-dc-text\">{option.label}</span>\n </label>\n )}\n\n {option.type === 'string' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">\n {option.label}\n {option.key === 'content' && (\n <span className=\"text-xs text-dc-text-muted ml-1\">\n (only headers, lists and links)\n </span>\n )}\n </label>\n {option.key === 'content' ? (\n <textarea\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n rows={8}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 font-mono resize-y bg-dc-surface text-dc-text\"\n />\n ) : (\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n )}\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'paletteColor' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex flex-wrap gap-2\">\n {colorPalette?.colors.map((color, index) => {\n const isSelected =\n ((displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0) === index\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: index\n })\n }\n className={`w-8 h-8 rounded border-2 transition-all duration-200 hover:scale-110 focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 ${\n isSelected\n ? 'ring-2 ring-offset-1 scale-110'\n : 'hover:border-dc-text-muted'\n }`}\n style={{\n backgroundColor: color,\n borderColor: isSelected ? 'var(--dc-primary)' : 'var(--dc-border)'\n }}\n title={`Color ${index + 1}: ${color}`}\n />\n )\n }) || [\n // Fallback if no palette available\n <button\n key={0}\n type=\"button\"\n onClick={() =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: 0\n })\n }\n className=\"w-8 h-8 rounded-sm border-2 ring-2 ring-offset-1\"\n style={{\n backgroundColor: '#8884d8',\n borderColor: 'var(--dc-primary)',\n boxShadow: '0 0 0 2px var(--dc-primary)'\n }}\n title=\"Default Color\"\n />\n ]}\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'number' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <input\n type=\"number\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as number) ??\n option.defaultValue ??\n 0\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value === '' ? undefined : Number(e.target.value)\n })\n }\n placeholder={option.placeholder}\n min={option.min}\n max={option.max}\n step={option.step}\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'select' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <select\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n ''\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-full px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n >\n {option.options?.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n\n {option.type === 'color' && (\n <div className=\"space-y-1\">\n <label className=\"text-sm text-dc-text-secondary\">{option.label}</label>\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"color\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n className=\"w-12 h-8 border border-dc-border rounded-sm cursor-pointer\"\n />\n <input\n type=\"text\"\n value={\n (displayConfig[option.key as keyof ChartDisplayConfig] as string) ??\n option.defaultValue ??\n '#8884d8'\n }\n onChange={(e) =>\n onDisplayConfigChange({\n ...displayConfig,\n [option.key]: e.target.value\n })\n }\n placeholder={option.placeholder || '#8884d8'}\n className=\"flex-1 px-2 py-1 text-sm border border-dc-border rounded-sm focus:ring-blue-500 focus:border-blue-500 bg-dc-surface text-dc-text\"\n />\n </div>\n {option.description && (\n <p className=\"text-xs text-dc-text-muted\">{option.description}</p>\n )}\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Help text when no fields are available */}\n {!shouldSkipQuery &&\n availableFields.measures.length === 0 &&\n availableFields.dimensions.length === 0 &&\n availableFields.timeDimensions.length === 0 && (\n <div className=\"text-center text-dc-text-muted text-sm py-4\">\n <p>Add metrics and breakdowns in the Query tab to configure your chart.</p>\n </div>\n )}\n </div>\n )\n}\n","/**\n * AnalysisQueryPanel Component\n *\n * Right-side panel containing Query and Chart tabs with sections for\n * Metrics, Filters, and Breakdowns.\n */\n\nimport { useEffect } from 'react'\nimport type { AnalysisQueryPanelProps } from './types'\nimport MetricsSection from './MetricsSection'\nimport BreakdownSection from './BreakdownSection'\nimport AnalysisFilterSection from './AnalysisFilterSection'\nimport AnalysisChartConfigPanel from './AnalysisChartConfigPanel'\n\n/**\n * AnalysisQueryPanel displays the right-side query builder with:\n * - Query/Chart tab switcher\n * - Metrics section (measures)\n * - Filter section\n * - Breakdown section (dimensions)\n * - Chart configuration (in Chart tab)\n */\nexport default function AnalysisQueryPanel({\n metrics,\n breakdowns,\n filters,\n schema,\n activeTab,\n onActiveTabChange,\n onAddMetric,\n onRemoveMetric,\n onAddBreakdown,\n onRemoveBreakdown,\n onBreakdownGranularityChange,\n onFiltersChange,\n // Sorting\n order,\n onOrderChange,\n // Chart configuration\n chartType,\n chartConfig,\n displayConfig,\n chartAvailability,\n onChartTypeChange,\n onChartConfigChange,\n onDisplayConfigChange\n}: AnalysisQueryPanelProps) {\n // Force query tab when no metrics are selected\n useEffect(() => {\n if (metrics.length === 0 && activeTab === 'chart') {\n onActiveTabChange('query')\n }\n }, [metrics.length, activeTab, onActiveTabChange])\n\n return (\n <div className=\"h-full flex flex-col bg-dc-surface\">\n {/* Tab Bar */}\n <div className=\"flex border-b border-dc-border flex-shrink-0\">\n <button\n onClick={() => onActiveTabChange('query')}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'query'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n >\n Query\n </button>\n <button\n onClick={() => metrics.length > 0 && onActiveTabChange('chart')}\n disabled={metrics.length === 0}\n className={`flex-1 px-4 py-3 text-sm font-medium transition-colors ${\n activeTab === 'chart'\n ? 'text-dc-primary border-b-2 border-dc-primary'\n : metrics.length === 0\n ? 'text-dc-text-muted cursor-not-allowed opacity-50'\n : 'text-dc-text-secondary hover:text-dc-text'\n }`}\n title={metrics.length === 0 ? 'Add metrics to configure chart' : 'Chart configuration'}\n >\n Chart\n </button>\n </div>\n\n {/* Tab Content */}\n <div className=\"flex-1 overflow-auto p-4\">\n {activeTab === 'query' ? (\n <div className=\"space-y-6\">\n {/* Metrics Section */}\n <MetricsSection\n metrics={metrics}\n schema={schema}\n onAdd={onAddMetric}\n onRemove={onRemoveMetric}\n order={order}\n onOrderChange={onOrderChange}\n />\n\n {/* Filter Section */}\n <AnalysisFilterSection\n filters={filters}\n schema={schema}\n onFiltersChange={onFiltersChange}\n />\n\n {/* Breakdown Section */}\n <BreakdownSection\n breakdowns={breakdowns}\n schema={schema}\n onAdd={onAddBreakdown}\n onRemove={onRemoveBreakdown}\n onGranularityChange={onBreakdownGranularityChange}\n order={order}\n onOrderChange={onOrderChange}\n />\n </div>\n ) : activeTab === 'chart' ? (\n /* Chart Tab Content */\n <AnalysisChartConfigPanel\n chartType={chartType}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n metrics={metrics}\n breakdowns={breakdowns}\n schema={schema}\n chartAvailability={chartAvailability}\n onChartTypeChange={onChartTypeChange}\n onChartConfigChange={onChartConfigChange}\n onDisplayConfigChange={onDisplayConfigChange}\n />\n ) : null}\n </div>\n </div>\n )\n}\n","/**\n * AnalysisBuilder Component\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\nimport { useState, useCallback, useEffect, useRef, useMemo, forwardRef, useImperativeHandle } from 'react'\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { useCubeQuery } from '../../hooks/useCubeQuery'\nimport type {\n AnalysisBuilderProps,\n AnalysisBuilderRef,\n AnalysisBuilderState,\n MetricItem,\n BreakdownItem,\n QueryPanelTab,\n ExecutionStatus,\n AnalysisBuilderStorageState,\n QueryAnalysis\n} from './types'\nimport type { CubeQuery, Filter, ChartType, ChartAxisConfig, ChartDisplayConfig } from '../../types'\nimport FieldSearchModal from './FieldSearchModal'\nimport AnalysisResultsPanel from './AnalysisResultsPanel'\nimport AnalysisQueryPanel from './AnalysisQueryPanel'\nimport type { MetaField, MetaResponse } from '../../shared/types'\nimport { cleanQueryForServer } from '../../shared/utils'\nimport { getAllChartAvailability, getSmartChartDefaults, shouldAutoSwitchChartType } from '../../shared/chartDefaults'\n\n// Storage key for localStorage persistence\nconst STORAGE_KEY = 'drizzle-cube-analysis-builder-state'\n\n// Debounce delay for auto-execute (ms)\nconst AUTO_EXECUTE_DELAY = 500\n\n/**\n * Generate a unique ID for items\n */\nfunction generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * Generate letter label for metrics (A, B, C, ..., AA, AB, ...)\n */\nfunction generateMetricLabel(index: number): string {\n let label = ''\n let n = index\n do {\n label = String.fromCharCode(65 + (n % 26)) + label\n n = Math.floor(n / 26) - 1\n } while (n >= 0)\n return label\n}\n\n/**\n * Convert metrics and breakdowns to CubeQuery format\n */\nfunction buildCubeQuery(\n metrics: MetricItem[],\n breakdowns: BreakdownItem[],\n filters: Filter[],\n order?: Record<string, 'asc' | 'desc'>\n): CubeQuery {\n const query: CubeQuery = {\n measures: metrics.map((m) => m.field),\n dimensions: breakdowns.filter((b) => !b.isTimeDimension).map((b) => b.field),\n timeDimensions: breakdowns\n .filter((b) => b.isTimeDimension)\n .map((b) => ({\n dimension: b.field,\n granularity: b.granularity || 'day'\n })),\n filters: filters.length > 0 ? filters : undefined,\n order: order && Object.keys(order).length > 0 ? order : undefined\n }\n\n // Clean up empty arrays\n if (query.measures?.length === 0) delete query.measures\n if (query.dimensions?.length === 0) delete query.dimensions\n if (query.timeDimensions?.length === 0) delete query.timeDimensions\n\n return query\n}\n\n/**\n * Create initial empty state\n */\nfunction createInitialState(): AnalysisBuilderState {\n return {\n metrics: [],\n breakdowns: [],\n filters: [],\n validationStatus: 'idle',\n validationError: null,\n executionStatus: 'idle',\n executionResults: null,\n executionError: null,\n totalRowCount: null,\n resultsStale: false\n }\n}\n\n/**\n * Load all state from localStorage once (to avoid repeated parsing)\n */\nfunction loadInitialStateFromStorage(\n disableLocalStorage: boolean\n): AnalysisBuilderStorageState | null {\n if (disableLocalStorage) return null\n\n try {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved) {\n return JSON.parse(saved) as AnalysisBuilderStorageState\n }\n } catch {\n // Ignore parse errors\n }\n return null\n}\n\nconst AnalysisBuilder = forwardRef<AnalysisBuilderRef, AnalysisBuilderProps>(\n (\n {\n className = '',\n maxHeight,\n initialQuery,\n disableLocalStorage: disableLocalStorageProp = false,\n hideSettings: _hideSettings = false,\n onQueryChange,\n onChartConfigChange\n },\n ref\n ) => {\n // Mark unused props for future use\n void _hideSettings\n\n // Disable localStorage when initialQuery is provided (parent manages state)\n const disableLocalStorage = disableLocalStorageProp || !!initialQuery\n\n // Get context - metaLoading and metaError used by FieldSearchModal internally\n const { meta, cubeApi } = useCubeContext()\n\n // Load localStorage once on mount (before useState calls) to avoid repeated parsing\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const cachedStorage = useMemo(\n () => loadInitialStateFromStorage(disableLocalStorageProp),\n [] // Only run once on mount\n )\n\n // Load initial state from localStorage or initialQuery\n const [state, setState] = useState<AnalysisBuilderState>(() => {\n // If initialQuery is provided, parse it to metrics/breakdowns\n if (initialQuery) {\n return {\n ...createInitialState(),\n metrics: (initialQuery.measures || []).map((field, index) => ({\n id: generateId(),\n field,\n label: generateMetricLabel(index)\n })),\n breakdowns: [\n ...(initialQuery.dimensions || []).map((field) => ({\n id: generateId(),\n field,\n isTimeDimension: false\n })),\n ...(initialQuery.timeDimensions || []).map((td) => ({\n id: generateId(),\n field: td.dimension,\n granularity: td.granularity,\n isTimeDimension: true\n }))\n ],\n filters: initialQuery.filters || []\n }\n }\n\n // Use cached localStorage data if available\n if (cachedStorage) {\n return {\n ...createInitialState(),\n metrics: cachedStorage.metrics || [],\n breakdowns: cachedStorage.breakdowns || [],\n filters: cachedStorage.filters || []\n }\n }\n\n return createInitialState()\n })\n\n // Chart configuration state - load from cached localStorage or defaults\n const [chartType, setChartType] = useState<ChartType>(() => {\n if (!initialQuery && cachedStorage?.chartType) {\n return cachedStorage.chartType\n }\n return 'line'\n })\n\n const [chartConfig, setChartConfig] = useState<ChartAxisConfig>(() => {\n if (!initialQuery && cachedStorage?.chartConfig) {\n return cachedStorage.chartConfig\n }\n return {}\n })\n\n const [displayConfig, setDisplayConfig] = useState<ChartDisplayConfig>(() => {\n if (!initialQuery && cachedStorage?.displayConfig) {\n return cachedStorage.displayConfig\n }\n return { showLegend: true, showGrid: true, showTooltip: true }\n })\n\n // Sort order state\n const [order, setOrder] = useState<Record<string, 'asc' | 'desc'> | undefined>(() => {\n // Load from initialQuery if provided\n if (initialQuery?.order) {\n return initialQuery.order\n }\n // Use cached localStorage data if available\n if (!initialQuery && cachedStorage?.order) {\n return cachedStorage.order\n }\n return undefined\n })\n\n // UI state\n const [activeTab, setActiveTab] = useState<QueryPanelTab>('query')\n const [activeView, setActiveView] = useState<'table' | 'chart'>(() => {\n if (!initialQuery && cachedStorage?.activeView) {\n return cachedStorage.activeView\n }\n return 'chart'\n })\n const [displayLimit, setDisplayLimit] = useState<number>(100)\n\n // Track whether user manually selected a chart type (vs auto-selection)\n const [userManuallySelectedChart, setUserManuallySelectedChart] = useState(false)\n\n // Debug data state (from dry-run API)\n const [debugData, setDebugData] = useState<{\n sql: { sql: string; params: any[] } | null\n analysis: QueryAnalysis | null\n loading: boolean\n error: string | null\n }>({ sql: null, analysis: null, loading: false, error: null })\n\n // Field search modal state\n const [showFieldModal, setShowFieldModal] = useState(false)\n const [fieldModalMode, setFieldModalMode] = useState<'metrics' | 'breakdown'>('metrics')\n\n // Build current query - memoized to prevent infinite loops\n const currentQuery = useMemo(\n () => buildCubeQuery(state.metrics, state.breakdowns, state.filters, order),\n [state.metrics, state.breakdowns, state.filters, order]\n )\n\n // Serialize query for comparison (prevents object reference issues)\n const currentQueryString = useMemo(() => JSON.stringify(currentQuery), [currentQuery])\n\n // Debounced query for auto-execution\n const [debouncedQuery, setDebouncedQuery] = useState<CubeQuery | null>(null)\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const lastQueryStringRef = useRef<string>('')\n\n // Determine if query is valid (has at least one measure OR one dimension)\n const isValidQuery =\n (currentQuery.measures && currentQuery.measures.length > 0) ||\n (currentQuery.dimensions && currentQuery.dimensions.length > 0) ||\n (currentQuery.timeDimensions && currentQuery.timeDimensions.length > 0)\n\n // Debounce query changes - use string comparison to avoid infinite loops\n useEffect(() => {\n // Skip if query hasn't actually changed\n if (currentQueryString === lastQueryStringRef.current) {\n return\n }\n\n // Clear existing timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n // Only debounce if we have a valid query\n if (isValidQuery) {\n debounceTimerRef.current = setTimeout(() => {\n lastQueryStringRef.current = currentQueryString\n setDebouncedQuery(currentQuery)\n }, AUTO_EXECUTE_DELAY)\n } else {\n // Clear debounced query if no valid query\n lastQueryStringRef.current = currentQueryString\n setDebouncedQuery(null)\n }\n\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n }\n }, [currentQueryString, currentQuery, isValidQuery])\n\n // Transform debounced query to server format (converts filter groups)\n const serverQuery = useMemo(() => {\n if (!debouncedQuery) return null\n return cleanQueryForServer(debouncedQuery)\n }, [debouncedQuery])\n\n // Execute query using useCubeQuery hook\n // resetResultSetOnChange: true ensures we don't show stale results while loading\n const { resultSet, isLoading, error } = useCubeQuery(serverQuery, {\n skip: !serverQuery,\n resetResultSetOnChange: true\n })\n\n // Derive execution status\n const executionStatus: ExecutionStatus = useMemo(() => {\n if (!debouncedQuery) return 'idle'\n if (isLoading && !resultSet) return 'loading'\n if (isLoading && resultSet) return 'refreshing'\n if (error) return 'error'\n if (resultSet) return 'success'\n return 'idle'\n }, [debouncedQuery, isLoading, error, resultSet])\n\n // Get execution results\n const executionResults = useMemo(() => {\n if (!resultSet) return null\n try {\n return resultSet.rawData()\n } catch {\n return null\n }\n }, [resultSet])\n\n // Note: We pass executionStatus, executionResults, error directly to PortletResultsPanel\n // instead of storing in state, to avoid render loops\n\n // Compute chart availability based on current metrics and breakdowns\n const chartAvailability = useMemo(\n () => getAllChartAvailability(state.metrics, state.breakdowns),\n [state.metrics, state.breakdowns]\n )\n\n // Helper to check if chart config is completely empty (no axes configured)\n const isChartConfigEmpty = useCallback((config: ChartAxisConfig): boolean => {\n const keys: (keyof ChartAxisConfig)[] = ['xAxis', 'yAxis', 'series', 'sizeField', 'colorField', 'dateField', 'valueField']\n return keys.every(key => {\n const val = config[key]\n if (val === undefined || val === null) return true\n if (Array.isArray(val)) return val.length === 0\n if (typeof val === 'string') return val === ''\n return false\n })\n }, [])\n\n // Smart chart defaulting - auto-configure chart type and axes when metrics/breakdowns change\n useEffect(() => {\n if (state.metrics.length === 0 && state.breakdowns.length === 0) {\n return // Nothing to configure\n }\n\n // Check if we should auto-switch chart type\n const newChartType = shouldAutoSwitchChartType(\n state.metrics,\n state.breakdowns,\n chartType,\n userManuallySelectedChart\n )\n\n if (newChartType) {\n // Chart type is changing - get smart defaults for the new chart type\n const { chartConfig: newChartConfig } = getSmartChartDefaults(\n state.metrics,\n state.breakdowns,\n newChartType\n )\n setChartType(newChartType)\n setChartConfig(newChartConfig)\n // Reset user selection flag since we auto-switched\n setUserManuallySelectedChart(false)\n } else if (state.metrics.length > 0 || state.breakdowns.length > 0) {\n // Only apply smart defaults if the chart config is COMPLETELY empty\n // Once user has configured ANY axis, don't auto-fill (respects user removals)\n if (isChartConfigEmpty(chartConfig)) {\n const { chartConfig: smartDefaults } = getSmartChartDefaults(\n state.metrics,\n state.breakdowns,\n chartType\n )\n setChartConfig(smartDefaults)\n }\n }\n }, [state.metrics, state.breakdowns, chartType, userManuallySelectedChart, chartConfig, isChartConfigEmpty])\n\n // Save state to localStorage whenever it changes (if not disabled)\n useEffect(() => {\n if (!disableLocalStorage) {\n try {\n const storageState: AnalysisBuilderStorageState = {\n metrics: state.metrics,\n breakdowns: state.breakdowns,\n filters: state.filters,\n order,\n chartType,\n chartConfig,\n displayConfig,\n activeView\n }\n localStorage.setItem(STORAGE_KEY, JSON.stringify(storageState))\n } catch {\n // Failed to save to localStorage\n }\n }\n }, [\n state.metrics,\n state.breakdowns,\n state.filters,\n order,\n chartType,\n chartConfig,\n displayConfig,\n activeView,\n disableLocalStorage\n ])\n\n // Call onQueryChange callback when query changes\n useEffect(() => {\n if (onQueryChange && isValidQuery) {\n onQueryChange(currentQuery)\n }\n }, [currentQuery, isValidQuery, onQueryChange])\n\n // Call onChartConfigChange callback when chart config changes\n useEffect(() => {\n if (onChartConfigChange) {\n onChartConfigChange({ chartType, chartConfig, displayConfig })\n }\n }, [chartType, chartConfig, displayConfig, onChartConfigChange])\n\n // Fetch dry-run data for debug tab\n useEffect(() => {\n // Clear debug data if no valid query\n if (!isValidQuery || !serverQuery) {\n setDebugData({ sql: null, analysis: null, loading: false, error: null })\n return\n }\n\n let isCancelled = false\n\n const fetchDebugData = async () => {\n setDebugData((prev) => ({ ...prev, loading: true, error: null }))\n try {\n const result = await cubeApi.dryRun(serverQuery)\n if (!isCancelled) {\n setDebugData({\n sql: result.sql,\n analysis: result.analysis,\n loading: false,\n error: null\n })\n }\n } catch (err) {\n if (!isCancelled) {\n setDebugData({\n sql: null,\n analysis: null,\n loading: false,\n error: err instanceof Error ? err.message : 'Failed to fetch debug info'\n })\n }\n }\n }\n\n fetchDebugData()\n\n return () => {\n isCancelled = true\n }\n }, [serverQuery, cubeApi, isValidQuery])\n\n // ========================================================================\n // Metric Handlers\n // ========================================================================\n\n const handleAddMetric = useCallback(() => {\n setFieldModalMode('metrics')\n setShowFieldModal(true)\n }, [])\n\n const handleRemoveMetric = useCallback((id: string) => {\n // Find the field name before removing\n const fieldToRemove = state.metrics.find((m) => m.id === id)?.field\n\n setState((prev) => ({\n ...prev,\n metrics: prev.metrics.filter((m) => m.id !== id),\n resultsStale: true\n }))\n\n // Clean up any sort order for the removed field\n if (fieldToRemove) {\n setOrder((prevOrder) => {\n if (!prevOrder || !prevOrder[fieldToRemove]) return prevOrder\n const newOrder = { ...prevOrder }\n delete newOrder[fieldToRemove]\n return Object.keys(newOrder).length > 0 ? newOrder : undefined\n })\n }\n }, [state.metrics])\n\n const handleFieldSelected = useCallback(\n (field: MetaField, fieldType: 'measure' | 'dimension' | 'timeDimension', _cubeName: string, keepOpen?: boolean) => {\n if (fieldModalMode === 'metrics' && fieldType === 'measure') {\n // Toggle metric - add if not present, remove if already added\n setState((prev) => {\n const existingIndex = prev.metrics.findIndex((m) => m.field === field.name)\n if (existingIndex >= 0) {\n // Remove existing metric\n return {\n ...prev,\n metrics: prev.metrics.filter((_, i) => i !== existingIndex),\n resultsStale: true\n }\n }\n // Add new metric\n const newMetric: MetricItem = {\n id: generateId(),\n field: field.name,\n label: generateMetricLabel(prev.metrics.length)\n }\n return {\n ...prev,\n metrics: [...prev.metrics, newMetric],\n resultsStale: true\n }\n })\n } else if (fieldModalMode === 'breakdown') {\n // Toggle breakdown - add if not present, remove if already added\n const isTimeDimension = fieldType === 'timeDimension'\n setState((prev) => {\n const existingIndex = prev.breakdowns.findIndex((b) => b.field === field.name)\n if (existingIndex >= 0) {\n // Remove existing breakdown\n return {\n ...prev,\n breakdowns: prev.breakdowns.filter((_, i) => i !== existingIndex),\n resultsStale: true\n }\n }\n // Add new breakdown\n const newBreakdown: BreakdownItem = {\n id: generateId(),\n field: field.name,\n isTimeDimension,\n granularity: isTimeDimension ? 'month' : undefined\n }\n return {\n ...prev,\n breakdowns: [...prev.breakdowns, newBreakdown],\n resultsStale: true\n }\n })\n }\n // Only close modal if not doing shift-click multi-select\n if (!keepOpen) {\n setShowFieldModal(false)\n }\n },\n [fieldModalMode]\n )\n\n // ========================================================================\n // Breakdown Handlers\n // ========================================================================\n\n const handleAddBreakdown = useCallback(() => {\n setFieldModalMode('breakdown')\n setShowFieldModal(true)\n }, [])\n\n const handleRemoveBreakdown = useCallback((id: string) => {\n // Find the field name before removing\n const fieldToRemove = state.breakdowns.find((b) => b.id === id)?.field\n\n setState((prev) => ({\n ...prev,\n breakdowns: prev.breakdowns.filter((b) => b.id !== id),\n resultsStale: true\n }))\n\n // Clean up any sort order for the removed field\n if (fieldToRemove) {\n setOrder((prevOrder) => {\n if (!prevOrder || !prevOrder[fieldToRemove]) return prevOrder\n const newOrder = { ...prevOrder }\n delete newOrder[fieldToRemove]\n return Object.keys(newOrder).length > 0 ? newOrder : undefined\n })\n }\n }, [state.breakdowns])\n\n const handleBreakdownGranularityChange = useCallback(\n (id: string, granularity: string) => {\n setState((prev) => ({\n ...prev,\n breakdowns: prev.breakdowns.map((b) =>\n b.id === id ? { ...b, granularity } : b\n ),\n resultsStale: true\n }))\n },\n []\n )\n\n // ========================================================================\n // Filter Handlers\n // ========================================================================\n\n // Filter change handler - connected to PortletQueryPanel\n const handleFiltersChange = useCallback((filters: Filter[]) => {\n setState((prev) => ({\n ...prev,\n filters,\n resultsStale: true\n }))\n }, [])\n\n // ========================================================================\n // Order Handlers\n // ========================================================================\n\n const handleOrderChange = useCallback(\n (fieldName: string, direction: 'asc' | 'desc' | null) => {\n setOrder((prev) => {\n const newOrder = { ...(prev || {}) }\n\n if (direction === null) {\n // Remove sort for this field\n delete newOrder[fieldName]\n } else {\n // Set or update sort direction\n newOrder[fieldName] = direction\n }\n\n // Return undefined if empty, otherwise return the new order\n return Object.keys(newOrder).length > 0 ? newOrder : undefined\n })\n },\n []\n )\n\n // ========================================================================\n // Clear Query\n // ========================================================================\n\n const handleClearQuery = useCallback(() => {\n setState(createInitialState())\n setOrder(undefined)\n setUserManuallySelectedChart(false)\n }, [])\n\n // Handle chart type change - track that user manually selected this\n const handleChartTypeChange = useCallback((type: ChartType) => {\n setChartType(type)\n setUserManuallySelectedChart(true)\n\n // Update chart config for the new chart type\n const { chartConfig: newChartConfig } = getSmartChartDefaults(\n state.metrics,\n state.breakdowns,\n type\n )\n setChartConfig(newChartConfig)\n }, [state.metrics, state.breakdowns])\n\n // ========================================================================\n // Expose API via ref\n // ========================================================================\n\n useImperativeHandle(\n ref,\n () => ({\n getCurrentQuery: () => currentQuery,\n getChartConfig: () => ({ chartType, chartConfig, displayConfig }),\n executeQuery: () => {\n // TODO: Implement manual execute\n },\n clearQuery: handleClearQuery\n }),\n [currentQuery, chartType, chartConfig, displayConfig, handleClearQuery]\n )\n\n // ========================================================================\n // Render\n // ========================================================================\n\n return (\n <div\n className={`flex flex-col lg:flex-row bg-dc-surface ${className}`}\n style={maxHeight ? { height: maxHeight, maxHeight, overflow: 'hidden' } : { height: '100%' }}\n >\n {/* Left Panel - Results (takes most space) */}\n <div className=\"flex-1 min-w-0 border-r border-dc-border p-4 overflow-auto\">\n <AnalysisResultsPanel\n executionStatus={executionStatus}\n executionResults={executionResults}\n executionError={error?.message || null}\n totalRowCount={null}\n resultsStale={isLoading && executionResults !== null}\n chartType={chartType}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n query={currentQuery}\n schema={meta as MetaResponse | null}\n activeView={activeView}\n onActiveViewChange={setActiveView}\n displayLimit={displayLimit}\n onDisplayLimitChange={setDisplayLimit}\n hasMetrics={state.metrics.length > 0}\n // Debug props (serverQuery is the cleaned/transformed version sent to server)\n debugQuery={serverQuery}\n debugSql={debugData.sql}\n debugAnalysis={debugData.analysis}\n debugLoading={debugData.loading}\n debugError={debugData.error}\n />\n </div>\n\n {/* Right Panel - Query Builder */}\n <div className=\"w-full lg:w-96 flex-shrink-0 h-full overflow-hidden\">\n <AnalysisQueryPanel\n metrics={state.metrics}\n breakdowns={state.breakdowns}\n filters={state.filters}\n schema={meta as MetaResponse | null}\n activeTab={activeTab}\n onActiveTabChange={setActiveTab}\n onAddMetric={handleAddMetric}\n onRemoveMetric={handleRemoveMetric}\n onAddBreakdown={handleAddBreakdown}\n onRemoveBreakdown={handleRemoveBreakdown}\n onBreakdownGranularityChange={handleBreakdownGranularityChange}\n onFiltersChange={handleFiltersChange}\n order={order}\n onOrderChange={handleOrderChange}\n chartType={chartType}\n chartConfig={chartConfig}\n displayConfig={displayConfig}\n chartAvailability={chartAvailability}\n onChartTypeChange={handleChartTypeChange}\n onChartConfigChange={setChartConfig}\n onDisplayConfigChange={setDisplayConfig}\n validationStatus={state.validationStatus}\n validationError={state.validationError}\n />\n </div>\n\n {/* Field Search Modal */}\n <FieldSearchModal\n isOpen={showFieldModal}\n onClose={() => setShowFieldModal(false)}\n onSelect={handleFieldSelected}\n mode={fieldModalMode}\n schema={meta as MetaResponse | null}\n selectedFields={[\n ...state.metrics.map((m) => m.field),\n ...state.breakdowns.map((b) => b.field)\n ]}\n />\n </div>\n )\n }\n)\n\nAnalysisBuilder.displayName = 'AnalysisBuilder'\n\nexport default AnalysisBuilder\n"],"names":["findFieldInSchema","fieldName","schema","cube","measure","m","dimension","getFieldTitle","found","schemaToFieldOptions","mode","options","isTime","filterFieldOptions","searchTerm","selectedCube","filtered","opt","term","groupFieldsByCube","grouped","option","existing","RECENT_FIELDS_KEY","MAX_RECENT_FIELDS","getRecentFields","stored","addRecentField","recent","f","getRecentFieldOptions","recentFieldNames","allOptions","recentOptions","getCubeNames","getCubeTitle","cubeName","c","CheckIcon","getIcon","FieldSearchItem","field","isSelected","isFocused","onClick","onMouseEnter","props","getFieldIcon","Icon","getMeasureTypeIcon","jsx","getFieldTypeIcon","getBadgeStyle","getTypeLabel","jsxs","FieldSearchItem$1","memo","FieldDetailPanel","getIconBgStyle","getTypeDisplay","FieldDetailPanel$1","SearchIcon","CloseIcon","FieldSearchModal","isOpen","onClose","onSelect","selectedFields","externalRecentFields","setSearchTerm","useState","setSelectedCube","focusedField","setFocusedField","focusedIndex","setFocusedIndex","lastSelectedIndex","setLastSelectedIndex","searchInputRef","useRef","resultsContainerRef","useMemo","fieldOptionsMode","allFieldOptions","cubeNames","filteredFields","groupedFields","flatFieldsList","list","fields","useEffect","selectSingleField","useCallback","keepOpen","metaField","handleSelectField","fieldIndex","shiftKey","startIndex","endIndex","i","rangeField","handleKeyDown","e","prev","next","focusedElement","searchPlaceholder","modalTitle","focusedFieldId","idx","sum","isSimpleFilter","filter","isGroupFilter","transformFiltersForServer","filters","transformFilter","transformedSubFilters","cleanQuery","query","cleanedQuery","cleanQueryForServer","getAvailableOperators","fieldType","operators","operator","meta","FILTER_OPERATORS","convertDateRangeTypeToValue","rangeType","number","typeMap","unit","unitSingular","requiresNumberInput","formatReason","reason","getReasonBadgeClasses","QueryAnalysisPanel","analysis","InfoIcon","ArrowRightIcon","WarningIcon","TableIcon","LinkIcon","SuccessIcon","ErrorIcon","jp","step","stepIdx","jc","pa","jk","w","isTimeDimension","breakdown","getFirstTimeDimension","breakdowns","getFirstDimension","b","getDimensions","getTimeDimensions","getChartAvailability","chartType","metrics","measureCount","dimensionCount","timeDimensionCount","totalBreakdowns","getAllChartAvailability","chartTypes","availability","selectBestChartType","currentChartType","hasTimeDimension","hasDimension","hasMeasure","getSmartChartDefaults","chartConfig","buildChartConfig","timeDimension","dimensions","allBreakdowns","shouldAutoSwitchChartType","userManuallySelected","recommendedType","AnalysisResultsPanel","executionStatus","executionResults","executionError","totalRowCount","resultsStale","displayConfig","activeView","onActiveViewChange","displayLimit","onDisplayLimitChange","hasMetrics","debugQuery","debugSql","debugAnalysis","debugLoading","debugError","showDebug","setShowDebug","ChartIcon","TimeIcon","CodeIcon","renderLoading","renderError","hasQueryContent","renderWaiting","renderEmpty","renderNoData","renderChart","isValidChartType","LazyChart","renderDebug","Fragment","renderTable","limitedData","renderOverlaySpinner","renderSuccess","hasResults","MetricItemCard","metric","fieldMeta","onRemove","sortDirection","sortPriority","onToggleSort","ChevronUpIcon","ChevronDownIcon","ChevronUpDownIcon","measureType","MeasureIcon","displayTitle","getSortIcon","getSortTooltip","findFieldMeta","getNextSortDirection","current","MetricsSection","onAdd","order","onOrderChange","AddIcon","orderKeys","metricsWithMeta","nextDirection","TIME_GRANULARITIES","BreakdownItemCard","onGranularityChange","DimensionIcon","g","d","BreakdownSection","breakdownsWithMeta","granularity","TimeDimensionIcon","AnalysisFilterItem","onUpdate","depth","isOperatorDropdownOpen","setIsOperatorDropdownOpen","isValueDropdownOpen","setIsValueDropdownOpen","isDateRangeDropdownOpen","setIsDateRangeDropdownOpen","setRangeType","numberValue","setNumberValue","searchText","setSearchText","containerRef","debouncedSearchText","useDebounce","fieldInfo","isTimeField","isMeasureField","isDimensionField","fieldTitle","operatorMeta","availableOperators","shouldShowDateRange","shouldShowComboBox","distinctValues","valuesLoading","valuesError","searchValues","useFilterValues","handleClickOutside","event","flexMatch","num","DATE_RANGE_OPTIONS","handleOperatorChange","newFilter","handleValueSelect","value","values","handleValueRemove","valueToRemove","v","handleDirectInput","numValue","handleBetweenStartInput","currentValues","newValues","handleBetweenEndInput","handleDateInput","handleRangeTypeChange","newRangeType","dateRange","today","handleNumberValueChange","handleCustomStartDate","start","end","handleCustomEndDate","operatorLabel","op","dateRangeLabel","FieldIcon","iconColor","renderValueInput","index","AnalysisFilterGroup","group","onAddFilter","hideRemoveButton","isAddMenuOpen","setIsAddMenuOpen","addMenuRef","handleToggleType","newType","handleUpdateFilter","newFilters","handleRemoveFilter","_","handleAddNestedGroup","type","newGroup","handleAddFilterClick","createNestedAddFilterHandler","nestedIndex","relativePath","getBorderColor","getGroupBgColor","conditionCount","conditionLabel","countFilters","count","getSelectedFields","addFilterAtPath","path","firstIndex","restPath","targetFilter","AnalysisFilterSection","onFiltersChange","showFieldModal","setShowFieldModal","pendingAddPath","totalFilterCount","handleFieldSelected","_fieldType","_cubeName","defaultOperator","updatedFilters","handleUpdateTopLevelFilter","handleRemoveTopLevelFilter","handleClearAll","createAddFilterHandler","basePath","renderFilter","parentPath","currentPath","AnalysisAxisDropZone","config","onDrop","onDragStart","onDragEnd","onDragOver","onReorder","draggedItem","getFieldMeta","key","label","description","mandatory","maxItems","emptyText","dragOverIndex","setDragOverIndex","isDraggedOver","setIsDraggedOver","isReorderDraggedOver","setIsReorderDraggedOver","getCanAcceptMore","effectiveCount","getIsFull","canAcceptMore","isFull","React","handleGlobalDragEnd","handleReorderDragOver","targetIndex","handleReorderDragLeave","handleReorderDrop","data","getDefaultFieldMeta","parts","renderFieldIcon","IconComponent","rect","isLeavingContainer","relatedTarget","isRelatedTargetOutside","isDragOver","isBeingDragged","AnalysisChartConfigPanel","colorPalette","chartAvailability","onChartTypeChange","onChartConfigChange","onDisplayConfigChange","setDraggedItem","availableFields","chartTypeConfig","getChartConfig","chartConfigRegistry","shouldSkipQuery","getFieldsForDropZone","allAvailableFields","hasChanges","newConfig","dropZone","currentFields","validFields","getFieldType","schemaMeta","breakdownItem","handleDragStart","fromAxis","fromIndex","handleDragOver","handleDragEnd","handleDrop","toAxis","fromValue","filteredValue","toValue","dz","handleRemoveFromAxis","handleReorder","toIndex","axisKey","newArray","movedItem","unassignedFields","assignedFields","hasUnassignedFields","ChartTypeSelector","color","AnalysisQueryPanel","activeTab","onActiveTabChange","onAddMetric","onRemoveMetric","onAddBreakdown","onRemoveBreakdown","onBreakdownGranularityChange","STORAGE_KEY","AUTO_EXECUTE_DELAY","generateId","generateMetricLabel","n","buildCubeQuery","createInitialState","loadInitialStateFromStorage","disableLocalStorage","saved","AnalysisBuilder","forwardRef","className","maxHeight","initialQuery","disableLocalStorageProp","_hideSettings","onQueryChange","ref","cubeApi","useCubeContext","cachedStorage","state","setState","td","setChartType","setChartConfig","setDisplayConfig","setOrder","setActiveTab","setActiveView","setDisplayLimit","userManuallySelectedChart","setUserManuallySelectedChart","debugData","setDebugData","fieldModalMode","setFieldModalMode","currentQuery","currentQueryString","debouncedQuery","setDebouncedQuery","debounceTimerRef","lastQueryStringRef","isValidQuery","serverQuery","resultSet","isLoading","error","useCubeQuery","isChartConfigEmpty","val","newChartType","newChartConfig","smartDefaults","storageState","isCancelled","result","err","handleAddMetric","handleRemoveMetric","id","fieldToRemove","prevOrder","newOrder","existingIndex","newMetric","newBreakdown","handleAddBreakdown","handleRemoveBreakdown","handleBreakdownGranularityChange","handleFiltersChange","handleOrderChange","direction","handleClearQuery","handleChartTypeChange","useImperativeHandle"],"mappings":"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"}