drizzle-cube 0.4.38 → 0.4.39

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.
@@ -604,35 +604,42 @@ function ee({ selection: e, meta: t, onClose: r }) {
604
604
  }
605
605
  //#endregion
606
606
  //#region src/client/components/SchemaVisualization/useERDLayout.ts
607
- var A = {
607
+ var te = {
608
608
  direction: "LR",
609
609
  nodeWidth: 340,
610
610
  nodeSep: 150,
611
611
  rankSep: 350
612
612
  };
613
- function j(e) {
613
+ function A(e) {
614
614
  switch (e) {
615
615
  case "TB": return "top";
616
616
  case "LR": return "left";
617
617
  default: return "top";
618
618
  }
619
619
  }
620
- function M(e) {
620
+ function j(e) {
621
621
  switch (e) {
622
622
  case "TB": return "bottom";
623
623
  case "LR": return "right";
624
624
  default: return "bottom";
625
625
  }
626
626
  }
627
- function N(e) {
627
+ function M(e) {
628
628
  let t = e.data?.cube;
629
629
  if (!t) return 300;
630
630
  let n = t.description ? 80 : 56, r = t.measures?.length ?? 0, i = t.dimensions?.filter((e) => e.type === "time").length ?? 0, a = t.dimensions?.filter((e) => e.type !== "time").length ?? 0;
631
631
  return r > 0 && (n += 36 + Math.min(r * 34, 256)), i > 0 && (n += 36 + Math.min(i * 34, 256)), a > 0 && (n += 36 + Math.min(a * 34, 256)), n + 30;
632
632
  }
633
- var P = null, F = import("elkjs/lib/elk.bundled.js").then((e) => (P = new (e.default || e)(), P)).catch(() => null);
633
+ var N = null, P = null;
634
+ function F() {
635
+ return P || (P = import([
636
+ "elkjs",
637
+ "lib",
638
+ "elk.bundled.js"
639
+ ].join("/")).then((e) => (N = new (e.default || e)(), N)).catch(() => null), P);
640
+ }
634
641
  async function I(e, t, n) {
635
- if (await F, !P) return {
642
+ if (await F(), !N) return {
636
643
  nodes: L(e, n),
637
644
  edges: t
638
645
  };
@@ -641,7 +648,7 @@ async function I(e, t, n) {
641
648
  a.has(e.source) || a.set(e.source, []), a.get(e.source).push(e.id), o.has(e.target) || o.set(e.target, []), o.get(e.target).push(e.id);
642
649
  });
643
650
  let s = e.map((e) => {
644
- let t = n.nodeWidth, s = N(e), c = a.get(e.id) || [], l = o.get(e.id) || [], u = [...c.map((t) => ({
651
+ let t = n.nodeWidth, s = M(e), c = a.get(e.id) || [], l = o.get(e.id) || [], u = [...c.map((t) => ({
645
652
  id: `${e.id}__src__${t}`,
646
653
  layoutOptions: { "elk.port.side": r }
647
654
  })), ...l.map((t) => ({
@@ -676,7 +683,7 @@ async function I(e, t, n) {
676
683
  },
677
684
  children: s,
678
685
  edges: c
679
- }, d = await P.layout(u), f = /* @__PURE__ */ new Map();
686
+ }, d = await N.layout(u), f = /* @__PURE__ */ new Map();
680
687
  if (d.children) for (let e of d.children) f.set(e.id, {
681
688
  x: e.x,
682
689
  y: e.y
@@ -685,8 +692,8 @@ async function I(e, t, n) {
685
692
  nodes: e.map((e) => ({
686
693
  ...e,
687
694
  position: f.get(e.id) || e.position,
688
- targetPosition: j(n.direction),
689
- sourcePosition: M(n.direction)
695
+ targetPosition: A(n.direction),
696
+ sourcePosition: j(n.direction)
690
697
  })),
691
698
  edges: t
692
699
  };
@@ -694,7 +701,7 @@ async function I(e, t, n) {
694
701
  function L(e, t) {
695
702
  let n = 0, r = 0;
696
703
  return e.map((e) => {
697
- let i = N(e);
704
+ let i = M(e);
698
705
  r + i > 1200 && r > 0 && (n++, r = 0);
699
706
  let a = {
700
707
  x: n * (t.nodeWidth + t.nodeSep),
@@ -703,14 +710,14 @@ function L(e, t) {
703
710
  return r += i + 40, {
704
711
  ...e,
705
712
  position: a,
706
- sourcePosition: M(t.direction),
707
- targetPosition: j(t.direction)
713
+ sourcePosition: j(t.direction),
714
+ targetPosition: A(t.direction)
708
715
  };
709
716
  });
710
717
  }
711
- function te(e, t, n = {}) {
718
+ function ne(e, t, n = {}) {
712
719
  let r = l(() => ({
713
- ...A,
720
+ ...te,
714
721
  ...n
715
722
  }), [
716
723
  n.direction,
@@ -747,10 +754,10 @@ function te(e, t, n = {}) {
747
754
  //#endregion
748
755
  //#region src/client/components/SchemaVisualization/index.tsx
749
756
  var R = /* @__PURE__ */ e({
750
- SchemaVisualization: () => z,
751
- default: () => z
752
- }), ne = { cubeNode: C }, re = { relationshipEdge: w };
753
- function ie({ token: e }) {
757
+ SchemaVisualization: () => B,
758
+ default: () => B
759
+ }), re = { cubeNode: C }, ie = { relationshipEdge: w };
760
+ function ae({ token: e }) {
754
761
  let { useNodesInitialized: t, useReactFlow: n } = _(), r = t(), { fitView: i } = n(), a = u(0);
755
762
  return c(() => {
756
763
  e === 0 || e === a.current || r && (a.current = e, i({ padding: .1 }));
@@ -760,7 +767,7 @@ function ie({ token: e }) {
760
767
  i
761
768
  ]), null;
762
769
  }
763
- var ae = [];
770
+ var z = [];
764
771
  function oe(e) {
765
772
  switch (e) {
766
773
  case "belongsTo": return "#10b981";
@@ -770,12 +777,12 @@ function oe(e) {
770
777
  default: return "#6b7280";
771
778
  }
772
779
  }
773
- function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlightedFields: a, searchTerm: s, height: f = "100%" }) {
774
- let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } = t(), w = i || ae, T = a || ae, [E, D] = d(null), [O, k] = d(s || ""), [A, j] = d(0), [M, N] = d(null), [P, F] = d(null), I = u(null), L = !r, [R, z] = d({}), [B, se] = d(!1), ce = n("search"), le = n("close"), V = s === void 0 ? O : s;
780
+ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlightedFields: a, searchTerm: s, height: f = "100%" }) {
781
+ let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } = t(), w = i || z, T = a || z, [E, D] = d(null), [O, k] = d(s || ""), [te, A] = d(0), [j, M] = d(null), [N, P] = d(null), F = u(null), I = !r, [L, R] = d({}), [B, se] = d(!1), ce = n("search"), le = n("close"), V = s === void 0 ? O : s;
775
782
  c(() => {
776
783
  try {
777
784
  let e = localStorage.getItem("drizzle-cube-erd-node-positions");
778
- e && z(JSON.parse(e));
785
+ e && R(JSON.parse(e));
779
786
  } catch {}
780
787
  se(!0);
781
788
  }, []);
@@ -815,13 +822,13 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
815
822
  structuralNodes: e,
816
823
  structuralEdges: t
817
824
  };
818
- }, [x]), W = A > 0 || B && Object.keys(R).length === 0, { nodes: G, edges: K, phase: ue } = te(W ? H : [], W ? U : [], {
825
+ }, [x]), W = te > 0 || B && Object.keys(L).length === 0, { nodes: G, edges: K, phase: ue } = ne(W ? H : [], W ? U : [], {
819
826
  direction: "LR",
820
827
  nodeWidth: 340,
821
828
  nodeSep: 150,
822
829
  rankSep: 350
823
830
  }), q = o((e, t) => {
824
- let n = I.current?.getBoundingClientRect();
831
+ let n = F.current?.getBoundingClientRect();
825
832
  if (!n) return {
826
833
  x: e,
827
834
  y: t
@@ -832,39 +839,39 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
832
839
  y: i
833
840
  };
834
841
  }, []), de = o((e, t, n, r) => {
835
- N((i) => i && i.cubeName === e && i.fieldName === t ? (F(null), null) : (r && F(q(r.x, r.y)), {
842
+ M((i) => i && i.cubeName === e && i.fieldName === t ? (P(null), null) : (r && P(q(r.x, r.y)), {
836
843
  cubeName: e,
837
844
  fieldName: t,
838
845
  fieldType: n
839
846
  }));
840
847
  }, [q]), fe = o((e, t) => {
841
- N((n) => n && n.cubeName === e && n.fieldName === null ? (F(null), null) : (t && F(q(t.x, t.y)), {
848
+ M((n) => n && n.cubeName === e && n.fieldName === null ? (P(null), null) : (t && P(q(t.x, t.y)), {
842
849
  cubeName: e,
843
850
  fieldName: null,
844
851
  fieldType: "cube"
845
852
  }));
846
- }, [q]), pe = L ? de : r, me = L ? fe : void 0, J = o((e) => ({
853
+ }, [q]), pe = I ? de : r, me = I ? fe : void 0, J = o((e) => ({
847
854
  cube: e,
848
855
  onFieldClick: pe,
849
856
  onCubeClick: me,
850
857
  isHighlighted: w.includes(e.name),
851
858
  highlightedFields: T,
852
859
  searchTerm: V,
853
- selectedField: L ? M : null
860
+ selectedField: I ? j : null
854
861
  }), [
855
862
  pe,
856
863
  me,
857
864
  w,
858
865
  T,
859
866
  V,
860
- L,
861
- M
867
+ I,
868
+ j
862
869
  ]), Y = !W || ue === "ready", X = l(() => !x || !Y || !B ? [] : W && G.length > 0 ? G.map((e) => ({
863
870
  ...e,
864
871
  data: J(e.data?.cube || x.cubes.find((t) => t.name === e.id))
865
872
  })) : H.map((e) => ({
866
873
  ...e,
867
- position: R[e.id] || e.position,
874
+ position: L[e.id] || e.position,
868
875
  data: J(e.data?.cube)
869
876
  })), [
870
877
  x,
@@ -873,7 +880,7 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
873
880
  W,
874
881
  G,
875
882
  H,
876
- R,
883
+ L,
877
884
  J
878
885
  ]), he = l(() => !x || !Y ? [] : W && K.length > 0 ? K : U, [
879
886
  x,
@@ -891,7 +898,7 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
891
898
  }, [X, he]);
892
899
  let be = u("");
893
900
  c(() => {
894
- let e = M ? `${M.cubeName}.${M.fieldName}` : "", t = `${w.join(",")}|${T.join(",")}|${V}|${String(r)}|${e}`;
901
+ let e = j ? `${j.cubeName}.${j.fieldName}` : "", t = `${w.join(",")}|${T.join(",")}|${V}|${String(r)}|${e}`;
895
902
  t !== be.current && (be.current = t, !(Z.length === 0 || !x) && Q((e) => e.map((e) => {
896
903
  let t = x.cubes.find((t) => t.name === e.id);
897
904
  return t ? {
@@ -904,7 +911,7 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
904
911
  T,
905
912
  V,
906
913
  r,
907
- M,
914
+ j,
908
915
  Z.length,
909
916
  x,
910
917
  J
@@ -918,7 +925,7 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
918
925
  try {
919
926
  localStorage.setItem("drizzle-cube-erd-node-positions", JSON.stringify(t));
920
927
  } catch {}
921
- return z(t), e;
928
+ return R(t), e;
922
929
  });
923
930
  }, []), Se = o((e) => {}, []), Ce = o((e) => {
924
931
  e.preventDefault(), e.stopPropagation(), D({
@@ -926,13 +933,13 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
926
933
  y: e.clientY
927
934
  });
928
935
  }, []), we = o(() => {
929
- E && D(null), M && (N(null), F(null));
930
- }, [E, M]), Te = o(() => {
931
- z({}), $.current = "";
936
+ E && D(null), j && (M(null), P(null));
937
+ }, [E, j]), Te = o(() => {
938
+ R({}), $.current = "";
932
939
  try {
933
940
  localStorage.removeItem("drizzle-cube-erd-node-positions");
934
941
  } catch {}
935
- j((e) => e + 1), D(null);
942
+ A((e) => e + 1), D(null);
936
943
  }, []);
937
944
  return S ? /* @__PURE__ */ p("div", {
938
945
  className: `dc:flex dc:items-center dc:justify-center dc:h-96 ${e}`,
@@ -993,7 +1000,7 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
993
1000
  ]
994
1001
  }),
995
1002
  /* @__PURE__ */ m("div", {
996
- ref: I,
1003
+ ref: F,
997
1004
  className: "dc:relative dc:flex-1 dc:min-h-0",
998
1005
  children: [/* @__PURE__ */ p("div", {
999
1006
  style: {
@@ -1005,8 +1012,8 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1005
1012
  edges: ge,
1006
1013
  onNodesChange: xe,
1007
1014
  onEdgesChange: Se,
1008
- nodeTypes: ne,
1009
- edgeTypes: re,
1015
+ nodeTypes: re,
1016
+ edgeTypes: ie,
1010
1017
  connectionMode: "loose",
1011
1018
  minZoom: .1,
1012
1019
  maxZoom: 2,
@@ -1024,20 +1031,20 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1024
1031
  gap: 12,
1025
1032
  size: 1
1026
1033
  }),
1027
- /* @__PURE__ */ p(ie, { token: ve })
1034
+ /* @__PURE__ */ p(ae, { token: ve })
1028
1035
  ]
1029
1036
  })
1030
- }), L && M && P && x && /* @__PURE__ */ p("div", {
1037
+ }), I && j && N && x && /* @__PURE__ */ p("div", {
1031
1038
  className: "dc:absolute dc:z-20",
1032
1039
  style: {
1033
- left: P.x,
1034
- top: P.y
1040
+ left: N.x,
1041
+ top: N.y
1035
1042
  },
1036
1043
  children: /* @__PURE__ */ p(ee, {
1037
- selection: M,
1044
+ selection: j,
1038
1045
  meta: x,
1039
1046
  onClose: () => {
1040
- N(null), F(null);
1047
+ M(null), P(null);
1041
1048
  }
1042
1049
  })
1043
1050
  })]
@@ -1069,4 +1076,4 @@ function z({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1069
1076
  //#endregion
1070
1077
  export { S as n, R as t };
1071
1078
 
1072
- //# sourceMappingURL=schema-visualization-XLFzV_7p.js.map
1079
+ //# sourceMappingURL=schema-visualization-BFPl_eKV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-visualization-BFPl_eKV.js","names":[],"sources":["../../../src/client/components/SchemaVisualization/xyflowContext.tsx","../../../src/client/components/SchemaVisualization/SchemaVisualizationLazy.tsx","../../../src/client/components/SchemaVisualization/CubeNode.tsx","../../../src/client/components/SchemaVisualization/RelationshipEdge.tsx","../../../src/client/components/SchemaVisualization/FieldDetailPanel.tsx","../../../src/client/components/SchemaVisualization/useERDLayout.ts","../../../src/client/components/SchemaVisualization/index.tsx"],"sourcesContent":["/**\n * React context for @xyflow/react modules.\n *\n * All xyflow imports are dynamic (via SchemaVisualizationLazy) so that\n * the built schema-visualization chunk has NO static imports from\n * @xyflow/react. This prevents consuming projects from failing at\n * build time when @xyflow/react is not installed.\n */\n\nimport { createContext, useContext } from 'react'\n\nexport type XyflowModule = typeof import('@xyflow/react')\n\nconst XyflowContext = createContext<XyflowModule | null>(null)\n\nexport const XyflowProvider = XyflowContext.Provider\n\nexport function useXyflow(): XyflowModule {\n const ctx = useContext(XyflowContext)\n if (!ctx) throw new Error('useXyflow must be used within XyflowProvider')\n return ctx\n}\n","/**\n * Lazy-loaded SchemaVisualization with graceful fallback\n * when @xyflow/react is not installed.\n *\n * All @xyflow/react imports are dynamic here so the built chunk\n * has NO static imports from @xyflow/react. This prevents consuming\n * projects from failing at build time when xyflow is not installed.\n */\n\nimport { lazy, Suspense, useState, useEffect } from 'react'\nimport type { SchemaVisualizationProps } from './index'\nimport { XyflowProvider } from './xyflowContext'\nimport type { XyflowModule } from './xyflowContext'\n\nlet loadFailed = false\n\nfunction MissingDependencyFallback(_props: SchemaVisualizationProps) {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:h-full dc:p-8\">\n <div className=\"dc:text-center dc:max-w-md\">\n <div className=\"dc:text-4xl dc:mb-4\">&#128269;</div>\n <h3 className=\"dc:text-lg dc:font-semibold text-dc-text dc:mb-2\">\n Schema Visualization requires additional packages\n </h3>\n <p className=\"dc:text-sm text-dc-text-secondary dc:mb-4\">\n Install the required dependencies to enable the interactive schema diagram:\n </p>\n <code className=\"dc:block dc:px-4 dc:py-2 dc:rounded bg-dc-surface-secondary dc:text-sm dc:font-mono text-dc-text dc:border border-dc-border\">\n npm install @xyflow/react elkjs\n </code>\n </div>\n </div>\n )\n}\n\nfunction LoadingFallback() {\n return (\n <div className=\"dc:flex dc:items-center dc:justify-center dc:h-full\">\n <div className=\"dc:text-center\">\n <div className=\"dc:animate-spin dc:rounded-full dc:h-8 dc:w-8 dc:border-b-2 border-dc-accent dc:mx-auto dc:mb-2\" />\n <p className=\"dc:text-sm text-dc-text-muted\">Loading schema visualization...</p>\n </div>\n </div>\n )\n}\n\nconst LazySchemaVisualization = lazy(async () => {\n const mod = await import('./index')\n return { default: mod.SchemaVisualization }\n})\n\nexport function SchemaVisualizationLazy(props: SchemaVisualizationProps) {\n const [xyflow, setXyflow] = useState<XyflowModule | null>(null)\n const [failed, setFailed] = useState(loadFailed)\n\n useEffect(() => {\n if (loadFailed) return\n let cancelled = false\n\n import('@xyflow/react')\n .then((mod) => {\n if (!cancelled) setXyflow(mod)\n })\n .catch(() => {\n loadFailed = true\n if (!cancelled) setFailed(true)\n })\n\n return () => { cancelled = true }\n }, [])\n\n if (failed) {\n return <MissingDependencyFallback {...props} />\n }\n\n if (!xyflow) {\n return <LoadingFallback />\n }\n\n return (\n <XyflowProvider value={xyflow}>\n <Suspense fallback={<LoadingFallback />}>\n <LazySchemaVisualization {...props} />\n </Suspense>\n </XyflowProvider>\n )\n}\n\nexport function isSchemaVisualizationAvailable(): boolean {\n return !loadFailed\n}\n","import type { MouseEvent } from 'react'\nimport type { CubeMetaCube } from '../../types'\nimport { getIcon } from '../../icons'\nimport { useXyflow } from './xyflowContext'\n\ninterface CubeNodeData {\n cube: CubeMetaCube\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension', pos?: { x: number; y: number }) => void\n onCubeClick?: (cubeName: string, pos?: { x: number; y: number }) => void\n isHighlighted: boolean\n highlightedFields: string[]\n searchTerm?: string\n selectedField?: { cubeName: string; fieldName: string | null } | null\n [key: string]: unknown\n}\n\ninterface CubeNodeProps {\n data: CubeNodeData\n}\n\nexport function CubeNode({ data }: CubeNodeProps) {\n const { Handle, Position } = useXyflow()\n const { cube, onFieldClick, onCubeClick, isHighlighted, highlightedFields, searchTerm, selectedField } = data\n\n const handleFieldClick = (e: MouseEvent, fieldName: string, fieldType: 'measure' | 'dimension') => {\n if (onFieldClick) {\n onFieldClick(cube.name, fieldName, fieldType, { x: e.clientX, y: e.clientY })\n }\n }\n\n const InfoIcon = getIcon('info')\n\n const handleCubeInfoClick = (e: MouseEvent) => {\n e.stopPropagation() // don't start drag\n if (onCubeClick) {\n onCubeClick(cube.name, { x: e.clientX, y: e.clientY })\n }\n }\n\n const isFieldSelected = (fieldName: string) => {\n if (!selectedField) return false\n return selectedField.cubeName === cube.name && selectedField.fieldName === fieldName\n }\n\n const isCubeSelected = selectedField?.cubeName === cube.name && selectedField?.fieldName === null\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\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 const cubeHasMatches = () => {\n if (!searchTerm?.trim()) return true\n return cube.measures.some(m => isFieldSearchMatch(m)) ||\n cube.dimensions.some(d => isFieldSearchMatch(d))\n }\n\n const hasCubeMatches = cubeHasMatches()\n\n const getFieldClasses = (\n field: { name: string; title?: string; type?: string },\n highlighted: boolean,\n _fieldType: 'measure' | 'dimension'\n ) => {\n const fieldName = field.name.split('.')[1] || field.name\n const selected = isFieldSelected(fieldName)\n const base = 'dc:px-4 dc:py-2 dc:text-xs dc:cursor-pointer dc:transition-all dc:border-b border-dc-border last:dc:border-b-0 nodrag nopan'\n\n if (selected) {\n return `${base} bg-dc-accent-bg text-dc-accent dc:font-semibold dc:ring-1 dc:ring-inset ring-dc-accent`\n }\n\n if (!hasCubeMatches && searchTerm?.trim()) {\n if (highlighted) return `${base} bg-dc-accent-bg text-dc-accent dc:font-semibold`\n return `${base} dc:hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n if (searchTerm?.trim() && !isFieldSearchMatch(field)) {\n return `${base} dc:opacity-40 dc:hover:opacity-60 text-dc-text-muted`\n }\n\n if (searchTerm?.trim() && isFieldSearchMatch(field) && !highlighted) {\n return `${base} dc:font-bold dc:hover:bg-dc-accent-bg`\n }\n\n if (highlighted) {\n return `${base} bg-dc-accent-bg text-dc-accent dc:font-semibold`\n }\n\n return `${base} dc:hover:bg-dc-surface-hover text-dc-text-secondary`\n }\n\n const timeDimensions = cube.dimensions.filter(d => d.type === 'time')\n const regularDimensions = cube.dimensions.filter(d => d.type !== 'time')\n\n return (\n <div\n className={`\n dc:border-2 dc:rounded-lg dc:shadow-lg dc:min-w-[280px] dc:overflow-hidden dc:transition-all\n ${!hasCubeMatches && searchTerm?.trim() ? 'dc:opacity-30 dc:grayscale' : ''}\n ${isHighlighted ? 'border-dc-accent dc:ring-2 ring-dc-accent' : 'border-dc-border'}\n `}\n style={{ backgroundColor: 'var(--dc-surface)' }}\n >\n {/* Cube Header */}\n <div className={`dc:px-4 dc:py-3 dc:transition-colors ${\n isHighlighted ? 'bg-dc-accent-bg' : 'bg-dc-surface-secondary'\n }`}>\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <div>\n <h3 className=\"dc:font-semibold text-dc-text dc:text-sm\">\n {cube.title || cube.name}\n </h3>\n {cube.description && (\n <p className=\"dc:text-xs text-dc-text-muted dc:mt-1 dc:line-clamp-2\">{cube.description}</p>\n )}\n </div>\n {onCubeClick && (\n <button\n className={`dc:ml-2 dc:p-1 dc:rounded dc:transition-colors nodrag nopan ${\n isCubeSelected\n ? 'bg-dc-accent-bg text-dc-accent'\n : 'text-dc-text-muted dc:hover:text-dc-text dc:hover:bg-dc-surface-hover'\n }`}\n onClick={handleCubeInfoClick}\n title=\"Cube info\"\n >\n <InfoIcon className=\"dc:w-5 dc:h-5\" />\n </button>\n )}\n {!onCubeClick && (\n <div className=\"dc:text-xs text-dc-text-muted dc:ml-2\">\n <div>{cube.measures.length}M</div>\n <div>{cube.dimensions.length}D</div>\n </div>\n )}\n </div>\n </div>\n\n {/* Measures */}\n {cube.measures.length > 0 && (\n <div className=\"dc:border-t border-dc-border\">\n <div className=\"dc:px-4 dc:py-1.5 dc:border-b border-dc-border\" style={{ backgroundColor: 'color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))' }}>\n <h4 className=\"dc:text-xs dc:font-medium text-dc-text-secondary dc:flex dc:items-center\">\n <span className=\"dc:w-2 dc:h-2 bg-dc-warning dc:rounded-full dc:mr-2\" />\n Measures ({cube.measures.length})\n </h4>\n </div>\n <div className=\"dc:max-h-64 dc:overflow-y-auto nowheel\">\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={getFieldClasses(measure, highlighted, 'measure')}\n onClick={(e) => handleFieldClick(e, fieldName, 'measure')}\n title={measure.title}\n >\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <span className=\"dc:font-mono dc:truncate\">\n {measure.shortTitle || measure.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted dc:ml-2 dc:text-[10px] dc:uppercase\">\n {measure.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Time Dimensions */}\n {timeDimensions.length > 0 && (\n <div className=\"dc:border-t border-dc-border\">\n <div className=\"dc:px-4 dc:py-1.5 dc:border-b border-dc-border\" style={{ backgroundColor: 'color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))' }}>\n <h4 className=\"dc:text-xs dc:font-medium text-dc-text-secondary dc:flex dc:items-center\">\n <span className=\"dc:w-2 dc:h-2 bg-dc-accent dc:rounded-full dc:mr-2\" />\n Time Dimensions ({timeDimensions.length})\n </h4>\n </div>\n <div className=\"dc:max-h-64 dc:overflow-y-auto nowheel\">\n {timeDimensions.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={getFieldClasses(dimension, highlighted, 'dimension')}\n onClick={(e) => handleFieldClick(e, fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <span className=\"dc:font-mono dc:truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted dc:ml-2 dc:text-[10px] dc:uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Regular Dimensions */}\n {regularDimensions.length > 0 && (\n <div className=\"dc:border-t border-dc-border\">\n <div className=\"dc:px-4 dc:py-1.5 dc:border-b border-dc-border\" style={{ backgroundColor: 'color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))' }}>\n <h4 className=\"dc:text-xs dc:font-medium text-dc-text-secondary dc:flex dc:items-center\">\n <span className=\"dc:w-2 dc:h-2 bg-dc-success dc:rounded-full dc:mr-2\" />\n Dimensions ({regularDimensions.length})\n </h4>\n </div>\n <div className=\"dc:max-h-64 dc:overflow-y-auto nowheel\">\n {regularDimensions.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={getFieldClasses(dimension, highlighted, 'dimension')}\n onClick={(e) => handleFieldClick(e, fieldName, 'dimension')}\n title={dimension.title}\n >\n <div className=\"dc:flex dc:items-center dc:justify-between\">\n <span className=\"dc:font-mono dc:truncate\">\n {dimension.shortTitle || dimension.title || fieldName}\n </span>\n <span className=\"text-dc-text-muted dc:ml-2 dc:text-[10px] dc:uppercase\">\n {dimension.type}\n </span>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {/* Connection handles - hidden */}\n <Handle type=\"source\" position={Position.Right} id=\"right\" className=\"dc:opacity-0\" isConnectable={false} />\n <Handle type=\"target\" position={Position.Left} id=\"left\" className=\"dc:opacity-0\" isConnectable={false} />\n <Handle type=\"source\" position={Position.Bottom} id=\"bottom\" className=\"dc:opacity-0\" isConnectable={false} />\n <Handle type=\"target\" position={Position.Top} id=\"top\" className=\"dc:opacity-0\" isConnectable={false} />\n </div>\n )\n}\n","import type { Edge, EdgeProps } from '@xyflow/react'\nimport type { CubeMetaRelationship } from '../../types'\nimport { useXyflow } from './xyflowContext'\n\ninterface RelationshipEdgeData {\n relationship: CubeMetaRelationship\n joinFields: Array<{\n sourceField: string\n targetField: string\n }>\n [key: string]: unknown\n}\n\nexport type RelationshipEdgeType = Edge<RelationshipEdgeData, 'relationshipEdge'>\n\nexport function RelationshipEdge({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n}: EdgeProps<RelationshipEdgeType>) {\n const { getBezierPath, BaseEdge, EdgeLabelRenderer } = useXyflow()\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 const getSymbol = (rel: string) => {\n switch (rel) {\n case 'belongsTo': return '\\u2208' // belongs to\n case 'hasOne': return '1:1'\n case 'hasMany': return '1:M'\n case 'belongsToMany': return 'M:M'\n default: return '?'\n }\n }\n\n const getColor = (rel: string) => {\n switch (rel) {\n case 'belongsTo': return '#10b981'\n case 'hasOne': return '#3b82f6'\n case 'hasMany': return '#f59e0b'\n case 'belongsToMany': return '#8b5cf6'\n default: return '#6b7280'\n }\n }\n\n const color = getColor(relationship.relationship)\n const symbol = getSymbol(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=\"dc:border-2 dc:rounded-md dc:px-2 dc:py-1 dc:shadow-xs\"\n style={{ backgroundColor: 'var(--dc-surface)', borderColor: color }}\n >\n <div className=\"dc:text-center\">\n <div className=\"dc:font-bold dc:text-xs dc:mb-1\" style={{ color }}>\n {symbol}\n </div>\n <div className=\"dc:text-[9px] text-dc-text-muted dc:leading-tight\">\n {joinFields.map((field, index) => (\n <div key={index} className=\"dc:font-mono\">\n {field.sourceField} → {field.targetField}\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </EdgeLabelRenderer>\n </>\n )\n}\n","import type { ReactNode } from 'react'\nimport type { CubeMetaCube, CubeMetaMeasure, CubeMetaDimension } from '../../types'\nimport { getIcon } from '../../icons'\n\nexport interface FieldSelection {\n cubeName: string\n fieldName: string | null // null = cube-level selection\n fieldType: 'measure' | 'dimension' | 'cube'\n}\n\ninterface FieldDetailPanelProps {\n selection: FieldSelection\n meta: { cubes: CubeMetaCube[] }\n onClose: () => void\n}\n\nfunction DetailRow({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div className=\"dc:flex dc:items-start dc:gap-2 dc:text-xs\">\n <span className=\"text-dc-text-muted dc:w-20 dc:flex-shrink-0 dc:font-medium\">{label}</span>\n <span className=\"text-dc-text dc:flex-1 dc:min-w-0\">{children}</span>\n </div>\n )\n}\n\nfunction TypeBadge({ type, color }: { type: string; color: string }) {\n return (\n <span\n className=\"dc:inline-flex dc:items-center dc:px-1.5 dc:py-0.5 dc:rounded dc:text-[10px] dc:font-medium dc:uppercase\"\n style={{ backgroundColor: `color-mix(in srgb, ${color} 15%, var(--dc-surface))`, color }}\n >\n {type}\n </span>\n )\n}\n\nfunction MeasureDetail({ measure, cube }: { measure: CubeMetaMeasure; cube: CubeMetaCube }) {\n const typeColor = {\n count: '#f59e0b',\n countDistinct: '#f59e0b',\n countDistinctApprox: '#f59e0b',\n sum: '#10b981',\n avg: '#3b82f6',\n min: '#8b5cf6',\n max: '#ec4899',\n runningTotal: '#06b6d4',\n number: '#6b7280',\n }[measure.type] || '#6b7280'\n\n return (\n <div className=\"dc:flex dc:flex-col dc:gap-2\">\n <DetailRow label=\"Cube\">{cube.title || cube.name}</DetailRow>\n <DetailRow label=\"Type\"><TypeBadge type={measure.type} color={typeColor} /></DetailRow>\n {measure.title && measure.title !== measure.shortTitle && (\n <DetailRow label=\"Title\">{measure.title}</DetailRow>\n )}\n {measure.drillMembers && measure.drillMembers.length > 0 && (\n <DetailRow label=\"Drill into\">\n <div className=\"dc:flex dc:flex-wrap dc:gap-1\">\n {measure.drillMembers.map(dm => (\n <span key={dm} className=\"dc:font-mono dc:text-[10px] dc:px-1 dc:py-0.5 dc:rounded bg-dc-surface-secondary border-dc-border dc:border\">\n {dm.split('.')[1] || dm}\n </span>\n ))}\n </div>\n </DetailRow>\n )}\n </div>\n )\n}\n\nfunction DimensionDetail({ dimension, cube }: { dimension: CubeMetaDimension; cube: CubeMetaCube }) {\n const typeColor = dimension.type === 'time' ? '#3b82f6' : '#10b981'\n\n // Find hierarchies this dimension belongs to\n const hierarchies = cube.hierarchies?.filter(h =>\n h.levels.some(l => l === dimension.name || l === `${cube.name}.${dimension.name.split('.')[1]}`)\n ) || []\n\n return (\n <div className=\"dc:flex dc:flex-col dc:gap-2\">\n <DetailRow label=\"Cube\">{cube.title || cube.name}</DetailRow>\n <DetailRow label=\"Type\"><TypeBadge type={dimension.type} color={typeColor} /></DetailRow>\n {dimension.title && dimension.title !== dimension.shortTitle && (\n <DetailRow label=\"Title\">{dimension.title}</DetailRow>\n )}\n {dimension.type === 'time' && dimension.granularities && dimension.granularities.length > 0 && (\n <DetailRow label=\"Granularity\">\n <div className=\"dc:flex dc:flex-wrap dc:gap-1\">\n {dimension.granularities.map(g => (\n <span key={g} className=\"dc:font-mono dc:text-[10px] dc:px-1 dc:py-0.5 dc:rounded bg-dc-surface-secondary border-dc-border dc:border\">\n {g}\n </span>\n ))}\n </div>\n </DetailRow>\n )}\n {hierarchies.length > 0 && (\n <DetailRow label=\"Hierarchy\">\n {hierarchies.map(h => (\n <div key={h.name} className=\"dc:text-[10px]\">\n <span className=\"dc:font-medium\">{h.title}</span>\n <span className=\"text-dc-text-muted dc:ml-1\">\n ({h.levels.map(l => l.split('.')[1] || l).join(' > ')})\n </span>\n </div>\n ))}\n </DetailRow>\n )}\n </div>\n )\n}\n\nfunction CubeDetail({ cube }: { cube: CubeMetaCube }) {\n const relationshipColors: Record<string, string> = {\n belongsTo: '#10b981',\n hasOne: '#3b82f6',\n hasMany: '#f59e0b',\n belongsToMany: '#8b5cf6',\n }\n\n return (\n <div className=\"dc:flex dc:flex-col dc:gap-2\">\n {cube.description && (\n <DetailRow label=\"Description\">{cube.description}</DetailRow>\n )}\n <DetailRow label=\"Measures\">\n <span className=\"dc:font-mono\">{cube.measures.length}</span>\n {cube.measures.length > 0 && (\n <span className=\"text-dc-text-muted dc:ml-1\">\n ({[...new Set(cube.measures.map(m => m.type))].join(', ')})\n </span>\n )}\n </DetailRow>\n <DetailRow label=\"Dimensions\">\n <span className=\"dc:font-mono\">{cube.dimensions.length}</span>\n {cube.dimensions.some(d => d.type === 'time') && (\n <span className=\"text-dc-text-muted dc:ml-1\">\n ({cube.dimensions.filter(d => d.type === 'time').length} time)\n </span>\n )}\n </DetailRow>\n {cube.relationships && cube.relationships.length > 0 && (\n <DetailRow label=\"Joins\">\n <div className=\"dc:flex dc:flex-col dc:gap-1\">\n {cube.relationships.map((rel, i) => (\n <div key={i} className=\"dc:flex dc:items-center dc:gap-1.5 dc:text-[10px]\">\n <TypeBadge type={rel.relationship} color={relationshipColors[rel.relationship] || '#6b7280'} />\n <span className=\"dc:font-mono\">{rel.targetCube}</span>\n </div>\n ))}\n </div>\n </DetailRow>\n )}\n {cube.hierarchies && cube.hierarchies.length > 0 && (\n <DetailRow label=\"Hierarchies\">\n <div className=\"dc:flex dc:flex-col dc:gap-1\">\n {cube.hierarchies.map(h => (\n <div key={h.name} className=\"dc:text-[10px]\">\n <span className=\"dc:font-medium\">{h.title}</span>\n <span className=\"text-dc-text-muted dc:ml-1\">\n ({h.levels.map(l => l.split('.')[1] || l).join(' > ')})\n </span>\n </div>\n ))}\n </div>\n </DetailRow>\n )}\n {cube.meta?.eventStream && (\n <DetailRow label=\"Event Stream\">\n <div className=\"dc:text-[10px]\">\n <span className=\"text-dc-text-muted\">binding: </span>\n <span className=\"dc:font-mono\">{cube.meta.eventStream.bindingKey.split('.')[1] || cube.meta.eventStream.bindingKey}</span>\n <span className=\"text-dc-text-muted dc:ml-2\">time: </span>\n <span className=\"dc:font-mono\">{cube.meta.eventStream.timeDimension.split('.')[1] || cube.meta.eventStream.timeDimension}</span>\n </div>\n </DetailRow>\n )}\n </div>\n )\n}\n\nexport function FieldDetailPanel({ selection, meta, onClose }: FieldDetailPanelProps) {\n const CloseIcon = getIcon('close')\n\n const cube = meta.cubes.find(c => c.name === selection.cubeName)\n if (!cube) return null\n\n // Determine what to show\n let title: string\n let dotColor: string\n let sectionBgColor: string\n let content: ReactNode\n\n if (selection.fieldType === 'cube' || !selection.fieldName) {\n title = cube.title || cube.name\n dotColor = 'var(--dc-accent)'\n sectionBgColor = 'color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))'\n content = <CubeDetail cube={cube} />\n } else if (selection.fieldType === 'measure') {\n const measure = cube.measures.find(m => {\n const mField = m.name.split('.')[1] || m.name\n return mField === selection.fieldName || m.name === selection.fieldName\n })\n if (!measure) return null\n title = measure.shortTitle || measure.title || selection.fieldName\n dotColor = 'var(--dc-warning)'\n sectionBgColor = 'color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))'\n content = <MeasureDetail measure={measure} cube={cube} />\n } else {\n const dimension = cube.dimensions.find(d => {\n const dField = d.name.split('.')[1] || d.name\n return dField === selection.fieldName || d.name === selection.fieldName\n })\n if (!dimension) return null\n title = dimension.shortTitle || dimension.title || selection.fieldName\n dotColor = dimension.type === 'time' ? 'var(--dc-accent)' : 'var(--dc-success)'\n sectionBgColor = dimension.type === 'time'\n ? 'color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))'\n : 'color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))'\n content = <DimensionDetail dimension={dimension} cube={cube} />\n }\n\n return (\n <div\n className=\"dc:border-2 dc:rounded-lg dc:shadow-lg dc:min-w-[260px] dc:max-w-[320px] dc:overflow-hidden dc:transition-all border-dc-border\"\n style={{ backgroundColor: 'var(--dc-surface)' }}\n >\n {/* Header - same style as CubeNode section headers */}\n <div\n className=\"dc:px-4 dc:py-2.5 dc:border-b border-dc-border dc:flex dc:items-center dc:justify-between\"\n style={{ backgroundColor: sectionBgColor }}\n >\n <div className=\"dc:flex dc:items-center dc:gap-2 dc:min-w-0\">\n <span\n className=\"dc:w-2 dc:h-2 dc:rounded-full dc:flex-shrink-0\"\n style={{ backgroundColor: dotColor }}\n />\n <h4 className=\"dc:text-sm dc:font-semibold text-dc-text dc:truncate\">{title}</h4>\n </div>\n <button\n onClick={onClose}\n className=\"dc:ml-2 dc:flex-shrink-0 text-dc-text-muted dc:hover:text-dc-text dc:transition-colors\"\n >\n <CloseIcon className=\"dc:w-3.5 dc:h-3.5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"dc:px-4 dc:py-3\">\n {content}\n </div>\n </div>\n )\n}\n","import { useState, useEffect, useRef, useMemo } from 'react'\nimport type { Node, Edge, Position } from '@xyflow/react'\n\nexport interface LayoutOptions {\n direction: 'TB' | 'LR'\n nodeWidth: number\n nodeSep: number\n rankSep: number\n}\n\nexport const defaultLayoutOptions: LayoutOptions = {\n direction: 'LR',\n nodeWidth: 340,\n nodeSep: 150,\n rankSep: 350,\n}\n\n/**\n * Layout state machine phases:\n * waiting → ELK not loaded yet, nothing to show\n * computing → ELK loaded, running layout algorithm\n * ready → layout complete, node positions available\n */\nexport type LayoutPhase = 'waiting' | 'computing' | 'ready'\n\nfunction getTargetPosition(direction: string): Position {\n switch (direction) {\n case 'TB': return 'top' as Position\n case 'LR': return 'left' as Position\n default: return 'top' as Position\n }\n}\n\nfunction getSourcePosition(direction: string): Position {\n switch (direction) {\n case 'TB': return 'bottom' as Position\n case 'LR': return 'right' as Position\n default: return 'bottom' as Position\n }\n}\n\n/**\n * Estimate the rendered pixel height of a CubeNode.\n */\nfunction estimateNodeHeight(node: Node): number {\n const cube = node.data?.cube as {\n measures?: unknown[]\n dimensions?: { type?: string }[]\n description?: string\n } | undefined\n if (!cube) return 300\n\n const HEADER = cube.description ? 80 : 56\n const SECTION_HEADER = 36\n const ROW = 34\n const MAX_BODY = 256\n const PADDING = 30\n\n let h = HEADER\n const measures = cube.measures?.length ?? 0\n const timeDims = cube.dimensions?.filter((d) => d.type === 'time').length ?? 0\n const regularDims = cube.dimensions?.filter((d) => d.type !== 'time').length ?? 0\n\n if (measures > 0) h += SECTION_HEADER + Math.min(measures * ROW, MAX_BODY)\n if (timeDims > 0) h += SECTION_HEADER + Math.min(timeDims * ROW, MAX_BODY)\n if (regularDims > 0) h += SECTION_HEADER + Math.min(regularDims * ROW, MAX_BODY)\n\n return h + PADDING\n}\n\n// --- ELK singleton (module-level, loaded once) ---\n\ninterface ELKInstance {\n layout(graph: unknown): Promise<unknown>\n}\n\nlet elkInstance: ELKInstance | null = null\nlet elkLoadPromise: Promise<ELKInstance | null> | null = null\n\nfunction loadElk(): Promise<ELKInstance | null> {\n if (elkLoadPromise) return elkLoadPromise\n // Use dynamic specifier so no bundler (Rollup, webpack) can statically resolve this.\n // elkjs is an optional peer dependency - if not installed, the catch() handles it.\n const specifier = ['elkjs', 'lib', 'elk.bundled.js'].join('/')\n elkLoadPromise = import(/* @vite-ignore */ specifier)\n .then((mod) => {\n const ELK = (mod as unknown as { default?: new () => ELKInstance }).default || mod\n elkInstance = new (ELK as unknown as new () => ELKInstance)()\n return elkInstance\n })\n .catch(() => null)\n return elkLoadPromise\n}\n\n// Force-export to prevent tree shaking of the side-effectful import\nexport { loadElk as _elkLoadPromise }\n\n// --- ELK layout computation (pure async function, no hooks) ---\n\ninterface ElkPort {\n id: string\n layoutOptions: Record<string, string>\n}\n\ninterface ElkNode {\n id: string\n width: number\n height: number\n layoutOptions?: Record<string, string>\n ports?: ElkPort[]\n}\n\ninterface ElkEdge {\n id: string\n sources: string[]\n targets: string[]\n}\n\ninterface ElkResultNode { id: string; x: number; y: number }\n\ninterface ElkResult {\n children?: ElkResultNode[]\n}\n\nexport interface ElkLayoutResult {\n nodes: Node[]\n edges: Edge[]\n}\n\nasync function computeElkLayout(\n nodes: Node[],\n edges: Edge[],\n opts: LayoutOptions,\n): Promise<ElkLayoutResult> {\n // Ensure ELK is loaded (lazy, webpack-safe)\n await loadElk()\n if (!elkInstance) {\n // ELK failed to load — return grid fallback\n return { nodes: layoutWithGrid(nodes, opts), edges }\n }\n\n const sourceSide = opts.direction === 'LR' ? 'EAST' : 'SOUTH'\n const targetSide = opts.direction === 'LR' ? 'WEST' : 'NORTH'\n\n // Per-edge ports so ELK spreads connections along the node side\n const nodeSourceEdges = new Map<string, string[]>()\n const nodeTargetEdges = new Map<string, string[]>()\n edges.forEach(edge => {\n if (!nodeSourceEdges.has(edge.source)) nodeSourceEdges.set(edge.source, [])\n nodeSourceEdges.get(edge.source)!.push(edge.id)\n if (!nodeTargetEdges.has(edge.target)) nodeTargetEdges.set(edge.target, [])\n nodeTargetEdges.get(edge.target)!.push(edge.id)\n })\n\n const elkNodes: ElkNode[] = nodes.map((node) => {\n const w = opts.nodeWidth\n const h = estimateNodeHeight(node)\n\n const srcEdges = nodeSourceEdges.get(node.id) || []\n const tgtEdges = nodeTargetEdges.get(node.id) || []\n const ports: ElkPort[] = [\n ...srcEdges.map(edgeId => ({\n id: `${node.id}__src__${edgeId}`,\n layoutOptions: { 'elk.port.side': sourceSide },\n })),\n ...tgtEdges.map(edgeId => ({\n id: `${node.id}__tgt__${edgeId}`,\n layoutOptions: { 'elk.port.side': targetSide },\n })),\n ]\n\n return {\n id: node.id,\n width: w,\n height: h,\n layoutOptions: { 'elk.portConstraints': 'FIXED_SIDE' },\n ports,\n }\n })\n\n const elkEdges: ElkEdge[] = edges.map((edge) => ({\n id: edge.id,\n sources: [`${edge.source}__src__${edge.id}`],\n targets: [`${edge.target}__tgt__${edge.id}`],\n }))\n\n const elkDirection = opts.direction === 'LR' ? 'RIGHT' : 'DOWN'\n\n const graph = {\n id: 'root',\n layoutOptions: {\n 'elk.algorithm': 'layered',\n 'elk.direction': elkDirection,\n 'elk.edgeRouting': 'SPLINES',\n 'elk.layered.edgeRouting.splines.mode': 'CONSERVATIVE',\n 'elk.spacing.nodeNode': String(opts.nodeSep),\n 'elk.layered.spacing.nodeNodeBetweenLayers': String(opts.rankSep),\n 'elk.spacing.edgeNode': '60',\n 'elk.layered.spacing.edgeNodeBetweenLayers': '60',\n 'elk.spacing.edgeEdge': '25',\n 'elk.layered.nodePlacement.strategy': 'NETWORK_SIMPLEX',\n 'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',\n },\n children: elkNodes,\n edges: elkEdges,\n }\n\n const result = await elkInstance.layout(graph) as ElkResult\n\n // Extract node positions (ELK returns top-left, same as React Flow)\n const positionMap = new Map<string, { x: number; y: number }>()\n if (result.children) {\n for (const child of result.children) {\n positionMap.set(child.id, { x: child.x, y: child.y })\n }\n }\n\n const layoutedNodes = nodes.map((node) => ({\n ...node,\n position: positionMap.get(node.id) || node.position,\n targetPosition: getTargetPosition(opts.direction),\n sourcePosition: getSourcePosition(opts.direction),\n }))\n\n // Return positioned nodes + original edges.\n // Edge rendering is handled by React Flow's getBezierPath() which knows\n // the actual handle positions — much more accurate than ELK's spline routes.\n return { nodes: layoutedNodes, edges }\n}\n\nfunction layoutWithGrid(nodes: Node[], opts: LayoutOptions): Node[] {\n const COL_HEIGHT_LIMIT = 1200\n let col = 0\n let colY = 0\n\n return nodes.map((node) => {\n const h = estimateNodeHeight(node)\n if (colY + h > COL_HEIGHT_LIMIT && colY > 0) {\n col++\n colY = 0\n }\n const position = { x: col * (opts.nodeWidth + opts.nodeSep), y: colY }\n colY += h + 40\n\n return {\n ...node,\n position,\n sourcePosition: getSourcePosition(opts.direction),\n targetPosition: getTargetPosition(opts.direction),\n }\n })\n}\n\n// --- Hook: single computation per structure key, no races ---\n\n/**\n * Layout hook with explicit state machine.\n *\n * - Waits for ELK to load (phase: 'waiting')\n * - Runs layout once per unique node/edge structure (phase: 'computing')\n * - Returns stable result (phase: 'ready')\n *\n * The effect only depends on a string structure key, NOT object references.\n * This prevents re-renders from cancelling in-flight computations.\n */\nexport function useERDLayout(\n nodes: Node[],\n edges: Edge[],\n options: Partial<LayoutOptions> = {}\n): { nodes: Node[]; edges: Edge[]; phase: LayoutPhase } {\n const opts = useMemo(\n () => ({ ...defaultLayoutOptions, ...options }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [options.direction, options.nodeWidth, options.nodeSep, options.rankSep]\n )\n\n // Stable structure key — only changes when node/edge IDs change\n const structureKey = useMemo(() => {\n if (nodes.length === 0) return ''\n return nodes.map(n => n.id).sort().join(',') + '|' + edges.map(e => e.id).sort().join(',')\n }, [nodes, edges])\n\n // Refs hold latest values so the effect closure always reads current data\n // without needing them as dependencies\n const nodesRef = useRef(nodes)\n const edgesRef = useRef(edges)\n const optsRef = useRef(opts)\n nodesRef.current = nodes\n edgesRef.current = edges\n optsRef.current = opts\n\n const [phase, setPhase] = useState<LayoutPhase>('waiting')\n const [result, setResult] = useState<ElkLayoutResult | null>(null)\n const [resultKey, setResultKey] = useState('')\n\n // Single computation per structure key\n const computeIdRef = useRef(0)\n\n useEffect(() => {\n if (!structureKey) {\n setPhase('ready')\n setResult(null)\n setResultKey('')\n return\n }\n\n const id = ++computeIdRef.current\n setPhase('computing')\n\n computeElkLayout(nodesRef.current, edgesRef.current, optsRef.current)\n .then(layoutResult => {\n // Only apply if this is still the latest computation\n if (id !== computeIdRef.current) return\n setResult(layoutResult)\n setResultKey(structureKey)\n setPhase('ready')\n })\n .catch(() => {\n if (id !== computeIdRef.current) return\n // On error, use grid fallback\n setResult({\n nodes: layoutWithGrid(nodesRef.current, optsRef.current),\n edges: edgesRef.current,\n })\n setResultKey(structureKey)\n setPhase('ready')\n })\n }, [structureKey]) // ONLY depends on structure key — no object refs\n\n // Output: only return layout when it matches current structure\n if (phase === 'ready' && result && resultKey === structureKey) {\n return { nodes: result.nodes, edges: result.edges, phase: 'ready' }\n }\n\n return { nodes: [], edges: [], phase }\n}\n","import { useCallback, useMemo, useEffect, useState, useRef } from 'react'\nimport type { MouseEvent as ReactMouseEvent } from 'react'\nimport type { Node, Edge, NodeChange, EdgeChange } from '@xyflow/react'\nimport '@xyflow/react/dist/style.css'\n\nimport { useCubeContext } from '../../providers/CubeProvider'\nimport { CubeNode } from './CubeNode'\nimport { RelationshipEdge } from './RelationshipEdge'\nimport { FieldDetailPanel } from './FieldDetailPanel'\nimport type { FieldSelection } from './FieldDetailPanel'\nimport { useERDLayout } from './useERDLayout'\nimport { getIcon } from '../../icons'\nimport { useXyflow } from './xyflowContext'\n\nconst nodeTypes = { cubeNode: CubeNode }\nconst edgeTypes = { relationshipEdge: RelationshipEdge }\n\n/**\n * Inner component that uses useNodesInitialized() (must be inside <ReactFlow>).\n * Calls fitView exactly once per fitViewToken change, after all nodes are measured.\n */\nfunction FitViewOnReady({ token }: { token: number }) {\n const { useNodesInitialized, useReactFlow } = useXyflow()\n const nodesInitialized = useNodesInitialized()\n const { fitView } = useReactFlow()\n const appliedTokenRef = useRef(0)\n\n useEffect(() => {\n if (token === 0 || token === appliedTokenRef.current) return\n if (!nodesInitialized) return\n appliedTokenRef.current = token\n fitView({ padding: 0.1 })\n }, [token, nodesInitialized, fitView])\n\n return null\n}\n\n// Stable empty arrays (avoid new [] on every render)\nconst EMPTY_STRINGS: string[] = []\n\nexport interface SchemaVisualizationProps {\n className?: string\n onFieldClick?: (cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension') => void\n highlightedCubes?: string[]\n highlightedFields?: string[]\n searchTerm?: string\n height?: string | number\n}\n\nfunction getRelationshipColor(relationship: string): string {\n switch (relationship) {\n case 'belongsTo': return '#10b981'\n case 'hasOne': return '#3b82f6'\n case 'hasMany': return '#f59e0b'\n case 'belongsToMany': return '#8b5cf6'\n default: return '#6b7280'\n }\n}\n\nexport function SchemaVisualization({\n className = '',\n onFieldClick,\n highlightedCubes,\n highlightedFields,\n searchTerm,\n height = '100%',\n}: SchemaVisualizationProps) {\n const {\n ReactFlow: ReactFlowComponent,\n Controls,\n MiniMap,\n Background,\n applyNodeChanges,\n } = useXyflow()\n const { meta, metaLoading, metaError } = useCubeContext()\n\n // Stabilize array props to avoid re-creating references every render\n const stableHighlightedCubes = highlightedCubes || EMPTY_STRINGS\n const stableHighlightedFields = highlightedFields || EMPTY_STRINGS\n\n const [contextMenu, setContextMenu] = useState<{ x: number; y: number } | null>(null)\n const [searchInput, setSearchInput] = useState(searchTerm || '')\n const [autoLayoutCounter, setAutoLayoutCounter] = useState(0)\n const [selectedField, setSelectedField] = useState<FieldSelection | null>(null)\n const [detailPosition, setDetailPosition] = useState<{ x: number; y: number } | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n // In standalone mode (no onFieldClick), clicking fields shows the detail panel\n const isStandaloneMode = !onFieldClick\n const [savedPositions, setSavedPositions] = useState<Record<string, { x: number; y: number }>>({})\n const [positionsLoaded, setPositionsLoaded] = useState(false)\n\n const SearchIcon = getIcon('search')\n const CloseIcon = getIcon('close')\n\n const effectiveSearchTerm = searchTerm !== undefined ? searchTerm : searchInput\n\n // Load saved positions from localStorage (once)\n useEffect(() => {\n try {\n const saved = localStorage.getItem('drizzle-cube-erd-node-positions')\n if (saved) setSavedPositions(JSON.parse(saved))\n } catch { /* ignore */ }\n setPositionsLoaded(true)\n }, [])\n\n // --- Structural data: only depends on meta (stable) ---\n // Separate structure (for layout) from presentation (highlights/search)\n\n const { structuralNodes, structuralEdges } = useMemo(() => {\n if (!meta) return { structuralNodes: [] as Node[], structuralEdges: [] as Edge[] }\n\n const nodes: Node[] = meta.cubes.map((cube, index) => ({\n id: cube.name,\n type: 'cubeNode',\n // Placeholder position — ELK will override for auto-layout\n position: { x: (index % 3) * 400, y: Math.floor(index / 3) * 300 },\n data: { cube },\n }))\n\n const edges: Edge[] = []\n meta.cubes.forEach(cube => {\n if (cube.relationships) {\n cube.relationships.forEach((rel, i) => {\n if (rel.relationship === 'belongsTo') return\n edges.push({\n id: `${cube.name}-${rel.targetCube}-${i}`,\n source: cube.name,\n target: rel.targetCube,\n type: 'relationshipEdge',\n data: { relationship: rel, joinFields: rel.joinFields || [] },\n animated: false,\n style: { stroke: getRelationshipColor(rel.relationship), strokeWidth: 2 },\n })\n })\n }\n })\n\n return { structuralNodes: nodes, structuralEdges: edges }\n }, [meta]) // Only meta — no highlights/search/callbacks\n\n // --- Layout decision ---\n const needsAutoLayout = autoLayoutCounter > 0 || (positionsLoaded && Object.keys(savedPositions).length === 0)\n\n // Run ELK layout (only when auto-layout needed, otherwise pass empty to skip)\n const { nodes: elkNodes, edges: elkEdges, phase: layoutPhase } = useERDLayout(\n needsAutoLayout ? structuralNodes : [],\n needsAutoLayout ? structuralEdges : [],\n { direction: 'LR', nodeWidth: 340, nodeSep: 150, rankSep: 350 }\n )\n\n // --- Build display data: merge layout positions + presentation data ---\n\n // Convert client coords to container-relative, clamped to keep panel in view\n const toContainerPos = useCallback((clientX: number, clientY: number) => {\n const rect = containerRef.current?.getBoundingClientRect()\n if (!rect) return { x: clientX, y: clientY }\n const panelW = 300, panelH = 200 // approximate panel size for clamping\n let x = clientX - rect.left + 12 // offset slightly right of cursor\n let y = clientY - rect.top + 12 // offset slightly below cursor\n // Clamp so panel doesn't overflow right/bottom\n if (x + panelW > rect.width) x = clientX - rect.left - panelW - 12\n if (y + panelH > rect.height) y = rect.height - panelH - 8\n if (x < 0) x = 8\n if (y < 0) y = 8\n return { x, y }\n }, [])\n\n // Internal field click handler for standalone mode\n const handleInternalFieldClick = useCallback((cubeName: string, fieldName: string, fieldType: 'measure' | 'dimension', pos?: { x: number; y: number }) => {\n setSelectedField(prev => {\n if (prev && prev.cubeName === cubeName && prev.fieldName === fieldName) {\n setDetailPosition(null)\n return null\n }\n if (pos) setDetailPosition(toContainerPos(pos.x, pos.y))\n return { cubeName, fieldName, fieldType }\n })\n }, [toContainerPos])\n\n const handleInternalCubeClick = useCallback((cubeName: string, pos?: { x: number; y: number }) => {\n setSelectedField(prev => {\n if (prev && prev.cubeName === cubeName && prev.fieldName === null) {\n setDetailPosition(null)\n return null\n }\n if (pos) setDetailPosition(toContainerPos(pos.x, pos.y))\n return { cubeName, fieldName: null, fieldType: 'cube' }\n })\n }, [toContainerPos])\n\n const effectiveFieldClick = isStandaloneMode ? handleInternalFieldClick : onFieldClick\n const effectiveCubeClick = isStandaloneMode ? handleInternalCubeClick : undefined\n\n const buildNodeData = useCallback((cube: unknown) => ({\n cube,\n onFieldClick: effectiveFieldClick,\n onCubeClick: effectiveCubeClick,\n isHighlighted: stableHighlightedCubes.includes((cube as { name: string }).name),\n highlightedFields: stableHighlightedFields,\n searchTerm: effectiveSearchTerm,\n selectedField: isStandaloneMode ? selectedField : null,\n }), [effectiveFieldClick, effectiveCubeClick, stableHighlightedCubes, stableHighlightedFields, effectiveSearchTerm, isStandaloneMode, selectedField])\n\n // Determine if layout is resolved (ready to render ReactFlow)\n const layoutReady = !needsAutoLayout || layoutPhase === 'ready'\n\n const displayNodes = useMemo(() => {\n if (!meta || !layoutReady || !positionsLoaded) return []\n\n if (needsAutoLayout && elkNodes.length > 0) {\n // Use ELK-positioned nodes, inject presentation data\n return elkNodes.map(node => ({\n ...node,\n data: buildNodeData(node.data?.cube || meta.cubes.find(c => c.name === node.id)),\n }))\n }\n\n // Use saved positions\n return structuralNodes.map(node => ({\n ...node,\n position: savedPositions[node.id] || node.position,\n data: buildNodeData(node.data?.cube),\n }))\n }, [meta, layoutReady, positionsLoaded, needsAutoLayout, elkNodes, structuralNodes, savedPositions, buildNodeData])\n\n const displayEdges = useMemo(() => {\n if (!meta || !layoutReady) return []\n if (needsAutoLayout && elkEdges.length > 0) return elkEdges\n return structuralEdges\n }, [meta, layoutReady, needsAutoLayout, elkEdges, structuralEdges])\n\n // --- Controlled ReactFlow state ---\n const [rfNodes, setRfNodes] = useState<Node[]>([])\n const [rfEdges, setRfEdges] = useState<Edge[]>([])\n const appliedLayoutKeyRef = useRef('')\n const [fitViewToken, setFitViewToken] = useState(0) // increment to request fitView\n\n // Push layout to ReactFlow — only when positions change (not on data-only changes)\n useEffect(() => {\n if (displayNodes.length === 0) return\n\n const key = displayNodes.map(n => `${n.id}:${Math.round(n.position.x)},${Math.round(n.position.y)}`).join('|')\n if (key === appliedLayoutKeyRef.current) return\n\n const isFirstLayout = appliedLayoutKeyRef.current === ''\n appliedLayoutKeyRef.current = key\n setRfNodes(displayNodes)\n setRfEdges(displayEdges)\n\n // Request fitView on first layout\n if (isFirstLayout) {\n setFitViewToken(t => t + 1)\n }\n }, [displayNodes, displayEdges])\n\n // Update presentation data (highlights, search) without resetting positions\n const prevPresentationRef = useRef('')\n useEffect(() => {\n const selectedKey = selectedField ? `${selectedField.cubeName}.${selectedField.fieldName}` : ''\n const presentationKey = `${stableHighlightedCubes.join(',')}|${stableHighlightedFields.join(',')}|${effectiveSearchTerm}|${String(onFieldClick)}|${selectedKey}`\n if (presentationKey === prevPresentationRef.current) return\n prevPresentationRef.current = presentationKey\n\n if (rfNodes.length === 0 || !meta) return\n setRfNodes(prev => prev.map(node => {\n const cube = meta.cubes.find(c => c.name === node.id)\n if (!cube) return node\n return { ...node, data: buildNodeData(cube) }\n }))\n }, [stableHighlightedCubes, stableHighlightedFields, effectiveSearchTerm, onFieldClick, selectedField, rfNodes.length, meta, buildNodeData])\n\n // Handle node changes (dragging)\n const handleNodesChange = useCallback((changes: NodeChange[]) => {\n setRfNodes(nds => applyNodeChanges(changes, nds))\n\n // Save positions on drag end\n const dragEnds = changes.filter(\n (c) => c.type === 'position' && 'dragging' in c && c.dragging === false\n )\n if (dragEnds.length > 0) {\n setRfNodes(currentNodes => {\n const positions: Record<string, { x: number; y: number }> = {}\n currentNodes.forEach(n => { if (n.position) positions[n.id] = n.position })\n try { localStorage.setItem('drizzle-cube-erd-node-positions', JSON.stringify(positions)) } catch { /* ignore */ }\n setSavedPositions(positions)\n return currentNodes\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const handleEdgesChange = useCallback((_changes: EdgeChange[]) => {}, [])\n\n const handleContextMenu = useCallback((event: ReactMouseEvent | MouseEvent) => {\n event.preventDefault()\n event.stopPropagation()\n setContextMenu({ x: event.clientX, y: event.clientY })\n }, [])\n\n const handleClick = useCallback(() => {\n if (contextMenu) setContextMenu(null)\n if (selectedField) { setSelectedField(null); setDetailPosition(null) }\n }, [contextMenu, selectedField])\n\n const handleAutoLayout = useCallback(() => {\n setSavedPositions({})\n appliedLayoutKeyRef.current = '' // force re-apply → layout effect will request fitView\n try { localStorage.removeItem('drizzle-cube-erd-node-positions') } catch { /* ignore */ }\n setAutoLayoutCounter(c => c + 1)\n setContextMenu(null)\n }, [])\n\n // --- Render ---\n\n if (metaLoading) {\n return (\n <div className={`dc:flex dc:items-center dc:justify-center dc:h-96 ${className}`}>\n <div className=\"dc:text-center\">\n <div className=\"dc:animate-spin dc:rounded-full dc:h-8 dc:w-8 dc:border-b-2 border-dc-accent dc:mx-auto dc:mb-2\" />\n <p className=\"text-dc-text-muted\">Loading cube schema...</p>\n </div>\n </div>\n )\n }\n\n if (metaError) {\n return (\n <div className={`dc:flex dc:items-center dc:justify-center dc:h-96 ${className}`}>\n <div className=\"dc:text-center text-dc-error\">\n <p className=\"dc:font-medium\">Failed to load cube schema</p>\n <p className=\"dc:text-sm dc:mt-1\">{metaError}</p>\n </div>\n </div>\n )\n }\n\n if (!meta || meta.cubes.length === 0) {\n return (\n <div className={`dc:flex dc:items-center dc:justify-center dc:h-96 ${className}`}>\n <div className=\"dc:text-center text-dc-text-muted\">\n <p className=\"dc:font-medium\">No cubes found</p>\n <p className=\"dc:text-sm dc:mt-1\">Register some cubes to see the relationship diagram</p>\n </div>\n </div>\n )\n }\n\n // Show loading while ELK computes layout (no grid flash)\n if (!layoutReady) {\n return (\n <div className={`dc:flex dc:items-center dc:justify-center dc:h-96 ${className}`}>\n <div className=\"dc:text-center\">\n <div className=\"dc:animate-spin dc:rounded-full dc:h-8 dc:w-8 dc:border-b-2 border-dc-accent dc:mx-auto dc:mb-2\" />\n <p className=\"text-dc-text-muted\">Computing layout...</p>\n </div>\n </div>\n )\n }\n\n return (\n <div className={`dc:flex dc:flex-col ${className}`} style={{ height, minHeight: 400 }}>\n {searchTerm === undefined && (\n <div className=\"dc:px-3 dc:py-2 dc:border-b border-dc-border bg-dc-surface dc:flex dc:items-center dc:gap-2 dc:flex-shrink-0\">\n <SearchIcon className=\"dc:w-4 dc:h-4 text-dc-text-muted\" />\n <input\n type=\"text\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder=\"Search cubes and fields...\"\n className=\"dc:flex-1 dc:text-sm dc:bg-transparent dc:outline-none text-dc-text dc:placeholder:text-dc-text-muted\"\n />\n {searchInput && (\n <button onClick={() => setSearchInput('')} className=\"text-dc-text-muted dc:hover:text-dc-text\">\n <CloseIcon className=\"dc:w-3 dc:h-3\" />\n </button>\n )}\n </div>\n )}\n\n <div ref={containerRef} className=\"dc:relative dc:flex-1 dc:min-h-0\">\n <div style={{ position: 'absolute', inset: 0 }}>\n <ReactFlowComponent\n nodes={rfNodes}\n edges={rfEdges}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n connectionMode={'loose' as never}\n minZoom={0.1}\n maxZoom={2}\n proOptions={{ hideAttribution: true }}\n onPaneContextMenu={handleContextMenu}\n onPaneClick={handleClick}\n >\n <Controls />\n <MiniMap\n nodeColor={(node) => stableHighlightedCubes.includes(node.id) ? '#8b5cf6' : '#e5e7eb'}\n maskColor=\"rgb(240, 242, 246, 0.7)\"\n />\n <Background variant={'dots' as never} gap={12} size={1} />\n <FitViewOnReady token={fitViewToken} />\n </ReactFlowComponent>\n </div>\n\n {/* Field detail panel for standalone browse mode */}\n {isStandaloneMode && selectedField && detailPosition && meta && (\n <div\n className=\"dc:absolute dc:z-20\"\n style={{ left: detailPosition.x, top: detailPosition.y }}\n >\n <FieldDetailPanel\n selection={selectedField}\n meta={meta}\n onClose={() => { setSelectedField(null); setDetailPosition(null) }}\n />\n </div>\n )}\n </div>\n\n {contextMenu && (\n <div\n className=\"dc:fixed dc:z-50 bg-dc-surface dc:rounded-md dc:shadow-lg dc:border border-dc-border dc:py-1 dc:min-w-[120px]\"\n style={{ left: contextMenu.x, top: contextMenu.y }}\n >\n <button\n onClick={handleAutoLayout}\n className=\"dc:w-full dc:px-3 dc:py-2 dc:text-sm text-dc-text-secondary dc:hover:bg-dc-surface-hover dc:text-left\"\n >\n Auto Layout\n </button>\n </div>\n )}\n </div>\n )\n}\n\nexport default SchemaVisualization\n"],"mappings":"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"}
@@ -16,8 +16,8 @@ export type LayoutPhase = 'waiting' | 'computing' | 'ready';
16
16
  interface ELKInstance {
17
17
  layout(graph: unknown): Promise<unknown>;
18
18
  }
19
- declare const elkLoadPromise: Promise<ELKInstance | null>;
20
- export { elkLoadPromise as _elkLoadPromise };
19
+ declare function loadElk(): Promise<ELKInstance | null>;
20
+ export { loadElk as _elkLoadPromise };
21
21
  export interface ElkLayoutResult {
22
22
  nodes: Node[];
23
23
  edges: Edge[];
@@ -1,4 +1,4 @@
1
- import { D as e, i as t, n, r, t as i } from "./chunks/DashboardEditModal-DrjEsyoO.js";
1
+ import { D as e, i as t, n, r, t as i } from "./chunks/DashboardEditModal-EmBxK-89.js";
2
2
  import { i as a, p as o } from "./chunks/FieldSearchModal-BxQ5JhWz.js";
3
3
  import { a as s, n as c, o as l, r as u, s as d, t as f } from "./chunks/utils-3FNmeZJR.js";
4
4
  export { a as AnalysisDisplayConfigPanel, r as AnalyticsDashboard, e as AnalyticsPortlet, i as DashboardEditModal, t as DashboardGrid, o as Modal, n as PortletContainer, f as createDashboardLayout, c as createSamplePortlet, u as findNextPosition, s as generatePortletId, l as generateResponsiveLayouts, d as validateCubeQuery };
@@ -6,7 +6,7 @@ import { a as oe, c as se, i as ce, l as le, o as ue, r as de, s as fe } from ".
6
6
  import { n as pe, r as me } from "./chunks/chart-sankey-8nRYnupt.js";
7
7
  import { n as he, t as ge } from "./chunks/providers-DX3Vw5kc.js";
8
8
  import { A as _e, _ as ve, c as ye, d as be, f as xe, g as Se, h as Ce, l as we, m as Te, p as Ee, u as De } from "./chunks/chart-activity-grid-wR2Twpo7.js";
9
- import { A as Oe, C as ke, D as Ae, E as je, M as Me, N as Ne, O as Pe, S as Fe, T as Ie, _ as Le, a as Re, b as ze, c as Be, d as Ve, f as He, g as Ue, h as We, i as Ge, j as Ke, k as qe, l as Je, m as Ye, n as Xe, o as Ze, p as Qe, r as $e, s as et, t as tt, u as nt, v as rt, w as it, x as at, y as ot } from "./chunks/DashboardEditModal-DrjEsyoO.js";
9
+ import { A as Oe, C as ke, D as Ae, E as je, M as Me, N as Ne, O as Pe, S as Fe, T as Ie, _ as Le, a as Re, b as ze, c as Be, d as Ve, f as He, g as Ue, h as We, i as Ge, j as Ke, k as qe, l as Je, m as Ye, n as Xe, o as Ze, p as Qe, r as $e, s as et, t as tt, u as nt, v as rt, w as it, x as at, y as ot } from "./chunks/DashboardEditModal-EmBxK-89.js";
10
10
  import { u as V } from "./chunks/chart-area-e9ysnatQ.js";
11
11
  import { a as st, i as ct, n as lt, o as ut, r as dt, s as ft, t as pt } from "./chunks/charts-loader-gZjOqZwG.js";
12
12
  import { A as mt, C as ht, D as gt, E as _t, F as vt, I as yt, L as bt, M as xt, N as St, O as Ct, P as wt, R as Tt, S as Et, T as Dt, h as Ot, j as kt, k as At, p as jt, r as Mt, t as Nt, w as Pt } from "./chunks/FieldSearchModal-BxQ5JhWz.js";
@@ -14,7 +14,7 @@ import { r as Ft } from "./chunks/syntaxHighlighting-BLl0ch4A.js";
14
14
  import { A as It, D as Lt, E as Rt, F as zt, I as Bt, M as Vt, O as Ht, P as Ut, S as Wt, T as Gt, _ as Kt, a as qt, b as Jt, c as Yt, d as Xt, f as Zt, g as Qt, h as $t, i as en, j as tn, k as nn, l as rn, n as an, o as on, p as sn, r as cn, s as ln, t as un, v as dn, w as fn, x as pn, y as mn } from "./chunks/analysis-builder-shared-BxHYfTzo.js";
15
15
  import { r as hn } from "./chunks/chart-markdown-B2X4IwLO.js";
16
16
  import { t as gn } from "./chunks/useNotebookLayout-BFZ_33Kb.js";
17
- import { n as _n } from "./chunks/schema-visualization-XLFzV_7p.js";
17
+ import { n as _n } from "./chunks/schema-visualization-BFPl_eKV.js";
18
18
  import { n as vn } from "./chunks/chart-bubble-DvyG15UB.js";
19
19
  import { i as yn, t as bn } from "./chunks/utils-3FNmeZJR.js";
20
20
  import H, { createContext as xn, useCallback as U, useContext as Sn, useEffect as W, useMemo as G, useRef as K, useState as q } from "react";