drizzle-cube 0.2.8 → 0.2.10

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 (94) hide show
  1. package/dist/client/charts.js +15 -15
  2. package/dist/client/chunks/{chart-activitygridchart-Cz4bEf3V.js → chart-activitygridchart-C1ts13cL.js} +40 -40
  3. package/dist/client/chunks/chart-activitygridchart-C1ts13cL.js.map +1 -0
  4. package/dist/client/chunks/chart-activitygridchart-config-AVBoHdRn.js +244 -0
  5. package/dist/client/chunks/chart-activitygridchart-config-AVBoHdRn.js.map +1 -0
  6. package/dist/client/chunks/{chart-areachart-config-DWN1E5ej.js → chart-areachart-config-0ICuIaRP.js} +2 -2
  7. package/dist/client/chunks/{chart-areachart-config-DWN1E5ej.js.map → chart-areachart-config-0ICuIaRP.js.map} +1 -1
  8. package/dist/client/chunks/{chart-areachart-DLdolSnU.js → chart-areachart-fOi6lwUq.js} +3 -3
  9. package/dist/client/chunks/{chart-areachart-DLdolSnU.js.map → chart-areachart-fOi6lwUq.js.map} +1 -1
  10. package/dist/client/chunks/{chart-barchart-Bdjz8DJp.js → chart-barchart-CJfPZQin.js} +4 -4
  11. package/dist/client/chunks/{chart-barchart-Bdjz8DJp.js.map → chart-barchart-CJfPZQin.js.map} +1 -1
  12. package/dist/client/chunks/{chart-barchart-config-DZA0xTns.js → chart-barchart-config-DalFHdmP.js} +2 -2
  13. package/dist/client/chunks/{chart-barchart-config-DZA0xTns.js.map → chart-barchart-config-DalFHdmP.js.map} +1 -1
  14. package/dist/client/chunks/{chart-bubblechart-BlQkmqkI.js → chart-bubblechart-BVk_qFly.js} +2 -2
  15. package/dist/client/chunks/{chart-bubblechart-BlQkmqkI.js.map → chart-bubblechart-BVk_qFly.js.map} +1 -1
  16. package/dist/client/chunks/{chart-bubblechart-config-C79lfDSO.js → chart-bubblechart-config-WjiDlqnP.js} +2 -2
  17. package/dist/client/chunks/{chart-bubblechart-config-C79lfDSO.js.map → chart-bubblechart-config-WjiDlqnP.js.map} +1 -1
  18. package/dist/client/chunks/{chart-charttooltip-k8soCd2n.js → chart-charttooltip-5tzcFRt0.js} +2 -2
  19. package/dist/client/chunks/{chart-charttooltip-k8soCd2n.js.map → chart-charttooltip-5tzcFRt0.js.map} +1 -1
  20. package/dist/client/chunks/{chart-datatable-Mo4gYCwa.js → chart-datatable-BW_dWRbb.js} +3 -3
  21. package/dist/client/chunks/{chart-datatable-Mo4gYCwa.js.map → chart-datatable-BW_dWRbb.js.map} +1 -1
  22. package/dist/client/chunks/{chart-datatable-config-DqGw99R3.js → chart-datatable-config-C7TgMD3u.js} +2 -2
  23. package/dist/client/chunks/{chart-datatable-config-DqGw99R3.js.map → chart-datatable-config-C7TgMD3u.js.map} +1 -1
  24. package/dist/client/chunks/{chart-kpidelta-CTcuIO9G.js → chart-kpidelta-D_VuZaVL.js} +2 -2
  25. package/dist/client/chunks/{chart-kpidelta-CTcuIO9G.js.map → chart-kpidelta-D_VuZaVL.js.map} +1 -1
  26. package/dist/client/chunks/{chart-kpidelta-config-B-Y-LHmd.js → chart-kpidelta-config-DtSDG4Kl.js} +2 -2
  27. package/dist/client/chunks/{chart-kpidelta-config-B-Y-LHmd.js.map → chart-kpidelta-config-DtSDG4Kl.js.map} +1 -1
  28. package/dist/client/chunks/{chart-kpinumber-slEXt8C-.js → chart-kpinumber-DeCkVi2e.js} +4 -4
  29. package/dist/client/chunks/{chart-kpinumber-slEXt8C-.js.map → chart-kpinumber-DeCkVi2e.js.map} +1 -1
  30. package/dist/client/chunks/{chart-kpinumber-config-BaNaJMI6.js → chart-kpinumber-config-Da2LFeKM.js} +2 -2
  31. package/dist/client/chunks/{chart-kpinumber-config-BaNaJMI6.js.map → chart-kpinumber-config-Da2LFeKM.js.map} +1 -1
  32. package/dist/client/chunks/{chart-kpitext-giq03TOK.js → chart-kpitext-D8OpA0CY.js} +3 -3
  33. package/dist/client/chunks/{chart-kpitext-giq03TOK.js.map → chart-kpitext-D8OpA0CY.js.map} +1 -1
  34. package/dist/client/chunks/{chart-kpitext-config-BNywYqEW.js → chart-kpitext-config-DjvigyfE.js} +2 -2
  35. package/dist/client/chunks/{chart-kpitext-config-BNywYqEW.js.map → chart-kpitext-config-DjvigyfE.js.map} +1 -1
  36. package/dist/client/chunks/{chart-linechart-BfnU6L-D.js → chart-linechart-BdfBVl3m.js} +4 -4
  37. package/dist/client/chunks/{chart-linechart-BfnU6L-D.js.map → chart-linechart-BdfBVl3m.js.map} +1 -1
  38. package/dist/client/chunks/{chart-linechart-config-BL_1mjHF.js → chart-linechart-config-C5tpU_2u.js} +2 -2
  39. package/dist/client/chunks/{chart-linechart-config-BL_1mjHF.js.map → chart-linechart-config-C5tpU_2u.js.map} +1 -1
  40. package/dist/client/chunks/{chart-markdownchart-config-DtZOfYu4.js → chart-markdownchart-config-CgOA3YSw.js} +2 -2
  41. package/dist/client/chunks/{chart-markdownchart-config-DtZOfYu4.js.map → chart-markdownchart-config-CgOA3YSw.js.map} +1 -1
  42. package/dist/client/chunks/{chart-piechart-CZRDQxeB.js → chart-piechart-CiFJQtC8.js} +3 -3
  43. package/dist/client/chunks/{chart-piechart-CZRDQxeB.js.map → chart-piechart-CiFJQtC8.js.map} +1 -1
  44. package/dist/client/chunks/{chart-piechart-config-Bg4jeIFo.js → chart-piechart-config-CtP_JkGm.js} +2 -2
  45. package/dist/client/chunks/{chart-piechart-config-Bg4jeIFo.js.map → chart-piechart-config-CtP_JkGm.js.map} +1 -1
  46. package/dist/client/chunks/{chart-radarchart-D5yRnY9j.js → chart-radarchart-CJ4kpk5J.js} +3 -3
  47. package/dist/client/chunks/{chart-radarchart-D5yRnY9j.js.map → chart-radarchart-CJ4kpk5J.js.map} +1 -1
  48. package/dist/client/chunks/{chart-radarchart-config-d6dLkI7B.js → chart-radarchart-config-BkD_6Khq.js} +2 -2
  49. package/dist/client/chunks/{chart-radarchart-config-d6dLkI7B.js.map → chart-radarchart-config-BkD_6Khq.js.map} +1 -1
  50. package/dist/client/chunks/{chart-radialbarchart-Djtcn7aH.js → chart-radialbarchart-DLQqN_1Z.js} +3 -3
  51. package/dist/client/chunks/{chart-radialbarchart-Djtcn7aH.js.map → chart-radialbarchart-DLQqN_1Z.js.map} +1 -1
  52. package/dist/client/chunks/{chart-radialbarchart-config-BGf97-BV.js → chart-radialbarchart-config-CBZDlB2k.js} +2 -2
  53. package/dist/client/chunks/{chart-radialbarchart-config-BGf97-BV.js.map → chart-radialbarchart-config-CBZDlB2k.js.map} +1 -1
  54. package/dist/client/chunks/{chart-scatterchart-C83KgqYY.js → chart-scatterchart-DeGqPbYm.js} +2 -2
  55. package/dist/client/chunks/{chart-scatterchart-C83KgqYY.js.map → chart-scatterchart-DeGqPbYm.js.map} +1 -1
  56. package/dist/client/chunks/{chart-scatterchart-config-DEIB74ot.js → chart-scatterchart-config-DsdmlpHr.js} +2 -2
  57. package/dist/client/chunks/{chart-scatterchart-config-DEIB74ot.js.map → chart-scatterchart-config-DsdmlpHr.js.map} +1 -1
  58. package/dist/client/chunks/{chart-treemapchart-BDKnKGTz.js → chart-treemapchart-ClXsAOjr.js} +3 -3
  59. package/dist/client/chunks/{chart-treemapchart-BDKnKGTz.js.map → chart-treemapchart-ClXsAOjr.js.map} +1 -1
  60. package/dist/client/chunks/{chart-treemapchart-config-ppKPTB96.js → chart-treemapchart-config-CdF9NvPP.js} +2 -2
  61. package/dist/client/chunks/{chart-treemapchart-config-ppKPTB96.js.map → chart-treemapchart-config-CdF9NvPP.js.map} +1 -1
  62. package/dist/client/chunks/{charts-MJLpxe3r.js → charts-DY7pF_-4.js} +42 -42
  63. package/dist/client/chunks/{charts-MJLpxe3r.js.map → charts-DY7pF_-4.js.map} +1 -1
  64. package/dist/client/chunks/components-DAOVOiM_.js +13429 -0
  65. package/dist/client/chunks/components-DAOVOiM_.js.map +1 -0
  66. package/dist/client/chunks/{index-CSeLP8gq.js → index-DH5abYWH.js} +2 -2
  67. package/dist/client/chunks/{index-CSeLP8gq.js.map → index-DH5abYWH.js.map} +1 -1
  68. package/dist/client/components/AnalysisBuilder/AnalysisFilterSection.d.ts +3 -1
  69. package/dist/client/components/AnalysisBuilder/AnalysisQueryPanel.d.ts +2 -1
  70. package/dist/client/components/AnalysisBuilder/AnalysisResultsPanel.d.ts +2 -1
  71. package/dist/client/components/AnalysisBuilder/BreakdownItemCard.d.ts +3 -1
  72. package/dist/client/components/AnalysisBuilder/BreakdownSection.d.ts +3 -2
  73. package/dist/client/components/AnalysisBuilder/MetricItemCard.d.ts +3 -1
  74. package/dist/client/components/AnalysisBuilder/MetricsSection.d.ts +3 -2
  75. package/dist/client/components/AnalysisBuilder/types.d.ts +61 -0
  76. package/dist/client/components/PortletAnalysisModal.d.ts +25 -0
  77. package/dist/client/components.js +3 -3
  78. package/dist/client/hooks.js +2 -2
  79. package/dist/client/icons/registry.d.ts +1 -1
  80. package/dist/client/icons.js +1 -1
  81. package/dist/client/index.d.ts +1 -0
  82. package/dist/client/index.js +51 -3202
  83. package/dist/client/index.js.map +1 -1
  84. package/dist/client/providers/CubeProvider.d.ts +1 -1
  85. package/dist/client/providers.js +1 -1
  86. package/dist/client/styles.css +1 -1
  87. package/dist/client/types.d.ts +1 -0
  88. package/dist/client-bundle-stats.html +1 -1
  89. package/package.json +1 -1
  90. package/dist/client/chunks/chart-activitygridchart-Cz4bEf3V.js.map +0 -1
  91. package/dist/client/chunks/chart-activitygridchart-config-BngZDVh_.js +0 -236
  92. package/dist/client/chunks/chart-activitygridchart-config-BngZDVh_.js.map +0 -1
  93. package/dist/client/chunks/components-CXA6-jJq.js +0 -9845
  94. package/dist/client/chunks/components-CXA6-jJq.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { jsxs as o, jsx as t, Fragment as J } from "react/jsx-runtime";
2
2
  import { useMemo as j, useState as H, useEffect as T, useCallback as S } from "react";
3
3
  import Z, { Handle as P, Position as p, getBezierPath as K, BaseEdge as Q, EdgeLabelRenderer as U, useNodesState as _, useEdgesState as ee, addEdge as te, ConnectionMode as se, Controls as re, MiniMap as ne, Background as oe, BackgroundVariant as ae } from "reactflow";
4
- import { u as ie } from "./chart-activitygridchart-Cz4bEf3V.js";
4
+ import { u as ie } from "./chart-activitygridchart-C1ts13cL.js";
5
5
  import O from "dagre";
6
6
  function de({ data: i }) {
7
7
  const { cube: s, onFieldClick: f, isHighlighted: r, highlightedFields: w, searchTerm: m } = i, l = () => {
@@ -548,4 +548,4 @@ export {
548
548
  Ce as CubeRelationshipDiagram,
549
549
  Ce as default
550
550
  };
551
- //# sourceMappingURL=index-CSeLP8gq.js.map
551
+ //# sourceMappingURL=index-DH5abYWH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-CSeLP8gq.js","sources":["../../../src/client/components/CubeRelationshipDiagram/CubeNode.tsx","../../../src/client/components/CubeRelationshipDiagram/RelationshipEdge.tsx","../../../src/client/components/CubeRelationshipDiagram/useERDLayout.ts","../../../src/client/components/CubeRelationshipDiagram/index.tsx"],"sourcesContent":["import { Handle, Position } from 'reactflow'\nimport type { CubeMetaCube } from '../../hooks/useCubeMeta'\n\ninterface CubeNodeProps {\n data: {\n cube: CubeMetaCube\n onCubeClick?: (cubeName: string) => void\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension') => void\n isHighlighted: boolean\n highlightedFields: string[]\n searchTerm?: string\n }\n}\n\nexport function CubeNode({ data }: CubeNodeProps) {\n const { cube, onFieldClick, isHighlighted, highlightedFields, searchTerm } = data\n\n const handleCubeHeaderClick = () => {\n // Do nothing - disable cube header clicks in ERD\n }\n\n const handleFieldClick = (fieldName: string, fieldType: 'measure' | 'dimension') => {\n if (onFieldClick) {\n onFieldClick(cube.name, fieldName, fieldType)\n }\n }\n\n const isFieldHighlighted = (fullFieldName: string) => {\n return highlightedFields.includes(fullFieldName)\n }\n\n const isFieldSearchMatch = (field: { name: string; title?: string }) => {\n if (!searchTerm?.trim()) return true // No search term, show all fields\n \n const term = searchTerm.toLowerCase()\n return (\n field.name.toLowerCase().includes(term) ||\n (field.title && field.title.toLowerCase().includes(term))\n )\n }\n\n // Check if the cube has any matching fields\n const cubeHasMatches = () => {\n if (!searchTerm?.trim()) return true // No search term, show all cubes normally\n \n // Check if any measure matches\n const measureMatches = cube.measures.some(measure => isFieldSearchMatch(measure))\n \n // Check if any dimension matches\n const dimensionMatches = cube.dimensions.some(dimension => isFieldSearchMatch(dimension))\n \n return measureMatches || dimensionMatches\n }\n\n const hasCubeMatches = cubeHasMatches()\n\n const getFieldVisibilityClasses = (field: { name: string; title?: string; type?: string }, isHighlighted: boolean, fieldType: 'measure' | 'dimension') => {\n const isSearchMatch = isFieldSearchMatch(field)\n const baseClasses = 'px-4 py-2 text-xs cursor-pointer transition-all border-b border-dc-border last:border-b-0'\n\n // If the whole cube has no matches, rely on cube-level fading\n if (!hasCubeMatches && searchTerm?.trim()) {\n // Still show selected field highlighting even in faded cubes\n if (isHighlighted) {\n if (fieldType === 'measure') {\n return `${baseClasses} bg-amber-100 text-amber-800`\n } else if (fieldType === 'dimension') {\n if (field.type === 'time') {\n return `${baseClasses} bg-blue-100 text-blue-800`\n } else {\n return `${baseClasses} bg-green-100 text-green-800`\n }\n }\n }\n return `${baseClasses} hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n // If searching and this specific field doesn't match, make it faded\n if (searchTerm?.trim() && !isSearchMatch) {\n return `${baseClasses} opacity-40 hover:opacity-60 text-dc-text-muted`\n }\n\n // If searching and this field matches, make it prominent with bold purple text\n if (searchTerm?.trim() && isSearchMatch && !isHighlighted) {\n return `${baseClasses} font-bold hover:bg-purple-50`\n }\n\n // Normal highlighting behavior for selected fields (takes priority over search match styling)\n if (isHighlighted) {\n if (fieldType === 'measure') {\n return `${baseClasses} bg-amber-100 text-amber-800 font-semibold`\n } else if (fieldType === 'dimension') {\n // Check if this is a time dimension\n if (field.type === 'time') {\n return `${baseClasses} bg-blue-100 text-blue-800 font-semibold` // time dimensions\n } else {\n return `${baseClasses} bg-green-100 text-green-800 font-semibold` // regular dimensions\n }\n }\n }\n\n return `${baseClasses} hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n return (\n <div\n className={`\n border-2 rounded-lg shadow-lg min-w-[280px] overflow-hidden transition-all\n ${!hasCubeMatches && searchTerm?.trim() ? 'opacity-30 grayscale' : ''}\n ${isHighlighted ? 'border-purple-500 ring-2 ring-purple-200' : 'border-dc-border'}\n `}\n style={{\n backgroundColor: 'var(--dc-surface)'\n }}\n >\n {/* Cube Header */}\n <div\n className={`\n px-4 py-3 cursor-pointer transition-colors\n ${isHighlighted ? 'bg-purple-100 hover:bg-purple-200' : 'bg-dc-surface-secondary hover:bg-dc-surface-hover'}\n `}\n onClick={handleCubeHeaderClick}\n >\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"font-semibold text-dc-text text-sm\">\n {cube.title || cube.name}\n </h3>\n {cube.description && (\n <p className=\"text-xs text-dc-text-muted mt-1 line-clamp-2\">\n {cube.description}\n </p>\n )}\n </div>\n <div className=\"text-xs text-dc-text-muted ml-2\">\n <div>{cube.measures.length}M</div>\n <div>{cube.dimensions.length}D</div>\n </div>\n </div>\n </div>\n\n {/* Measures Section */}\n {cube.measures.length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-amber-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-amber-800 flex items-center\">\n <span className=\"w-2 h-2 bg-amber-500 rounded-full mr-2\"></span>\n Measures ({cube.measures.length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.measures.map((measure) => {\n const fieldName = measure.name.split('.')[1] || measure.name\n const highlighted = isFieldHighlighted(measure.name)\n return (\n <div\n key={measure.name}\n className={getFieldVisibilityClasses(measure, highlighted, 'measure')}\n onClick={() => handleFieldClick(fieldName, 'measure')}\n title={measure.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {measure.shortTitle || measure.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {measure.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Time Dimensions Section */}\n {cube.dimensions.filter(d => d.type === 'time').length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-blue-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-blue-800 flex items-center\">\n <span className=\"w-2 h-2 bg-blue-500 rounded-full mr-2\"></span>\n Time Dimensions ({cube.dimensions.filter(d => d.type === 'time').length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.dimensions.filter(d => d.type === 'time').map((dimension) => {\n const fieldName = dimension.name.split('.')[1] || dimension.name\n const highlighted = isFieldHighlighted(dimension.name)\n return (\n <div\n key={dimension.name}\n className={getFieldVisibilityClasses(dimension, highlighted, 'dimension')}\n onClick={() => handleFieldClick(fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Dimensions Section (non-time) */}\n {cube.dimensions.filter(d => d.type !== 'time').length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-green-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-green-800 flex items-center\">\n <span className=\"w-2 h-2 bg-green-500 rounded-full mr-2\"></span>\n Dimensions ({cube.dimensions.filter(d => d.type !== 'time').length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.dimensions.filter(d => d.type !== 'time').map((dimension) => {\n const fieldName = dimension.name.split('.')[1] || dimension.name\n const highlighted = isFieldHighlighted(dimension.name)\n return (\n <div\n key={dimension.name}\n className={getFieldVisibilityClasses(dimension, highlighted, 'dimension')}\n onClick={() => handleFieldClick(fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Connection handles for relationships - hidden */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"right\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"left\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"source\"\n position={Position.Bottom}\n id=\"bottom\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"top\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n </div>\n )\n}\n\nexport default CubeNode","import { \n EdgeProps, \n getBezierPath, \n EdgeLabelRenderer,\n BaseEdge,\n} from 'reactflow'\nimport type { CubeMetaRelationship } from '../../hooks/useCubeMeta'\n\ninterface RelationshipEdgeData {\n relationship: CubeMetaRelationship\n joinFields: Array<{\n sourceField: string\n targetField: string\n }>\n}\n\nexport function RelationshipEdge({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n}: EdgeProps<RelationshipEdgeData>) {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n\n if (!data) return null\n\n const { relationship, joinFields } = data\n\n // Get relationship symbols and colors\n const getRelationshipSymbol = (rel: string) => {\n switch (rel) {\n case 'belongsTo':\n return '∈' // belongs to symbol\n case 'hasOne':\n return '1:1'\n case 'hasMany':\n return '1:M'\n default:\n return '?'\n }\n }\n\n const getRelationshipColor = (rel: string) => {\n switch (rel) {\n case 'belongsTo':\n return '#10b981' // green\n case 'hasOne':\n return '#3b82f6' // blue\n case 'hasMany':\n return '#f59e0b' // amber\n default:\n return '#6b7280' // gray\n }\n }\n\n const color = getRelationshipColor(relationship.relationship)\n const symbol = getRelationshipSymbol(relationship.relationship)\n\n return (\n <>\n <BaseEdge path={edgePath} markerEnd={markerEnd} style={{ ...style, stroke: color }} />\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n fontSize: 10,\n pointerEvents: 'all',\n }}\n className=\"nodrag nopan\"\n >\n <div\n className=\"border-2 rounded-md px-2 py-1 shadow-xs\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: color\n }}\n >\n <div className=\"text-center\">\n <div\n className=\"font-bold text-xs mb-1\"\n style={{ color }}\n >\n {symbol}\n </div>\n <div className=\"text-[9px] text-dc-text-muted leading-tight\">\n {joinFields.map((field, index) => (\n <div key={index} className=\"font-mono\">\n {field.sourceField} → {field.targetField}\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </EdgeLabelRenderer>\n </>\n )\n}\n\nexport default RelationshipEdge","import { useMemo } from 'react'\nimport { Node, Edge, Position } from 'reactflow'\nimport dagre from 'dagre'\n\nexport interface LayoutOptions {\n direction: 'TB' | 'BT' | 'LR' | 'RL'\n nodeWidth: number\n nodeHeight: number\n nodeSep: number\n rankSep: number\n ranker: 'network-simplex' | 'tight-tree' | 'longest-path'\n}\n\nconst defaultOptions: LayoutOptions = {\n direction: 'TB',\n nodeWidth: 320,\n nodeHeight: 220,\n nodeSep: 80,\n rankSep: 150,\n ranker: 'network-simplex',\n}\n\nexport function useERDLayout(\n nodes: Node[],\n edges: Edge[],\n options: Partial<LayoutOptions> = {}\n): { nodes: Node[], edges: Edge[] } {\n const layoutOptions = useMemo(() => ({ ...defaultOptions, ...options }), [options])\n\n const { layoutedNodes, layoutedEdges } = useMemo(() => {\n if (nodes.length === 0) {\n return { layoutedNodes: [], layoutedEdges: [] }\n }\n\n // Create a new dagre graph\n const dagreGraph = new dagre.graphlib.Graph()\n dagreGraph.setDefaultEdgeLabel(() => ({}))\n dagreGraph.setGraph({ \n rankdir: layoutOptions.direction,\n nodesep: layoutOptions.nodeSep,\n ranksep: layoutOptions.rankSep,\n ranker: layoutOptions.ranker,\n })\n\n // Add nodes to the graph\n nodes.forEach((node) => {\n dagreGraph.setNode(node.id, { \n width: layoutOptions.nodeWidth, \n height: layoutOptions.nodeHeight \n })\n })\n\n // Add edges to the graph\n edges.forEach((edge) => {\n dagreGraph.setEdge(edge.source, edge.target)\n })\n\n // Run the layout algorithm\n dagre.layout(dagreGraph)\n\n // Apply the calculated positions to nodes\n const layoutedNodes = nodes.map((node) => {\n const nodeWithPosition = dagreGraph.node(node.id)\n \n const newNode = {\n ...node,\n targetPosition: getTargetPosition(layoutOptions.direction),\n sourcePosition: getSourcePosition(layoutOptions.direction),\n position: {\n x: nodeWithPosition.x - layoutOptions.nodeWidth / 2,\n y: nodeWithPosition.y - layoutOptions.nodeHeight / 2,\n },\n }\n\n return newNode\n })\n\n return { \n layoutedNodes, \n layoutedEdges: edges \n }\n }, [nodes, edges, layoutOptions.direction, layoutOptions.nodeSep, layoutOptions.rankSep, layoutOptions.ranker, layoutOptions.nodeWidth, layoutOptions.nodeHeight])\n\n return { nodes: layoutedNodes, edges: layoutedEdges }\n}\n\n// Helper functions to determine handle positions based on layout direction\nfunction getTargetPosition(direction: string): Position {\n switch (direction) {\n case 'TB':\n return Position.Top\n case 'BT':\n return Position.Bottom\n case 'LR':\n return Position.Left\n case 'RL':\n return Position.Right\n default:\n return Position.Top\n }\n}\n\nfunction getSourcePosition(direction: string): Position {\n switch (direction) {\n case 'TB':\n return Position.Bottom\n case 'BT':\n return Position.Top\n case 'LR':\n return Position.Right\n case 'RL':\n return Position.Left\n default:\n return Position.Bottom\n }\n}\n\n// Custom layout function for manual positioning with smart defaults\nexport function useManualLayout(\n nodes: Node[],\n edges: Edge[],\n spacing = { x: 400, y: 300 }\n): { nodes: Node[], edges: Edge[] } {\n return useMemo(() => {\n if (nodes.length === 0) {\n return { nodes: [], edges }\n }\n\n // Simple grid layout as fallback\n const layoutedNodes = nodes.map((node, index) => ({\n ...node,\n position: {\n x: (index % 3) * spacing.x,\n y: Math.floor(index / 3) * spacing.y,\n },\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n }))\n\n return { nodes: layoutedNodes, edges }\n }, [nodes, edges, spacing])\n}\n\nexport default useERDLayout","import { useCallback, useMemo, useEffect, useState } from 'react'\nimport ReactFlow, {\n Node,\n Edge,\n addEdge,\n Connection,\n useNodesState,\n useEdgesState,\n Controls,\n MiniMap,\n Background,\n BackgroundVariant,\n ConnectionMode,\n} from 'reactflow'\nimport 'reactflow/dist/style.css'\n\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { CubeNode } from './CubeNode'\nimport { RelationshipEdge } from './RelationshipEdge'\nimport { useERDLayout } from './useERDLayout'\n\n// Define the custom node and edge types OUTSIDE the component to prevent re-creation\nconst nodeTypes = {\n cubeNode: CubeNode,\n}\n\nconst edgeTypes = {\n relationshipEdge: RelationshipEdge,\n}\n\ninterface CubeRelationshipDiagramProps {\n className?: string\n onCubeClick?: (cubeName: string) => void\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension') => void\n highlightedCubes?: string[]\n highlightedFields?: string[]\n searchTerm?: string\n}\n\nexport function CubeRelationshipDiagram({\n className = '',\n onCubeClick,\n onFieldClick,\n highlightedCubes = [],\n highlightedFields = [],\n searchTerm,\n}: CubeRelationshipDiagramProps) {\n const { meta, metaLoading, metaError } = useCubeContext()\n\n const [savedPositions, setSavedPositions] = useState<Record<string, {x: number, y: number}>>({})\n const [autoLayoutRequested, setAutoLayoutRequested] = useState(false)\n const [contextMenu, setContextMenu] = useState<{x: number, y: number} | null>(null)\n\n // Load saved positions from localStorage on mount\n useEffect(() => {\n try {\n const savedPos = localStorage.getItem('drizzle-cube-erd-node-positions')\n if (savedPos) {\n setSavedPositions(JSON.parse(savedPos))\n }\n } catch (error) {\n // Ignore localStorage errors\n }\n }, [])\n\n // Create base nodes and edges structure (without selection data)\n const { nodes: baseNodes, edges: baseEdges } = useMemo(() => {\n if (!meta) return { nodes: [], edges: [] }\n\n const nodes: Node[] = []\n const edges: Edge[] = []\n\n // Create nodes for each cube\n meta.cubes.forEach((cube, index) => {\n nodes.push({\n id: cube.name,\n type: 'cubeNode',\n position: savedPositions[cube.name] || { x: (index % 3) * 400, y: Math.floor(index / 3) * 300 },\n data: {\n cube,\n onCubeClick,\n onFieldClick,\n isHighlighted: false, // Will be updated separately\n highlightedFields: [], // Will be updated separately\n },\n })\n })\n\n // Create edges for relationships (excluding belongsTo)\n meta.cubes.forEach(cube => {\n if (cube.relationships) {\n cube.relationships.forEach((relationship, index) => {\n // Skip belongsTo relationships\n if (relationship.relationship === 'belongsTo') {\n return\n }\n \n const edgeId = `${cube.name}-${relationship.targetCube}-${index}`\n edges.push({\n id: edgeId,\n source: cube.name,\n target: relationship.targetCube,\n type: 'relationshipEdge',\n data: {\n relationship,\n joinFields: relationship.joinFields,\n },\n animated: false,\n style: {\n stroke: getRelationshipColor(relationship.relationship),\n strokeWidth: 2,\n },\n })\n })\n }\n })\n\n return { nodes, edges }\n }, [meta, onCubeClick, onFieldClick, savedPositions])\n\n // Apply auto-layout when explicitly requested or if no saved positions\n const needsAutoLayout = autoLayoutRequested || Object.keys(savedPositions).length === 0\n \n // Get auto-layout result\n const { nodes: autoLayoutedNodes, edges: autoLayoutedEdges } = useERDLayout(baseNodes, baseEdges, {\n direction: 'LR',\n nodeWidth: 320,\n nodeHeight: 220,\n nodeSep: 100,\n rankSep: 200\n })\n \n // Use auto-layout or base nodes based on needsAutoLayout, and update selection data\n const layoutedNodes = useMemo(() => {\n const nodes = needsAutoLayout ? autoLayoutedNodes : baseNodes\n return nodes.map((node) => ({\n ...node,\n data: {\n ...node.data,\n isHighlighted: highlightedCubes.includes(node.id),\n highlightedFields: highlightedFields,\n searchTerm: searchTerm,\n }\n }))\n }, [needsAutoLayout, autoLayoutedNodes, baseNodes, highlightedCubes, highlightedFields, searchTerm])\n \n const layoutedEdges = needsAutoLayout ? autoLayoutedEdges : baseEdges\n \n // Reset auto-layout request and clear saved positions when auto-layout is applied\n useEffect(() => {\n if (autoLayoutRequested && layoutedNodes.length > 0) {\n // Clear saved positions so we use the new auto-layout positions\n setSavedPositions({})\n try {\n localStorage.removeItem('drizzle-cube-erd-node-positions')\n } catch (error) {\n // Ignore localStorage errors\n }\n setAutoLayoutRequested(false)\n }\n }, [autoLayoutRequested, layoutedNodes])\n\n const [nodes, setNodes, onNodesChange] = useNodesState(layoutedNodes)\n const [edges, setEdges, onEdgesChange] = useEdgesState(layoutedEdges)\n\n\n // Sync React Flow nodes with layout changes\n useEffect(() => {\n setNodes(layoutedNodes)\n }, [layoutedNodes, setNodes])\n\n // Sync React Flow edges with changes\n useEffect(() => {\n setEdges(layoutedEdges)\n }, [layoutedEdges, setEdges])\n\n // Save node positions to localStorage when manually moved\n const handleNodesChange = useCallback((changes: any[]) => {\n onNodesChange(changes)\n \n // Check if any nodes were dragged and save positions\n const dragChanges = changes.filter(change => change.type === 'position' && change.dragging === false)\n if (dragChanges.length > 0) {\n setNodes((currentNodes) => {\n const newPositions: Record<string, {x: number, y: number}> = {}\n currentNodes.forEach(node => {\n if (node.position) {\n newPositions[node.id] = node.position\n }\n })\n \n // Save to localStorage\n try {\n localStorage.setItem('drizzle-cube-erd-node-positions', JSON.stringify(newPositions))\n } catch (error) {\n // Ignore localStorage errors\n }\n \n setSavedPositions(newPositions)\n return currentNodes\n })\n }\n }, [onNodesChange, setNodes])\n\n const onConnect = useCallback(\n (params: Connection) => setEdges((eds) => addEdge(params, eds)),\n [setEdges]\n )\n\n // Handle right-click context menu\n const handleContextMenu = useCallback((event: React.MouseEvent) => {\n event.preventDefault()\n event.stopPropagation()\n console.log('Context menu triggered at:', event.clientX, event.clientY) // Debug\n setContextMenu({\n x: event.clientX,\n y: event.clientY,\n })\n }, [])\n\n // Close context menu when clicking elsewhere\n const handleClick = useCallback(() => {\n if (contextMenu) {\n setContextMenu(null)\n }\n }, [contextMenu])\n\n // Handle auto layout from context menu\n const handleAutoLayout = useCallback(() => {\n setAutoLayoutRequested(true)\n setContextMenu(null)\n }, [])\n\n\n // Loading state\n if (metaLoading) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-2\"></div>\n <p className=\"text-dc-text-muted\">Loading cube schema...</p>\n </div>\n </div>\n )\n }\n\n // Error state\n if (metaError) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center text-red-500\">\n <p className=\"font-medium\">Failed to load cube schema</p>\n <p className=\"text-sm mt-1\">{metaError}</p>\n </div>\n </div>\n )\n }\n\n // Empty state\n if (!meta || meta.cubes.length === 0) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center text-dc-text-muted\">\n <p className=\"font-medium\">No cubes found</p>\n <p className=\"text-sm mt-1\">Register some cubes to see the relationship diagram</p>\n </div>\n </div>\n )\n }\n\n return (\n <div className={`h-full ${className}`} style={{ height: '600px' }}>\n <div className=\"h-full\">\n <ReactFlow\n nodes={nodes}\n edges={edges}\n onNodesChange={handleNodesChange}\n onEdgesChange={onEdgesChange}\n onConnect={onConnect}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n connectionMode={ConnectionMode.Loose}\n fitView // Always fit view to show entire ERD\n minZoom={0.1}\n maxZoom={2}\n defaultViewport={{ x: 0, y: 0, zoom: 0.8 }}\n proOptions={{ hideAttribution: true }}\n onPaneContextMenu={handleContextMenu}\n onPaneClick={handleClick}\n >\n <Controls />\n <MiniMap \n nodeColor={(node) => {\n const isHighlighted = highlightedCubes.includes(node.id)\n return isHighlighted ? '#8b5cf6' : '#e5e7eb'\n }}\n maskColor=\"rgb(240, 242, 246, 0.7)\"\n />\n <Background variant={BackgroundVariant.Dots} gap={12} size={1} />\n </ReactFlow>\n </div>\n\n {/* Context Menu */}\n {contextMenu && (\n <div\n className=\"fixed z-50 bg-dc-surface rounded-md shadow-lg border border-dc-border py-1 min-w-[120px]\"\n style={{\n left: contextMenu.x,\n top: contextMenu.y,\n }}\n >\n <button\n onClick={handleAutoLayout}\n className=\"w-full px-3 py-2 text-sm text-dc-text-secondary hover:bg-dc-surface-hover text-left\"\n >\n Auto Layout\n </button>\n </div>\n )}\n </div>\n )\n}\n\n// Helper function to get relationship colors\nfunction getRelationshipColor(relationship: 'belongsTo' | 'hasOne' | 'hasMany'): string {\n switch (relationship) {\n case 'belongsTo':\n return '#10b981' // green\n case 'hasOne':\n return '#3b82f6' // blue\n case 'hasMany':\n return '#f59e0b' // amber\n default:\n return '#6b7280' // gray\n }\n}\n\nexport default CubeRelationshipDiagram"],"names":["CubeNode","data","cube","onFieldClick","isHighlighted","highlightedFields","searchTerm","handleCubeHeaderClick","handleFieldClick","fieldName","fieldType","isFieldHighlighted","fullFieldName","isFieldSearchMatch","field","term","hasCubeMatches","measureMatches","measure","dimensionMatches","dimension","getFieldVisibilityClasses","isSearchMatch","baseClasses","jsxs","jsx","highlighted","d","Handle","Position","RelationshipEdge","sourceX","sourceY","targetX","targetY","sourcePosition","targetPosition","style","markerEnd","edgePath","labelX","labelY","getBezierPath","relationship","joinFields","getRelationshipSymbol","rel","color","symbol","Fragment","BaseEdge","EdgeLabelRenderer","index","defaultOptions","useERDLayout","nodes","edges","options","layoutOptions","useMemo","layoutedNodes","layoutedEdges","dagreGraph","dagre","node","edge","nodeWithPosition","getTargetPosition","getSourcePosition","direction","nodeTypes","edgeTypes","CubeRelationshipDiagram","className","onCubeClick","highlightedCubes","meta","metaLoading","metaError","useCubeContext","savedPositions","setSavedPositions","useState","autoLayoutRequested","setAutoLayoutRequested","contextMenu","setContextMenu","useEffect","savedPos","baseNodes","baseEdges","edgeId","getRelationshipColor","needsAutoLayout","autoLayoutedNodes","autoLayoutedEdges","setNodes","onNodesChange","useNodesState","setEdges","onEdgesChange","useEdgesState","handleNodesChange","useCallback","changes","change","currentNodes","newPositions","onConnect","params","eds","addEdge","handleContextMenu","event","handleClick","handleAutoLayout","ReactFlow","ConnectionMode","Controls","MiniMap","Background","BackgroundVariant"],"mappings":"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"}
1
+ {"version":3,"file":"index-DH5abYWH.js","sources":["../../../src/client/components/CubeRelationshipDiagram/CubeNode.tsx","../../../src/client/components/CubeRelationshipDiagram/RelationshipEdge.tsx","../../../src/client/components/CubeRelationshipDiagram/useERDLayout.ts","../../../src/client/components/CubeRelationshipDiagram/index.tsx"],"sourcesContent":["import { Handle, Position } from 'reactflow'\nimport type { CubeMetaCube } from '../../hooks/useCubeMeta'\n\ninterface CubeNodeProps {\n data: {\n cube: CubeMetaCube\n onCubeClick?: (cubeName: string) => void\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension') => void\n isHighlighted: boolean\n highlightedFields: string[]\n searchTerm?: string\n }\n}\n\nexport function CubeNode({ data }: CubeNodeProps) {\n const { cube, onFieldClick, isHighlighted, highlightedFields, searchTerm } = data\n\n const handleCubeHeaderClick = () => {\n // Do nothing - disable cube header clicks in ERD\n }\n\n const handleFieldClick = (fieldName: string, fieldType: 'measure' | 'dimension') => {\n if (onFieldClick) {\n onFieldClick(cube.name, fieldName, fieldType)\n }\n }\n\n const isFieldHighlighted = (fullFieldName: string) => {\n return highlightedFields.includes(fullFieldName)\n }\n\n const isFieldSearchMatch = (field: { name: string; title?: string }) => {\n if (!searchTerm?.trim()) return true // No search term, show all fields\n \n const term = searchTerm.toLowerCase()\n return (\n field.name.toLowerCase().includes(term) ||\n (field.title && field.title.toLowerCase().includes(term))\n )\n }\n\n // Check if the cube has any matching fields\n const cubeHasMatches = () => {\n if (!searchTerm?.trim()) return true // No search term, show all cubes normally\n \n // Check if any measure matches\n const measureMatches = cube.measures.some(measure => isFieldSearchMatch(measure))\n \n // Check if any dimension matches\n const dimensionMatches = cube.dimensions.some(dimension => isFieldSearchMatch(dimension))\n \n return measureMatches || dimensionMatches\n }\n\n const hasCubeMatches = cubeHasMatches()\n\n const getFieldVisibilityClasses = (field: { name: string; title?: string; type?: string }, isHighlighted: boolean, fieldType: 'measure' | 'dimension') => {\n const isSearchMatch = isFieldSearchMatch(field)\n const baseClasses = 'px-4 py-2 text-xs cursor-pointer transition-all border-b border-dc-border last:border-b-0'\n\n // If the whole cube has no matches, rely on cube-level fading\n if (!hasCubeMatches && searchTerm?.trim()) {\n // Still show selected field highlighting even in faded cubes\n if (isHighlighted) {\n if (fieldType === 'measure') {\n return `${baseClasses} bg-amber-100 text-amber-800`\n } else if (fieldType === 'dimension') {\n if (field.type === 'time') {\n return `${baseClasses} bg-blue-100 text-blue-800`\n } else {\n return `${baseClasses} bg-green-100 text-green-800`\n }\n }\n }\n return `${baseClasses} hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n // If searching and this specific field doesn't match, make it faded\n if (searchTerm?.trim() && !isSearchMatch) {\n return `${baseClasses} opacity-40 hover:opacity-60 text-dc-text-muted`\n }\n\n // If searching and this field matches, make it prominent with bold purple text\n if (searchTerm?.trim() && isSearchMatch && !isHighlighted) {\n return `${baseClasses} font-bold hover:bg-purple-50`\n }\n\n // Normal highlighting behavior for selected fields (takes priority over search match styling)\n if (isHighlighted) {\n if (fieldType === 'measure') {\n return `${baseClasses} bg-amber-100 text-amber-800 font-semibold`\n } else if (fieldType === 'dimension') {\n // Check if this is a time dimension\n if (field.type === 'time') {\n return `${baseClasses} bg-blue-100 text-blue-800 font-semibold` // time dimensions\n } else {\n return `${baseClasses} bg-green-100 text-green-800 font-semibold` // regular dimensions\n }\n }\n }\n\n return `${baseClasses} hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n return (\n <div\n className={`\n border-2 rounded-lg shadow-lg min-w-[280px] overflow-hidden transition-all\n ${!hasCubeMatches && searchTerm?.trim() ? 'opacity-30 grayscale' : ''}\n ${isHighlighted ? 'border-purple-500 ring-2 ring-purple-200' : 'border-dc-border'}\n `}\n style={{\n backgroundColor: 'var(--dc-surface)'\n }}\n >\n {/* Cube Header */}\n <div\n className={`\n px-4 py-3 cursor-pointer transition-colors\n ${isHighlighted ? 'bg-purple-100 hover:bg-purple-200' : 'bg-dc-surface-secondary hover:bg-dc-surface-hover'}\n `}\n onClick={handleCubeHeaderClick}\n >\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"font-semibold text-dc-text text-sm\">\n {cube.title || cube.name}\n </h3>\n {cube.description && (\n <p className=\"text-xs text-dc-text-muted mt-1 line-clamp-2\">\n {cube.description}\n </p>\n )}\n </div>\n <div className=\"text-xs text-dc-text-muted ml-2\">\n <div>{cube.measures.length}M</div>\n <div>{cube.dimensions.length}D</div>\n </div>\n </div>\n </div>\n\n {/* Measures Section */}\n {cube.measures.length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-amber-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-amber-800 flex items-center\">\n <span className=\"w-2 h-2 bg-amber-500 rounded-full mr-2\"></span>\n Measures ({cube.measures.length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.measures.map((measure) => {\n const fieldName = measure.name.split('.')[1] || measure.name\n const highlighted = isFieldHighlighted(measure.name)\n return (\n <div\n key={measure.name}\n className={getFieldVisibilityClasses(measure, highlighted, 'measure')}\n onClick={() => handleFieldClick(fieldName, 'measure')}\n title={measure.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {measure.shortTitle || measure.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {measure.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Time Dimensions Section */}\n {cube.dimensions.filter(d => d.type === 'time').length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-blue-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-blue-800 flex items-center\">\n <span className=\"w-2 h-2 bg-blue-500 rounded-full mr-2\"></span>\n Time Dimensions ({cube.dimensions.filter(d => d.type === 'time').length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.dimensions.filter(d => d.type === 'time').map((dimension) => {\n const fieldName = dimension.name.split('.')[1] || dimension.name\n const highlighted = isFieldHighlighted(dimension.name)\n return (\n <div\n key={dimension.name}\n className={getFieldVisibilityClasses(dimension, highlighted, 'dimension')}\n onClick={() => handleFieldClick(fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Dimensions Section (non-time) */}\n {cube.dimensions.filter(d => d.type !== 'time').length > 0 && (\n <div className=\"border-t border-dc-border\">\n <div className=\"px-4 py-2 bg-green-50 border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-green-800 flex items-center\">\n <span className=\"w-2 h-2 bg-green-500 rounded-full mr-2\"></span>\n Dimensions ({cube.dimensions.filter(d => d.type !== 'time').length})\n </h4>\n </div>\n <div className=\"max-h-32 overflow-y-auto\">\n {cube.dimensions.filter(d => d.type !== 'time').map((dimension) => {\n const fieldName = dimension.name.split('.')[1] || dimension.name\n const highlighted = isFieldHighlighted(dimension.name)\n return (\n <div\n key={dimension.name}\n className={getFieldVisibilityClasses(dimension, highlighted, 'dimension')}\n onClick={() => handleFieldClick(fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"font-mono truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted ml-2 text-[10px] uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Connection handles for relationships - hidden */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"right\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"left\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"source\"\n position={Position.Bottom}\n id=\"bottom\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"top\"\n className=\"opacity-0\"\n isConnectable={false}\n />\n </div>\n )\n}\n\nexport default CubeNode","import { \n EdgeProps, \n getBezierPath, \n EdgeLabelRenderer,\n BaseEdge,\n} from 'reactflow'\nimport type { CubeMetaRelationship } from '../../hooks/useCubeMeta'\n\ninterface RelationshipEdgeData {\n relationship: CubeMetaRelationship\n joinFields: Array<{\n sourceField: string\n targetField: string\n }>\n}\n\nexport function RelationshipEdge({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n}: EdgeProps<RelationshipEdgeData>) {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n\n if (!data) return null\n\n const { relationship, joinFields } = data\n\n // Get relationship symbols and colors\n const getRelationshipSymbol = (rel: string) => {\n switch (rel) {\n case 'belongsTo':\n return '∈' // belongs to symbol\n case 'hasOne':\n return '1:1'\n case 'hasMany':\n return '1:M'\n default:\n return '?'\n }\n }\n\n const getRelationshipColor = (rel: string) => {\n switch (rel) {\n case 'belongsTo':\n return '#10b981' // green\n case 'hasOne':\n return '#3b82f6' // blue\n case 'hasMany':\n return '#f59e0b' // amber\n default:\n return '#6b7280' // gray\n }\n }\n\n const color = getRelationshipColor(relationship.relationship)\n const symbol = getRelationshipSymbol(relationship.relationship)\n\n return (\n <>\n <BaseEdge path={edgePath} markerEnd={markerEnd} style={{ ...style, stroke: color }} />\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n fontSize: 10,\n pointerEvents: 'all',\n }}\n className=\"nodrag nopan\"\n >\n <div\n className=\"border-2 rounded-md px-2 py-1 shadow-xs\"\n style={{\n backgroundColor: 'var(--dc-surface)',\n borderColor: color\n }}\n >\n <div className=\"text-center\">\n <div\n className=\"font-bold text-xs mb-1\"\n style={{ color }}\n >\n {symbol}\n </div>\n <div className=\"text-[9px] text-dc-text-muted leading-tight\">\n {joinFields.map((field, index) => (\n <div key={index} className=\"font-mono\">\n {field.sourceField} → {field.targetField}\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </EdgeLabelRenderer>\n </>\n )\n}\n\nexport default RelationshipEdge","import { useMemo } from 'react'\nimport { Node, Edge, Position } from 'reactflow'\nimport dagre from 'dagre'\n\nexport interface LayoutOptions {\n direction: 'TB' | 'BT' | 'LR' | 'RL'\n nodeWidth: number\n nodeHeight: number\n nodeSep: number\n rankSep: number\n ranker: 'network-simplex' | 'tight-tree' | 'longest-path'\n}\n\nconst defaultOptions: LayoutOptions = {\n direction: 'TB',\n nodeWidth: 320,\n nodeHeight: 220,\n nodeSep: 80,\n rankSep: 150,\n ranker: 'network-simplex',\n}\n\nexport function useERDLayout(\n nodes: Node[],\n edges: Edge[],\n options: Partial<LayoutOptions> = {}\n): { nodes: Node[], edges: Edge[] } {\n const layoutOptions = useMemo(() => ({ ...defaultOptions, ...options }), [options])\n\n const { layoutedNodes, layoutedEdges } = useMemo(() => {\n if (nodes.length === 0) {\n return { layoutedNodes: [], layoutedEdges: [] }\n }\n\n // Create a new dagre graph\n const dagreGraph = new dagre.graphlib.Graph()\n dagreGraph.setDefaultEdgeLabel(() => ({}))\n dagreGraph.setGraph({ \n rankdir: layoutOptions.direction,\n nodesep: layoutOptions.nodeSep,\n ranksep: layoutOptions.rankSep,\n ranker: layoutOptions.ranker,\n })\n\n // Add nodes to the graph\n nodes.forEach((node) => {\n dagreGraph.setNode(node.id, { \n width: layoutOptions.nodeWidth, \n height: layoutOptions.nodeHeight \n })\n })\n\n // Add edges to the graph\n edges.forEach((edge) => {\n dagreGraph.setEdge(edge.source, edge.target)\n })\n\n // Run the layout algorithm\n dagre.layout(dagreGraph)\n\n // Apply the calculated positions to nodes\n const layoutedNodes = nodes.map((node) => {\n const nodeWithPosition = dagreGraph.node(node.id)\n \n const newNode = {\n ...node,\n targetPosition: getTargetPosition(layoutOptions.direction),\n sourcePosition: getSourcePosition(layoutOptions.direction),\n position: {\n x: nodeWithPosition.x - layoutOptions.nodeWidth / 2,\n y: nodeWithPosition.y - layoutOptions.nodeHeight / 2,\n },\n }\n\n return newNode\n })\n\n return { \n layoutedNodes, \n layoutedEdges: edges \n }\n }, [nodes, edges, layoutOptions.direction, layoutOptions.nodeSep, layoutOptions.rankSep, layoutOptions.ranker, layoutOptions.nodeWidth, layoutOptions.nodeHeight])\n\n return { nodes: layoutedNodes, edges: layoutedEdges }\n}\n\n// Helper functions to determine handle positions based on layout direction\nfunction getTargetPosition(direction: string): Position {\n switch (direction) {\n case 'TB':\n return Position.Top\n case 'BT':\n return Position.Bottom\n case 'LR':\n return Position.Left\n case 'RL':\n return Position.Right\n default:\n return Position.Top\n }\n}\n\nfunction getSourcePosition(direction: string): Position {\n switch (direction) {\n case 'TB':\n return Position.Bottom\n case 'BT':\n return Position.Top\n case 'LR':\n return Position.Right\n case 'RL':\n return Position.Left\n default:\n return Position.Bottom\n }\n}\n\n// Custom layout function for manual positioning with smart defaults\nexport function useManualLayout(\n nodes: Node[],\n edges: Edge[],\n spacing = { x: 400, y: 300 }\n): { nodes: Node[], edges: Edge[] } {\n return useMemo(() => {\n if (nodes.length === 0) {\n return { nodes: [], edges }\n }\n\n // Simple grid layout as fallback\n const layoutedNodes = nodes.map((node, index) => ({\n ...node,\n position: {\n x: (index % 3) * spacing.x,\n y: Math.floor(index / 3) * spacing.y,\n },\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n }))\n\n return { nodes: layoutedNodes, edges }\n }, [nodes, edges, spacing])\n}\n\nexport default useERDLayout","import { useCallback, useMemo, useEffect, useState } from 'react'\nimport ReactFlow, {\n Node,\n Edge,\n addEdge,\n Connection,\n useNodesState,\n useEdgesState,\n Controls,\n MiniMap,\n Background,\n BackgroundVariant,\n ConnectionMode,\n} from 'reactflow'\nimport 'reactflow/dist/style.css'\n\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { CubeNode } from './CubeNode'\nimport { RelationshipEdge } from './RelationshipEdge'\nimport { useERDLayout } from './useERDLayout'\n\n// Define the custom node and edge types OUTSIDE the component to prevent re-creation\nconst nodeTypes = {\n cubeNode: CubeNode,\n}\n\nconst edgeTypes = {\n relationshipEdge: RelationshipEdge,\n}\n\ninterface CubeRelationshipDiagramProps {\n className?: string\n onCubeClick?: (cubeName: string) => void\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension') => void\n highlightedCubes?: string[]\n highlightedFields?: string[]\n searchTerm?: string\n}\n\nexport function CubeRelationshipDiagram({\n className = '',\n onCubeClick,\n onFieldClick,\n highlightedCubes = [],\n highlightedFields = [],\n searchTerm,\n}: CubeRelationshipDiagramProps) {\n const { meta, metaLoading, metaError } = useCubeContext()\n\n const [savedPositions, setSavedPositions] = useState<Record<string, {x: number, y: number}>>({})\n const [autoLayoutRequested, setAutoLayoutRequested] = useState(false)\n const [contextMenu, setContextMenu] = useState<{x: number, y: number} | null>(null)\n\n // Load saved positions from localStorage on mount\n useEffect(() => {\n try {\n const savedPos = localStorage.getItem('drizzle-cube-erd-node-positions')\n if (savedPos) {\n setSavedPositions(JSON.parse(savedPos))\n }\n } catch (error) {\n // Ignore localStorage errors\n }\n }, [])\n\n // Create base nodes and edges structure (without selection data)\n const { nodes: baseNodes, edges: baseEdges } = useMemo(() => {\n if (!meta) return { nodes: [], edges: [] }\n\n const nodes: Node[] = []\n const edges: Edge[] = []\n\n // Create nodes for each cube\n meta.cubes.forEach((cube, index) => {\n nodes.push({\n id: cube.name,\n type: 'cubeNode',\n position: savedPositions[cube.name] || { x: (index % 3) * 400, y: Math.floor(index / 3) * 300 },\n data: {\n cube,\n onCubeClick,\n onFieldClick,\n isHighlighted: false, // Will be updated separately\n highlightedFields: [], // Will be updated separately\n },\n })\n })\n\n // Create edges for relationships (excluding belongsTo)\n meta.cubes.forEach(cube => {\n if (cube.relationships) {\n cube.relationships.forEach((relationship, index) => {\n // Skip belongsTo relationships\n if (relationship.relationship === 'belongsTo') {\n return\n }\n \n const edgeId = `${cube.name}-${relationship.targetCube}-${index}`\n edges.push({\n id: edgeId,\n source: cube.name,\n target: relationship.targetCube,\n type: 'relationshipEdge',\n data: {\n relationship,\n joinFields: relationship.joinFields,\n },\n animated: false,\n style: {\n stroke: getRelationshipColor(relationship.relationship),\n strokeWidth: 2,\n },\n })\n })\n }\n })\n\n return { nodes, edges }\n }, [meta, onCubeClick, onFieldClick, savedPositions])\n\n // Apply auto-layout when explicitly requested or if no saved positions\n const needsAutoLayout = autoLayoutRequested || Object.keys(savedPositions).length === 0\n \n // Get auto-layout result\n const { nodes: autoLayoutedNodes, edges: autoLayoutedEdges } = useERDLayout(baseNodes, baseEdges, {\n direction: 'LR',\n nodeWidth: 320,\n nodeHeight: 220,\n nodeSep: 100,\n rankSep: 200\n })\n \n // Use auto-layout or base nodes based on needsAutoLayout, and update selection data\n const layoutedNodes = useMemo(() => {\n const nodes = needsAutoLayout ? autoLayoutedNodes : baseNodes\n return nodes.map((node) => ({\n ...node,\n data: {\n ...node.data,\n isHighlighted: highlightedCubes.includes(node.id),\n highlightedFields: highlightedFields,\n searchTerm: searchTerm,\n }\n }))\n }, [needsAutoLayout, autoLayoutedNodes, baseNodes, highlightedCubes, highlightedFields, searchTerm])\n \n const layoutedEdges = needsAutoLayout ? autoLayoutedEdges : baseEdges\n \n // Reset auto-layout request and clear saved positions when auto-layout is applied\n useEffect(() => {\n if (autoLayoutRequested && layoutedNodes.length > 0) {\n // Clear saved positions so we use the new auto-layout positions\n setSavedPositions({})\n try {\n localStorage.removeItem('drizzle-cube-erd-node-positions')\n } catch (error) {\n // Ignore localStorage errors\n }\n setAutoLayoutRequested(false)\n }\n }, [autoLayoutRequested, layoutedNodes])\n\n const [nodes, setNodes, onNodesChange] = useNodesState(layoutedNodes)\n const [edges, setEdges, onEdgesChange] = useEdgesState(layoutedEdges)\n\n\n // Sync React Flow nodes with layout changes\n useEffect(() => {\n setNodes(layoutedNodes)\n }, [layoutedNodes, setNodes])\n\n // Sync React Flow edges with changes\n useEffect(() => {\n setEdges(layoutedEdges)\n }, [layoutedEdges, setEdges])\n\n // Save node positions to localStorage when manually moved\n const handleNodesChange = useCallback((changes: any[]) => {\n onNodesChange(changes)\n \n // Check if any nodes were dragged and save positions\n const dragChanges = changes.filter(change => change.type === 'position' && change.dragging === false)\n if (dragChanges.length > 0) {\n setNodes((currentNodes) => {\n const newPositions: Record<string, {x: number, y: number}> = {}\n currentNodes.forEach(node => {\n if (node.position) {\n newPositions[node.id] = node.position\n }\n })\n \n // Save to localStorage\n try {\n localStorage.setItem('drizzle-cube-erd-node-positions', JSON.stringify(newPositions))\n } catch (error) {\n // Ignore localStorage errors\n }\n \n setSavedPositions(newPositions)\n return currentNodes\n })\n }\n }, [onNodesChange, setNodes])\n\n const onConnect = useCallback(\n (params: Connection) => setEdges((eds) => addEdge(params, eds)),\n [setEdges]\n )\n\n // Handle right-click context menu\n const handleContextMenu = useCallback((event: React.MouseEvent) => {\n event.preventDefault()\n event.stopPropagation()\n console.log('Context menu triggered at:', event.clientX, event.clientY) // Debug\n setContextMenu({\n x: event.clientX,\n y: event.clientY,\n })\n }, [])\n\n // Close context menu when clicking elsewhere\n const handleClick = useCallback(() => {\n if (contextMenu) {\n setContextMenu(null)\n }\n }, [contextMenu])\n\n // Handle auto layout from context menu\n const handleAutoLayout = useCallback(() => {\n setAutoLayoutRequested(true)\n setContextMenu(null)\n }, [])\n\n\n // Loading state\n if (metaLoading) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center\">\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-2\"></div>\n <p className=\"text-dc-text-muted\">Loading cube schema...</p>\n </div>\n </div>\n )\n }\n\n // Error state\n if (metaError) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center text-red-500\">\n <p className=\"font-medium\">Failed to load cube schema</p>\n <p className=\"text-sm mt-1\">{metaError}</p>\n </div>\n </div>\n )\n }\n\n // Empty state\n if (!meta || meta.cubes.length === 0) {\n return (\n <div className={`flex items-center justify-center h-96 ${className}`}>\n <div className=\"text-center text-dc-text-muted\">\n <p className=\"font-medium\">No cubes found</p>\n <p className=\"text-sm mt-1\">Register some cubes to see the relationship diagram</p>\n </div>\n </div>\n )\n }\n\n return (\n <div className={`h-full ${className}`} style={{ height: '600px' }}>\n <div className=\"h-full\">\n <ReactFlow\n nodes={nodes}\n edges={edges}\n onNodesChange={handleNodesChange}\n onEdgesChange={onEdgesChange}\n onConnect={onConnect}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n connectionMode={ConnectionMode.Loose}\n fitView // Always fit view to show entire ERD\n minZoom={0.1}\n maxZoom={2}\n defaultViewport={{ x: 0, y: 0, zoom: 0.8 }}\n proOptions={{ hideAttribution: true }}\n onPaneContextMenu={handleContextMenu}\n onPaneClick={handleClick}\n >\n <Controls />\n <MiniMap \n nodeColor={(node) => {\n const isHighlighted = highlightedCubes.includes(node.id)\n return isHighlighted ? '#8b5cf6' : '#e5e7eb'\n }}\n maskColor=\"rgb(240, 242, 246, 0.7)\"\n />\n <Background variant={BackgroundVariant.Dots} gap={12} size={1} />\n </ReactFlow>\n </div>\n\n {/* Context Menu */}\n {contextMenu && (\n <div\n className=\"fixed z-50 bg-dc-surface rounded-md shadow-lg border border-dc-border py-1 min-w-[120px]\"\n style={{\n left: contextMenu.x,\n top: contextMenu.y,\n }}\n >\n <button\n onClick={handleAutoLayout}\n className=\"w-full px-3 py-2 text-sm text-dc-text-secondary hover:bg-dc-surface-hover text-left\"\n >\n Auto Layout\n </button>\n </div>\n )}\n </div>\n )\n}\n\n// Helper function to get relationship colors\nfunction getRelationshipColor(relationship: 'belongsTo' | 'hasOne' | 'hasMany'): string {\n switch (relationship) {\n case 'belongsTo':\n return '#10b981' // green\n case 'hasOne':\n return '#3b82f6' // blue\n case 'hasMany':\n return '#f59e0b' // amber\n default:\n return '#6b7280' // gray\n }\n}\n\nexport default CubeRelationshipDiagram"],"names":["CubeNode","data","cube","onFieldClick","isHighlighted","highlightedFields","searchTerm","handleCubeHeaderClick","handleFieldClick","fieldName","fieldType","isFieldHighlighted","fullFieldName","isFieldSearchMatch","field","term","hasCubeMatches","measureMatches","measure","dimensionMatches","dimension","getFieldVisibilityClasses","isSearchMatch","baseClasses","jsxs","jsx","highlighted","d","Handle","Position","RelationshipEdge","sourceX","sourceY","targetX","targetY","sourcePosition","targetPosition","style","markerEnd","edgePath","labelX","labelY","getBezierPath","relationship","joinFields","getRelationshipSymbol","rel","color","symbol","Fragment","BaseEdge","EdgeLabelRenderer","index","defaultOptions","useERDLayout","nodes","edges","options","layoutOptions","useMemo","layoutedNodes","layoutedEdges","dagreGraph","dagre","node","edge","nodeWithPosition","getTargetPosition","getSourcePosition","direction","nodeTypes","edgeTypes","CubeRelationshipDiagram","className","onCubeClick","highlightedCubes","meta","metaLoading","metaError","useCubeContext","savedPositions","setSavedPositions","useState","autoLayoutRequested","setAutoLayoutRequested","contextMenu","setContextMenu","useEffect","savedPos","baseNodes","baseEdges","edgeId","getRelationshipColor","needsAutoLayout","autoLayoutedNodes","autoLayoutedEdges","setNodes","onNodesChange","useNodesState","setEdges","onEdgesChange","useEdgesState","handleNodesChange","useCallback","changes","change","currentNodes","newPositions","onConnect","params","eds","addEdge","handleContextMenu","event","handleClick","handleAutoLayout","ReactFlow","ConnectionMode","Controls","MiniMap","Background","BackgroundVariant"],"mappings":"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"}
@@ -7,6 +7,8 @@ interface AnalysisFilterSectionProps {
7
7
  schema: MetaResponse | null;
8
8
  /** Callback when filters change */
9
9
  onFiltersChange: (filters: Filter[]) => void;
10
+ /** Callback when a field is dropped from another section */
11
+ onFieldDropped?: (field: string) => void;
10
12
  }
11
- export default function AnalysisFilterSection({ filters, schema, onFiltersChange }: AnalysisFilterSectionProps): import("react/jsx-runtime").JSX.Element;
13
+ export default function AnalysisFilterSection({ filters, schema, onFiltersChange, onFieldDropped }: AnalysisFilterSectionProps): import("react/jsx-runtime").JSX.Element;
12
14
  export {};
@@ -7,4 +7,5 @@ import { AnalysisQueryPanelProps } from './types';
7
7
  * - Breakdown section (dimensions)
8
8
  * - Chart configuration (in Chart tab)
9
9
  */
10
- export default function AnalysisQueryPanel({ metrics, breakdowns, filters, schema, activeTab, onActiveTabChange, onAddMetric, onRemoveMetric, onAddBreakdown, onRemoveBreakdown, onBreakdownGranularityChange, onFiltersChange, order, onOrderChange, chartType, chartConfig, displayConfig, chartAvailability, onChartTypeChange, onChartConfigChange, onDisplayConfigChange }: AnalysisQueryPanelProps): import("react/jsx-runtime").JSX.Element;
10
+ declare const AnalysisQueryPanel: import('react').NamedExoticComponent<AnalysisQueryPanelProps>;
11
+ export default AnalysisQueryPanel;
@@ -9,4 +9,5 @@ import { AnalysisResultsPanelProps } from './types';
9
9
  * - Stale results indicator
10
10
  * - Display limit control for tables
11
11
  */
12
- export default function AnalysisResultsPanel({ executionStatus, executionResults, executionError, totalRowCount, resultsStale, chartType, chartConfig, displayConfig, query, activeView, onActiveViewChange, displayLimit, onDisplayLimitChange, hasMetrics, debugQuery, debugSql, debugAnalysis, debugLoading, debugError }: AnalysisResultsPanelProps): import("react/jsx-runtime").JSX.Element;
12
+ declare const AnalysisResultsPanel: import('react').NamedExoticComponent<AnalysisResultsPanelProps>;
13
+ export default AnalysisResultsPanel;
@@ -6,5 +6,7 @@ import { BreakdownItemCardProps } from './types';
6
6
  * - Granularity dropdown (for time dimensions)
7
7
  * - Sort toggle button (visible on hover, or always visible when sorted)
8
8
  * - Remove button (visible on hover)
9
+ * - Drag handle for reordering
9
10
  */
10
- export default function BreakdownItemCard({ breakdown, fieldMeta, onRemove, onGranularityChange, sortDirection, sortPriority, onToggleSort }: BreakdownItemCardProps): import("react/jsx-runtime").JSX.Element;
11
+ declare const BreakdownItemCard: import('react').NamedExoticComponent<BreakdownItemCardProps>;
12
+ export default BreakdownItemCard;
@@ -3,6 +3,7 @@ import { BreakdownSectionProps } from './types';
3
3
  * BreakdownSection displays a collapsible section with:
4
4
  * - Header with title and add button
5
5
  * - List of selected breakdowns (using BreakdownItemCard)
6
- * - Empty state with add button
6
+ * - Drag/drop reordering support
7
7
  */
8
- export default function BreakdownSection({ breakdowns, schema, onAdd, onRemove, onGranularityChange, order, onOrderChange }: BreakdownSectionProps): import("react/jsx-runtime").JSX.Element;
8
+ declare const BreakdownSection: import('react').NamedExoticComponent<BreakdownSectionProps>;
9
+ export default BreakdownSection;
@@ -5,5 +5,7 @@ import { MetricItemCardProps } from './types';
5
5
  * - Field title or full name
6
6
  * - Sort toggle button (visible on hover, or always visible when sorted)
7
7
  * - Remove button (visible on hover)
8
+ * - Drag handle for reordering
8
9
  */
9
- export default function MetricItemCard({ metric, fieldMeta, onRemove, sortDirection, sortPriority, onToggleSort }: MetricItemCardProps): import("react/jsx-runtime").JSX.Element;
10
+ declare const MetricItemCard: import('react').NamedExoticComponent<MetricItemCardProps>;
11
+ export default MetricItemCard;
@@ -3,6 +3,7 @@ import { MetricsSectionProps } from './types';
3
3
  * MetricsSection displays a collapsible section with:
4
4
  * - Header with title and add button
5
5
  * - List of selected metrics (using MetricItemCard)
6
- * - Empty state with add button
6
+ * - Drag/drop reordering support
7
7
  */
8
- export default function MetricsSection({ metrics, schema, onAdd, onRemove, order, onOrderChange }: MetricsSectionProps): import("react/jsx-runtime").JSX.Element;
8
+ declare const MetricsSection: import('react').NamedExoticComponent<MetricsSectionProps>;
9
+ export default MetricsSection;
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  import { CubeQuery, Filter, ChartType, ChartAxisConfig, ChartDisplayConfig } from '../../types';
3
+ import { ColorPalette } from '../../utils/colorPalettes';
3
4
  import { MetaResponse, MetaField, MetaCube, QueryAnalysis } from '../../shared/types';
4
5
  import { ChartAvailabilityMap } from '../../shared/chartDefaults';
5
6
  export type { MetaResponse, MetaField, MetaCube, QueryAnalysis };
@@ -139,10 +140,13 @@ export interface AnalysisQueryPanelProps {
139
140
  onActiveTabChange: (tab: QueryPanelTab) => void;
140
141
  onAddMetric: () => void;
141
142
  onRemoveMetric: (id: string) => void;
143
+ onReorderMetrics?: (fromIndex: number, toIndex: number) => void;
142
144
  onAddBreakdown: () => void;
143
145
  onRemoveBreakdown: (id: string) => void;
144
146
  onBreakdownGranularityChange: (id: string, granularity: string) => void;
147
+ onReorderBreakdowns?: (fromIndex: number, toIndex: number) => void;
145
148
  onFiltersChange: (filters: Filter[]) => void;
149
+ onDropFieldToFilter?: (field: string) => void;
146
150
  /** Current sort order */
147
151
  order?: Record<string, 'asc' | 'desc'>;
148
152
  /** Callback when sort order changes */
@@ -150,6 +154,8 @@ export interface AnalysisQueryPanelProps {
150
154
  chartType: ChartType;
151
155
  chartConfig: ChartAxisConfig;
152
156
  displayConfig: ChartDisplayConfig;
157
+ /** Color palette for display config options */
158
+ colorPalette?: ColorPalette;
153
159
  /** Map of chart type availability for disabling unavailable chart types */
154
160
  chartAvailability?: ChartAvailabilityMap;
155
161
  onChartTypeChange: (type: ChartType) => void;
@@ -178,6 +184,12 @@ export interface AnalysisResultsPanelProps {
178
184
  chartConfig: ChartAxisConfig;
179
185
  /** Chart display configuration */
180
186
  displayConfig: ChartDisplayConfig;
187
+ /** Color palette for charts */
188
+ colorPalette?: ColorPalette;
189
+ /** Current palette name (for selector) */
190
+ currentPaletteName?: string;
191
+ /** Callback when color palette changes (shows selector when provided) */
192
+ onColorPaletteChange?: (paletteName: string) => void;
181
193
  /** Current query object (for annotation/metadata) */
182
194
  query: CubeQuery;
183
195
  /** Schema metadata */
@@ -200,6 +212,9 @@ export interface AnalysisResultsPanelProps {
200
212
  debugAnalysis?: QueryAnalysis | null;
201
213
  debugLoading?: boolean;
202
214
  debugError?: string | null;
215
+ onShareClick?: () => void;
216
+ canShare?: boolean;
217
+ shareButtonState?: 'idle' | 'copied' | 'copied-no-chart';
203
218
  }
204
219
  /**
205
220
  * Props for the MetricsSection component
@@ -221,6 +236,10 @@ export interface MetricsSectionProps {
221
236
  order?: Record<string, 'asc' | 'desc'>;
222
237
  /** Callback when sort order changes */
223
238
  onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void;
239
+ /** Callback when metrics are reordered via drag/drop */
240
+ onReorder?: (fromIndex: number, toIndex: number) => void;
241
+ /** Callback when a metric is dragged to the filter section */
242
+ onDragToFilter?: (field: string) => void;
224
243
  }
225
244
  /**
226
245
  * Props for the BreakdownSection component
@@ -244,6 +263,10 @@ export interface BreakdownSectionProps {
244
263
  order?: Record<string, 'asc' | 'desc'>;
245
264
  /** Callback when sort order changes */
246
265
  onOrderChange?: (fieldName: string, direction: 'asc' | 'desc' | null) => void;
266
+ /** Callback when breakdowns are reordered via drag/drop */
267
+ onReorder?: (fromIndex: number, toIndex: number) => void;
268
+ /** Callback when a breakdown is dragged to the filter section */
269
+ onDragToFilter?: (field: string) => void;
247
270
  }
248
271
  /**
249
272
  * Props for MetricItemCard component
@@ -261,6 +284,20 @@ export interface MetricItemCardProps {
261
284
  sortPriority?: number;
262
285
  /** Toggle sort handler */
263
286
  onToggleSort?: () => void;
287
+ /** Index in the list (for drag/drop) */
288
+ index?: number;
289
+ /** Whether this item is being dragged */
290
+ isDragging?: boolean;
291
+ /** Whether dragging over this item */
292
+ isDragOver?: boolean;
293
+ /** Drag start handler */
294
+ onDragStart?: (e: React.DragEvent, index: number) => void;
295
+ /** Drag over handler */
296
+ onDragOver?: (e: React.DragEvent, index: number) => void;
297
+ /** Drop handler */
298
+ onDrop?: (e: React.DragEvent, index: number) => void;
299
+ /** Drag end handler */
300
+ onDragEnd?: () => void;
264
301
  }
265
302
  /**
266
303
  * Props for BreakdownItemCard component
@@ -280,6 +317,20 @@ export interface BreakdownItemCardProps {
280
317
  sortPriority?: number;
281
318
  /** Toggle sort handler */
282
319
  onToggleSort?: () => void;
320
+ /** Index in the list (for drag/drop) */
321
+ index?: number;
322
+ /** Whether this item is being dragged */
323
+ isDragging?: boolean;
324
+ /** Whether dragging over this item */
325
+ isDragOver?: boolean;
326
+ /** Drag start handler */
327
+ onDragStart?: (e: React.DragEvent, index: number) => void;
328
+ /** Drag over handler */
329
+ onDragOver?: (e: React.DragEvent, index: number) => void;
330
+ /** Drop handler */
331
+ onDrop?: (e: React.DragEvent, index: number) => void;
332
+ /** Drag end handler */
333
+ onDragEnd?: () => void;
283
334
  }
284
335
  /**
285
336
  * Props for the main AnalysisBuilder component
@@ -291,6 +342,16 @@ export interface AnalysisBuilderProps {
291
342
  maxHeight?: string;
292
343
  /** Initial query to load */
293
344
  initialQuery?: CubeQuery;
345
+ /** Initial chart configuration (for editing existing portlets) */
346
+ initialChartConfig?: {
347
+ chartType?: ChartType;
348
+ chartConfig?: ChartAxisConfig;
349
+ displayConfig?: ChartDisplayConfig;
350
+ };
351
+ /** Initial data to display (avoids re-fetching when editing existing portlets) */
352
+ initialData?: any[];
353
+ /** Color palette for chart visualization */
354
+ colorPalette?: ColorPalette;
294
355
  /** Disable localStorage persistence */
295
356
  disableLocalStorage?: boolean;
296
357
  /** Hide settings button */
@@ -0,0 +1,25 @@
1
+ import { PortletConfig, ColorPalette } from '../types';
2
+ interface PortletAnalysisModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ onSave: (portlet: PortletConfig | Omit<PortletConfig, 'id' | 'x' | 'y'>) => void;
6
+ portlet?: PortletConfig | null;
7
+ /** Initial data to display (avoids re-fetching when editing) */
8
+ initialData?: any[];
9
+ title: string;
10
+ submitText: string;
11
+ colorPalette?: ColorPalette;
12
+ }
13
+ /**
14
+ * PortletAnalysisModal - A modal wrapper around AnalysisBuilder for portlet editing
15
+ *
16
+ * This replaces PortletEditModal with the modern AnalysisBuilder interface.
17
+ * Features:
18
+ * - Two-panel layout with results and query builder
19
+ * - Auto-execution of queries
20
+ * - Smart chart defaults
21
+ * - Title input in header
22
+ * - Initial data support (no re-fetch when editing)
23
+ */
24
+ export default function PortletAnalysisModal({ isOpen, onClose, onSave, portlet, initialData, title: modalTitle, submitText, colorPalette }: PortletAnalysisModalProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
@@ -1,5 +1,5 @@
1
- import { a as t, A as s, e as o, b as r, M as d, P as l, d as i, Q as n } from "./chunks/components-CXA6-jJq.js";
2
- import { c as b, j as u, h as y, e as c, d as h, v as p } from "./chunks/charts-MJLpxe3r.js";
1
+ import { a as t, A as s, d as o, D as r, M as d, P as l, b as i, Q as n } from "./chunks/components-DAOVOiM_.js";
2
+ import { c as b, j as u, h as y, e as c, d as h, v as D } from "./chunks/charts-DY7pF_-4.js";
3
3
  export {
4
4
  t as AnalyticsDashboard,
5
5
  s as AnalyticsPortlet,
@@ -14,6 +14,6 @@ export {
14
14
  y as findNextPosition,
15
15
  c as generatePortletId,
16
16
  h as generateResponsiveLayouts,
17
- p as validateCubeQuery
17
+ D as validateCubeQuery
18
18
  };
19
19
  //# sourceMappingURL=components.js.map
@@ -1,6 +1,6 @@
1
1
  import { useState as b, useRef as w, useEffect as y, useCallback as C, useMemo as m } from "react";
2
- import { u as L } from "./chunks/chart-activitygridchart-Cz4bEf3V.js";
3
- import { D as F } from "./chunks/chart-activitygridchart-Cz4bEf3V.js";
2
+ import { u as L } from "./chunks/chart-activitygridchart-C1ts13cL.js";
3
+ import { D as F } from "./chunks/chart-activitygridchart-C1ts13cL.js";
4
4
  function W(e, r = {}) {
5
5
  const { cubeApi: s, batchCoordinator: u, enableBatching: a } = L(), [l, d] = b({
6
6
  resultSet: null,
@@ -8,7 +8,7 @@ export declare function getIconRegistry(): IconRegistry;
8
8
  /**
9
9
  * Get a specific icon as a React component
10
10
  * @param name The icon name from the registry
11
- * @returns A React component that renders the icon
11
+ * @returns A React component that renders the icon (cached for stable references)
12
12
  */
13
13
  export declare function getIcon(name: IconName): ComponentType<IconProps>;
14
14
  /**
@@ -1,4 +1,4 @@
1
- import { D as a, g as t, c as o, b as c, d as g, f as I, h as n, a as r, r as y, e as p, s as T } from "./chunks/chart-activitygridchart-config-BngZDVh_.js";
1
+ import { D as a, g as t, h as o, b as c, c as g, e as I, f as n, a as r, r as y, d as p, s as T } from "./chunks/chart-activitygridchart-config-AVBoHdRn.js";
2
2
  export {
3
3
  a as DEFAULT_ICONS,
4
4
  t as getChartTypeIcon,
@@ -7,6 +7,7 @@ export type { LazyChartProps } from './charts/ChartLoader';
7
7
  export { default as DashboardGrid } from './components/DashboardGrid';
8
8
  export { default as PortletContainer } from './components/PortletContainer';
9
9
  export { default as PortletEditModal } from './components/PortletEditModal';
10
+ export { default as PortletAnalysisModal } from './components/PortletAnalysisModal';
10
11
  export { default as DashboardEditModal } from './components/DashboardEditModal';
11
12
  export { default as Modal } from './components/Modal';
12
13
  export { default as QueryBuilder } from './components/QueryBuilder';