@finos/legend-application-studio 28.20.0 → 28.21.0

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 (61) hide show
  1. package/lib/__lib__/LegendStudioUserDataHelper.d.ts +4 -1
  2. package/lib/__lib__/LegendStudioUserDataHelper.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioUserDataHelper.js +18 -0
  4. package/lib/__lib__/LegendStudioUserDataHelper.js.map +1 -1
  5. package/lib/components/editor/editor-group/EditorGroup.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/EditorGroup.js +5 -0
  7. package/lib/components/editor/editor-group/EditorGroup.js.map +1 -1
  8. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  9. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +13 -44
  10. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  11. package/lib/components/editor/editor-group/database-editor/DatabaseAnnotationDisplay.d.ts +26 -0
  12. package/lib/components/editor/editor-group/database-editor/DatabaseAnnotationDisplay.d.ts.map +1 -0
  13. package/lib/components/editor/editor-group/database-editor/DatabaseAnnotationDisplay.js +101 -0
  14. package/lib/components/editor/editor-group/database-editor/DatabaseAnnotationDisplay.js.map +1 -0
  15. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.d.ts +23 -0
  16. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.d.ts.map +1 -0
  17. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.js +434 -0
  18. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.js.map +1 -0
  19. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramHelper.d.ts +242 -0
  20. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramHelper.d.ts.map +1 -0
  21. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramHelper.js +371 -0
  22. package/lib/components/editor/editor-group/database-editor/DatabaseDiagramHelper.js.map +1 -0
  23. package/lib/components/editor/editor-group/database-editor/DatabaseEditor.d.ts +29 -0
  24. package/lib/components/editor/editor-group/database-editor/DatabaseEditor.d.ts.map +1 -0
  25. package/lib/components/editor/editor-group/database-editor/DatabaseEditor.js +78 -0
  26. package/lib/components/editor/editor-group/database-editor/DatabaseEditor.js.map +1 -0
  27. package/lib/components/editor/editor-group/database-editor/DatabaseSchemaTree.d.ts +30 -0
  28. package/lib/components/editor/editor-group/database-editor/DatabaseSchemaTree.d.ts.map +1 -0
  29. package/lib/components/editor/editor-group/database-editor/DatabaseSchemaTree.js +331 -0
  30. package/lib/components/editor/editor-group/database-editor/DatabaseSchemaTree.js.map +1 -0
  31. package/lib/components/editor/editor-group/database-editor/DatabaseTableNode.d.ts +104 -0
  32. package/lib/components/editor/editor-group/database-editor/DatabaseTableNode.d.ts.map +1 -0
  33. package/lib/components/editor/editor-group/database-editor/DatabaseTableNode.js +151 -0
  34. package/lib/components/editor/editor-group/database-editor/DatabaseTableNode.js.map +1 -0
  35. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.d.ts.map +1 -1
  36. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js +3 -78
  37. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js.map +1 -1
  38. package/lib/index.css +2 -2
  39. package/lib/index.css.map +1 -1
  40. package/lib/package.json +4 -1
  41. package/lib/stores/editor/EditorTabManagerState.d.ts.map +1 -1
  42. package/lib/stores/editor/EditorTabManagerState.js +5 -3
  43. package/lib/stores/editor/EditorTabManagerState.js.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/DatabaseEditorState.d.ts +252 -0
  45. package/lib/stores/editor/editor-state/element-editor-state/DatabaseEditorState.d.ts.map +1 -0
  46. package/lib/stores/editor/editor-state/element-editor-state/DatabaseEditorState.js +755 -0
  47. package/lib/stores/editor/editor-state/element-editor-state/DatabaseEditorState.js.map +1 -0
  48. package/package.json +12 -9
  49. package/src/__lib__/LegendStudioUserDataHelper.ts +30 -0
  50. package/src/components/editor/editor-group/EditorGroup.tsx +4 -0
  51. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +0 -52
  52. package/src/components/editor/editor-group/database-editor/DatabaseAnnotationDisplay.tsx +200 -0
  53. package/src/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.tsx +701 -0
  54. package/src/components/editor/editor-group/database-editor/DatabaseDiagramHelper.ts +555 -0
  55. package/src/components/editor/editor-group/database-editor/DatabaseEditor.tsx +246 -0
  56. package/src/components/editor/editor-group/database-editor/DatabaseSchemaTree.tsx +1053 -0
  57. package/src/components/editor/editor-group/database-editor/DatabaseTableNode.tsx +465 -0
  58. package/src/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.tsx +2 -242
  59. package/src/stores/editor/EditorTabManagerState.ts +4 -5
  60. package/src/stores/editor/editor-state/element-editor-state/DatabaseEditorState.ts +938 -0
  61. package/tsconfig.json +7 -0
@@ -0,0 +1,434 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Copyright (c) 2020-present, Goldman Sachs
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { Background, BackgroundVariant, Controls, getNodesBounds, getViewportForBounds, MiniMap, ReactFlow, ReactFlowProvider, useEdgesState, useNodesState, useReactFlow, } from '@xyflow/react';
18
+ import '@xyflow/react/dist/style.css';
19
+ import { observer } from 'mobx-react-lite';
20
+ import { useCallback, useEffect, useMemo } from 'react';
21
+ import { noop } from '@finos/legend-shared';
22
+ import { toPng, toSvg } from 'html-to-image';
23
+ import { DownloadIcon, ExpandIcon, RefreshIcon, ResizeIcon, } from '@finos/legend-art';
24
+ import { DatabaseTableNode, DatabaseForeignRelationStubNode, } from './DatabaseTableNode.js';
25
+ import { buildJoinEdges, collectForeignKeyColumns, estimateNodeHeight, getRelationId, isView, layoutDatabaseDiagram, getOrderedRelations, resolveJoinFormula, } from './DatabaseDiagramHelper.js';
26
+ const NODE_TYPES = {
27
+ table: DatabaseTableNode,
28
+ foreignStub: DatabaseForeignRelationStubNode,
29
+ };
30
+ /**
31
+ * Resolve a Table or View by its on-canvas node id (`<schema>.<name>`).
32
+ * Used by the click handler to translate React Flow's string id back into a
33
+ * metamodel reference for selection.
34
+ */
35
+ const findRelationById = (editorState, id) => {
36
+ for (const schema of editorState.database.schemas) {
37
+ for (const table of schema.tables) {
38
+ if (getRelationId(table) === id) {
39
+ return table;
40
+ }
41
+ }
42
+ for (const view of schema.views) {
43
+ if (getRelationId(view) === id) {
44
+ return view;
45
+ }
46
+ }
47
+ }
48
+ return undefined;
49
+ };
50
+ /**
51
+ * Inner canvas — must be wrapped in `<ReactFlowProvider>` so that the
52
+ * `useReactFlow()` hook can fit-view after layout.
53
+ */
54
+ const DatabaseDiagramCanvasInner = observer((props) => {
55
+ const { editorState } = props;
56
+ const { database, selectedRelation, selectedColumn, selectedJoin, selectedFilter, filterFormulas, joinFormulas, viewColumnFormulas, viewGroupByFormulas, selectedViewColumnName, panToSelectedRequestCounter, fitAllRequestCounter, resetLayoutRequestCounter, } = editorState;
57
+ // Compute nodes + edges from the metamodel. We rebuild on metamodel changes
58
+ // (driven by `database` identity), but the layout itself (positions) is
59
+ // memoized so dagre runs only once per metamodel snapshot.
60
+ const { laidOutNodes, laidOutEdges } = useMemo(() => {
61
+ const fkColumns = collectForeignKeyColumns(database);
62
+ // Build canvas nodes for both tables AND views. The kind tag drives the
63
+ // table-node component's icon choice and column-row content.
64
+ const relationNodes = getOrderedRelations(database).map(({ schema, relation }) => ({
65
+ id: getRelationId(relation),
66
+ relation,
67
+ schemaName: schema.name,
68
+ estimatedHeight: estimateNodeHeight(relation),
69
+ }));
70
+ const { edges: joinEdges, foreignStubs } = buildJoinEdges(database);
71
+ // Foreign stubs participate in dagre layout the same way real nodes do,
72
+ // so cross-database join edges get a sensible position. They render as
73
+ // a smaller placeholder node (see `DatabaseForeignRelationStubNode`).
74
+ const FOREIGN_STUB_HEIGHT = 60;
75
+ const positions = layoutDatabaseDiagram([
76
+ ...relationNodes.map((n) => ({
77
+ id: n.id,
78
+ relation: n.relation,
79
+ estimatedHeight: n.estimatedHeight,
80
+ })),
81
+ ...foreignStubs.map((s) => ({
82
+ id: s.id,
83
+ // The layout helper only reads `id` and `estimatedHeight`; the
84
+ // `relation` field is unused for stubs but required by the
85
+ // shared type. Coerce safely — the helper never dereferences
86
+ // it.
87
+ relation: undefined,
88
+ estimatedHeight: FOREIGN_STUB_HEIGHT,
89
+ })),
90
+ ], joinEdges);
91
+ const reactFlowNodes = relationNodes.map((node) => {
92
+ const pos = positions.get(node.id) ?? { x: 0, y: 0 };
93
+ return {
94
+ id: node.id,
95
+ type: 'table',
96
+ position: { x: pos.x, y: pos.y },
97
+ data: {
98
+ relation: node.relation,
99
+ kind: isView(node.relation) ? 'view' : 'table',
100
+ schemaName: node.schemaName,
101
+ isSelected: false,
102
+ isJoinEndpoint: false,
103
+ fkColumns,
104
+ selectedColumn: undefined,
105
+ // Filled in by `selectionAwareNodes` from observable state.
106
+ viewColumnFormulas: new Map(),
107
+ viewGroupByFormulas: new Map(),
108
+ selectedViewColumnName: undefined,
109
+ },
110
+ };
111
+ });
112
+ // Stub nodes for foreign endpoints of cross-database joins. Rendered
113
+ // smaller and visually distinct (dashed border) so users can tell at a
114
+ // glance that the actual relation lives in another store.
115
+ foreignStubs.forEach((stub) => {
116
+ const pos = positions.get(stub.id) ?? { x: 0, y: 0 };
117
+ reactFlowNodes.push({
118
+ id: stub.id,
119
+ type: 'foreignStub',
120
+ position: { x: pos.x, y: pos.y },
121
+ data: {
122
+ schemaName: stub.schemaName,
123
+ relationName: stub.relationName,
124
+ ownerPath: stub.ownerPath,
125
+ isJoinEndpoint: false,
126
+ },
127
+ });
128
+ });
129
+ const reactFlowEdges = joinEdges.map((edge) => ({
130
+ id: edge.id,
131
+ source: edge.source,
132
+ target: edge.target,
133
+ label: edge.name,
134
+ // Loop self-joins use the React Flow `step` edge type so the path
135
+ // bows out cleanly into a loop instead of overlapping the node.
136
+ // Cross-database edges keep the standard smoothstep — same shape
137
+ // but the dashed style below conveys the foreign endpoint.
138
+ type: edge.isSelfJoin ? 'smoothstep' : 'smoothstep',
139
+ animated: false,
140
+ labelBgPadding: [4, 2],
141
+ labelBgBorderRadius: 2,
142
+ data: {
143
+ join: edge.join,
144
+ endpoints: { sourceId: edge.source, targetId: edge.target },
145
+ isSelfJoin: edge.isSelfJoin,
146
+ isCrossDatabase: edge.isCrossDatabase,
147
+ },
148
+ // Cross-database edges use a dashed stroke; self-joins keep the
149
+ // solid line but the loop shape itself signals self-join. Both
150
+ // get overridden again by the selection-aware pass below when the
151
+ // user picks one.
152
+ ...(edge.isCrossDatabase
153
+ ? { style: { strokeDasharray: '4 3' } }
154
+ : {}),
155
+ }));
156
+ return { laidOutNodes: reactFlowNodes, laidOutEdges: reactFlowEdges };
157
+ }, [database]);
158
+ const [nodes, setNodes, onNodesChange] = useNodesState(laidOutNodes);
159
+ const [edges, , onEdgesChange] = useEdgesState(laidOutEdges);
160
+ const { fitView } = useReactFlow();
161
+ // Reset whenever the database identity changes (e.g. after graph rebuild).
162
+ useEffect(() => {
163
+ setNodes(laidOutNodes);
164
+ const timer = window.setTimeout(() => {
165
+ fitView({ padding: 0.15, duration: 200 }).catch(noop());
166
+ }, 0);
167
+ return () => window.clearTimeout(timer);
168
+ }, [laidOutNodes, setNodes, fitView]);
169
+ // Resolve the two endpoint table ids of the selected join (if any). Used
170
+ // both for the `--join-endpoint` highlight on the two nodes and for the
171
+ // pan-to-fit-both effect below. We compute it here once per selection
172
+ // change rather than walking edges in multiple places.
173
+ const selectedJoinEndpointIds = useMemo(() => {
174
+ if (!selectedJoin) {
175
+ return null;
176
+ }
177
+ const match = laidOutEdges.find((e) => e.data?.join === selectedJoin);
178
+ return match?.data?.endpoints ?? null;
179
+ }, [selectedJoin, laidOutEdges]);
180
+ // Mirror selection from MobX into node data so each table-node renders
181
+ // its current visual state. Three independent flags:
182
+ // - isSelected: blue ring (single-table focus)
183
+ // - isJoinEndpoint: yellow ring (one of the two endpoints of the
184
+ // selected join — distinct color so the user can tell the two modes
185
+ // apart)
186
+ // - selectedColumn: forwarded only to the matching table
187
+ const selectionAwareNodes = useMemo(() => nodes.map((n) => {
188
+ const isSelected = n.type === 'table' && selectedRelation
189
+ ? n.id === getRelationId(selectedRelation)
190
+ : false;
191
+ const isJoinEndpoint = selectedJoinEndpointIds !== null &&
192
+ (n.id === selectedJoinEndpointIds.sourceId ||
193
+ n.id === selectedJoinEndpointIds.targetId);
194
+ if (n.type === 'foreignStub') {
195
+ return {
196
+ ...n,
197
+ data: {
198
+ ...n.data,
199
+ isJoinEndpoint,
200
+ },
201
+ };
202
+ }
203
+ return {
204
+ ...n,
205
+ data: {
206
+ ...n.data,
207
+ isSelected,
208
+ isJoinEndpoint,
209
+ selectedColumn: isSelected ? selectedColumn : undefined,
210
+ // Forward the live formula maps. Only view-kind nodes use
211
+ // them, but it's cheap to pass to all and keeps the data
212
+ // shape uniform.
213
+ viewColumnFormulas,
214
+ viewGroupByFormulas,
215
+ // Same story for the view column-mapping selection — only
216
+ // the focused view's node ends up with a non-undefined
217
+ // value, but every node receives the prop for shape stability.
218
+ selectedViewColumnName: isSelected
219
+ ? selectedViewColumnName
220
+ : undefined,
221
+ },
222
+ };
223
+ }), [
224
+ nodes,
225
+ selectedRelation,
226
+ selectedColumn,
227
+ selectedJoinEndpointIds,
228
+ viewColumnFormulas,
229
+ viewGroupByFormulas,
230
+ selectedViewColumnName,
231
+ ]);
232
+ // Highlight the selected edge with a yellow stroke that matches the
233
+ // endpoint-table ring color, and lift it visually. Other edges keep their
234
+ // default style (driven by SCSS in `_database-editor.scss`).
235
+ const selectionAwareEdges = useMemo(() => edges.map((e) => {
236
+ const isSelected = Boolean(selectedJoin && e.data?.join === selectedJoin);
237
+ // Build with `exactOptionalPropertyTypes` in mind — only attach
238
+ // `style` when actually overriding it, so TS doesn't see `undefined`
239
+ // assigned to an optional-but-not-undefined-allowed prop.
240
+ const styled = {
241
+ ...e,
242
+ labelStyle: {
243
+ fontSize: 10,
244
+ fill: isSelected
245
+ ? 'var(--color-yellow-200)'
246
+ : 'var(--color-light-grey-200)',
247
+ },
248
+ labelBgStyle: {
249
+ fill: 'var(--color-dark-grey-100)',
250
+ },
251
+ zIndex: isSelected ? 10 : 0,
252
+ };
253
+ if (isSelected) {
254
+ styled.style = {
255
+ stroke: 'var(--color-yellow-200)',
256
+ strokeWidth: 2,
257
+ };
258
+ }
259
+ return styled;
260
+ }), [edges, selectedJoin]);
261
+ // Pan to whatever's selected when the panel asks us to. Two modes:
262
+ // - Table selected → fit on that one node.
263
+ // - Join selected → fit to encompass both endpoint nodes.
264
+ // The counter (rather than the selection itself) drives this so canvas
265
+ // clicks don't pan — the user is already looking at what they clicked.
266
+ useEffect(() => {
267
+ if (panToSelectedRequestCounter === 0) {
268
+ return;
269
+ }
270
+ if (selectedJoinEndpointIds) {
271
+ fitView({
272
+ nodes: [
273
+ { id: selectedJoinEndpointIds.sourceId },
274
+ { id: selectedJoinEndpointIds.targetId },
275
+ ],
276
+ duration: 400,
277
+ padding: 0.3,
278
+ maxZoom: 1.2,
279
+ }).catch(noop());
280
+ return;
281
+ }
282
+ if (selectedRelation) {
283
+ fitView({
284
+ nodes: [{ id: getRelationId(selectedRelation) }],
285
+ duration: 400,
286
+ padding: 0.4,
287
+ maxZoom: 1.2,
288
+ }).catch(noop());
289
+ }
290
+ // Intentional: only the counter triggers re-pan. Selection identities
291
+ // are resolved at fire time from the closure.
292
+ // eslint-disable-next-line react-hooks/exhaustive-deps
293
+ }, [panToSelectedRequestCounter]);
294
+ // Toolbar: fit-all. Increments via `editorState.requestFitAll()`. Skips
295
+ // the initial render (counter starts at 0) so we don't double-fit on
296
+ // mount \u2014 React Flow already runs `fitView={true}` on first layout.
297
+ useEffect(() => {
298
+ if (fitAllRequestCounter === 0) {
299
+ return;
300
+ }
301
+ fitView({ duration: 400, padding: 0.15 }).catch(noop());
302
+ // eslint-disable-next-line react-hooks/exhaustive-deps
303
+ }, [fitAllRequestCounter]);
304
+ // Toolbar: reset layout. Re-runs dagre over the ORIGINAL `laidOutNodes`
305
+ // positions and replaces the live `nodes` state with them, undoing any
306
+ // user-initiated drags. Edges don't carry positions so they pass
307
+ // through untouched.
308
+ useEffect(() => {
309
+ if (resetLayoutRequestCounter === 0) {
310
+ return undefined;
311
+ }
312
+ setNodes(laidOutNodes);
313
+ // Defer the fit so React Flow has a frame to apply the new positions.
314
+ const timer = window.setTimeout(() => {
315
+ fitView({ padding: 0.15, duration: 300 }).catch(noop());
316
+ }, 0);
317
+ return () => window.clearTimeout(timer);
318
+ // eslint-disable-next-line react-hooks/exhaustive-deps
319
+ }, [resetLayoutRequestCounter]);
320
+ /**
321
+ * Toolbar: export the diagram as a PNG. The strategy is the standard
322
+ * React Flow recipe \u2014 compute the bounding box of every current
323
+ * node, ask React Flow for the matching viewport (so the rendered
324
+ * image fits the entire graph at a sensible zoom), then rasterize the
325
+ * `.react-flow__viewport` element with `html-to-image`'s `toPng`.
326
+ *
327
+ * We pass the viewport transform via `style` so html-to-image clones
328
+ * the viewport with the right CSS transform applied; that yields a
329
+ * complete picture even when the user has panned/zoomed off-screen.
330
+ * We pass the viewport transform via `style` so html-to-image clones
331
+ * the viewport with the right CSS transform applied; that yields a
332
+ * complete picture even when the user has panned/zoomed off-screen.
333
+ *
334
+ * Image width/height are clamped: the natural viewport size would
335
+ * either be too small (no nodes selected, default zoom) or huge
336
+ * (large databases). 1920x1080 is the upper bound; the helper
337
+ * scales down if needed while preserving aspect.
338
+ */
339
+ const exportDiagramAsPng = useCallback(async (format = 'png') => {
340
+ const viewportEl = document.querySelector('.database-diagram__canvas-shell .react-flow__viewport');
341
+ if (!viewportEl) {
342
+ return;
343
+ }
344
+ const bounds = getNodesBounds(selectionAwareNodes);
345
+ const padding = 40;
346
+ // Cap output size so the export stays usable as an image asset.
347
+ // The cap matters for PNG (hard pixel ceiling); for SVG it just
348
+ // sets the root viewBox — vector graphics scale infinitely.
349
+ const maxWidth = 1920;
350
+ const maxHeight = 1080;
351
+ const naturalWidth = bounds.width + padding * 2;
352
+ const naturalHeight = bounds.height + padding * 2;
353
+ const scale = Math.min(1, maxWidth / naturalWidth, maxHeight / naturalHeight);
354
+ const imageWidth = naturalWidth * scale;
355
+ const imageHeight = naturalHeight * scale;
356
+ const transform = getViewportForBounds(bounds, imageWidth, imageHeight, 0.1, 4, 0.1);
357
+ const options = {
358
+ backgroundColor: 'transparent',
359
+ width: imageWidth,
360
+ height: imageHeight,
361
+ style: {
362
+ width: `${imageWidth}px`,
363
+ height: `${imageHeight}px`,
364
+ transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.zoom})`,
365
+ },
366
+ // Bust caches so re-exports after edits pick up new content.
367
+ cacheBust: true,
368
+ };
369
+ // `toPng` returns a base64 data URL; `toSvg` returns a
370
+ // `data:image/svg+xml;...` URL with the inlined SVG markup.
371
+ // Either works as the `href` of a download anchor.
372
+ const dataUrl = format === 'svg'
373
+ ? await toSvg(viewportEl, options)
374
+ : await toPng(viewportEl, options);
375
+ const link = document.createElement('a');
376
+ // Path-based filename so the user can correlate the file with the
377
+ // database it came from when they have many such exports.
378
+ const safeName = editorState.database.path.replace(/[^a-z0-9_.-]/gi, '_');
379
+ link.download = `${safeName}.${format}`;
380
+ link.href = dataUrl;
381
+ link.click();
382
+ }, [selectionAwareNodes, editorState]);
383
+ return (_jsxs("div", { className: "database-diagram__canvas-shell", children: [_jsxs(ReactFlow, { className: "database-diagram__canvas", nodes: selectionAwareNodes, edges: selectionAwareEdges, nodeTypes: NODE_TYPES, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onNodeClick: (_, node) => {
384
+ // Foreign-stub nodes don't correspond to a real relation in this
385
+ // database, so a click on them is just an inert acknowledgement
386
+ // — we skip the relation selection rather than clearing it.
387
+ if (node.type === 'foreignStub') {
388
+ return;
389
+ }
390
+ const matching = findRelationById(editorState, node.id);
391
+ editorState.setSelectedRelation(matching);
392
+ }, onEdgeClick: (_, edge) => {
393
+ if (edge.data?.join) {
394
+ editorState.focusOnJoin(edge.data.join);
395
+ }
396
+ }, onPaneClick: () => editorState.clearSelection(), nodesDraggable: true, nodesConnectable: false, elementsSelectable: true, proOptions: { hideAttribution: true }, minZoom: 0.2, maxZoom: 1.5, fitView: true, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 18, size: 1 }), _jsx(Controls, { showInteractive: false }), _jsx(MiniMap, { pannable: true, zoomable: true, className: "database-diagram__minimap",
397
+ // Highlight the currently focused node(s) on the minimap so the
398
+ // user can see at a glance where their selection sits relative
399
+ // to the rest of the graph (especially useful for large
400
+ // databases where the selection can scroll off-screen).
401
+ nodeColor: (node) => {
402
+ const data = node.data;
403
+ if (data?.isJoinEndpoint) {
404
+ return 'var(--color-yellow-200)';
405
+ }
406
+ if (data?.isSelected) {
407
+ return 'var(--color-blue-200)';
408
+ }
409
+ return 'var(--color-dark-grey-200)';
410
+ }, maskColor: "rgba(0, 0, 0, 0.6)" })] }), _jsxs("div", { className: "database-diagram__toolbar", children: [_jsx("button", { type: "button", className: "database-diagram__toolbar__btn", title: "Fit all to view", onClick: () => editorState.requestFitAll(), children: _jsx(ExpandIcon, {}) }), _jsx("button", { type: "button", className: "database-diagram__toolbar__btn", title: "Fit selection to view", disabled: !selectedRelation && !selectedJoin, onClick: () => {
411
+ // Reuse the existing pan-to-selected pipeline by re-issuing
412
+ // the current focus. We bump the counter via the matching
413
+ // focus action so the canvas effect runs the same fit logic
414
+ // it does for side-panel clicks.
415
+ if (selectedJoin) {
416
+ editorState.focusOnJoin(selectedJoin);
417
+ }
418
+ else if (selectedRelation) {
419
+ editorState.focusOnRelation(selectedRelation);
420
+ }
421
+ }, children: _jsx(ResizeIcon, {}) }), _jsx("button", { type: "button", className: "database-diagram__toolbar__btn", title: "Reset layout (re-run auto-layout)", onClick: () => editorState.requestResetLayout(), children: _jsx(RefreshIcon, {}) }), _jsxs("button", { type: "button", className: "database-diagram__toolbar__btn", title: "Export diagram as PNG", onClick: () => {
422
+ exportDiagramAsPng('png').catch(noop());
423
+ }, children: [_jsx(DownloadIcon, {}), _jsx("span", { className: "database-diagram__toolbar__btn__label", children: "PNG" })] }), _jsxs("button", { type: "button", className: "database-diagram__toolbar__btn", title: "Export diagram as SVG (vector, editable)", onClick: () => {
424
+ exportDiagramAsPng('svg').catch(noop());
425
+ }, children: [_jsx(DownloadIcon, {}), _jsx("span", { className: "database-diagram__toolbar__btn__label", children: "SVG" })] })] }), selectedJoin && (_jsxs("div", { className: "database-diagram__floating-card database-diagram__floating-card--join", children: [_jsxs("div", { className: "database-diagram__floating-card__title", children: [_jsx("span", { className: "database-diagram__floating-card__kind", children: "JOIN" }), _jsx("span", { className: "database-diagram__floating-card__name", children: selectedJoin.name })] }), _jsx("div", { className: "database-diagram__floating-card__formula", children: resolveJoinFormula(joinFormulas, selectedJoin.name) })] })), selectedFilter && (_jsxs("div", {
426
+ // Filters don't have an on-canvas anchor (they live at the
427
+ // database level, not on a specific table/edge). Showing them
428
+ // as a floating card is the canvas-level affordance: clicking
429
+ // a filter in the side panel still gives users an immediate
430
+ // visual response on the canvas surface they're staring at.
431
+ className: "database-diagram__floating-card database-diagram__floating-card--filter", children: [_jsxs("div", { className: "database-diagram__floating-card__title", children: [_jsx("span", { className: "database-diagram__floating-card__kind", children: "FILTER" }), _jsx("span", { className: "database-diagram__floating-card__name", children: selectedFilter.name })] }), _jsx("div", { className: "database-diagram__floating-card__formula", children: filterFormulas.get(selectedFilter.name) ?? 'filter [...]' })] }))] }));
432
+ });
433
+ export const DatabaseDiagramCanvas = observer((props) => (_jsx(ReactFlowProvider, { children: _jsx(DatabaseDiagramCanvasInner, { editorState: props.editorState }) })));
434
+ //# sourceMappingURL=DatabaseDiagramCanvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseDiagramCanvas.js","sourceRoot":"","sources":["../../../../../src/components/editor/editor-group/database-editor/DatabaseDiagramCanvas.tsx"],"names":[],"mappings":"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"}