@memberjunction/ng-entity-relationship-diagram 5.30.1 → 5.32.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.
- package/dist/__tests__/compute-erd-layout.test.d.ts +2 -0
- package/dist/__tests__/compute-erd-layout.test.d.ts.map +1 -0
- package/dist/__tests__/compute-erd-layout.test.js +207 -0
- package/dist/__tests__/compute-erd-layout.test.js.map +1 -0
- package/dist/lib/components/entity-details/entity-details.component.d.ts +2 -1
- package/dist/lib/components/entity-details/entity-details.component.d.ts.map +1 -1
- package/dist/lib/components/entity-details/entity-details.component.js +7 -7
- package/dist/lib/components/entity-details/entity-details.component.js.map +1 -1
- package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts +10 -4
- package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts.map +1 -1
- package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js +60 -72
- package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js.map +1 -1
- package/dist/lib/components/erd-composite/erd-composite.component.d.ts +4 -1
- package/dist/lib/components/erd-composite/erd-composite.component.d.ts.map +1 -1
- package/dist/lib/components/erd-composite/erd-composite.component.js +22 -8
- package/dist/lib/components/erd-composite/erd-composite.component.js.map +1 -1
- package/dist/lib/components/erd-diagram.component.d.ts +169 -443
- package/dist/lib/components/erd-diagram.component.d.ts.map +1 -1
- package/dist/lib/components/erd-diagram.component.js +916 -1777
- package/dist/lib/components/erd-diagram.component.js.map +1 -1
- package/dist/lib/components/mj-entity-erd.component.d.ts +3 -2
- package/dist/lib/components/mj-entity-erd.component.d.ts.map +1 -1
- package/dist/lib/components/mj-entity-erd.component.js +6 -6
- package/dist/lib/components/mj-entity-erd.component.js.map +1 -1
- package/dist/lib/entity-relationship-diagram.module.d.ts +2 -1
- package/dist/lib/entity-relationship-diagram.module.d.ts.map +1 -1
- package/dist/lib/entity-relationship-diagram.module.js +9 -3
- package/dist/lib/entity-relationship-diagram.module.js.map +1 -1
- package/dist/lib/interfaces/erd-types.d.ts +38 -7
- package/dist/lib/interfaces/erd-types.d.ts.map +1 -1
- package/dist/lib/interfaces/erd-types.js.map +1 -1
- package/dist/lib/layout/compute-dagre-layout.d.ts +32 -0
- package/dist/lib/layout/compute-dagre-layout.d.ts.map +1 -0
- package/dist/lib/layout/compute-dagre-layout.js +168 -0
- package/dist/lib/layout/compute-dagre-layout.js.map +1 -0
- package/dist/lib/layout/compute-erd-layout.d.ts +103 -0
- package/dist/lib/layout/compute-erd-layout.d.ts.map +1 -0
- package/dist/lib/layout/compute-erd-layout.js +254 -0
- package/dist/lib/layout/compute-erd-layout.js.map +1 -0
- package/package.json +6 -5
|
@@ -1,488 +1,214 @@
|
|
|
1
|
-
import { EventEmitter, ElementRef, AfterViewInit, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
-
import { ERDNode, ERDLink, ERDConfig, ERDNodeClickEvent, ERDNodeDoubleClickEvent, ERDLinkClickEvent, ERDZoomEvent, ERDState, ERDNodeHoverEvent, ERDLinkHoverEvent, ERDNodeContextMenuEvent, ERDLinkContextMenuEvent, ERDDiagramContextMenuEvent, ERDNodeDragEvent, ERDRelationshipInfo } from '../interfaces/erd-types';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* ## Features
|
|
12
|
-
*
|
|
13
|
-
* - **Interactive Force-Directed Layout**: Nodes automatically arrange themselves
|
|
14
|
-
* using physics-based simulation with customizable forces
|
|
15
|
-
* - **Zoom and Pan**: Mouse wheel zoom and drag-to-pan with configurable limits
|
|
16
|
-
* - **Node Selection**: Click to select nodes with visual highlighting
|
|
17
|
-
* - **Focus Mode**: Show a single node with its N-hop related entities
|
|
18
|
-
* - **Relationship Visualization**: Arrows show foreign key relationships
|
|
19
|
-
* - **Customizable Styling**: Full control over colors, sizes, and appearance
|
|
20
|
-
* - **Rich Event System**: Comprehensive events for integration with parent components
|
|
21
|
-
* - **State Persistence**: Save and restore diagram state (zoom, pan, selection, positions)
|
|
22
|
-
*
|
|
23
|
-
* ## Basic Usage
|
|
24
|
-
*
|
|
25
|
-
* ```html
|
|
26
|
-
* <mj-erd-diagram
|
|
27
|
-
* [nodes]="entityNodes"
|
|
28
|
-
* [selectedNodeId]="selectedId"
|
|
29
|
-
* [config]="erdConfig"
|
|
30
|
-
* (nodeClick)="onNodeClick($event)"
|
|
31
|
-
* (nodeSelected)="onNodeSelected($event)"
|
|
32
|
-
* (zoomChange)="onZoomChange($event)">
|
|
33
|
-
* </mj-erd-diagram>
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* ## Focus Mode Example
|
|
37
|
-
*
|
|
38
|
-
* Show a single entity with its immediate relationships:
|
|
39
|
-
*
|
|
40
|
-
* ```html
|
|
41
|
-
* <mj-erd-diagram
|
|
42
|
-
* [nodes]="allNodes"
|
|
43
|
-
* [focusNodeId]="'user-entity-id'"
|
|
44
|
-
* [focusDepth]="1"
|
|
45
|
-
* (nodeSelected)="onNodeSelected($event)">
|
|
46
|
-
* </mj-erd-diagram>
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* ## State Persistence Example
|
|
2
|
+
* @module erd-diagram.component
|
|
3
|
+
* @description
|
|
4
|
+
* Schema-grouped Entity Relationship Diagram. Each schema becomes a rounded
|
|
5
|
+
* rectangular band; entities tile in a grid within the band. Click a node to
|
|
6
|
+
* enter focus mode (neighbours highlighted, everything else dimmed) and see a
|
|
7
|
+
* floating details card with its inbound and outbound FKs.
|
|
50
8
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* localStorage.setItem('erd-state', JSON.stringify(state));
|
|
9
|
+
* The component is pure Angular + SVG (no D3, no Dagre). Layout is computed
|
|
10
|
+
* by a pure function in `../layout/compute-erd-layout.ts` that is easily
|
|
11
|
+
* unit-tested.
|
|
55
12
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @see ERDNode for the node data structure
|
|
62
|
-
* @see ERDConfig for configuration options
|
|
63
|
-
* @see ERDState for state persistence
|
|
13
|
+
* Public API is preserved from the previous D3-based implementation so
|
|
14
|
+
* existing consumers (Database Designer wizard preview, admin ERD dashboard,
|
|
15
|
+
* Entity Record view) continue to work without changes.
|
|
64
16
|
*/
|
|
17
|
+
import { EventEmitter, AfterViewInit, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
|
|
18
|
+
import { ERDNode, ERDField, ERDLink, ERDConfig, ERDNodeClickEvent, ERDNodeDoubleClickEvent, ERDLinkClickEvent, ERDZoomEvent, ERDState, ERDNodeHoverEvent, ERDLinkHoverEvent, ERDNodeContextMenuEvent, ERDLinkContextMenuEvent, ERDDiagramContextMenuEvent, ERDNodeDragEvent } from '../interfaces/erd-types';
|
|
19
|
+
import { type ErdLayout, type LaidOutNode, type LaidOutEdge, type LaidOutBand } from '../layout/compute-erd-layout';
|
|
20
|
+
import * as i0 from "@angular/core";
|
|
21
|
+
interface SchemaChip {
|
|
22
|
+
name: string;
|
|
23
|
+
count: number;
|
|
24
|
+
active: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** 2D transform (pan x/y + zoom scale) for the SVG stage. */
|
|
27
|
+
interface Transform {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
k: number;
|
|
31
|
+
}
|
|
65
32
|
export declare class ERDDiagramComponent implements AfterViewInit, OnDestroy, OnChanges {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* The nodes (entities) to display in the diagram.
|
|
69
|
-
* Each node should conform to the `ERDNode` interface.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```typescript
|
|
73
|
-
* nodes: ERDNode[] = [
|
|
74
|
-
* {
|
|
75
|
-
* id: 'user-1',
|
|
76
|
-
* name: 'Users',
|
|
77
|
-
* fields: [
|
|
78
|
-
* { id: 'id', name: 'ID', isPrimaryKey: true },
|
|
79
|
-
* { id: 'email', name: 'Email', isPrimaryKey: false }
|
|
80
|
-
* ]
|
|
81
|
-
* }
|
|
82
|
-
* ];
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
33
|
+
private readonly cdr;
|
|
34
|
+
private readonly host;
|
|
85
35
|
nodes: ERDNode[];
|
|
86
|
-
/**
|
|
87
|
-
* ID of the currently selected node.
|
|
88
|
-
* Use this for external control of selection state.
|
|
89
|
-
* The component will highlight this node and emit selection events accordingly.
|
|
90
|
-
*
|
|
91
|
-
* @example `[selectedNodeId]="'entity-123'"`
|
|
92
|
-
*/
|
|
93
36
|
selectedNodeId: string | null;
|
|
94
|
-
/**
|
|
95
|
-
* IDs of nodes to highlight (in addition to selected node).
|
|
96
|
-
* Highlighted nodes receive a distinct visual style (orange border by default).
|
|
97
|
-
* Useful for showing search results or related items.
|
|
98
|
-
*
|
|
99
|
-
* @example `[highlightedNodeIds]="['entity-1', 'entity-2']"`
|
|
100
|
-
*/
|
|
101
37
|
highlightedNodeIds: string[];
|
|
102
|
-
/**
|
|
103
|
-
* ID of the node to focus on.
|
|
104
|
-
* When set, the diagram will only show this node and its related nodes
|
|
105
|
-
* up to `focusDepth` hops away. This is useful for entity-centric views.
|
|
106
|
-
*
|
|
107
|
-
* Set to `null` to show all nodes.
|
|
108
|
-
*
|
|
109
|
-
* @example `[focusNodeId]="'user-entity-id'"`
|
|
110
|
-
*/
|
|
111
38
|
focusNodeId: string | null;
|
|
112
|
-
/**
|
|
113
|
-
* Number of relationship hops to include when in focus mode.
|
|
114
|
-
* - `0`: Show only the focus node
|
|
115
|
-
* - `1`: Show focus node + directly related nodes
|
|
116
|
-
* - `2`: Show focus node + nodes within 2 relationship hops
|
|
117
|
-
*
|
|
118
|
-
* Only applies when `focusNodeId` is set.
|
|
119
|
-
*
|
|
120
|
-
* @default 1
|
|
121
|
-
* @example `[focusDepth]="2"`
|
|
122
|
-
*/
|
|
123
39
|
focusDepth: number;
|
|
124
|
-
/**
|
|
125
|
-
* Whether the diagram is currently refreshing/loading.
|
|
126
|
-
* When `true`, displays a loading overlay on the diagram.
|
|
127
|
-
*
|
|
128
|
-
* @example `[isRefreshing]="isLoadingData"`
|
|
129
|
-
*/
|
|
130
40
|
isRefreshing: boolean;
|
|
131
|
-
/**
|
|
132
|
-
* Whether the diagram is in read-only mode.
|
|
133
|
-
* When `true`, disables dragging and selection (zoom/pan still work).
|
|
134
|
-
*
|
|
135
|
-
* @default false
|
|
136
|
-
*/
|
|
137
41
|
readOnly: boolean;
|
|
138
|
-
/**
|
|
139
|
-
* Configuration options for the diagram.
|
|
140
|
-
* All options are optional with sensible defaults.
|
|
141
|
-
*
|
|
142
|
-
* @see ERDConfig for all available options
|
|
143
|
-
* @example
|
|
144
|
-
* ```typescript
|
|
145
|
-
* config: ERDConfig = {
|
|
146
|
-
* nodeWidth: 200,
|
|
147
|
-
* chargeStrength: -1000,
|
|
148
|
-
* colors: {
|
|
149
|
-
* nodeHeader: '#0066cc'
|
|
150
|
-
* }
|
|
151
|
-
* };
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
42
|
config: ERDConfig;
|
|
155
|
-
/**
|
|
156
|
-
* Whether to show the header bar with zoom controls.
|
|
157
|
-
* Set to `false` to hide the header and use programmatic control instead.
|
|
158
|
-
*
|
|
159
|
-
* @default true
|
|
160
|
-
*/
|
|
161
43
|
showHeader: boolean;
|
|
162
|
-
/**
|
|
163
|
-
* Title to display in the header bar.
|
|
164
|
-
* Only visible when `showHeader` is `true`.
|
|
165
|
-
*
|
|
166
|
-
* @default 'Entity Relationship Diagram'
|
|
167
|
-
*/
|
|
168
44
|
headerTitle: string;
|
|
169
|
-
/**
|
|
170
|
-
* Emitted when a node is clicked.
|
|
171
|
-
* Set `event.cancel = true` to prevent the default selection behavior.
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* ```typescript
|
|
175
|
-
* onNodeClick(event: ERDNodeClickEvent) {
|
|
176
|
-
* console.log('Clicked:', event.node.name);
|
|
177
|
-
* // Prevent selection for certain nodes
|
|
178
|
-
* if (event.node.customData?.['locked']) {
|
|
179
|
-
* event.cancel = true;
|
|
180
|
-
* }
|
|
181
|
-
* }
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
45
|
nodeClick: EventEmitter<ERDNodeClickEvent>;
|
|
185
|
-
/**
|
|
186
|
-
* Emitted when a node is double-clicked.
|
|
187
|
-
* Useful for opening detail views or triggering actions.
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```typescript
|
|
191
|
-
* onNodeDoubleClick(event: ERDNodeDoubleClickEvent) {
|
|
192
|
-
* this.openEntityDetail(event.node.id);
|
|
193
|
-
* }
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
196
46
|
nodeDoubleClick: EventEmitter<ERDNodeDoubleClickEvent>;
|
|
197
|
-
/**
|
|
198
|
-
* Emitted when a node is selected (after click, unless cancelled).
|
|
199
|
-
* The node parameter contains the full `ERDNode` data.
|
|
200
|
-
*/
|
|
201
47
|
nodeSelected: EventEmitter<ERDNode>;
|
|
202
|
-
/**
|
|
203
|
-
* Emitted when the current node is deselected.
|
|
204
|
-
* This happens when clicking the background or selecting a different node.
|
|
205
|
-
*/
|
|
206
48
|
nodeDeselected: EventEmitter<void>;
|
|
207
|
-
/**
|
|
208
|
-
* Emitted when a relationship link is clicked.
|
|
209
|
-
* The event includes both source and target nodes for context.
|
|
210
|
-
*/
|
|
211
49
|
linkClick: EventEmitter<ERDLinkClickEvent>;
|
|
212
|
-
/**
|
|
213
|
-
* Emitted when the mouse enters a node.
|
|
214
|
-
* Includes related nodes and position for tooltip display.
|
|
215
|
-
*
|
|
216
|
-
* @example
|
|
217
|
-
* ```typescript
|
|
218
|
-
* onNodeHover(event: ERDNodeHoverEvent) {
|
|
219
|
-
* this.showTooltip(event.node, event.position);
|
|
220
|
-
* }
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
50
|
nodeHover: EventEmitter<ERDNodeHoverEvent>;
|
|
224
|
-
/**
|
|
225
|
-
* Emitted when the mouse leaves a node.
|
|
226
|
-
*/
|
|
227
51
|
nodeHoverEnd: EventEmitter<ERDNode>;
|
|
228
|
-
/**
|
|
229
|
-
* Emitted when the mouse enters a relationship link.
|
|
230
|
-
*/
|
|
231
52
|
linkHover: EventEmitter<ERDLinkHoverEvent>;
|
|
232
|
-
/**
|
|
233
|
-
* Emitted when the mouse leaves a relationship link.
|
|
234
|
-
*/
|
|
235
53
|
linkHoverEnd: EventEmitter<ERDLink>;
|
|
236
|
-
/**
|
|
237
|
-
* Emitted when a node is right-clicked.
|
|
238
|
-
* Set `event.cancel = true` to prevent the default browser context menu.
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* ```typescript
|
|
242
|
-
* onNodeContextMenu(event: ERDNodeContextMenuEvent) {
|
|
243
|
-
* event.cancel = true;
|
|
244
|
-
* this.showContextMenu(event.node, event.position);
|
|
245
|
-
* }
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
54
|
nodeContextMenu: EventEmitter<ERDNodeContextMenuEvent>;
|
|
249
|
-
/**
|
|
250
|
-
* Emitted when a relationship link is right-clicked.
|
|
251
|
-
*/
|
|
252
55
|
linkContextMenu: EventEmitter<ERDLinkContextMenuEvent>;
|
|
253
|
-
/**
|
|
254
|
-
* Emitted when the diagram background is right-clicked.
|
|
255
|
-
* Includes diagram coordinates for adding new nodes at click position.
|
|
256
|
-
*/
|
|
257
56
|
diagramContextMenu: EventEmitter<ERDDiagramContextMenuEvent>;
|
|
258
|
-
/**
|
|
259
|
-
* Emitted when a node drag operation starts.
|
|
260
|
-
* Set `event.cancel = true` to prevent the drag.
|
|
261
|
-
*/
|
|
262
57
|
nodeDragStart: EventEmitter<ERDNodeDragEvent>;
|
|
263
|
-
/**
|
|
264
|
-
* Emitted when a node drag operation ends.
|
|
265
|
-
*/
|
|
266
58
|
nodeDragEnd: EventEmitter<ERDNodeDragEvent>;
|
|
267
|
-
/**
|
|
268
|
-
* Emitted when zoom level or pan position changes.
|
|
269
|
-
* Useful for synchronizing zoom controls or saving view state.
|
|
270
|
-
*/
|
|
271
59
|
zoomChange: EventEmitter<ERDZoomEvent>;
|
|
272
|
-
/**
|
|
273
|
-
* Emitted when the diagram requests a refresh.
|
|
274
|
-
* Triggered by the refresh button in the header.
|
|
275
|
-
*/
|
|
276
60
|
refreshRequested: EventEmitter<void>;
|
|
277
|
-
/**
|
|
278
|
-
* Emitted when the force simulation completes initial layout.
|
|
279
|
-
* Useful for performing actions after nodes have settled.
|
|
280
|
-
*/
|
|
281
61
|
layoutComplete: EventEmitter<void>;
|
|
282
|
-
/**
|
|
283
|
-
* Emitted when diagram state changes (selection, zoom, highlights).
|
|
284
|
-
* Useful for auto-saving state or syncing with other components.
|
|
285
|
-
*/
|
|
286
62
|
stateChange: EventEmitter<ERDState>;
|
|
287
|
-
private
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
63
|
+
private canvasRef?;
|
|
64
|
+
/** Current pan + zoom. */
|
|
65
|
+
transform: Transform;
|
|
66
|
+
/** Set of schema names the user has filtered IN. Null means "all". */
|
|
67
|
+
activeSchemas: Set<string> | null;
|
|
68
|
+
/** Search query string. */
|
|
69
|
+
searchQuery: string;
|
|
70
|
+
/** Node IDs the user has clicked "+N more fields" on. */
|
|
71
|
+
expandedNodeIds: Set<string>;
|
|
72
|
+
/** Node currently being hovered (for highlight preview). */
|
|
73
|
+
hoverNodeId: string | null;
|
|
74
|
+
/** Cached layout — recomputed when nodes, filter, search or expansion changes. */
|
|
75
|
+
layout: ErdLayout;
|
|
76
|
+
/**
|
|
77
|
+
* Active layout algorithm. Starts from `config.layoutAlgorithm` (default
|
|
78
|
+
* `schema-grid`) but can be toggled at runtime via `setLayoutAlgorithm`.
|
|
79
|
+
* Exposed so the chrome toggle + saved user state can drive it.
|
|
80
|
+
*/
|
|
81
|
+
activeLayout: 'schema-grid' | 'dagre';
|
|
82
|
+
/** Derived schema summary for the chip row. */
|
|
83
|
+
schemaChips: SchemaChip[];
|
|
84
|
+
/** Derived — number of entities currently visible. */
|
|
85
|
+
visibleCount: number;
|
|
86
|
+
/** Derived — total entities in the input, before any filtering. */
|
|
87
|
+
totalCount: number;
|
|
88
|
+
/** Derived — the Set of IDs in the focus/hover neighbourhood (null when no highlight active). */
|
|
89
|
+
highlightSet: Set<string> | null;
|
|
90
|
+
/** Derived — the single selected entity, if any. */
|
|
91
|
+
selectedEntity: ERDNode | null;
|
|
92
|
+
panning: boolean;
|
|
93
|
+
private panStart;
|
|
94
|
+
/** Raw mousedown coords — used to compute drag distance for the
|
|
95
|
+
* pan-vs-click threshold. */
|
|
96
|
+
private dragOrigin;
|
|
97
|
+
/** True once movement crossed the drag threshold — used to suppress
|
|
98
|
+
* the synthetic click that follows the mouseup. */
|
|
99
|
+
private dragMoved;
|
|
100
|
+
/** Pixels of movement before mousedown is treated as a drag. */
|
|
101
|
+
private static readonly DRAG_THRESHOLD;
|
|
102
|
+
/** Bound window listeners — kept on the instance so we can detach. */
|
|
103
|
+
private boundWindowMove?;
|
|
104
|
+
private boundWindowUp?;
|
|
294
105
|
private resizeObserver?;
|
|
295
|
-
|
|
296
|
-
private resizeTimeout?;
|
|
297
|
-
private mergedConfig;
|
|
298
|
-
private layoutCompleted;
|
|
299
|
-
private isLayoutFrozen;
|
|
300
|
-
ngAfterViewInit(): void;
|
|
106
|
+
readonly rootClass = true;
|
|
301
107
|
ngOnChanges(changes: SimpleChanges): void;
|
|
108
|
+
/** True iff any config field that influences the cached layout changed. */
|
|
109
|
+
private configAffectsLayout;
|
|
110
|
+
ngAfterViewInit(): void;
|
|
302
111
|
ngOnDestroy(): void;
|
|
303
|
-
/**
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
112
|
+
/** Rebuild the layout + derived view-model from current inputs/state. */
|
|
113
|
+
private recompute;
|
|
114
|
+
/**
|
|
115
|
+
* Switch between the schema-grid and dagre hierarchical layouts at
|
|
116
|
+
* runtime. Emits a state change so the consumer can persist the
|
|
117
|
+
* user's preference (via `userStateChange` on `mj-erd-composite`).
|
|
118
|
+
*
|
|
119
|
+
* Also clears the current focus/selection — switching layouts moves
|
|
120
|
+
* cards to entirely new positions, so the previously-selected entity
|
|
121
|
+
* would otherwise stay highlighted in a different spot with the side
|
|
122
|
+
* panel still open, which is jarring. A clean slate is better.
|
|
123
|
+
*/
|
|
124
|
+
setLayoutAlgorithm(algo: 'schema-grid' | 'dagre'): void;
|
|
125
|
+
private buildSchemaChips;
|
|
126
|
+
private updateHighlightSet;
|
|
127
|
+
private updateSelectedEntity;
|
|
128
|
+
private watchResize;
|
|
129
|
+
/**
|
|
130
|
+
* Mousedown anywhere on the SVG (background OR a node card). We
|
|
131
|
+
* arm a potential pan and attach window-level move/up listeners so
|
|
132
|
+
* the drag continues even if the cursor leaves the canvas (passes
|
|
133
|
+
* over the focus card, scrollbars, the chrome, etc.).
|
|
134
|
+
*
|
|
135
|
+
* The actual `panning = true` flip happens in the move handler once
|
|
136
|
+
* the cursor crosses `DRAG_THRESHOLD` — that way short clicks still
|
|
137
|
+
* register as clicks on cards (no accidental selection-toggle from
|
|
138
|
+
* a tiny mouse jitter).
|
|
139
|
+
*/
|
|
140
|
+
onBackgroundMouseDown(e: MouseEvent): void;
|
|
141
|
+
private onWindowMouseMove;
|
|
142
|
+
private onWindowMouseUp;
|
|
143
|
+
onWheel(e: WheelEvent): void;
|
|
144
|
+
zoomBy(factor: number): void;
|
|
145
|
+
fitToView(): void;
|
|
146
|
+
private centerOn;
|
|
147
|
+
private emitZoom;
|
|
148
|
+
onNodeClick(node: LaidOutNode, e: MouseEvent): void;
|
|
149
|
+
onNodeMouseEnter(node: LaidOutNode, e: MouseEvent): void;
|
|
150
|
+
onNodeMouseLeave(node: LaidOutNode): void;
|
|
151
|
+
onToggleExpand(nodeId: string, e: Event): void;
|
|
152
|
+
onSearchChange(value: string): void;
|
|
153
|
+
onClearSearch(): void;
|
|
154
|
+
onSchemaChipToggle(schemaName: string): void;
|
|
155
|
+
onRequestRefresh(): void;
|
|
156
|
+
/** Path string for an edge — uses the orthogonal polyline from layout. */
|
|
157
|
+
edgePath(edge: LaidOutEdge): string;
|
|
158
|
+
/**
|
|
159
|
+
* Whether to render FK field labels along edges. Defaults to ON in
|
|
160
|
+
* both layouts — the zoom-gate (>=0.55x) keeps the labels off when
|
|
161
|
+
* the user is zoomed out far enough to see hundreds of entities, so
|
|
162
|
+
* "noise on dense views" isn't a real concern. Consumers can still
|
|
163
|
+
* force off via `config.showRelationshipLabels: false`.
|
|
164
|
+
*/
|
|
165
|
+
get showEdgeLabels(): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Pick a point along the edge polyline for a label and approximate
|
|
168
|
+
* its width. Returns null for self-loops (no good place to put text).
|
|
169
|
+
* Uses the longest horizontal segment when one exists; falls back to
|
|
170
|
+
* the segment midpoint otherwise.
|
|
171
|
+
*/
|
|
172
|
+
edgeLabelPosition(edge: LaidOutEdge): {
|
|
173
|
+
x: number;
|
|
174
|
+
y: number;
|
|
175
|
+
w: number;
|
|
176
|
+
} | null;
|
|
177
|
+
/** Whether a node should appear dimmed (highlight mode active, node not in set). */
|
|
178
|
+
isDimmed(nodeId: string): boolean;
|
|
179
|
+
/** Whether a node is the current focus (strong border). */
|
|
180
|
+
isFocus(nodeId: string): boolean;
|
|
181
|
+
/** Whether a node is a 1-hop neighbour of the focus (medium border). */
|
|
182
|
+
isNeighbour(nodeId: string): boolean;
|
|
183
|
+
/** Whether an edge is part of the active highlight subgraph. */
|
|
184
|
+
isEdgeActive(edge: LaidOutEdge): boolean;
|
|
185
|
+
/** Whether an edge should appear dimmed. */
|
|
186
|
+
isEdgeDimmed(edge: LaidOutEdge): boolean;
|
|
187
|
+
/** Zoom percentage string for the toolbar readout. */
|
|
188
|
+
get zoomPercent(): string;
|
|
189
|
+
/** Short friendly row-count string (e.g. 1248 → "1.2k"). */
|
|
190
|
+
formatCount(n: number | undefined): string;
|
|
191
|
+
/** Number of PK fields — handy aggregate (kept for external API parity). */
|
|
192
|
+
pkCount(entity: ERDNode): number;
|
|
193
|
+
/** Number of FK fields — handy aggregate (kept for external API parity). */
|
|
194
|
+
fkCount(entity: ERDNode): number;
|
|
307
195
|
zoomIn(): void;
|
|
308
|
-
/**
|
|
309
|
-
* Zoom out on the diagram by a fixed factor (0.83x).
|
|
310
|
-
* Uses smooth animation transition.
|
|
311
|
-
*/
|
|
312
196
|
zoomOut(): void;
|
|
313
|
-
/**
|
|
314
|
-
* Reset zoom to default level (1x) and center the diagram.
|
|
315
|
-
* Uses smooth animation transition.
|
|
316
|
-
*/
|
|
317
197
|
resetZoom(): void;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
*
|
|
321
|
-
* @param nodeId - ID of the node to center on
|
|
322
|
-
* @param scale - Optional zoom scale (default: 1.5)
|
|
323
|
-
*
|
|
324
|
-
* @example
|
|
325
|
-
* ```typescript
|
|
326
|
-
* // Center on node with default zoom
|
|
327
|
-
* this.erdDiagram.zoomToNode('user-entity-id');
|
|
328
|
-
*
|
|
329
|
-
* // Center with custom zoom level
|
|
330
|
-
* this.erdDiagram.zoomToNode('user-entity-id', 2.0);
|
|
331
|
-
* ```
|
|
332
|
-
*/
|
|
333
|
-
zoomToNode(nodeId: string, scale?: number): void;
|
|
334
|
-
/**
|
|
335
|
-
* Fit all visible nodes within the viewport.
|
|
336
|
-
* Calculates optimal zoom level and position to show all nodes.
|
|
337
|
-
*
|
|
338
|
-
* @param padding - Padding around nodes (default: 50px)
|
|
339
|
-
*/
|
|
340
|
-
zoomToFit(padding?: number): void;
|
|
341
|
-
/**
|
|
342
|
-
* Programmatically select a node by ID.
|
|
343
|
-
*
|
|
344
|
-
* @param nodeId - ID of the node to select
|
|
345
|
-
* @returns `true` if node was found and selected, `false` otherwise
|
|
346
|
-
*/
|
|
347
|
-
selectNode(nodeId: string): boolean;
|
|
348
|
-
/**
|
|
349
|
-
* Clear all selections.
|
|
350
|
-
*/
|
|
351
|
-
deselectAll(): void;
|
|
352
|
-
/**
|
|
353
|
-
* Highlight a specific node.
|
|
354
|
-
*
|
|
355
|
-
* @param nodeId - ID of the node to highlight
|
|
356
|
-
*/
|
|
357
|
-
highlightNode(nodeId: string): void;
|
|
358
|
-
/**
|
|
359
|
-
* Clear all highlights.
|
|
360
|
-
*/
|
|
361
|
-
clearHighlights(): void;
|
|
362
|
-
/**
|
|
363
|
-
* Highlight a node and all its directly related nodes.
|
|
364
|
-
*
|
|
365
|
-
* @param nodeId - ID of the center node
|
|
366
|
-
* @param depth - Number of relationship hops to highlight (default: 1)
|
|
367
|
-
*/
|
|
368
|
-
highlightRelated(nodeId: string, depth?: number): void;
|
|
369
|
-
/**
|
|
370
|
-
* Get nodes that are related to a specific node.
|
|
371
|
-
*
|
|
372
|
-
* @param nodeId - ID of the node to find relationships for
|
|
373
|
-
* @param depth - Number of relationship hops (default: 1)
|
|
374
|
-
* @returns Array of relationship information
|
|
375
|
-
*/
|
|
376
|
-
getRelatedNodes(nodeId: string, depth?: number): ERDRelationshipInfo[];
|
|
377
|
-
/**
|
|
378
|
-
* Get the current state of the diagram for persistence.
|
|
379
|
-
* Includes selection, highlights, zoom, pan, and node positions.
|
|
380
|
-
*
|
|
381
|
-
* @returns Current diagram state
|
|
382
|
-
*
|
|
383
|
-
* @example
|
|
384
|
-
* ```typescript
|
|
385
|
-
* // Save to localStorage
|
|
386
|
-
* const state = erdDiagram.getState();
|
|
387
|
-
* localStorage.setItem('erd-state', JSON.stringify(state));
|
|
388
|
-
* ```
|
|
389
|
-
*/
|
|
390
|
-
getState(): ERDState;
|
|
391
|
-
/**
|
|
392
|
-
* Restore a previously saved diagram state.
|
|
393
|
-
*
|
|
394
|
-
* @param state - State object from `getState()`
|
|
395
|
-
* @param restorePositions - Whether to restore node positions (default: true)
|
|
396
|
-
*
|
|
397
|
-
* @example
|
|
398
|
-
* ```typescript
|
|
399
|
-
* // Restore from localStorage
|
|
400
|
-
* const savedState = JSON.parse(localStorage.getItem('erd-state'));
|
|
401
|
-
* if (savedState) {
|
|
402
|
-
* erdDiagram.setState(savedState);
|
|
403
|
-
* }
|
|
404
|
-
* ```
|
|
405
|
-
*/
|
|
406
|
-
setState(state: Partial<ERDState>, restorePositions?: boolean): void;
|
|
407
|
-
/**
|
|
408
|
-
* Freeze the layout simulation.
|
|
409
|
-
* Nodes will stay in their current positions and won't move.
|
|
410
|
-
*/
|
|
411
|
-
freezeLayout(): void;
|
|
412
|
-
/**
|
|
413
|
-
* Unfreeze the layout simulation.
|
|
414
|
-
* Nodes will resume natural movement based on forces.
|
|
415
|
-
*/
|
|
416
|
-
unfreezeLayout(): void;
|
|
417
|
-
/**
|
|
418
|
-
* Center the diagram without changing zoom level.
|
|
419
|
-
*/
|
|
420
|
-
centerDiagram(): void;
|
|
421
|
-
/**
|
|
422
|
-
* Rebuild the entire ERD visualization.
|
|
423
|
-
*/
|
|
424
|
-
refresh(): void;
|
|
425
|
-
/**
|
|
426
|
-
* Trigger a resize recalculation.
|
|
427
|
-
* Call this when the container size changes.
|
|
428
|
-
*/
|
|
198
|
+
zoomToFit(_padding?: number): void;
|
|
199
|
+
zoomToNode(nodeId: string, _scale?: number): void;
|
|
429
200
|
triggerResize(): void;
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
* @returns Current zoom level and translation
|
|
434
|
-
*/
|
|
435
|
-
getZoomState(): ERDZoomEvent;
|
|
436
|
-
/**
|
|
437
|
-
* Export the diagram as an SVG string.
|
|
438
|
-
*
|
|
439
|
-
* @returns SVG markup string
|
|
440
|
-
*/
|
|
201
|
+
refresh(): void;
|
|
202
|
+
getState(): ERDState;
|
|
203
|
+
setState(state: Partial<ERDState>, _restorePositions?: boolean): void;
|
|
441
204
|
exportAsSVG(): string;
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
private applyFocusMode;
|
|
448
|
-
private getRelatedNodeIds;
|
|
449
|
-
private createInternalNodes;
|
|
450
|
-
private createInternalLinks;
|
|
451
|
-
/**
|
|
452
|
-
* Applies dagre hierarchical layout to position nodes and compute edge paths.
|
|
453
|
-
* This provides clean, orthogonal edge routing.
|
|
454
|
-
*/
|
|
455
|
-
private applyDagreLayout;
|
|
456
|
-
/**
|
|
457
|
-
* Checks if the current layout algorithm uses dagre.
|
|
458
|
-
*/
|
|
459
|
-
private usesDagreLayout;
|
|
460
|
-
private createVisualization;
|
|
461
|
-
private renderNodeFields;
|
|
462
|
-
/** Truncate an SVG text element to fit within maxWidth, adding "…" if needed */
|
|
463
|
-
private truncateTextElement;
|
|
464
|
-
private attachNodeEventHandlers;
|
|
465
|
-
private attachLinkEventHandlers;
|
|
466
|
-
private updatePositions;
|
|
467
|
-
private getSourceConnectionPoint;
|
|
468
|
-
private getTargetConnectionPoint;
|
|
469
|
-
private createOrthogonalPath;
|
|
470
|
-
/**
|
|
471
|
-
* Creates an SVG path string from dagre's edge points.
|
|
472
|
-
* Dagre provides an array of points for each edge that forms a clean orthogonal path.
|
|
473
|
-
* @param points Array of {x, y} coordinates from dagre layout
|
|
474
|
-
* @returns SVG path string
|
|
475
|
-
*/
|
|
476
|
-
private createPathFromDagrePoints;
|
|
477
|
-
private screenToDiagramCoords;
|
|
478
|
-
private clearAllHighlighting;
|
|
479
|
-
private updateSelectionHighlighting;
|
|
480
|
-
private updateHighlighting;
|
|
481
|
-
private emitStateChange;
|
|
482
|
-
private dragstarted;
|
|
483
|
-
private dragged;
|
|
484
|
-
private dragended;
|
|
205
|
+
trackByBand: (_: number, b: LaidOutBand) => string;
|
|
206
|
+
trackByEdge: (_: number, e: LaidOutEdge) => string;
|
|
207
|
+
trackByNode: (_: number, n: LaidOutNode) => string;
|
|
208
|
+
trackByField: (_: number, f: ERDField) => string;
|
|
209
|
+
trackByChip: (_: number, c: SchemaChip) => string;
|
|
485
210
|
static ɵfac: i0.ɵɵFactoryDeclaration<ERDDiagramComponent, never>;
|
|
486
211
|
static ɵcmp: i0.ɵɵComponentDeclaration<ERDDiagramComponent, "mj-erd-diagram", never, { "nodes": { "alias": "nodes"; "required": false; }; "selectedNodeId": { "alias": "selectedNodeId"; "required": false; }; "highlightedNodeIds": { "alias": "highlightedNodeIds"; "required": false; }; "focusNodeId": { "alias": "focusNodeId"; "required": false; }; "focusDepth": { "alias": "focusDepth"; "required": false; }; "isRefreshing": { "alias": "isRefreshing"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "config": { "alias": "config"; "required": false; }; "showHeader": { "alias": "showHeader"; "required": false; }; "headerTitle": { "alias": "headerTitle"; "required": false; }; }, { "nodeClick": "nodeClick"; "nodeDoubleClick": "nodeDoubleClick"; "nodeSelected": "nodeSelected"; "nodeDeselected": "nodeDeselected"; "linkClick": "linkClick"; "nodeHover": "nodeHover"; "nodeHoverEnd": "nodeHoverEnd"; "linkHover": "linkHover"; "linkHoverEnd": "linkHoverEnd"; "nodeContextMenu": "nodeContextMenu"; "linkContextMenu": "linkContextMenu"; "diagramContextMenu": "diagramContextMenu"; "nodeDragStart": "nodeDragStart"; "nodeDragEnd": "nodeDragEnd"; "zoomChange": "zoomChange"; "refreshRequested": "refreshRequested"; "layoutComplete": "layoutComplete"; "stateChange": "stateChange"; }, never, never, false, never>;
|
|
487
212
|
}
|
|
213
|
+
export {};
|
|
488
214
|
//# sourceMappingURL=erd-diagram.component.d.ts.map
|