drizzle-cube 0.2.25 → 0.2.27

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 (95) hide show
  1. package/dist/client/charts.js +2 -2
  2. package/dist/client/chunks/{charts-BsXrHSCm.js → charts-BfXEKIrq.js} +44 -44
  3. package/dist/client/chunks/{charts-BsXrHSCm.js.map → charts-BfXEKIrq.js.map} +1 -1
  4. package/dist/client/chunks/charts-DQuOI5HA.js +9465 -0
  5. package/dist/client/chunks/charts-DQuOI5HA.js.map +1 -0
  6. package/dist/client/chunks/components-CWMeA5e-.js +14872 -0
  7. package/dist/client/chunks/components-CWMeA5e-.js.map +1 -0
  8. package/dist/client/chunks/core-DrhYtHHa.js +6 -0
  9. package/dist/client/chunks/core-DrhYtHHa.js.map +1 -0
  10. package/dist/client/chunks/hooks-CAKGR-w0.js +828 -0
  11. package/dist/client/chunks/hooks-CAKGR-w0.js.map +1 -0
  12. package/dist/client/components/AIAssistant/index.d.ts +5 -2
  13. package/dist/client/components/AnalysisBuilder/index.d.ts +6 -0
  14. package/dist/client/components/AnalysisBuilder/types.d.ts +9 -7
  15. package/dist/client/components/AnalysisBuilder/utils/fieldUtils.d.ts +46 -0
  16. package/dist/client/components/AnalysisBuilder/utils/filterUtils.d.ts +19 -0
  17. package/dist/client/components/AnalysisBuilder/utils/idUtils.d.ts +11 -0
  18. package/dist/client/components/AnalysisBuilder/utils/index.d.ts +11 -0
  19. package/dist/client/components/AnalysisBuilder/utils/queryUtils.d.ts +11 -0
  20. package/dist/client/components/AnalysisBuilder/utils/recentFieldsUtils.d.ts +14 -0
  21. package/dist/client/components/AnalysisBuilder/utils/storageUtils.d.ts +42 -0
  22. package/dist/client/components/ConfirmModal.d.ts +30 -0
  23. package/dist/client/components/DashboardFilters/CompactFilterBar.d.ts +13 -0
  24. package/dist/client/components/DashboardFilters/CustomDateDropdown.d.ts +10 -0
  25. package/dist/client/components/DashboardFilters/DashboardFilterConfigModal.d.ts +20 -0
  26. package/dist/client/components/DashboardFilters/DashboardFilterItem.d.ts +14 -0
  27. package/dist/client/components/DashboardFilters/DatePresetChips.d.ts +8 -0
  28. package/dist/client/components/DashboardFilters/FilterChip.d.ts +12 -0
  29. package/dist/client/components/DashboardFilters/FilterValuePopover.d.ts +11 -0
  30. package/dist/client/components/DashboardFilters/XTDDropdown.d.ts +10 -0
  31. package/dist/client/components/DashboardPortletCard.d.ts +13 -34
  32. package/dist/client/components/PortletAnalysisModal.d.ts +4 -2
  33. package/dist/client/components/QueryBuilder/types.d.ts +0 -17
  34. package/dist/client/components/shared/utils.d.ts +33 -109
  35. package/dist/client/components.d.ts +0 -1
  36. package/dist/client/components.js +12 -13
  37. package/dist/client/hooks/queries/index.d.ts +15 -0
  38. package/dist/client/hooks/queries/useCubeLoadQuery.d.ts +67 -0
  39. package/dist/client/hooks/queries/useCubeMetaQuery.d.ts +51 -0
  40. package/dist/client/hooks/queries/useDryRunQuery.d.ts +103 -0
  41. package/dist/client/hooks/queries/useMultiCubeLoadQuery.d.ts +68 -0
  42. package/dist/client/hooks/useAnalysisAI.d.ts +44 -0
  43. package/dist/client/hooks/useAnalysisBuilderHook.d.ts +113 -0
  44. package/dist/client/hooks/useAnalysisChartDefaults.d.ts +35 -0
  45. package/dist/client/hooks/useAnalysisCombinedFields.d.ts +18 -0
  46. package/dist/client/hooks/useAnalysisInitialization.d.ts +25 -0
  47. package/dist/client/hooks/useAnalysisQueryBuilder.d.ts +32 -0
  48. package/dist/client/hooks/useAnalysisQueryExecution.d.ts +38 -0
  49. package/dist/client/hooks/useAnalysisShare.d.ts +23 -0
  50. package/dist/client/hooks/useAnalysisUIState.d.ts +24 -0
  51. package/dist/client/hooks/useDashboardHook.d.ts +108 -0
  52. package/dist/client/hooks/useDebounceQuery.d.ts +48 -0
  53. package/dist/client/hooks/useDirtyStateTracking.d.ts +37 -0
  54. package/dist/client/hooks/useFilterValues.d.ts +4 -1
  55. package/dist/client/hooks.d.ts +4 -2
  56. package/dist/client/hooks.js +12 -170
  57. package/dist/client/hooks.js.map +1 -1
  58. package/dist/client/icons.js +1 -1
  59. package/dist/client/index.d.ts +11 -4
  60. package/dist/client/index.js +99 -70
  61. package/dist/client/providers/CubeMetaProvider.d.ts +1 -1
  62. package/dist/client/providers/CubeProvider.d.ts +7 -3
  63. package/dist/client/providers.js +1 -1
  64. package/dist/client/shared/queryKey.d.ts +1 -0
  65. package/dist/client/shared/utils.d.ts +5 -0
  66. package/dist/client/stores/analysisBuilderStore.d.ts +271 -0
  67. package/dist/client/stores/dashboardStore.d.ts +267 -0
  68. package/dist/client/stores/index.d.ts +13 -0
  69. package/dist/client/styles.css +1 -1
  70. package/dist/client/types.d.ts +27 -1
  71. package/dist/client/utils/chartUtils.d.ts +1 -2
  72. package/dist/client/utils/filterUtils.d.ts +15 -10
  73. package/dist/client/utils/pivotUtils.d.ts +1 -2
  74. package/dist/client-bundle-stats.html +1 -1
  75. package/package.json +13 -19
  76. package/dist/client/chunks/charts-BvLb1eub.js +0 -7427
  77. package/dist/client/chunks/charts-BvLb1eub.js.map +0 -1
  78. package/dist/client/chunks/components-DhA8GIUY.js +0 -14851
  79. package/dist/client/chunks/components-DhA8GIUY.js.map +0 -1
  80. package/dist/client/chunks/core-DcwgBEzv.js +0 -6
  81. package/dist/client/chunks/core-DcwgBEzv.js.map +0 -1
  82. package/dist/client/chunks/index-9x0R-Fme.js +0 -551
  83. package/dist/client/chunks/index-9x0R-Fme.js.map +0 -1
  84. package/dist/client/components/AIAssistant/AIAssistantModal.d.ts +0 -10
  85. package/dist/client/components/AnalysisBuilder/utils.d.ts +0 -103
  86. package/dist/client/components/CubeRelationshipDiagram/CubeNode.d.ts +0 -13
  87. package/dist/client/components/CubeRelationshipDiagram/ERDControls.d.ts +0 -7
  88. package/dist/client/components/CubeRelationshipDiagram/RelationshipEdge.d.ts +0 -11
  89. package/dist/client/components/CubeRelationshipDiagram/index.d.ts +0 -10
  90. package/dist/client/components/CubeRelationshipDiagram/useERDLayout.d.ts +0 -21
  91. package/dist/client/components/PortletEditModal.d.ts +0 -12
  92. package/dist/client/components/shared/CubeMetaExplorer.d.ts +0 -4
  93. package/dist/client/hooks/useCubeMeta.d.ts +0 -39
  94. package/dist/client/hooks/useCubeQuery.d.ts +0 -9
  95. package/dist/client/hooks/useMultiCubeQuery.d.ts +0 -36
@@ -1,6 +0,0 @@
1
- import { H as a } from "./components-DhA8GIUY.js";
2
- export {
3
- a as HighlightJS,
4
- a as default
5
- };
6
- //# sourceMappingURL=core-DcwgBEzv.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-DcwgBEzv.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,551 +0,0 @@
1
- import { jsxs as o, jsx as t, Fragment as J } from "react/jsx-runtime";
2
- import { useMemo as j, useState as H, useEffect as T, useCallback as S } from "react";
3
- import Z, { Handle as P, Position as g, getBezierPath as K, BaseEdge as Q, EdgeLabelRenderer as U, useNodesState as _, useEdgesState as ee, addEdge as te, ConnectionMode as se, Controls as ne, MiniMap as re, Background as oe, BackgroundVariant as ae } from "reactflow";
4
- import { u as ie } from "./charts-BvLb1eub.js";
5
- import O from "dagre";
6
- function ce({ data: i }) {
7
- const { cube: s, onFieldClick: f, isHighlighted: n, highlightedFields: w, searchTerm: m } = i, d = () => {
8
- }, y = (e, r) => {
9
- f && f(s.name, e, r);
10
- }, l = (e) => w.includes(e), b = (e) => {
11
- if (!m?.trim()) return !0;
12
- const r = m.toLowerCase();
13
- return e.name.toLowerCase().includes(r) || e.title && e.title.toLowerCase().includes(r);
14
- }, k = (() => {
15
- if (!m?.trim()) return !0;
16
- const e = s.measures.some((c) => b(c)), r = s.dimensions.some((c) => b(c));
17
- return e || r;
18
- })(), N = (e, r, c) => {
19
- const v = b(e), u = "px-4 py-2 text-xs cursor-pointer transition-all border-b border-dc-border last:border-b-0";
20
- if (!k && m?.trim()) {
21
- if (r) {
22
- if (c === "measure")
23
- return `${u} bg-dc-warning-bg text-dc-warning`;
24
- if (c === "dimension")
25
- return e.type === "time" ? `${u} bg-dc-accent-bg text-dc-accent` : `${u} bg-dc-success-bg text-dc-success`;
26
- }
27
- return `${u} hover:bg-dc-surface-hover text-dc-text-secondary`;
28
- }
29
- if (m?.trim() && !v)
30
- return `${u} opacity-40 hover:opacity-60 text-dc-text-muted`;
31
- if (m?.trim() && v && !r)
32
- return `${u} font-bold hover:bg-dc-accent-bg`;
33
- if (r) {
34
- if (c === "measure")
35
- return `${u} bg-dc-warning-bg text-dc-warning font-semibold`;
36
- if (c === "dimension")
37
- return e.type === "time" ? `${u} bg-dc-accent-bg text-dc-accent font-semibold` : `${u} bg-dc-success-bg text-dc-success font-semibold`;
38
- }
39
- return `${u} hover:bg-dc-surface-hover text-dc-text-secondary`;
40
- };
41
- return /* @__PURE__ */ o(
42
- "div",
43
- {
44
- className: `
45
- border-2 rounded-lg shadow-lg min-w-[280px] overflow-hidden transition-all
46
- ${!k && m?.trim() ? "opacity-30 grayscale" : ""}
47
- ${n ? "border-dc-accent ring-2 ring-dc-accent" : "border-dc-border"}
48
- `,
49
- style: {
50
- backgroundColor: "var(--dc-surface)"
51
- },
52
- children: [
53
- /* @__PURE__ */ t(
54
- "div",
55
- {
56
- className: `
57
- px-4 py-3 cursor-pointer transition-colors
58
- ${n ? "bg-dc-accent-bg hover:bg-dc-accent-bg" : "bg-dc-surface-secondary hover:bg-dc-surface-hover"}
59
- `,
60
- onClick: d,
61
- children: /* @__PURE__ */ o("div", { className: "flex items-center justify-between", children: [
62
- /* @__PURE__ */ o("div", { children: [
63
- /* @__PURE__ */ t("h3", { className: "font-semibold text-dc-text text-sm", children: s.title || s.name }),
64
- s.description && /* @__PURE__ */ t("p", { className: "text-xs text-dc-text-muted mt-1 line-clamp-2", children: s.description })
65
- ] }),
66
- /* @__PURE__ */ o("div", { className: "text-xs text-dc-text-muted ml-2", children: [
67
- /* @__PURE__ */ o("div", { children: [
68
- s.measures.length,
69
- "M"
70
- ] }),
71
- /* @__PURE__ */ o("div", { children: [
72
- s.dimensions.length,
73
- "D"
74
- ] })
75
- ] })
76
- ] })
77
- }
78
- ),
79
- s.measures.length > 0 && /* @__PURE__ */ o("div", { className: "border-t border-dc-border", children: [
80
- /* @__PURE__ */ t("div", { className: "px-4 py-2 bg-dc-warning-bg border-b border-dc-border", children: /* @__PURE__ */ o("h4", { className: "text-xs font-medium text-dc-warning flex items-center", children: [
81
- /* @__PURE__ */ t("span", { className: "w-2 h-2 bg-dc-warning-bg0 rounded-full mr-2" }),
82
- "Measures (",
83
- s.measures.length,
84
- ")"
85
- ] }) }),
86
- /* @__PURE__ */ t("div", { className: "max-h-32 overflow-y-auto", children: s.measures.map((e) => {
87
- const r = e.name.split(".")[1] || e.name, c = l(e.name);
88
- return /* @__PURE__ */ t(
89
- "div",
90
- {
91
- className: N(e, c, "measure"),
92
- onClick: () => y(r, "measure"),
93
- title: e.title,
94
- children: /* @__PURE__ */ o("div", { className: "flex items-center justify-between", children: [
95
- /* @__PURE__ */ t("span", { className: "font-mono truncate", children: e.shortTitle || e.title || r }),
96
- /* @__PURE__ */ t("span", { className: "text-dc-text-muted ml-2 text-[10px] uppercase", children: e.type })
97
- ] })
98
- },
99
- e.name
100
- );
101
- }) })
102
- ] }),
103
- s.dimensions.filter((e) => e.type === "time").length > 0 && /* @__PURE__ */ o("div", { className: "border-t border-dc-border", children: [
104
- /* @__PURE__ */ t("div", { className: "px-4 py-2 bg-dc-accent-bg border-b border-dc-border", children: /* @__PURE__ */ o("h4", { className: "text-xs font-medium text-dc-accent flex items-center", children: [
105
- /* @__PURE__ */ t("span", { className: "w-2 h-2 bg-dc-accent-bg0 rounded-full mr-2" }),
106
- "Time Dimensions (",
107
- s.dimensions.filter((e) => e.type === "time").length,
108
- ")"
109
- ] }) }),
110
- /* @__PURE__ */ t("div", { className: "max-h-32 overflow-y-auto", children: s.dimensions.filter((e) => e.type === "time").map((e) => {
111
- const r = e.name.split(".")[1] || e.name, c = l(e.name);
112
- return /* @__PURE__ */ t(
113
- "div",
114
- {
115
- className: N(e, c, "dimension"),
116
- onClick: () => y(r, "dimension"),
117
- title: e.title,
118
- children: /* @__PURE__ */ o("div", { className: "flex items-center justify-between", children: [
119
- /* @__PURE__ */ t("span", { className: "font-mono truncate", children: e.shortTitle || e.title || r }),
120
- /* @__PURE__ */ t("span", { className: "text-dc-text-muted ml-2 text-[10px] uppercase", children: e.type })
121
- ] })
122
- },
123
- e.name
124
- );
125
- }) })
126
- ] }),
127
- s.dimensions.filter((e) => e.type !== "time").length > 0 && /* @__PURE__ */ o("div", { className: "border-t border-dc-border", children: [
128
- /* @__PURE__ */ t("div", { className: "px-4 py-2 bg-dc-success-bg border-b border-dc-border", children: /* @__PURE__ */ o("h4", { className: "text-xs font-medium text-dc-success flex items-center", children: [
129
- /* @__PURE__ */ t("span", { className: "w-2 h-2 bg-dc-success-bg0 rounded-full mr-2" }),
130
- "Dimensions (",
131
- s.dimensions.filter((e) => e.type !== "time").length,
132
- ")"
133
- ] }) }),
134
- /* @__PURE__ */ t("div", { className: "max-h-32 overflow-y-auto", children: s.dimensions.filter((e) => e.type !== "time").map((e) => {
135
- const r = e.name.split(".")[1] || e.name, c = l(e.name);
136
- return /* @__PURE__ */ t(
137
- "div",
138
- {
139
- className: N(e, c, "dimension"),
140
- onClick: () => y(r, "dimension"),
141
- title: e.title,
142
- children: /* @__PURE__ */ o("div", { className: "flex items-center justify-between", children: [
143
- /* @__PURE__ */ t("span", { className: "font-mono truncate", children: e.shortTitle || e.title || r }),
144
- /* @__PURE__ */ t("span", { className: "text-dc-text-muted ml-2 text-[10px] uppercase", children: e.type })
145
- ] })
146
- },
147
- e.name
148
- );
149
- }) })
150
- ] }),
151
- /* @__PURE__ */ t(
152
- P,
153
- {
154
- type: "source",
155
- position: g.Right,
156
- id: "right",
157
- className: "opacity-0",
158
- isConnectable: !1
159
- }
160
- ),
161
- /* @__PURE__ */ t(
162
- P,
163
- {
164
- type: "target",
165
- position: g.Left,
166
- id: "left",
167
- className: "opacity-0",
168
- isConnectable: !1
169
- }
170
- ),
171
- /* @__PURE__ */ t(
172
- P,
173
- {
174
- type: "source",
175
- position: g.Bottom,
176
- id: "bottom",
177
- className: "opacity-0",
178
- isConnectable: !1
179
- }
180
- ),
181
- /* @__PURE__ */ t(
182
- P,
183
- {
184
- type: "target",
185
- position: g.Top,
186
- id: "top",
187
- className: "opacity-0",
188
- isConnectable: !1
189
- }
190
- )
191
- ]
192
- }
193
- );
194
- }
195
- function de({
196
- sourceX: i,
197
- sourceY: s,
198
- targetX: f,
199
- targetY: n,
200
- sourcePosition: w,
201
- targetPosition: m,
202
- style: d = {},
203
- data: y,
204
- markerEnd: l
205
- }) {
206
- const [b, E, k] = K({
207
- sourceX: i,
208
- sourceY: s,
209
- sourcePosition: w,
210
- targetX: f,
211
- targetY: n,
212
- targetPosition: m
213
- });
214
- if (!y) return null;
215
- const { relationship: N, joinFields: e } = y, r = (C) => {
216
- switch (C) {
217
- case "belongsTo":
218
- return "∈";
219
- // belongs to symbol
220
- case "hasOne":
221
- return "1:1";
222
- case "hasMany":
223
- return "1:M";
224
- default:
225
- return "?";
226
- }
227
- }, v = ((C) => {
228
- switch (C) {
229
- case "belongsTo":
230
- return "#10b981";
231
- // green
232
- case "hasOne":
233
- return "#3b82f6";
234
- // blue
235
- case "hasMany":
236
- return "#f59e0b";
237
- // amber
238
- default:
239
- return "#6b7280";
240
- }
241
- })(N.relationship), u = r(N.relationship);
242
- return /* @__PURE__ */ o(J, { children: [
243
- /* @__PURE__ */ t(Q, { path: b, markerEnd: l, style: { ...d, stroke: v } }),
244
- /* @__PURE__ */ t(U, { children: /* @__PURE__ */ t(
245
- "div",
246
- {
247
- style: {
248
- position: "absolute",
249
- transform: `translate(-50%, -50%) translate(${E}px,${k}px)`,
250
- fontSize: 10,
251
- pointerEvents: "all"
252
- },
253
- className: "nodrag nopan",
254
- children: /* @__PURE__ */ t(
255
- "div",
256
- {
257
- className: "border-2 rounded-md px-2 py-1 shadow-xs",
258
- style: {
259
- backgroundColor: "var(--dc-surface)",
260
- borderColor: v
261
- },
262
- children: /* @__PURE__ */ o("div", { className: "text-center", children: [
263
- /* @__PURE__ */ t(
264
- "div",
265
- {
266
- className: "font-bold text-xs mb-1",
267
- style: { color: v },
268
- children: u
269
- }
270
- ),
271
- /* @__PURE__ */ t("div", { className: "text-[9px] text-dc-text-muted leading-tight", children: e.map((C, B) => /* @__PURE__ */ o("div", { className: "font-mono", children: [
272
- C.sourceField,
273
- " → ",
274
- C.targetField
275
- ] }, B)) })
276
- ] })
277
- }
278
- )
279
- }
280
- ) })
281
- ] });
282
- }
283
- const le = {
284
- direction: "TB",
285
- nodeWidth: 320,
286
- nodeHeight: 220,
287
- nodeSep: 80,
288
- rankSep: 150,
289
- ranker: "network-simplex"
290
- };
291
- function ue(i, s, f = {}) {
292
- const n = j(() => ({ ...le, ...f }), [f]), { layoutedNodes: w, layoutedEdges: m } = j(() => {
293
- if (i.length === 0)
294
- return { layoutedNodes: [], layoutedEdges: [] };
295
- const d = new O.graphlib.Graph();
296
- return d.setDefaultEdgeLabel(() => ({})), d.setGraph({
297
- rankdir: n.direction,
298
- nodesep: n.nodeSep,
299
- ranksep: n.rankSep,
300
- ranker: n.ranker
301
- }), i.forEach((l) => {
302
- d.setNode(l.id, {
303
- width: n.nodeWidth,
304
- height: n.nodeHeight
305
- });
306
- }), s.forEach((l) => {
307
- d.setEdge(l.source, l.target);
308
- }), O.layout(d), {
309
- layoutedNodes: i.map((l) => {
310
- const b = d.node(l.id);
311
- return {
312
- ...l,
313
- targetPosition: me(n.direction),
314
- sourcePosition: he(n.direction),
315
- position: {
316
- x: b.x - n.nodeWidth / 2,
317
- y: b.y - n.nodeHeight / 2
318
- }
319
- };
320
- }),
321
- layoutedEdges: s
322
- };
323
- }, [i, s, n.direction, n.nodeSep, n.rankSep, n.ranker, n.nodeWidth, n.nodeHeight]);
324
- return { nodes: w, edges: m };
325
- }
326
- function me(i) {
327
- switch (i) {
328
- case "TB":
329
- return g.Top;
330
- case "BT":
331
- return g.Bottom;
332
- case "LR":
333
- return g.Left;
334
- case "RL":
335
- return g.Right;
336
- default:
337
- return g.Top;
338
- }
339
- }
340
- function he(i) {
341
- switch (i) {
342
- case "TB":
343
- return g.Bottom;
344
- case "BT":
345
- return g.Top;
346
- case "LR":
347
- return g.Right;
348
- case "RL":
349
- return g.Left;
350
- default:
351
- return g.Bottom;
352
- }
353
- }
354
- const ge = {
355
- cubeNode: ce
356
- }, pe = {
357
- relationshipEdge: de
358
- };
359
- function Ce({
360
- className: i = "",
361
- onCubeClick: s,
362
- onFieldClick: f,
363
- highlightedCubes: n = [],
364
- highlightedFields: w = [],
365
- searchTerm: m
366
- }) {
367
- const { meta: d, metaLoading: y, metaError: l } = ie(), [b, E] = H({}), [k, N] = H(!1), [e, r] = H(null);
368
- T(() => {
369
- try {
370
- const a = localStorage.getItem("drizzle-cube-erd-node-positions");
371
- a && E(JSON.parse(a));
372
- } catch {
373
- }
374
- }, []);
375
- const { nodes: c, edges: v } = j(() => {
376
- if (!d) return { nodes: [], edges: [] };
377
- const a = [], x = [];
378
- return d.cubes.forEach((h, p) => {
379
- a.push({
380
- id: h.name,
381
- type: "cubeNode",
382
- position: b[h.name] || { x: p % 3 * 400, y: Math.floor(p / 3) * 300 },
383
- data: {
384
- cube: h,
385
- onCubeClick: s,
386
- onFieldClick: f,
387
- isHighlighted: !1,
388
- // Will be updated separately
389
- highlightedFields: []
390
- // Will be updated separately
391
- }
392
- });
393
- }), d.cubes.forEach((h) => {
394
- h.relationships && h.relationships.forEach((p, M) => {
395
- if (p.relationship === "belongsTo")
396
- return;
397
- const q = `${h.name}-${p.targetCube}-${M}`;
398
- x.push({
399
- id: q,
400
- source: h.name,
401
- target: p.targetCube,
402
- type: "relationshipEdge",
403
- data: {
404
- relationship: p,
405
- joinFields: p.joinFields
406
- },
407
- animated: !1,
408
- style: {
409
- stroke: be(p.relationship),
410
- strokeWidth: 2
411
- }
412
- });
413
- });
414
- }), { nodes: a, edges: x };
415
- }, [d, s, f, b]), u = k || Object.keys(b).length === 0, { nodes: C, edges: B } = ue(c, v, {
416
- direction: "LR",
417
- nodeWidth: 320,
418
- nodeHeight: 220,
419
- nodeSep: 100,
420
- rankSep: 200
421
- }), L = j(() => (u ? C : c).map((x) => ({
422
- ...x,
423
- data: {
424
- ...x.data,
425
- isHighlighted: n.includes(x.id),
426
- highlightedFields: w,
427
- searchTerm: m
428
- }
429
- })), [u, C, c, n, w, m]), F = u ? B : v;
430
- T(() => {
431
- if (k && L.length > 0) {
432
- E({});
433
- try {
434
- localStorage.removeItem("drizzle-cube-erd-node-positions");
435
- } catch {
436
- }
437
- N(!1);
438
- }
439
- }, [k, L]);
440
- const [D, $, z] = _(L), [W, R, A] = ee(F);
441
- T(() => {
442
- $(L);
443
- }, [L, $]), T(() => {
444
- R(F);
445
- }, [F, R]);
446
- const I = S((a) => {
447
- z(a), a.filter((h) => h.type === "position" && h.dragging === !1).length > 0 && $((h) => {
448
- const p = {};
449
- h.forEach((M) => {
450
- M.position && (p[M.id] = M.position);
451
- });
452
- try {
453
- localStorage.setItem("drizzle-cube-erd-node-positions", JSON.stringify(p));
454
- } catch {
455
- }
456
- return E(p), h;
457
- });
458
- }, [z, $]), V = S(
459
- (a) => R((x) => te(a, x)),
460
- [R]
461
- ), G = S((a) => {
462
- a.preventDefault(), a.stopPropagation(), console.log("Context menu triggered at:", a.clientX, a.clientY), r({
463
- x: a.clientX,
464
- y: a.clientY
465
- });
466
- }, []), X = S(() => {
467
- e && r(null);
468
- }, [e]), Y = S(() => {
469
- N(!0), r(null);
470
- }, []);
471
- return y ? /* @__PURE__ */ t("div", { className: `flex items-center justify-center h-96 ${i}`, children: /* @__PURE__ */ o("div", { className: "text-center", children: [
472
- /* @__PURE__ */ t("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-dc-accent mx-auto mb-2" }),
473
- /* @__PURE__ */ t("p", { className: "text-dc-text-muted", children: "Loading cube schema..." })
474
- ] }) }) : l ? /* @__PURE__ */ t("div", { className: `flex items-center justify-center h-96 ${i}`, children: /* @__PURE__ */ o("div", { className: "text-center text-dc-error", children: [
475
- /* @__PURE__ */ t("p", { className: "font-medium", children: "Failed to load cube schema" }),
476
- /* @__PURE__ */ t("p", { className: "text-sm mt-1", children: l })
477
- ] }) }) : !d || d.cubes.length === 0 ? /* @__PURE__ */ t("div", { className: `flex items-center justify-center h-96 ${i}`, children: /* @__PURE__ */ o("div", { className: "text-center text-dc-text-muted", children: [
478
- /* @__PURE__ */ t("p", { className: "font-medium", children: "No cubes found" }),
479
- /* @__PURE__ */ t("p", { className: "text-sm mt-1", children: "Register some cubes to see the relationship diagram" })
480
- ] }) }) : /* @__PURE__ */ o("div", { className: `h-full ${i}`, style: { height: "600px" }, children: [
481
- /* @__PURE__ */ t("div", { className: "h-full", children: /* @__PURE__ */ o(
482
- Z,
483
- {
484
- nodes: D,
485
- edges: W,
486
- onNodesChange: I,
487
- onEdgesChange: A,
488
- onConnect: V,
489
- nodeTypes: ge,
490
- edgeTypes: pe,
491
- connectionMode: se.Loose,
492
- fitView: !0,
493
- minZoom: 0.1,
494
- maxZoom: 2,
495
- defaultViewport: { x: 0, y: 0, zoom: 0.8 },
496
- proOptions: { hideAttribution: !0 },
497
- onPaneContextMenu: G,
498
- onPaneClick: X,
499
- children: [
500
- /* @__PURE__ */ t(ne, {}),
501
- /* @__PURE__ */ t(
502
- re,
503
- {
504
- nodeColor: (a) => n.includes(a.id) ? "#8b5cf6" : "#e5e7eb",
505
- maskColor: "rgb(240, 242, 246, 0.7)"
506
- }
507
- ),
508
- /* @__PURE__ */ t(oe, { variant: ae.Dots, gap: 12, size: 1 })
509
- ]
510
- }
511
- ) }),
512
- e && /* @__PURE__ */ t(
513
- "div",
514
- {
515
- className: "fixed z-50 bg-dc-surface rounded-md shadow-lg border border-dc-border py-1 min-w-[120px]",
516
- style: {
517
- left: e.x,
518
- top: e.y
519
- },
520
- children: /* @__PURE__ */ t(
521
- "button",
522
- {
523
- onClick: Y,
524
- className: "w-full px-3 py-2 text-sm text-dc-text-secondary hover:bg-dc-surface-hover text-left",
525
- children: "Auto Layout"
526
- }
527
- )
528
- }
529
- )
530
- ] });
531
- }
532
- function be(i) {
533
- switch (i) {
534
- case "belongsTo":
535
- return "#10b981";
536
- // green
537
- case "hasOne":
538
- return "#3b82f6";
539
- // blue
540
- case "hasMany":
541
- return "#f59e0b";
542
- // amber
543
- default:
544
- return "#6b7280";
545
- }
546
- }
547
- export {
548
- Ce as CubeRelationshipDiagram,
549
- Ce as default
550
- };
551
- //# sourceMappingURL=index-9x0R-Fme.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-9x0R-Fme.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-dc-warning-bg text-dc-warning`\n } else if (fieldType === 'dimension') {\n if (field.type === 'time') {\n return `${baseClasses} bg-dc-accent-bg text-dc-accent`\n } else {\n return `${baseClasses} bg-dc-success-bg text-dc-success`\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-dc-accent-bg`\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-dc-warning-bg text-dc-warning font-semibold`\n } else if (fieldType === 'dimension') {\n // Check if this is a time dimension\n if (field.type === 'time') {\n return `${baseClasses} bg-dc-accent-bg text-dc-accent font-semibold` // time dimensions\n } else {\n return `${baseClasses} bg-dc-success-bg text-dc-success 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-dc-accent ring-2 ring-dc-accent' : '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-dc-accent-bg hover:bg-dc-accent-bg' : '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-dc-warning-bg border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-dc-warning flex items-center\">\n <span className=\"w-2 h-2 bg-dc-warning-bg0 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-dc-accent-bg border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-dc-accent flex items-center\">\n <span className=\"w-2 h-2 bg-dc-accent-bg0 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-dc-success-bg border-b border-dc-border\">\n <h4 className=\"text-xs font-medium text-dc-success flex items-center\">\n <span className=\"w-2 h-2 bg-dc-success-bg0 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, MouseEvent } 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 {\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 {\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 {\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: 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-dc-accent 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-dc-error\">\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":";;;;;AAcO,SAASA,GAAS,EAAE,MAAAC,KAAuB;AAChD,QAAM,EAAE,MAAAC,GAAM,cAAAC,GAAc,eAAAC,GAAe,mBAAAC,GAAmB,YAAAC,MAAeL,GAEvEM,IAAwB,MAAM;AAAA,EAEpC,GAEMC,IAAmB,CAACC,GAAmBC,MAAuC;AAClF,IAAIP,KACFA,EAAaD,EAAK,MAAMO,GAAWC,CAAS;AAAA,EAEhD,GAEMC,IAAqB,CAACC,MACnBP,EAAkB,SAASO,CAAa,GAG3CC,IAAqB,CAACC,MAA4C;AACtE,QAAI,CAACR,GAAY,KAAA,EAAQ,QAAO;AAEhC,UAAMS,IAAOT,EAAW,YAAA;AACxB,WACEQ,EAAM,KAAK,YAAA,EAAc,SAASC,CAAI,KACrCD,EAAM,SAASA,EAAM,MAAM,YAAA,EAAc,SAASC,CAAI;AAAA,EAE3D,GAeMC,KAZiB,MAAM;AAC3B,QAAI,CAACV,GAAY,KAAA,EAAQ,QAAO;AAGhC,UAAMW,IAAiBf,EAAK,SAAS,KAAK,CAAAgB,MAAWL,EAAmBK,CAAO,CAAC,GAG1EC,IAAmBjB,EAAK,WAAW,KAAK,CAAAkB,MAAaP,EAAmBO,CAAS,CAAC;AAExF,WAAOH,KAAkBE;AAAA,EAC3B,GAEuB,GAEjBE,IAA4B,CAACP,GAAwDV,GAAwBM,MAAuC;AACxJ,UAAMY,IAAgBT,EAAmBC,CAAK,GACxCS,IAAc;AAGpB,QAAI,CAACP,KAAkBV,GAAY,QAAQ;AAEzC,UAAIF,GAAe;AACjB,YAAIM,MAAc;AAChB,iBAAO,GAAGa,CAAW;AACvB,YAAWb,MAAc;AACvB,iBAAII,EAAM,SAAS,SACV,GAAGS,CAAW,oCAEd,GAAGA,CAAW;AAAA,MAG3B;AACA,aAAO,GAAGA,CAAW;AAAA,IACvB;AAGA,QAAIjB,GAAY,UAAU,CAACgB;AACzB,aAAO,GAAGC,CAAW;AAIvB,QAAIjB,GAAY,KAAA,KAAUgB,KAAiB,CAAClB;AAC1C,aAAO,GAAGmB,CAAW;AAIvB,QAAInB,GAAe;AACjB,UAAIM,MAAc;AAChB,eAAO,GAAGa,CAAW;AACvB,UAAWb,MAAc;AAEvB,eAAII,EAAM,SAAS,SACV,GAAGS,CAAW,kDAEd,GAAGA,CAAW;AAAA,IAG3B;AAEA,WAAO,GAAGA,CAAW;AAAA,EACvB;AAEA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA;AAAA,UAEP,CAACR,KAAkBV,GAAY,KAAA,IAAS,yBAAyB,EAAE;AAAA,UACnEF,IAAgB,2CAA2C,kBAAkB;AAAA;AAAA,MAEjF,OAAO;AAAA,QACL,iBAAiB;AAAA,MAAA;AAAA,MAInB,UAAA;AAAA,QAAA,gBAAAqB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA;AAAA,YAEPrB,IAAgB,0CAA0C,mDAAmD;AAAA;AAAA,YAEjH,SAASG;AAAA,YAET,UAAA,gBAAAiB,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,gBAAA,gBAAAC,EAAC,QAAG,WAAU,sCACX,UAAAvB,EAAK,SAASA,EAAK,MACtB;AAAA,gBACCA,EAAK,eACJ,gBAAAuB,EAAC,OAAE,WAAU,gDACV,YAAK,YAAA,CACR;AAAA,cAAA,GAEJ;AAAA,cACA,gBAAAD,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,gBAAA,gBAAAA,EAAC,OAAA,EAAK,UAAA;AAAA,kBAAAtB,EAAK,SAAS;AAAA,kBAAO;AAAA,gBAAA,GAAC;AAAA,kCAC3B,OAAA,EAAK,UAAA;AAAA,kBAAAA,EAAK,WAAW;AAAA,kBAAO;AAAA,gBAAA,EAAA,CAAC;AAAA,cAAA,EAAA,CAChC;AAAA,YAAA,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAIDA,EAAK,SAAS,SAAS,KACtB,gBAAAsB,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAI,WAAU,wDACb,UAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,yDACZ,UAAA;AAAA,YAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,8CAAA,CAA8C;AAAA,YAAO;AAAA,YAC1DvB,EAAK,SAAS;AAAA,YAAO;AAAA,UAAA,EAAA,CAClC,EAAA,CACF;AAAA,UACA,gBAAAuB,EAAC,SAAI,WAAU,4BACZ,YAAK,SAAS,IAAI,CAACP,MAAY;AAC9B,kBAAMT,IAAYS,EAAQ,KAAK,MAAM,GAAG,EAAE,CAAC,KAAKA,EAAQ,MAClDQ,IAAcf,EAAmBO,EAAQ,IAAI;AACnD,mBACE,gBAAAO;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAWJ,EAA0BH,GAASQ,GAAa,SAAS;AAAA,gBACpE,SAAS,MAAMlB,EAAiBC,GAAW,SAAS;AAAA,gBACpD,OAAOS,EAAQ;AAAA,gBAEf,UAAA,gBAAAM,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,kBAAA,gBAAAC,EAAC,UAAK,WAAU,sBACb,YAAQ,cAAcP,EAAQ,SAAST,EAAA,CAC1C;AAAA,kBACA,gBAAAgB,EAAC,QAAA,EAAK,WAAU,iDACb,YAAQ,KAAA,CACX;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,cAZKP,EAAQ;AAAA,YAAA;AAAA,UAenB,CAAC,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAIDhB,EAAK,WAAW,OAAO,CAAAyB,MAAKA,EAAE,SAAS,MAAM,EAAE,SAAS,KACvD,gBAAAH,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAI,WAAU,uDACb,UAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,wDACZ,UAAA;AAAA,YAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,6CAAA,CAA6C;AAAA,YAAO;AAAA,YAClDvB,EAAK,WAAW,OAAO,OAAKyB,EAAE,SAAS,MAAM,EAAE;AAAA,YAAO;AAAA,UAAA,EAAA,CAC1E,EAAA,CACF;AAAA,UACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,4BACZ,YAAK,WAAW,OAAO,CAAAE,MAAKA,EAAE,SAAS,MAAM,EAAE,IAAI,CAACP,MAAc;AACjE,kBAAMX,IAAYW,EAAU,KAAK,MAAM,GAAG,EAAE,CAAC,KAAKA,EAAU,MACtDM,IAAcf,EAAmBS,EAAU,IAAI;AACrD,mBACE,gBAAAK;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAWJ,EAA0BD,GAAWM,GAAa,WAAW;AAAA,gBACxE,SAAS,MAAMlB,EAAiBC,GAAW,WAAW;AAAA,gBACtD,OAAOW,EAAU;AAAA,gBAEjB,UAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,kBAAA,gBAAAC,EAAC,UAAK,WAAU,sBACb,YAAU,cAAcL,EAAU,SAASX,EAAA,CAC9C;AAAA,kBACA,gBAAAgB,EAAC,QAAA,EAAK,WAAU,iDACb,YAAU,KAAA,CACb;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,cAZKL,EAAU;AAAA,YAAA;AAAA,UAerB,CAAC,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAIDlB,EAAK,WAAW,OAAO,CAAAyB,MAAKA,EAAE,SAAS,MAAM,EAAE,SAAS,KACvD,gBAAAH,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAI,WAAU,wDACb,UAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,yDACZ,UAAA;AAAA,YAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,8CAAA,CAA8C;AAAA,YAAO;AAAA,YACxDvB,EAAK,WAAW,OAAO,OAAKyB,EAAE,SAAS,MAAM,EAAE;AAAA,YAAO;AAAA,UAAA,EAAA,CACrE,EAAA,CACF;AAAA,UACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,4BACZ,YAAK,WAAW,OAAO,CAAAE,MAAKA,EAAE,SAAS,MAAM,EAAE,IAAI,CAACP,MAAc;AACjE,kBAAMX,IAAYW,EAAU,KAAK,MAAM,GAAG,EAAE,CAAC,KAAKA,EAAU,MACtDM,IAAcf,EAAmBS,EAAU,IAAI;AACrD,mBACE,gBAAAK;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAWJ,EAA0BD,GAAWM,GAAa,WAAW;AAAA,gBACxE,SAAS,MAAMlB,EAAiBC,GAAW,WAAW;AAAA,gBACtD,OAAOW,EAAU;AAAA,gBAEjB,UAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,kBAAA,gBAAAC,EAAC,UAAK,WAAU,sBACb,YAAU,cAAcL,EAAU,SAASX,EAAA,CAC9C;AAAA,kBACA,gBAAAgB,EAAC,QAAA,EAAK,WAAU,iDACb,YAAU,KAAA,CACb;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,cAZKL,EAAU;AAAA,YAAA;AAAA,UAerB,CAAC,EAAA,CACH;AAAA,QAAA,GACF;AAAA,QAIF,gBAAAK;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,QAEjB,gBAAAJ;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,QAEjB,gBAAAJ;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,QAEjB,gBAAAJ;AAAA,UAACG;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,MACjB;AAAA,IAAA;AAAA,EAAA;AAGN;ACrQO,SAASC,GAAiB;AAAA,EAC/B,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,OAAAC,IAAQ,CAAA;AAAA,EACR,MAAApC;AAAA,EACA,WAAAqC;AACF,GAAoC;AAClC,QAAM,CAACC,GAAUC,GAAQC,CAAM,IAAIC,EAAc;AAAA,IAC/C,SAAAX;AAAA,IACA,SAAAC;AAAA,IACA,gBAAAG;AAAA,IACA,SAAAF;AAAA,IACA,SAAAC;AAAA,IACA,gBAAAE;AAAA,EAAA,CACD;AAED,MAAI,CAACnC,EAAM,QAAO;AAElB,QAAM,EAAE,cAAA0C,GAAc,YAAAC,EAAA,IAAe3C,GAG/B4C,IAAwB,CAACC,MAAgB;AAC7C,YAAQA,GAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb,GAeMC,KAbuB,CAACD,MAAgB;AAC5C,YAAQA,GAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA;AAAA,MACT,KAAK;AACH,eAAO;AAAA;AAAA,MACT,KAAK;AACH,eAAO;AAAA;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb,GAEmCH,EAAa,YAAY,GACtDK,IAASH,EAAsBF,EAAa,YAAY;AAE9D,SACE,gBAAAnB,EAAAyB,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAxB,EAACyB,GAAA,EAAS,MAAMX,GAAU,WAAAD,GAAsB,OAAO,EAAE,GAAGD,GAAO,QAAQU,EAAA,EAAM,CAAG;AAAA,sBACnFI,GAAA,EACC,UAAA,gBAAA1B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,WAAW,mCAAmCe,CAAM,MAAMC,CAAM;AAAA,UAChE,UAAU;AAAA,UACV,eAAe;AAAA,QAAA;AAAA,QAEjB,WAAU;AAAA,QAEV,UAAA,gBAAAhB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,iBAAiB;AAAA,cACjB,aAAasB;AAAA,YAAA;AAAA,YAGf,UAAA,gBAAAvB,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,cAAA,gBAAAC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,OAAAsB,EAAA;AAAA,kBAER,UAAAC;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEH,gBAAAvB,EAAC,OAAA,EAAI,WAAU,+CACZ,UAAAmB,EAAW,IAAI,CAAC9B,GAAOsC,MACtB,gBAAA5B,EAAC,OAAA,EAAgB,WAAU,aACxB,UAAA;AAAA,gBAAAV,EAAM;AAAA,gBAAY;AAAA,gBAAIA,EAAM;AAAA,cAAA,EAAA,GADrBsC,CAEV,CACD,EAAA,CACH;AAAA,YAAA,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;ACjGA,MAAMC,KAAgC;AAAA,EACpC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,SAASC,GACdC,GACAC,GACAC,IAAkC,CAAA,GACA;AAClC,QAAMC,IAAgBC,EAAQ,OAAO,EAAE,GAAGN,IAAgB,GAAGI,EAAA,IAAY,CAACA,CAAO,CAAC,GAE5E,EAAE,eAAAG,GAAe,eAAAC,EAAA,IAAkBF,EAAQ,MAAM;AACrD,QAAIJ,EAAM,WAAW;AACnB,aAAO,EAAE,eAAe,IAAI,eAAe,CAAA,EAAC;AAI9C,UAAMO,IAAa,IAAIC,EAAM,SAAS,MAAA;AACtC,WAAAD,EAAW,oBAAoB,OAAO,CAAA,EAAG,GACzCA,EAAW,SAAS;AAAA,MAClB,SAASJ,EAAc;AAAA,MACvB,SAASA,EAAc;AAAA,MACvB,SAASA,EAAc;AAAA,MACvB,QAAQA,EAAc;AAAA,IAAA,CACvB,GAGDH,EAAM,QAAQ,CAACS,MAAS;AACtB,MAAAF,EAAW,QAAQE,EAAK,IAAI;AAAA,QAC1B,OAAON,EAAc;AAAA,QACrB,QAAQA,EAAc;AAAA,MAAA,CACvB;AAAA,IACH,CAAC,GAGDF,EAAM,QAAQ,CAACS,MAAS;AACtB,MAAAH,EAAW,QAAQG,EAAK,QAAQA,EAAK,MAAM;AAAA,IAC7C,CAAC,GAGDF,EAAM,OAAOD,CAAU,GAmBhB;AAAA,MACL,eAjBoBP,EAAM,IAAI,CAACS,MAAS;AACxC,cAAME,IAAmBJ,EAAW,KAAKE,EAAK,EAAE;AAYhD,eAVgB;AAAA,UACd,GAAGA;AAAA,UACH,gBAAgBG,GAAkBT,EAAc,SAAS;AAAA,UACzD,gBAAgBU,GAAkBV,EAAc,SAAS;AAAA,UACzD,UAAU;AAAA,YACR,GAAGQ,EAAiB,IAAIR,EAAc,YAAY;AAAA,YAClD,GAAGQ,EAAiB,IAAIR,EAAc,aAAa;AAAA,UAAA;AAAA,QACrD;AAAA,MAIJ,CAAC;AAAA,MAIC,eAAeF;AAAA,IAAA;AAAA,EAEnB,GAAG,CAACD,GAAOC,GAAOE,EAAc,WAAWA,EAAc,SAASA,EAAc,SAASA,EAAc,QAAQA,EAAc,WAAWA,EAAc,UAAU,CAAC;AAEjK,SAAO,EAAE,OAAOE,GAAe,OAAOC,EAAA;AACxC;AAGA,SAASM,GAAkBE,GAA6B;AACtD,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAOxC,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB;AACE,aAAOA,EAAS;AAAA,EAAA;AAEtB;AAEA,SAASuC,GAAkBC,GAA6B;AACtD,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAOxC,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB,KAAK;AACH,aAAOA,EAAS;AAAA,IAClB;AACE,aAAOA,EAAS;AAAA,EAAA;AAEtB;AC7FA,MAAMyC,KAAY;AAAA,EAChB,UAAUtE;AACZ,GAEMuE,KAAY;AAAA,EAChB,kBAAkBzC;AACpB;AAWO,SAAS0C,GAAwB;AAAA,EACtC,WAAAC,IAAY;AAAA,EACZ,aAAAC;AAAA,EACA,cAAAvE;AAAA,EACA,kBAAAwE,IAAmB,CAAA;AAAA,EACnB,mBAAAtE,IAAoB,CAAA;AAAA,EACpB,YAAAC;AACF,GAAiC;AAC/B,QAAM,EAAE,MAAAsE,GAAM,aAAAC,GAAa,WAAAC,EAAA,IAAcC,GAAA,GAEnC,CAACC,GAAgBC,CAAiB,IAAIC,EAAiD,CAAA,CAAE,GACzF,CAACC,GAAqBC,CAAsB,IAAIF,EAAS,EAAK,GAC9D,CAACG,GAAaC,CAAc,IAAIJ,EAAwC,IAAI;AAGlF,EAAAK,EAAU,MAAM;AACd,QAAI;AACF,YAAMC,IAAW,aAAa,QAAQ,iCAAiC;AACvE,MAAIA,KACFP,EAAkB,KAAK,MAAMO,CAAQ,CAAC;AAAA,IAE1C,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAA,CAAE;AAGL,QAAM,EAAE,OAAOC,GAAW,OAAOC,EAAA,IAAc/B,EAAQ,MAAM;AAC3D,QAAI,CAACiB,EAAM,QAAO,EAAE,OAAO,CAAA,GAAI,OAAO,GAAC;AAEvC,UAAMrB,IAAgB,CAAA,GAChBC,IAAgB,CAAA;AAGtB,WAAAoB,EAAK,MAAM,QAAQ,CAAC1E,GAAMkD,MAAU;AAClCG,MAAAA,EAAM,KAAK;AAAA,QACT,IAAIrD,EAAK;AAAA,QACT,MAAM;AAAA,QACN,UAAU8E,EAAe9E,EAAK,IAAI,KAAK,EAAE,GAAIkD,IAAQ,IAAK,KAAK,GAAG,KAAK,MAAMA,IAAQ,CAAC,IAAI,IAAA;AAAA,QAC1F,MAAM;AAAA,UACJ,MAAAlD;AAAA,UACA,aAAAwE;AAAA,UACA,cAAAvE;AAAA,UACA,eAAe;AAAA;AAAA,UACf,mBAAmB,CAAA;AAAA;AAAA,QAAC;AAAA,MACtB,CACD;AAAA,IACH,CAAC,GAGDyE,EAAK,MAAM,QAAQ,CAAA1E,MAAQ;AACzB,MAAIA,EAAK,iBACPA,EAAK,cAAc,QAAQ,CAACyC,GAAcS,MAAU;AAElD,YAAIT,EAAa,iBAAiB;AAChC;AAGF,cAAMgD,IAAS,GAAGzF,EAAK,IAAI,IAAIyC,EAAa,UAAU,IAAIS,CAAK;AAC/DI,QAAAA,EAAM,KAAK;AAAA,UACT,IAAImC;AAAA,UACJ,QAAQzF,EAAK;AAAA,UACb,QAAQyC,EAAa;AAAA,UACrB,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,cAAAA;AAAA,YACA,YAAYA,EAAa;AAAA,UAAA;AAAA,UAE3B,UAAU;AAAA,UACV,OAAO;AAAA,YACL,QAAQiD,GAAqBjD,EAAa,YAAY;AAAA,YACtD,aAAa;AAAA,UAAA;AAAA,QACf,CACD;AAAA,MACH,CAAC;AAAA,IAEL,CAAC,GAEM,EAAE,OAAAY,GAAO,OAAAC,EAAAA;AAAAA,EAClB,GAAG,CAACoB,GAAMF,GAAavE,GAAc6E,CAAc,CAAC,GAG9Ca,IAAkBV,KAAuB,OAAO,KAAKH,CAAc,EAAE,WAAW,GAGhF,EAAE,OAAOc,GAAmB,OAAOC,MAAsBzC,GAAamC,GAAWC,GAAW;AAAA,IAChG,WAAW;AAAA,IACX,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,EAAA,CACV,GAGK9B,IAAgBD,EAAQ,OACdkC,IAAkBC,IAAoBL,GACvC,IAAI,CAACzB,OAAU;AAAA,IAC1B,GAAGA;AAAA,IACH,MAAM;AAAA,MACJ,GAAGA,EAAK;AAAA,MACR,eAAeW,EAAiB,SAASX,EAAK,EAAE;AAAA,MAChD,mBAAA3D;AAAA,MACA,YAAAC;AAAA,IAAA;AAAA,EACF,EACA,GACD,CAACuF,GAAiBC,GAAmBL,GAAWd,GAAkBtE,GAAmBC,CAAU,CAAC,GAE7FuD,IAAgBgC,IAAkBE,IAAoBL;AAG5D,EAAAH,EAAU,MAAM;AACd,QAAIJ,KAAuBvB,EAAc,SAAS,GAAG;AAEnD,MAAAqB,EAAkB,CAAA,CAAE;AACpB,UAAI;AACF,qBAAa,WAAW,iCAAiC;AAAA,MAC3D,QAAQ;AAAA,MAER;AACA,MAAAG,EAAuB,EAAK;AAAA,IAC9B;AAAA,EACF,GAAG,CAACD,GAAqBvB,CAAa,CAAC;AAEvC,QAAM,CAACL,GAAOyC,GAAUC,CAAa,IAAIC,EAActC,CAAa,GAC9D,CAACJ,GAAO2C,GAAUC,CAAa,IAAIC,GAAcxC,CAAa;AAIpE,EAAA0B,EAAU,MAAM;AACd,IAAAS,EAASpC,CAAa;AAAA,EACxB,GAAG,CAACA,GAAeoC,CAAQ,CAAC,GAG5BT,EAAU,MAAM;AACd,IAAAY,EAAStC,CAAa;AAAA,EACxB,GAAG,CAACA,GAAesC,CAAQ,CAAC;AAG5B,QAAMG,IAAoBC,EAAY,CAACC,MAAmB;AACxD,IAAAP,EAAcO,CAAO,GAGDA,EAAQ,OAAO,CAAAC,MAAUA,EAAO,SAAS,cAAcA,EAAO,aAAa,EAAK,EACpF,SAAS,KACvBT,EAAS,CAACU,MAAiB;AACzB,YAAMC,IAAuD,CAAA;AAC7D,MAAAD,EAAa,QAAQ,CAAA1C,MAAQ;AAC3B,QAAIA,EAAK,aACP2C,EAAa3C,EAAK,EAAE,IAAIA,EAAK;AAAA,MAEjC,CAAC;AAGD,UAAI;AACF,qBAAa,QAAQ,mCAAmC,KAAK,UAAU2C,CAAY,CAAC;AAAA,MACtF,QAAQ;AAAA,MAER;AAEA,aAAA1B,EAAkB0B,CAAY,GACvBD;AAAA,IACT,CAAC;AAAA,EAEL,GAAG,CAACT,GAAeD,CAAQ,CAAC,GAEtBY,IAAYL;AAAA,IAChB,CAACM,MAAuBV,EAAS,CAACW,MAAQC,GAAQF,GAAQC,CAAG,CAAC;AAAA,IAC9D,CAACX,CAAQ;AAAA,EAAA,GAILa,IAAoBT,EAAY,CAACU,MAAsB;AAC3D,IAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA,GACN,QAAQ,IAAI,8BAA8BA,EAAM,SAASA,EAAM,OAAO,GACtE3B,EAAe;AAAA,MACb,GAAG2B,EAAM;AAAA,MACT,GAAGA,EAAM;AAAA,IAAA,CACV;AAAA,EACH,GAAG,CAAA,CAAE,GAGCC,IAAcX,EAAY,MAAM;AACpC,IAAIlB,KACFC,EAAe,IAAI;AAAA,EAEvB,GAAG,CAACD,CAAW,CAAC,GAGV8B,IAAmBZ,EAAY,MAAM;AACzC,IAAAnB,EAAuB,EAAI,GAC3BE,EAAe,IAAI;AAAA,EACrB,GAAG,CAAA,CAAE;AAIL,SAAIT,IAEA,gBAAApD,EAAC,SAAI,WAAW,yCAAyCgD,CAAS,IAChE,UAAA,gBAAAjD,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,6EAAA,CAA6E;AAAA,IAC5F,gBAAAA,EAAC,KAAA,EAAE,WAAU,sBAAqB,UAAA,yBAAA,CAAsB;AAAA,EAAA,EAAA,CAC1D,EAAA,CACF,IAKAqD,IAEA,gBAAArD,EAAC,SAAI,WAAW,yCAAyCgD,CAAS,IAChE,UAAA,gBAAAjD,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,KAAA,EAAE,WAAU,eAAc,UAAA,8BAA0B;AAAA,IACrD,gBAAAA,EAAC,KAAA,EAAE,WAAU,gBAAgB,UAAAqD,EAAA,CAAU;AAAA,EAAA,EAAA,CACzC,EAAA,CACF,IAKA,CAACF,KAAQA,EAAK,MAAM,WAAW,IAE/B,gBAAAnD,EAAC,SAAI,WAAW,yCAAyCgD,CAAS,IAChE,UAAA,gBAAAjD,EAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,KAAA,EAAE,WAAU,eAAc,UAAA,kBAAc;AAAA,IACzC,gBAAAA,EAAC,KAAA,EAAE,WAAU,gBAAe,UAAA,sDAAA,CAAmD;AAAA,EAAA,EAAA,CACjF,EAAA,CACF,IAKF,gBAAAD,EAAC,OAAA,EAAI,WAAW,UAAUiD,CAAS,IAAI,OAAO,EAAE,QAAQ,QAAA,GACtD,UAAA;AAAA,IAAA,gBAAAhD,EAAC,OAAA,EAAI,WAAU,UACb,UAAA,gBAAAD;AAAA,MAAC4F;AAAA,MAAA;AAAA,QACC,OAAA7D;AAAA,QACA,OAAAC;AAAA,QACA,eAAe8C;AAAA,QACf,eAAAF;AAAA,QACA,WAAAQ;AAAA,QACA,WAAAtC;AAAA,QACA,WAAAC;AAAA,QACA,gBAAgB8C,GAAe;AAAA,QAC/B,SAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,iBAAiB,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,IAAA;AAAA,QACrC,YAAY,EAAE,iBAAiB,GAAA;AAAA,QAC/B,mBAAmBL;AAAA,QACnB,aAAaE;AAAA,QAEb,UAAA;AAAA,UAAA,gBAAAzF,EAAC6F,IAAA,EAAS;AAAA,UACV,gBAAA7F;AAAA,YAAC8F;AAAA,YAAA;AAAA,cACC,WAAW,CAACvD,MACYW,EAAiB,SAASX,EAAK,EAAE,IAChC,YAAY;AAAA,cAErC,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZ,gBAAAvC,EAAC+F,MAAW,SAASC,GAAkB,MAAM,KAAK,IAAI,MAAM,EAAA,CAAG;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAEnE;AAAA,IAGCpC,KACC,gBAAA5D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO;AAAA,UACL,MAAM4D,EAAY;AAAA,UAClB,KAAKA,EAAY;AAAA,QAAA;AAAA,QAGnB,UAAA,gBAAA5D;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS0F;AAAA,YACT,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED;AAAA,IAAA;AAAA,EACF,GAEJ;AAEJ;AAGA,SAASvB,GAAqBjD,GAA0D;AACtF,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;"}