@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.
Files changed (40) hide show
  1. package/dist/__tests__/compute-erd-layout.test.d.ts +2 -0
  2. package/dist/__tests__/compute-erd-layout.test.d.ts.map +1 -0
  3. package/dist/__tests__/compute-erd-layout.test.js +207 -0
  4. package/dist/__tests__/compute-erd-layout.test.js.map +1 -0
  5. package/dist/lib/components/entity-details/entity-details.component.d.ts +2 -1
  6. package/dist/lib/components/entity-details/entity-details.component.d.ts.map +1 -1
  7. package/dist/lib/components/entity-details/entity-details.component.js +7 -7
  8. package/dist/lib/components/entity-details/entity-details.component.js.map +1 -1
  9. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts +10 -4
  10. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts.map +1 -1
  11. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js +60 -72
  12. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js.map +1 -1
  13. package/dist/lib/components/erd-composite/erd-composite.component.d.ts +4 -1
  14. package/dist/lib/components/erd-composite/erd-composite.component.d.ts.map +1 -1
  15. package/dist/lib/components/erd-composite/erd-composite.component.js +22 -8
  16. package/dist/lib/components/erd-composite/erd-composite.component.js.map +1 -1
  17. package/dist/lib/components/erd-diagram.component.d.ts +169 -443
  18. package/dist/lib/components/erd-diagram.component.d.ts.map +1 -1
  19. package/dist/lib/components/erd-diagram.component.js +916 -1777
  20. package/dist/lib/components/erd-diagram.component.js.map +1 -1
  21. package/dist/lib/components/mj-entity-erd.component.d.ts +3 -2
  22. package/dist/lib/components/mj-entity-erd.component.d.ts.map +1 -1
  23. package/dist/lib/components/mj-entity-erd.component.js +6 -6
  24. package/dist/lib/components/mj-entity-erd.component.js.map +1 -1
  25. package/dist/lib/entity-relationship-diagram.module.d.ts +2 -1
  26. package/dist/lib/entity-relationship-diagram.module.d.ts.map +1 -1
  27. package/dist/lib/entity-relationship-diagram.module.js +9 -3
  28. package/dist/lib/entity-relationship-diagram.module.js.map +1 -1
  29. package/dist/lib/interfaces/erd-types.d.ts +38 -7
  30. package/dist/lib/interfaces/erd-types.d.ts.map +1 -1
  31. package/dist/lib/interfaces/erd-types.js.map +1 -1
  32. package/dist/lib/layout/compute-dagre-layout.d.ts +32 -0
  33. package/dist/lib/layout/compute-dagre-layout.d.ts.map +1 -0
  34. package/dist/lib/layout/compute-dagre-layout.js +168 -0
  35. package/dist/lib/layout/compute-dagre-layout.js.map +1 -0
  36. package/dist/lib/layout/compute-erd-layout.d.ts +103 -0
  37. package/dist/lib/layout/compute-erd-layout.d.ts.map +1 -0
  38. package/dist/lib/layout/compute-erd-layout.js +254 -0
  39. package/dist/lib/layout/compute-erd-layout.js.map +1 -0
  40. package/package.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"file":"mj-entity-erd.component.js","sourceRoot":"","sources":["../../../src/lib/components/mj-entity-erd.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n SimpleChanges,\n ViewChild,\n ChangeDetectionStrategy\n} from '@angular/core';\nimport { EntityInfo, Metadata } from '@memberjunction/core';\nimport { ERDDiagramComponent } from './erd-diagram.component';\nimport {\n ERDNode,\n ERDConfig,\n ERDState,\n ERDNodeClickEvent,\n ERDNodeDoubleClickEvent,\n ERDZoomEvent\n} from '../interfaces/erd-types';\nimport {\n buildERDDataFromEntities,\n getOriginalEntityFromERDNode\n} from '../utils/entity-to-erd-adapter';\n\n/**\n * Event emitted when an entity is selected in the ERD.\n * Set `cancel = true` in your handler to prevent default behavior.\n */\nexport interface EntitySelectedEvent {\n /** The selected EntityInfo */\n entity: EntityInfo;\n /** The corresponding ERD node */\n node: ERDNode;\n /**\n * Set to true to cancel default behavior.\n * Default behavior: updates internal selection state.\n */\n cancel?: boolean;\n}\n\n/**\n * Event emitted when requesting to open an entity record.\n * Set `cancel = true` in your handler to prevent default behavior.\n */\nexport interface OpenEntityRecordEvent {\n /** Entity name for the record */\n EntityName: string;\n /** Record ID to open */\n RecordID: string;\n /** The EntityInfo being opened */\n entity: EntityInfo;\n /**\n * Set to true to cancel default behavior.\n * Default behavior: none (just emits the event).\n * Container is expected to handle navigation.\n */\n cancel?: boolean;\n}\n\n/**\n * Higher-level MemberJunction Entity ERD component that provides a simplified API\n * for displaying entity relationship diagrams using EntityInfo objects.\n *\n * This component wraps the generic `ERDDiagramComponent` and handles the transformation\n * of MemberJunction EntityInfo objects to the generic ERD format automatically.\n *\n * ## Key Features\n *\n * - **Simple Input**: Just pass `EntityInfo[]` - no manual transformation needed\n * - **Auto-Discovery**: Automatically discovers and displays relationships\n * - **Configurable Depth**: Control how many relationship hops to include\n * - **State Control**: Parent controls selection/state - component doesn't persist\n *\n * ## Usage Modes\n *\n * ### Single Entity Mode (Entity Form)\n * Show one entity and its immediate relationships:\n *\n * ```html\n * <mj-entity-erd\n * [entities]=\"[currentEntity]\"\n * [selectedEntityId]=\"currentEntity.ID\"\n * [depth]=\"1\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * ### Multi-Entity Mode (Schema Explorer)\n * Show multiple entities with persistence handled by parent:\n *\n * ```html\n * <mj-entity-erd\n * [entities]=\"filteredEntities\"\n * [selectedEntityId]=\"savedSelectedId\"\n * [depth]=\"savedDepth\"\n * (entitySelected)=\"onEntitySelected($event); saveState()\"\n * (stateChange)=\"onStateChange($event); saveState()\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * ## Important Design Decisions\n *\n * - **No State Persistence**: This component does NOT persist user state (selection, zoom, etc.).\n * The parent is responsible for saving/restoring state via the inputs and events.\n * - **No Filtering**: The caller filters entities before passing them. This keeps the component simple.\n * - **Controlled Selection**: Selection is controlled via `selectedEntityId` input. The component\n * emits `entitySelected` when user clicks, but parent decides what to do.\n *\n * @see ERDDiagramComponent for the underlying generic component\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-erd',\n template: `\n <mj-erd-diagram\n [nodes]=\"erdNodes\"\n [selectedNodeId]=\"selectedEntityId\"\n [highlightedNodeIds]=\"highlightedEntityIds\"\n [focusNodeId]=\"focusEntityId\"\n [focusDepth]=\"focusDepth\"\n [config]=\"config\"\n [showHeader]=\"showHeader\"\n [headerTitle]=\"headerTitle\"\n [isRefreshing]=\"isRefreshing\"\n [readOnly]=\"readOnly\"\n (nodeClick)=\"onNodeClick($event)\"\n (nodeDoubleClick)=\"onNodeDoubleClick($event)\"\n (nodeSelected)=\"onNodeSelected($event)\"\n (nodeDeselected)=\"onNodeDeselected()\"\n (zoomChange)=\"onZoomChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n (refreshRequested)=\"onRefreshRequested()\">\n </mj-erd-diagram>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MJEntityERDComponent implements OnChanges {\n @ViewChild(ERDDiagramComponent) erdDiagram!: ERDDiagramComponent;\n\n // ============================================================================\n // INPUTS - Data\n // ============================================================================\n\n /**\n * The entities to display in the ERD.\n * Pass one or more EntityInfo objects. The component will automatically\n * discover and display related entities based on the `depth` setting.\n *\n * @example\n * ```typescript\n * // Single entity\n * [entities]=\"[currentEntity]\"\n *\n * // Multiple entities (schema view)\n * [entities]=\"filteredEntities\"\n * ```\n */\n @Input() entities: EntityInfo[] = [];\n\n /**\n * All entities in the system for relationship discovery.\n * If not provided, uses Metadata.Entities automatically.\n * This is used to look up related entities when building the ERD.\n */\n @Input() allEntities?: EntityInfo[];\n\n /**\n * ID of the currently selected entity.\n * Controlled by parent - the component emits selection events but doesn't\n * manage selection state internally.\n */\n @Input() selectedEntityId: string | null = null;\n\n /**\n * IDs of entities to highlight (in addition to selected).\n */\n @Input() highlightedEntityIds: string[] = [];\n\n /**\n * ID of entity to focus on (shows only this entity and related up to depth).\n * If null, shows all provided entities.\n */\n @Input() focusEntityId: string | null = null;\n\n /**\n * Focus depth when focusEntityId is set.\n */\n @Input() focusDepth = 1;\n\n // ============================================================================\n // INPUTS - Relationship Options\n // ============================================================================\n\n /**\n * Number of relationship hops to include when auto-discovering related entities.\n * - `0`: Show only the provided entities (no auto-discovery)\n * - `1`: Show provided entities + directly related entities (default)\n * - `2+`: Show entities within N relationship hops\n *\n * @default 1\n */\n @Input() depth = 1;\n\n /**\n * Include incoming relationships (entities that reference these entities).\n * @default true\n */\n @Input() includeIncoming = true;\n\n /**\n * Include outgoing relationships (entities these reference via FK).\n * @default true\n */\n @Input() includeOutgoing = true;\n\n // ============================================================================\n // INPUTS - Configuration\n // ============================================================================\n\n /**\n * Configuration options passed to the underlying ERD component.\n */\n @Input() config: ERDConfig = {};\n\n /**\n * Whether to show the header bar with controls.\n * @default true\n */\n @Input() showHeader = true;\n\n /**\n * Title for the header bar.\n */\n @Input() headerTitle = 'Entity Relationship Diagram';\n\n /**\n * Whether the diagram is in a loading/refreshing state.\n */\n @Input() isRefreshing = false;\n\n /**\n * Whether the diagram is read-only (no selection/dragging).\n */\n @Input() readOnly = false;\n\n // ============================================================================\n // OUTPUTS\n // ============================================================================\n\n /**\n * Emitted when an entity is selected by clicking.\n * The parent should update `selectedEntityId` in response.\n */\n @Output() entitySelected = new EventEmitter<EntitySelectedEvent>();\n\n /**\n * Emitted when the selection is cleared.\n */\n @Output() entityDeselected = new EventEmitter<void>();\n\n /**\n * Emitted when an entity is double-clicked.\n * Typically used to open the entity record.\n */\n @Output() entityDoubleClick = new EventEmitter<EntitySelectedEvent>();\n\n /**\n * Emitted when requesting to open an entity record.\n * This is the standard MJ pattern for navigation.\n */\n @Output() openRecord = new EventEmitter<OpenEntityRecordEvent>();\n\n /**\n * Emitted when zoom/pan changes.\n * Parent can use this for state persistence.\n */\n @Output() zoomChange = new EventEmitter<ERDZoomEvent>();\n\n /**\n * Emitted when diagram state changes (selection, zoom, etc.).\n * Parent can use this for state persistence.\n */\n @Output() stateChange = new EventEmitter<ERDState>();\n\n /**\n * Emitted when user requests a refresh via the header button.\n */\n @Output() refreshRequested = new EventEmitter<void>();\n\n // ============================================================================\n // INTERNAL STATE\n // ============================================================================\n\n /** Computed ERD nodes */\n erdNodes: ERDNode[] = [];\n\n private _metadata = new Metadata();\n\n // ============================================================================\n // LIFECYCLE\n // ============================================================================\n\n ngOnChanges(changes: SimpleChanges): void {\n // Rebuild ERD data when entities or relationship options change\n if (\n changes['entities'] ||\n changes['allEntities'] ||\n changes['depth'] ||\n changes['includeIncoming'] ||\n changes['includeOutgoing']\n ) {\n this.buildERDData();\n }\n }\n\n // ============================================================================\n // ERD DATA BUILDING\n // ============================================================================\n\n private buildERDData(): void {\n if (!this.entities || this.entities.length === 0) {\n this.erdNodes = [];\n return;\n }\n\n // Use provided allEntities or fall back to Metadata\n const allEntities = this.allEntities || this._metadata.Entities;\n\n const result = buildERDDataFromEntities(this.entities, {\n allEntities,\n includeIncoming: this.includeIncoming,\n includeOutgoing: this.includeOutgoing,\n depth: this.depth\n });\n\n // Note: Links are derived automatically by the ERD diagram component\n // from the node field relationships (relatedNodeId)\n this.erdNodes = result.nodes;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n onNodeClick(_event: ERDNodeClickEvent): void {\n // Let the base component handle the click\n // Selection is handled via nodeSelected\n }\n\n onNodeDoubleClick(event: ERDNodeDoubleClickEvent): void {\n const entity = getOriginalEntityFromERDNode(event.node);\n if (entity) {\n this.entityDoubleClick.emit({ entity, node: event.node });\n // Also emit openRecord for convenience - container handles navigation\n this.openRecord.emit({\n EntityName: 'MJ: Entities',\n RecordID: entity.ID,\n entity\n });\n }\n }\n\n onNodeSelected(node: ERDNode): void {\n const entity = getOriginalEntityFromERDNode(node);\n if (entity) {\n this.entitySelected.emit({ entity, node });\n }\n }\n\n onNodeDeselected(): void {\n this.entityDeselected.emit();\n }\n\n onZoomChange(event: ERDZoomEvent): void {\n this.zoomChange.emit(event);\n }\n\n onStateChange(state: ERDState): void {\n this.stateChange.emit(state);\n }\n\n onRefreshRequested(): void {\n this.refreshRequested.emit();\n }\n\n // ============================================================================\n // PUBLIC API (Delegates to underlying component)\n // ============================================================================\n\n /**\n * Zoom in on the diagram.\n */\n public zoomIn(): void {\n this.erdDiagram?.zoomIn();\n }\n\n /**\n * Zoom out on the diagram.\n */\n public zoomOut(): void {\n this.erdDiagram?.zoomOut();\n }\n\n /**\n * Reset zoom to default.\n */\n public resetZoom(): void {\n this.erdDiagram?.resetZoom();\n }\n\n /**\n * Fit all nodes in view.\n */\n public zoomToFit(padding?: number): void {\n this.erdDiagram?.zoomToFit(padding);\n }\n\n /**\n * Zoom to a specific entity.\n */\n public zoomToEntity(entityId: string, scale?: number): void {\n this.erdDiagram?.zoomToNode(entityId, scale);\n }\n\n /**\n * Get current diagram state for persistence.\n */\n public getState(): ERDState | null {\n return this.erdDiagram?.getState() || null;\n }\n\n /**\n * Restore diagram state.\n */\n public setState(state: Partial<ERDState>, restorePositions?: boolean): void {\n this.erdDiagram?.setState(state, restorePositions);\n }\n\n /**\n * Refresh the diagram.\n */\n public refresh(): void {\n this.buildERDData();\n this.erdDiagram?.refresh();\n }\n\n /**\n * Export diagram as SVG.\n */\n public exportAsSVG(): string {\n return this.erdDiagram?.exportAsSVG() || '';\n }\n\n /**\n * Trigger a resize recalculation. Call this when the container size changes.\n */\n public triggerResize(): void {\n this.erdDiagram?.triggerResize();\n }\n}\n"]}
1
+ {"version":3,"file":"mj-entity-erd.component.js","sourceRoot":"","sources":["../../../src/lib/components/mj-entity-erd.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnChanges,\n SimpleChanges,\n ViewChild,\n ChangeDetectionStrategy\n} from '@angular/core';\nimport { EntityInfo } from '@memberjunction/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { ERDDiagramComponent } from './erd-diagram.component';\nimport {\n ERDNode,\n ERDConfig,\n ERDState,\n ERDNodeClickEvent,\n ERDNodeDoubleClickEvent,\n ERDZoomEvent\n} from '../interfaces/erd-types';\nimport {\n buildERDDataFromEntities,\n getOriginalEntityFromERDNode\n} from '../utils/entity-to-erd-adapter';\n\n/**\n * Event emitted when an entity is selected in the ERD.\n * Set `cancel = true` in your handler to prevent default behavior.\n */\nexport interface EntitySelectedEvent {\n /** The selected EntityInfo */\n entity: EntityInfo;\n /** The corresponding ERD node */\n node: ERDNode;\n /**\n * Set to true to cancel default behavior.\n * Default behavior: updates internal selection state.\n */\n cancel?: boolean;\n}\n\n/**\n * Event emitted when requesting to open an entity record.\n * Set `cancel = true` in your handler to prevent default behavior.\n */\nexport interface OpenEntityRecordEvent {\n /** Entity name for the record */\n EntityName: string;\n /** Record ID to open */\n RecordID: string;\n /** The EntityInfo being opened */\n entity: EntityInfo;\n /**\n * Set to true to cancel default behavior.\n * Default behavior: none (just emits the event).\n * Container is expected to handle navigation.\n */\n cancel?: boolean;\n}\n\n/**\n * Higher-level MemberJunction Entity ERD component that provides a simplified API\n * for displaying entity relationship diagrams using EntityInfo objects.\n *\n * This component wraps the generic `ERDDiagramComponent` and handles the transformation\n * of MemberJunction EntityInfo objects to the generic ERD format automatically.\n *\n * ## Key Features\n *\n * - **Simple Input**: Just pass `EntityInfo[]` - no manual transformation needed\n * - **Auto-Discovery**: Automatically discovers and displays relationships\n * - **Configurable Depth**: Control how many relationship hops to include\n * - **State Control**: Parent controls selection/state - component doesn't persist\n *\n * ## Usage Modes\n *\n * ### Single Entity Mode (Entity Form)\n * Show one entity and its immediate relationships:\n *\n * ```html\n * <mj-entity-erd\n * [entities]=\"[currentEntity]\"\n * [selectedEntityId]=\"currentEntity.ID\"\n * [depth]=\"1\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * ### Multi-Entity Mode (Schema Explorer)\n * Show multiple entities with persistence handled by parent:\n *\n * ```html\n * <mj-entity-erd\n * [entities]=\"filteredEntities\"\n * [selectedEntityId]=\"savedSelectedId\"\n * [depth]=\"savedDepth\"\n * (entitySelected)=\"onEntitySelected($event); saveState()\"\n * (stateChange)=\"onStateChange($event); saveState()\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * ## Important Design Decisions\n *\n * - **No State Persistence**: This component does NOT persist user state (selection, zoom, etc.).\n * The parent is responsible for saving/restoring state via the inputs and events.\n * - **No Filtering**: The caller filters entities before passing them. This keeps the component simple.\n * - **Controlled Selection**: Selection is controlled via `selectedEntityId` input. The component\n * emits `entitySelected` when user clicks, but parent decides what to do.\n *\n * @see ERDDiagramComponent for the underlying generic component\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-erd',\n template: `\n <mj-erd-diagram\n [nodes]=\"erdNodes\"\n [selectedNodeId]=\"selectedEntityId\"\n [highlightedNodeIds]=\"highlightedEntityIds\"\n [focusNodeId]=\"focusEntityId\"\n [focusDepth]=\"focusDepth\"\n [config]=\"config\"\n [showHeader]=\"showHeader\"\n [headerTitle]=\"headerTitle\"\n [isRefreshing]=\"isRefreshing\"\n [readOnly]=\"readOnly\"\n (nodeClick)=\"onNodeClick($event)\"\n (nodeDoubleClick)=\"onNodeDoubleClick($event)\"\n (nodeSelected)=\"onNodeSelected($event)\"\n (nodeDeselected)=\"onNodeDeselected()\"\n (zoomChange)=\"onZoomChange($event)\"\n (stateChange)=\"onStateChange($event)\"\n (refreshRequested)=\"onRefreshRequested()\">\n </mj-erd-diagram>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MJEntityERDComponent extends BaseAngularComponent implements OnChanges {\n @ViewChild(ERDDiagramComponent) erdDiagram!: ERDDiagramComponent;\n\n // ============================================================================\n // INPUTS - Data\n // ============================================================================\n\n /**\n * The entities to display in the ERD.\n * Pass one or more EntityInfo objects. The component will automatically\n * discover and display related entities based on the `depth` setting.\n *\n * @example\n * ```typescript\n * // Single entity\n * [entities]=\"[currentEntity]\"\n *\n * // Multiple entities (schema view)\n * [entities]=\"filteredEntities\"\n * ```\n */\n @Input() entities: EntityInfo[] = [];\n\n /**\n * All entities in the system for relationship discovery.\n * If not provided, uses Metadata.Entities automatically.\n * This is used to look up related entities when building the ERD.\n */\n @Input() allEntities?: EntityInfo[];\n\n /**\n * ID of the currently selected entity.\n * Controlled by parent - the component emits selection events but doesn't\n * manage selection state internally.\n */\n @Input() selectedEntityId: string | null = null;\n\n /**\n * IDs of entities to highlight (in addition to selected).\n */\n @Input() highlightedEntityIds: string[] = [];\n\n /**\n * ID of entity to focus on (shows only this entity and related up to depth).\n * If null, shows all provided entities.\n */\n @Input() focusEntityId: string | null = null;\n\n /**\n * Focus depth when focusEntityId is set.\n */\n @Input() focusDepth = 1;\n\n // ============================================================================\n // INPUTS - Relationship Options\n // ============================================================================\n\n /**\n * Number of relationship hops to include when auto-discovering related entities.\n * - `0`: Show only the provided entities (no auto-discovery)\n * - `1`: Show provided entities + directly related entities (default)\n * - `2+`: Show entities within N relationship hops\n *\n * @default 1\n */\n @Input() depth = 1;\n\n /**\n * Include incoming relationships (entities that reference these entities).\n * @default true\n */\n @Input() includeIncoming = true;\n\n /**\n * Include outgoing relationships (entities these reference via FK).\n * @default true\n */\n @Input() includeOutgoing = true;\n\n // ============================================================================\n // INPUTS - Configuration\n // ============================================================================\n\n /**\n * Configuration options passed to the underlying ERD component.\n */\n @Input() config: ERDConfig = {};\n\n /**\n * Whether to show the header bar with controls.\n * @default true\n */\n @Input() showHeader = true;\n\n /**\n * Title for the header bar.\n */\n @Input() headerTitle = 'Entity Relationship Diagram';\n\n /**\n * Whether the diagram is in a loading/refreshing state.\n */\n @Input() isRefreshing = false;\n\n /**\n * Whether the diagram is read-only (no selection/dragging).\n */\n @Input() readOnly = false;\n\n // ============================================================================\n // OUTPUTS\n // ============================================================================\n\n /**\n * Emitted when an entity is selected by clicking.\n * The parent should update `selectedEntityId` in response.\n */\n @Output() entitySelected = new EventEmitter<EntitySelectedEvent>();\n\n /**\n * Emitted when the selection is cleared.\n */\n @Output() entityDeselected = new EventEmitter<void>();\n\n /**\n * Emitted when an entity is double-clicked.\n * Typically used to open the entity record.\n */\n @Output() entityDoubleClick = new EventEmitter<EntitySelectedEvent>();\n\n /**\n * Emitted when requesting to open an entity record.\n * This is the standard MJ pattern for navigation.\n */\n @Output() openRecord = new EventEmitter<OpenEntityRecordEvent>();\n\n /**\n * Emitted when zoom/pan changes.\n * Parent can use this for state persistence.\n */\n @Output() zoomChange = new EventEmitter<ERDZoomEvent>();\n\n /**\n * Emitted when diagram state changes (selection, zoom, etc.).\n * Parent can use this for state persistence.\n */\n @Output() stateChange = new EventEmitter<ERDState>();\n\n /**\n * Emitted when user requests a refresh via the header button.\n */\n @Output() refreshRequested = new EventEmitter<void>();\n\n // ============================================================================\n // INTERNAL STATE\n // ============================================================================\n\n /** Computed ERD nodes */\n erdNodes: ERDNode[] = [];\n\n private get _metadata() { return this.ProviderToUse; }\n\n // ============================================================================\n // LIFECYCLE\n // ============================================================================\n\n ngOnChanges(changes: SimpleChanges): void {\n // Rebuild ERD data when entities or relationship options change\n if (\n changes['entities'] ||\n changes['allEntities'] ||\n changes['depth'] ||\n changes['includeIncoming'] ||\n changes['includeOutgoing']\n ) {\n this.buildERDData();\n }\n }\n\n // ============================================================================\n // ERD DATA BUILDING\n // ============================================================================\n\n private buildERDData(): void {\n if (!this.entities || this.entities.length === 0) {\n this.erdNodes = [];\n return;\n }\n\n // Use provided allEntities or fall back to Metadata\n const allEntities = this.allEntities || this._metadata.Entities;\n\n const result = buildERDDataFromEntities(this.entities, {\n allEntities,\n includeIncoming: this.includeIncoming,\n includeOutgoing: this.includeOutgoing,\n depth: this.depth\n });\n\n // Note: Links are derived automatically by the ERD diagram component\n // from the node field relationships (relatedNodeId)\n this.erdNodes = result.nodes;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n onNodeClick(_event: ERDNodeClickEvent): void {\n // Let the base component handle the click\n // Selection is handled via nodeSelected\n }\n\n onNodeDoubleClick(event: ERDNodeDoubleClickEvent): void {\n const entity = getOriginalEntityFromERDNode(event.node);\n if (entity) {\n this.entityDoubleClick.emit({ entity, node: event.node });\n // Also emit openRecord for convenience - container handles navigation\n this.openRecord.emit({\n EntityName: 'MJ: Entities',\n RecordID: entity.ID,\n entity\n });\n }\n }\n\n onNodeSelected(node: ERDNode): void {\n const entity = getOriginalEntityFromERDNode(node);\n if (entity) {\n this.entitySelected.emit({ entity, node });\n }\n }\n\n onNodeDeselected(): void {\n this.entityDeselected.emit();\n }\n\n onZoomChange(event: ERDZoomEvent): void {\n this.zoomChange.emit(event);\n }\n\n onStateChange(state: ERDState): void {\n this.stateChange.emit(state);\n }\n\n onRefreshRequested(): void {\n this.refreshRequested.emit();\n }\n\n // ============================================================================\n // PUBLIC API (Delegates to underlying component)\n // ============================================================================\n\n /**\n * Zoom in on the diagram.\n */\n public zoomIn(): void {\n this.erdDiagram?.zoomIn();\n }\n\n /**\n * Zoom out on the diagram.\n */\n public zoomOut(): void {\n this.erdDiagram?.zoomOut();\n }\n\n /**\n * Reset zoom to default.\n */\n public resetZoom(): void {\n this.erdDiagram?.resetZoom();\n }\n\n /**\n * Fit all nodes in view.\n */\n public zoomToFit(padding?: number): void {\n this.erdDiagram?.zoomToFit(padding);\n }\n\n /**\n * Zoom to a specific entity.\n */\n public zoomToEntity(entityId: string, scale?: number): void {\n this.erdDiagram?.zoomToNode(entityId, scale);\n }\n\n /**\n * Get current diagram state for persistence.\n */\n public getState(): ERDState | null {\n return this.erdDiagram?.getState() || null;\n }\n\n /**\n * Restore diagram state.\n */\n public setState(state: Partial<ERDState>, restorePositions?: boolean): void {\n this.erdDiagram?.setState(state, restorePositions);\n }\n\n /**\n * Refresh the diagram.\n */\n public refresh(): void {\n this.buildERDData();\n this.erdDiagram?.refresh();\n }\n\n /**\n * Export diagram as SVG.\n */\n public exportAsSVG(): string {\n return this.erdDiagram?.exportAsSVG() || '';\n }\n\n /**\n * Trigger a resize recalculation. Call this when the container size changes.\n */\n public triggerResize(): void {\n this.erdDiagram?.triggerResize();\n }\n}\n"]}
@@ -7,6 +7,7 @@ import * as i5 from "./components/erd-composite/erd-composite.component";
7
7
  import * as i6 from "@angular/common";
8
8
  import * as i7 from "@angular/forms";
9
9
  import * as i8 from "angular-split";
10
+ import * as i9 from "@memberjunction/ng-ui-components";
10
11
  /**
11
12
  * Module for the Entity Relationship Diagram (ERD) visualization components.
12
13
  *
@@ -77,7 +78,7 @@ import * as i8 from "angular-split";
77
78
  */
78
79
  export declare class EntityRelationshipDiagramModule {
79
80
  static ɵfac: i0.ɵɵFactoryDeclaration<EntityRelationshipDiagramModule, never>;
80
- static ɵmod: i0.ɵɵNgModuleDeclaration<EntityRelationshipDiagramModule, [typeof i1.ERDDiagramComponent, typeof i2.MJEntityERDComponent, typeof i3.EntityDetailsComponent, typeof i4.EntityFilterPanelComponent, typeof i5.ERDCompositeComponent], [typeof i6.CommonModule, typeof i7.FormsModule, typeof i8.AngularSplitModule], [typeof i1.ERDDiagramComponent, typeof i2.MJEntityERDComponent, typeof i3.EntityDetailsComponent, typeof i4.EntityFilterPanelComponent, typeof i5.ERDCompositeComponent]>;
81
+ static ɵmod: i0.ɵɵNgModuleDeclaration<EntityRelationshipDiagramModule, [typeof i1.ERDDiagramComponent, typeof i2.MJEntityERDComponent, typeof i3.EntityDetailsComponent, typeof i4.EntityFilterPanelComponent, typeof i5.ERDCompositeComponent], [typeof i6.CommonModule, typeof i7.FormsModule, typeof i8.AngularSplitModule, typeof i9.MJButtonDirective, typeof i9.MJDropdownComponent], [typeof i1.ERDDiagramComponent, typeof i2.MJEntityERDComponent, typeof i3.EntityDetailsComponent, typeof i4.EntityFilterPanelComponent, typeof i5.ERDCompositeComponent]>;
81
82
  static ɵinj: i0.ɵɵInjectorDeclaration<EntityRelationshipDiagramModule>;
82
83
  }
83
84
  //# sourceMappingURL=entity-relationship-diagram.module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity-relationship-diagram.module.d.ts","sourceRoot":"","sources":["../../src/lib/entity-relationship-diagram.module.ts"],"names":[],"mappings":";;;;;;;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,qBAqBa,+BAA+B;yCAA/B,+BAA+B;0CAA/B,+BAA+B;0CAA/B,+BAA+B;CAAG"}
1
+ {"version":3,"file":"entity-relationship-diagram.module.d.ts","sourceRoot":"","sources":["../../src/lib/entity-relationship-diagram.module.ts"],"names":[],"mappings":";;;;;;;;;;AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,qBAuBa,+BAA+B;yCAA/B,+BAA+B;0CAA/B,+BAA+B;0CAA/B,+BAA+B;CAAG"}
@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormsModule } from '@angular/forms';
4
4
  import { AngularSplitModule } from 'angular-split';
5
+ import { MJButtonDirective, MJDropdownComponent } from '@memberjunction/ng-ui-components';
5
6
  import { ERDDiagramComponent } from './components/erd-diagram.component';
6
7
  import { MJEntityERDComponent } from './components/mj-entity-erd.component';
7
8
  import { EntityDetailsComponent } from './components/entity-details/entity-details.component';
@@ -81,7 +82,8 @@ export class EntityRelationshipDiagramModule {
81
82
  static ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: EntityRelationshipDiagramModule });
82
83
  static ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonModule,
83
84
  FormsModule,
84
- AngularSplitModule] });
85
+ AngularSplitModule,
86
+ MJDropdownComponent] });
85
87
  }
86
88
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityRelationshipDiagramModule, [{
87
89
  type: NgModule,
@@ -96,7 +98,9 @@ export class EntityRelationshipDiagramModule {
96
98
  imports: [
97
99
  CommonModule,
98
100
  FormsModule,
99
- AngularSplitModule
101
+ AngularSplitModule,
102
+ MJButtonDirective,
103
+ MJDropdownComponent,
100
104
  ],
101
105
  exports: [
102
106
  ERDDiagramComponent,
@@ -113,7 +117,9 @@ export class EntityRelationshipDiagramModule {
113
117
  EntityFilterPanelComponent,
114
118
  ERDCompositeComponent], imports: [CommonModule,
115
119
  FormsModule,
116
- AngularSplitModule], exports: [ERDDiagramComponent,
120
+ AngularSplitModule,
121
+ MJButtonDirective,
122
+ MJDropdownComponent], exports: [ERDDiagramComponent,
117
123
  MJEntityERDComponent,
118
124
  EntityDetailsComponent,
119
125
  EntityFilterPanelComponent,
@@ -1 +1 @@
1
- {"version":3,"file":"entity-relationship-diagram.module.js","sourceRoot":"","sources":["../../src/lib/entity-relationship-diagram.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAC9F,OAAO,EAAE,0BAA0B,EAAE,MAAM,gEAAgE,CAAC;AAC5G,OAAO,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AAsBH,MAAM,OAAO,+BAA+B;yHAA/B,+BAA+B;4DAA/B,+BAA+B;gEAZxC,YAAY;YACZ,WAAW;YACX,kBAAkB;;iFAUT,+BAA+B;cArB3C,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,mBAAmB;oBACnB,oBAAoB;oBACpB,sBAAsB;oBACtB,0BAA0B;oBAC1B,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,kBAAkB;iBACnB;gBACD,OAAO,EAAE;oBACP,mBAAmB;oBACnB,oBAAoB;oBACpB,sBAAsB;oBACtB,0BAA0B;oBAC1B,qBAAqB;iBACtB;aACF;;wFACY,+BAA+B,mBAnBxC,mBAAmB;QACnB,oBAAoB;QACpB,sBAAsB;QACtB,0BAA0B;QAC1B,qBAAqB,aAGrB,YAAY;QACZ,WAAW;QACX,kBAAkB,aAGlB,mBAAmB;QACnB,oBAAoB;QACpB,sBAAsB;QACtB,0BAA0B;QAC1B,qBAAqB","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { AngularSplitModule } from 'angular-split';\n\nimport { ERDDiagramComponent } from './components/erd-diagram.component';\nimport { MJEntityERDComponent } from './components/mj-entity-erd.component';\nimport { EntityDetailsComponent } from './components/entity-details/entity-details.component';\nimport { EntityFilterPanelComponent } from './components/entity-filter-panel/entity-filter-panel.component';\nimport { ERDCompositeComponent } from './components/erd-composite/erd-composite.component';\n\n/**\n * Module for the Entity Relationship Diagram (ERD) visualization components.\n *\n * This module provides a complete suite of components for visualizing and\n * exploring entity relationships:\n *\n * ## Components\n *\n * ### 1. ERDDiagramComponent (`<mj-erd-diagram>`)\n * A generic, reusable ERD component that visualizes entity relationships using\n * D3.js force-directed graphs. It works with any data conforming to the `ERDNode`\n * interface and is completely decoupled from MemberJunction-specific types.\n *\n * ### 2. MJEntityERDComponent (`<mj-entity-erd>`)\n * A higher-level wrapper specifically for MemberJunction. It accepts `EntityInfo[]`\n * directly and handles all the transformation to ERD format automatically.\n *\n * ### 3. EntityDetailsComponent (`<mj-entity-details>`)\n * A detail panel that shows entity information, fields, and relationships when\n * an entity is selected. Designed to work alongside the ERD diagram.\n *\n * ### 4. EntityFilterPanelComponent (`<mj-entity-filter-panel>`)\n * A filter panel for filtering entities by schema, name, status, and base table.\n *\n * ### 5. ERDCompositeComponent (`<mj-erd-composite>`)\n * A complete, ready-to-use ERD exploration interface that combines:\n * - Left panel: Entity filter controls\n * - Center: Interactive ERD diagram\n * - Right panel: Entity details (shown when an entity is selected)\n *\n * ### Choosing Which Component to Use\n *\n * | Use Case | Component |\n * |----------|-----------|\n * | Complete ERD exploration UI | `<mj-erd-composite>` |\n * | ERD diagram with MJ EntityInfo | `<mj-entity-erd>` |\n * | Custom data sources (non-MJ) | `<mj-erd-diagram>` |\n * | Entity detail panel standalone | `<mj-entity-details>` |\n * | Entity filter panel standalone | `<mj-entity-filter-panel>` |\n *\n * @example Using the composite (recommended for dashboards)\n * ```html\n * <mj-erd-composite\n * (userStateChange)=\"saveUserPreferences($event)\"\n * (openRecord)=\"navigateToRecord($event)\">\n * </mj-erd-composite>\n * ```\n *\n * @example Using the MJ wrapper\n * ```html\n * <mj-entity-erd\n * [entities]=\"[currentEntity]\"\n * [selectedEntityId]=\"currentEntity.ID\"\n * [depth]=\"1\"\n * (entitySelected)=\"onEntitySelected($event)\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * @example Using the generic component\n * ```html\n * <mj-erd-diagram\n * [nodes]=\"myNodes\"\n * [selectedNodeId]=\"selectedId\"\n * (nodeSelected)=\"onNodeSelected($event)\">\n * </mj-erd-diagram>\n * ```\n */\n@NgModule({\n declarations: [\n ERDDiagramComponent,\n MJEntityERDComponent,\n EntityDetailsComponent,\n EntityFilterPanelComponent,\n ERDCompositeComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n AngularSplitModule\n ],\n exports: [\n ERDDiagramComponent,\n MJEntityERDComponent,\n EntityDetailsComponent,\n EntityFilterPanelComponent,\n ERDCompositeComponent\n ]\n})\nexport class EntityRelationshipDiagramModule {}\n"]}
1
+ {"version":3,"file":"entity-relationship-diagram.module.js","sourceRoot":"","sources":["../../src/lib/entity-relationship-diagram.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAE1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAC9F,OAAO,EAAE,0BAA0B,EAAE,MAAM,gEAAgE,CAAC;AAC5G,OAAO,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AAwBH,MAAM,OAAO,+BAA+B;yHAA/B,+BAA+B;4DAA/B,+BAA+B;gEAdxC,YAAY;YACZ,WAAW;YACX,kBAAkB;YAElB,mBAAmB;;iFAUV,+BAA+B;cAvB3C,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,mBAAmB;oBACnB,oBAAoB;oBACpB,sBAAsB;oBACtB,0BAA0B;oBAC1B,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,kBAAkB;oBAClB,iBAAiB;oBACjB,mBAAmB;iBACpB;gBACD,OAAO,EAAE;oBACP,mBAAmB;oBACnB,oBAAoB;oBACpB,sBAAsB;oBACtB,0BAA0B;oBAC1B,qBAAqB;iBACtB;aACF;;wFACY,+BAA+B,mBArBxC,mBAAmB;QACnB,oBAAoB;QACpB,sBAAsB;QACtB,0BAA0B;QAC1B,qBAAqB,aAGrB,YAAY;QACZ,WAAW;QACX,kBAAkB;QAClB,iBAAiB;QACjB,mBAAmB,aAGnB,mBAAmB;QACnB,oBAAoB;QACpB,sBAAsB;QACtB,0BAA0B;QAC1B,qBAAqB","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { AngularSplitModule } from 'angular-split';\nimport { MJButtonDirective, MJDropdownComponent } from '@memberjunction/ng-ui-components';\n\nimport { ERDDiagramComponent } from './components/erd-diagram.component';\nimport { MJEntityERDComponent } from './components/mj-entity-erd.component';\nimport { EntityDetailsComponent } from './components/entity-details/entity-details.component';\nimport { EntityFilterPanelComponent } from './components/entity-filter-panel/entity-filter-panel.component';\nimport { ERDCompositeComponent } from './components/erd-composite/erd-composite.component';\n\n/**\n * Module for the Entity Relationship Diagram (ERD) visualization components.\n *\n * This module provides a complete suite of components for visualizing and\n * exploring entity relationships:\n *\n * ## Components\n *\n * ### 1. ERDDiagramComponent (`<mj-erd-diagram>`)\n * A generic, reusable ERD component that visualizes entity relationships using\n * D3.js force-directed graphs. It works with any data conforming to the `ERDNode`\n * interface and is completely decoupled from MemberJunction-specific types.\n *\n * ### 2. MJEntityERDComponent (`<mj-entity-erd>`)\n * A higher-level wrapper specifically for MemberJunction. It accepts `EntityInfo[]`\n * directly and handles all the transformation to ERD format automatically.\n *\n * ### 3. EntityDetailsComponent (`<mj-entity-details>`)\n * A detail panel that shows entity information, fields, and relationships when\n * an entity is selected. Designed to work alongside the ERD diagram.\n *\n * ### 4. EntityFilterPanelComponent (`<mj-entity-filter-panel>`)\n * A filter panel for filtering entities by schema, name, status, and base table.\n *\n * ### 5. ERDCompositeComponent (`<mj-erd-composite>`)\n * A complete, ready-to-use ERD exploration interface that combines:\n * - Left panel: Entity filter controls\n * - Center: Interactive ERD diagram\n * - Right panel: Entity details (shown when an entity is selected)\n *\n * ### Choosing Which Component to Use\n *\n * | Use Case | Component |\n * |----------|-----------|\n * | Complete ERD exploration UI | `<mj-erd-composite>` |\n * | ERD diagram with MJ EntityInfo | `<mj-entity-erd>` |\n * | Custom data sources (non-MJ) | `<mj-erd-diagram>` |\n * | Entity detail panel standalone | `<mj-entity-details>` |\n * | Entity filter panel standalone | `<mj-entity-filter-panel>` |\n *\n * @example Using the composite (recommended for dashboards)\n * ```html\n * <mj-erd-composite\n * (userStateChange)=\"saveUserPreferences($event)\"\n * (openRecord)=\"navigateToRecord($event)\">\n * </mj-erd-composite>\n * ```\n *\n * @example Using the MJ wrapper\n * ```html\n * <mj-entity-erd\n * [entities]=\"[currentEntity]\"\n * [selectedEntityId]=\"currentEntity.ID\"\n * [depth]=\"1\"\n * (entitySelected)=\"onEntitySelected($event)\"\n * (openRecord)=\"onOpenRecord($event)\">\n * </mj-entity-erd>\n * ```\n *\n * @example Using the generic component\n * ```html\n * <mj-erd-diagram\n * [nodes]=\"myNodes\"\n * [selectedNodeId]=\"selectedId\"\n * (nodeSelected)=\"onNodeSelected($event)\">\n * </mj-erd-diagram>\n * ```\n */\n@NgModule({\n declarations: [\n ERDDiagramComponent,\n MJEntityERDComponent,\n EntityDetailsComponent,\n EntityFilterPanelComponent,\n ERDCompositeComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n AngularSplitModule,\n MJButtonDirective,\n MJDropdownComponent,\n ],\n exports: [\n ERDDiagramComponent,\n MJEntityERDComponent,\n EntityDetailsComponent,\n EntityFilterPanelComponent,\n ERDCompositeComponent\n ]\n})\nexport class EntityRelationshipDiagramModule {}\n"]}
@@ -114,8 +114,15 @@ export interface ERDConfig {
114
114
  linkDistance?: number;
115
115
  /** Collision radius padding */
116
116
  collisionPadding?: number;
117
- /** Whether to show field details in nodes */
117
+ /** Whether to show field details in nodes (PK + FK rows). Defaults to true. */
118
118
  showFieldDetails?: boolean;
119
+ /**
120
+ * Whether to render all non-PK/non-FK fields as well. When true, every field on
121
+ * each node is rendered (PKs first, FKs next, then all other fields in declaration
122
+ * order). Use for "table card" style diagrams where users want to see every column.
123
+ * Defaults to false (classic schema-relationship view: keys only).
124
+ */
125
+ showAllFields?: boolean;
119
126
  /** Whether to show relationship labels */
120
127
  showRelationshipLabels?: boolean;
121
128
  /** Whether to enable node dragging */
@@ -267,6 +274,12 @@ export interface ERDState {
267
274
  fx?: number | null;
268
275
  fy?: number | null;
269
276
  }>;
277
+ /**
278
+ * Active layout algorithm — persisted so a user's preferred view
279
+ * (schema-grid vs. dagre hierarchical) survives navigation and
280
+ * reloads. Defaults to 'schema-grid' when absent.
281
+ */
282
+ layoutAlgorithm?: 'schema-grid' | 'dagre';
270
283
  }
271
284
  /**
272
285
  * Event data for node hover events.
@@ -384,13 +397,14 @@ export interface ERDNodeDragEvent {
384
397
  }
385
398
  /**
386
399
  * Layout algorithm options for the ERD diagram.
387
- * - 'force': D3 force-directed layout (dynamic, animated)
388
- * - 'dagre': Dagre hierarchical layout with orthogonal edges (static, clean)
389
- * - 'horizontal': Left-to-right hierarchical layout using Dagre
390
- * - 'vertical': Top-to-bottom hierarchical layout using Dagre
400
+ * - 'schema-grid': Schema-grouped rectangular bands with grid-tiled nodes (default, clean, predictable)
401
+ * - 'force': Legacy D3 force-directed layout (dynamic, animated) — retained for compat
402
+ * - 'dagre': Legacy Dagre hierarchical layout with orthogonal edges — retained for compat
403
+ * - 'horizontal': Left-to-right hierarchical layout using Dagre — retained for compat
404
+ * - 'vertical': Top-to-bottom hierarchical layout using Dagre — retained for compat
391
405
  * - 'radial': Radial layout (not yet implemented)
392
406
  */
393
- export type ERDLayoutAlgorithm = 'force' | 'dagre' | 'horizontal' | 'vertical' | 'radial';
407
+ export type ERDLayoutAlgorithm = 'schema-grid' | 'force' | 'dagre' | 'horizontal' | 'vertical' | 'radial';
394
408
  /**
395
409
  * Dagre-specific layout configuration options.
396
410
  */
@@ -449,6 +463,13 @@ export interface ERDConfig {
449
463
  minZoom?: number;
450
464
  /** Maximum zoom level. Default: 4 */
451
465
  maxZoom?: number;
466
+ /**
467
+ * Maximum zoom level applied during fit-to-view. Default 2.5 — allows small
468
+ * diagrams (e.g. Database Designer wizard preview with 1–3 entities) to scale
469
+ * up enough to fill the pane without looking "lost", while still letting
470
+ * manual zoom (wheel/pinch) go higher up to `maxZoom`.
471
+ */
472
+ maxFitZoom?: number;
452
473
  /** Initial zoom level (1 = 100%). Default: 1 */
453
474
  initialZoom?: number;
454
475
  /** Enable multi-select with Ctrl+click. Default: false */
@@ -468,10 +489,20 @@ export interface ERDConfig {
468
489
  emptyStateMessage?: string;
469
490
  /** Icon class for empty state. Default: 'fa-solid fa-diagram-project' */
470
491
  emptyStateIcon?: string;
471
- /** Layout algorithm to use. Default: 'force' */
492
+ /** Layout algorithm to use. Default: 'schema-grid' */
472
493
  layoutAlgorithm?: ERDLayoutAlgorithm;
473
494
  /** Dagre-specific layout configuration (only used when layoutAlgorithm is 'dagre', 'horizontal', or 'vertical') */
474
495
  dagreConfig?: ERDDagreConfig;
496
+ /** Draw rounded rectangular bands grouping nodes by schema. Default: true (schema-grid layout only) */
497
+ showSchemaBands?: boolean;
498
+ /** Draw crow's-foot markers at the source end of edges (many side). Default: true */
499
+ crowsFoot?: boolean;
500
+ /**
501
+ * Max visible fields on a node before the "+N more" toggle kicks in.
502
+ * Default: Infinity when `showAllFields` is true; when `showAllFields` is false,
503
+ * only PK + FK fields are shown regardless of this value.
504
+ */
505
+ maxVisibleFields?: number;
475
506
  /** Color scheme for the diagram */
476
507
  colors?: ERDColorScheme;
477
508
  }
@@ -1 +1 @@
1
- {"version":3,"file":"erd-types.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/erd-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"erd-types.d.ts","sourceRoot":"","sources":["../../../src/lib/interfaces/erd-types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"erd-types.js","sourceRoot":"","sources":["../../../src/lib/interfaces/erd-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * Generic ERD Types for the Entity Relationship Diagram component.\n * These types are designed to be framework-agnostic and can work with any data source.\n */\n\n/**\n * Represents a field in an ERD node (entity).\n */\nexport interface ERDField {\n /** Unique identifier for the field */\n id: string;\n /** Display name of the field */\n name: string;\n /** Data type of the field (e.g., 'string', 'int', 'uuid') */\n type?: string;\n /** Whether this field is a primary key */\n isPrimaryKey: boolean;\n /** ID of the related node (for foreign keys) */\n relatedNodeId?: string;\n /** Name of the related node (for display purposes) */\n relatedNodeName?: string;\n /** Name of the field in the related node (for FK relationships) */\n relatedFieldName?: string;\n /** Optional description of the field */\n description?: string;\n /** Whether the field allows null values */\n allowsNull?: boolean;\n /** Default value for the field */\n defaultValue?: string;\n /** Maximum length (for string fields) */\n length?: number;\n /** Precision (for numeric fields) */\n precision?: number;\n /** Scale (for numeric fields) */\n scale?: number;\n /** Whether the field is virtual/computed */\n isVirtual?: boolean;\n /** Whether the field is auto-increment */\n autoIncrement?: boolean;\n /** Possible values for the field (for enums/dropdowns) */\n possibleValues?: ERDFieldValue[];\n /** Additional custom data */\n customData?: Record<string, unknown>;\n}\n\n/**\n * Represents a possible value for an ERD field (enum values, dropdown options, etc.)\n */\nexport interface ERDFieldValue {\n /** Unique identifier for the value */\n id?: string;\n /** The actual value */\n value: string;\n /** Code representation (may differ from value) */\n code?: string;\n /** Description of what this value means */\n description?: string;\n /** Sort order */\n sequence?: number;\n}\n\n/**\n * Represents a node (entity/table) in the ERD.\n */\nexport interface ERDNode {\n /** Unique identifier for the node */\n id: string;\n /** Display name of the node */\n name: string;\n /** Optional schema/namespace name */\n schemaName?: string;\n /** Optional description */\n description?: string;\n /** Status of the node (e.g., 'Active', 'Deprecated') */\n status?: string;\n /** Base table name (if different from display name) */\n baseTable?: string;\n /** All fields in this node */\n fields: ERDField[];\n /** Additional custom data that can be used by the consumer */\n customData?: Record<string, unknown>;\n}\n\n/**\n * Represents a link (relationship) between two nodes in the ERD.\n */\nexport interface ERDLink {\n /** ID of the source node */\n sourceNodeId: string;\n /** ID of the target node */\n targetNodeId: string;\n /** The field that creates this relationship (usually the FK field) */\n sourceField: ERDField;\n /** The field in the target node (usually the PK field) */\n targetField?: ERDField;\n /** Whether this is a self-referencing relationship */\n isSelfReference: boolean;\n /** Relationship type (e.g., 'one-to-many', 'many-to-one') */\n relationshipType?: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many';\n /** Optional label for the relationship */\n label?: string;\n}\n\n/**\n * Configuration options for the ERD diagram.\n */\nexport interface ERDConfig {\n /** Width of each node box in pixels */\n nodeWidth?: number;\n /** Base height of each node box in pixels */\n nodeBaseHeight?: number;\n /** Height per field in pixels */\n fieldHeight?: number;\n /** Maximum height of a node in pixels */\n maxNodeHeight?: number;\n /** Charge strength for force simulation (negative = repel) */\n chargeStrength?: number;\n /** Link distance for force simulation */\n linkDistance?: number;\n /** Collision radius padding */\n collisionPadding?: number;\n /** Whether to show field details in nodes */\n showFieldDetails?: boolean;\n /** Whether to show relationship labels */\n showRelationshipLabels?: boolean;\n /** Whether to enable node dragging */\n enableDragging?: boolean;\n /** Whether to enable zoom/pan */\n enableZoom?: boolean;\n /** Initial zoom level */\n initialZoom?: number;\n /** Colors for different node states */\n colors?: ERDColorScheme;\n}\n\n/**\n * Color scheme for the ERD diagram.\n */\nexport interface ERDColorScheme {\n /** Background color for node rectangles */\n nodeBackground?: string;\n /** Border color for node rectangles */\n nodeBorder?: string;\n /** Header background color for nodes */\n nodeHeader?: string;\n /** Text color for node headers */\n nodeHeaderText?: string;\n /** Background color for primary key fields */\n primaryKeyBackground?: string;\n /** Text color for primary key fields */\n primaryKeyText?: string;\n /** Background color for foreign key fields */\n foreignKeyBackground?: string;\n /** Text color for foreign key fields */\n foreignKeyText?: string;\n /** Color for relationship links */\n linkColor?: string;\n /** Color for selected nodes */\n selectedBorder?: string;\n /** Color for highlighted nodes */\n highlightBorder?: string;\n /** Color for related nodes (when showing relationships) */\n relatedBorder?: string;\n}\n\n/**\n * Filter configuration for the ERD.\n */\nexport interface ERDFilter {\n /** Filter by schema name */\n schemaName?: string | null;\n /** Filter by node name (search) */\n nodeName?: string;\n /** Filter by node status */\n nodeStatus?: string | null;\n /** Filter by base table name (search) */\n baseTable?: string;\n /** Custom filter function */\n customFilter?: (node: ERDNode) => boolean;\n}\n\n/**\n * Event data for node selection events.\n */\nexport interface ERDNodeSelectionEvent {\n /** The selected node (null if deselected) */\n node: ERDNode | null;\n /** Previous selected node (null if none) */\n previousNode: ERDNode | null;\n /** Whether the consumer can cancel this selection */\n cancel: boolean;\n}\n\n/**\n * Event data for node click events.\n */\nexport interface ERDNodeClickEvent {\n /** The clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior (selection) */\n cancel: boolean;\n}\n\n/**\n * Event data for node double-click events.\n */\nexport interface ERDNodeDoubleClickEvent {\n /** The double-clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior */\n cancel: boolean;\n}\n\n/**\n * Event data for link click events.\n */\nexport interface ERDLinkClickEvent {\n /** The clicked link */\n link: ERDLink;\n /** Source node */\n sourceNode: ERDNode;\n /** Target node */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior */\n cancel: boolean;\n}\n\n/**\n * Event data for zoom change events.\n */\nexport interface ERDZoomEvent {\n /** Current zoom level */\n zoomLevel: number;\n /** X translation */\n translateX: number;\n /** Y translation */\n translateY: number;\n}\n\n/**\n * State of the ERD diagram for saving/restoring.\n * Use with `getState()` and `setState()` methods for persistence.\n *\n * @example\n * ```typescript\n * // Save state to localStorage\n * const state = erdComponent.getState();\n * localStorage.setItem('erd-state', JSON.stringify(state));\n *\n * // Restore state\n * const savedState = JSON.parse(localStorage.getItem('erd-state'));\n * erdComponent.setState(savedState);\n * ```\n */\nexport interface ERDState {\n /** ID of the currently selected node */\n selectedNodeId: string | null;\n /** IDs of highlighted nodes */\n highlightedNodeIds: string[];\n /** Current zoom level (1 = 100%) */\n zoomLevel: number;\n /** X translation (pan position) */\n translateX: number;\n /** Y translation (pan position) */\n translateY: number;\n /** Focus node ID (if in focus mode) */\n focusNodeId: string | null;\n /** Focus depth (number of relationship hops to show) */\n focusDepth: number;\n /** Node positions for restoring exact layout */\n nodePositions: Record<string, { x: number; y: number; fx?: number | null; fy?: number | null }>;\n}\n\n/**\n * Event data for node hover events.\n * Emitted when the mouse enters a node.\n */\nexport interface ERDNodeHoverEvent {\n /** The hovered node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Nodes directly connected to this node via relationships */\n relatedNodes: ERDNode[];\n /** Position for displaying tooltips */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for link hover events.\n * Emitted when the mouse enters a relationship link.\n */\nexport interface ERDLinkHoverEvent {\n /** The hovered link */\n link: ERDLink;\n /** Source node of the relationship */\n sourceNode: ERDNode;\n /** Target node of the relationship */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Position for displaying tooltips */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on nodes.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDNodeContextMenuEvent {\n /** The right-clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on links.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDLinkContextMenuEvent {\n /** The right-clicked link */\n link: ERDLink;\n /** Source node */\n sourceNode: ERDNode;\n /** Target node */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on the diagram background.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDDiagramContextMenuEvent {\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n /** Diagram coordinates of the click */\n diagramPosition: { x: number; y: number };\n}\n\n/**\n * Event data for node drag events.\n * Set `cancel = true` in dragStart to prevent dragging.\n */\nexport interface ERDNodeDragEvent {\n /** The dragged node */\n node: ERDNode;\n /** Position when drag started */\n startPosition: { x: number; y: number };\n /** Current position during drag */\n currentPosition: { x: number; y: number };\n /** Set to true in dragStart to cancel the drag */\n cancel: boolean;\n}\n\n/**\n * Layout algorithm options for the ERD diagram.\n * - 'force': D3 force-directed layout (dynamic, animated)\n * - 'dagre': Dagre hierarchical layout with orthogonal edges (static, clean)\n * - 'horizontal': Left-to-right hierarchical layout using Dagre\n * - 'vertical': Top-to-bottom hierarchical layout using Dagre\n * - 'radial': Radial layout (not yet implemented)\n */\nexport type ERDLayoutAlgorithm = 'force' | 'dagre' | 'horizontal' | 'vertical' | 'radial';\n\n/**\n * Dagre-specific layout configuration options.\n */\nexport interface ERDDagreConfig {\n /** Direction of the graph layout. Default: 'LR' (left-to-right) */\n rankDir?: 'TB' | 'BT' | 'LR' | 'RL';\n /** Horizontal separation between nodes. Default: 50 */\n nodeSep?: number;\n /** Vertical separation between ranks/layers. Default: 100 */\n rankSep?: number;\n /** Separation between different edge paths. Default: 10 */\n edgeSep?: number;\n /** Algorithm for ranking nodes: 'network-simplex', 'tight-tree', 'longest-path'. Default: 'network-simplex' */\n ranker?: 'network-simplex' | 'tight-tree' | 'longest-path';\n /** Alignment of nodes within their rank: 'UL', 'UR', 'DL', 'DR'. Default: undefined (centered) */\n align?: 'UL' | 'UR' | 'DL' | 'DR';\n}\n\n/**\n * Extended configuration options for the ERD diagram.\n * All options are optional with sensible defaults.\n */\nexport interface ERDConfig {\n // ============================================================================\n // Node Sizing\n // ============================================================================\n\n /** Width of each node box in pixels. Default: 180 */\n nodeWidth?: number;\n /** Base height of each node box in pixels (before adding fields). Default: 60 */\n nodeBaseHeight?: number;\n /** Height per field row in pixels. Default: 20 */\n fieldHeight?: number;\n /** Maximum height of a node in pixels. Default: 300 */\n maxNodeHeight?: number;\n\n // ============================================================================\n // Force Simulation\n // ============================================================================\n\n /** Charge strength for force simulation (negative = repel). Default: -800 */\n chargeStrength?: number;\n /** Base distance between linked nodes. Default: 80 */\n linkDistance?: number;\n /** Extra padding for collision detection. Default: 20 */\n collisionPadding?: number;\n\n // ============================================================================\n // Display Options\n // ============================================================================\n\n /** Whether to show field details (PKs, FKs) in nodes. Default: true */\n showFieldDetails?: boolean;\n /** Whether to show relationship labels on links. Default: true */\n showRelationshipLabels?: boolean;\n /** Whether to show the header bar with controls. Default: true */\n showHeader?: boolean;\n /** Whether to show node count in header. Default: true */\n showNodeCount?: boolean;\n /** Whether to show a minimap for navigation. Default: false */\n showMinimap?: boolean;\n /** Whether to show a legend explaining colors. Default: false */\n showLegend?: boolean;\n\n // ============================================================================\n // Interaction Options\n // ============================================================================\n\n /** Enable node dragging. Default: true */\n enableDragging?: boolean;\n /** Enable zoom with mouse wheel. Default: true */\n enableZoom?: boolean;\n /** Enable panning by dragging background. Default: true */\n enablePan?: boolean;\n /** Minimum zoom level. Default: 0.1 */\n minZoom?: number;\n /** Maximum zoom level. Default: 4 */\n maxZoom?: number;\n /** Initial zoom level (1 = 100%). Default: 1 */\n initialZoom?: number;\n /** Enable multi-select with Ctrl+click. Default: false */\n enableMultiSelect?: boolean;\n\n // ============================================================================\n // Animation\n // ============================================================================\n\n /** Duration of zoom/pan animations in milliseconds. Default: 750 */\n animationDuration?: number;\n /** Whether to auto-fit diagram to container on initial load. Default: true */\n fitOnLoad?: boolean;\n /**\n * Skip the D3 force simulation animation and render immediately.\n * When true, the simulation runs to completion synchronously and nodes\n * are positioned immediately without animation.\n * Default: false\n */\n skipAnimation?: boolean;\n\n // ============================================================================\n // Empty State\n // ============================================================================\n\n /** Message to show when no nodes are provided. Default: 'No entities to display' */\n emptyStateMessage?: string;\n /** Icon class for empty state. Default: 'fa-solid fa-diagram-project' */\n emptyStateIcon?: string;\n\n // ============================================================================\n // Layout\n // ============================================================================\n\n /** Layout algorithm to use. Default: 'force' */\n layoutAlgorithm?: ERDLayoutAlgorithm;\n\n /** Dagre-specific layout configuration (only used when layoutAlgorithm is 'dagre', 'horizontal', or 'vertical') */\n dagreConfig?: ERDDagreConfig;\n\n // ============================================================================\n // Colors\n // ============================================================================\n\n /** Color scheme for the diagram */\n colors?: ERDColorScheme;\n}\n\n/**\n * Information about a relationship for highlighting purposes.\n */\nexport interface ERDRelationshipInfo {\n /** The related node */\n node: ERDNode;\n /** The link connecting them */\n link: ERDLink;\n /** Direction of relationship from the perspective of the source node */\n direction: 'outgoing' | 'incoming';\n /** The field creating this relationship */\n field: ERDField;\n}\n"]}
1
+ {"version":3,"file":"erd-types.js","sourceRoot":"","sources":["../../../src/lib/interfaces/erd-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * Generic ERD Types for the Entity Relationship Diagram component.\n * These types are designed to be framework-agnostic and can work with any data source.\n */\n\n/**\n * Represents a field in an ERD node (entity).\n */\nexport interface ERDField {\n /** Unique identifier for the field */\n id: string;\n /** Display name of the field */\n name: string;\n /** Data type of the field (e.g., 'string', 'int', 'uuid') */\n type?: string;\n /** Whether this field is a primary key */\n isPrimaryKey: boolean;\n /** ID of the related node (for foreign keys) */\n relatedNodeId?: string;\n /** Name of the related node (for display purposes) */\n relatedNodeName?: string;\n /** Name of the field in the related node (for FK relationships) */\n relatedFieldName?: string;\n /** Optional description of the field */\n description?: string;\n /** Whether the field allows null values */\n allowsNull?: boolean;\n /** Default value for the field */\n defaultValue?: string;\n /** Maximum length (for string fields) */\n length?: number;\n /** Precision (for numeric fields) */\n precision?: number;\n /** Scale (for numeric fields) */\n scale?: number;\n /** Whether the field is virtual/computed */\n isVirtual?: boolean;\n /** Whether the field is auto-increment */\n autoIncrement?: boolean;\n /** Possible values for the field (for enums/dropdowns) */\n possibleValues?: ERDFieldValue[];\n /** Additional custom data */\n customData?: Record<string, unknown>;\n}\n\n/**\n * Represents a possible value for an ERD field (enum values, dropdown options, etc.)\n */\nexport interface ERDFieldValue {\n /** Unique identifier for the value */\n id?: string;\n /** The actual value */\n value: string;\n /** Code representation (may differ from value) */\n code?: string;\n /** Description of what this value means */\n description?: string;\n /** Sort order */\n sequence?: number;\n}\n\n/**\n * Represents a node (entity/table) in the ERD.\n */\nexport interface ERDNode {\n /** Unique identifier for the node */\n id: string;\n /** Display name of the node */\n name: string;\n /** Optional schema/namespace name */\n schemaName?: string;\n /** Optional description */\n description?: string;\n /** Status of the node (e.g., 'Active', 'Deprecated') */\n status?: string;\n /** Base table name (if different from display name) */\n baseTable?: string;\n /** All fields in this node */\n fields: ERDField[];\n /** Additional custom data that can be used by the consumer */\n customData?: Record<string, unknown>;\n}\n\n/**\n * Represents a link (relationship) between two nodes in the ERD.\n */\nexport interface ERDLink {\n /** ID of the source node */\n sourceNodeId: string;\n /** ID of the target node */\n targetNodeId: string;\n /** The field that creates this relationship (usually the FK field) */\n sourceField: ERDField;\n /** The field in the target node (usually the PK field) */\n targetField?: ERDField;\n /** Whether this is a self-referencing relationship */\n isSelfReference: boolean;\n /** Relationship type (e.g., 'one-to-many', 'many-to-one') */\n relationshipType?: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many';\n /** Optional label for the relationship */\n label?: string;\n}\n\n/**\n * Configuration options for the ERD diagram.\n */\nexport interface ERDConfig {\n /** Width of each node box in pixels */\n nodeWidth?: number;\n /** Base height of each node box in pixels */\n nodeBaseHeight?: number;\n /** Height per field in pixels */\n fieldHeight?: number;\n /** Maximum height of a node in pixels */\n maxNodeHeight?: number;\n /** Charge strength for force simulation (negative = repel) */\n chargeStrength?: number;\n /** Link distance for force simulation */\n linkDistance?: number;\n /** Collision radius padding */\n collisionPadding?: number;\n /** Whether to show field details in nodes (PK + FK rows). Defaults to true. */\n showFieldDetails?: boolean;\n /**\n * Whether to render all non-PK/non-FK fields as well. When true, every field on\n * each node is rendered (PKs first, FKs next, then all other fields in declaration\n * order). Use for \"table card\" style diagrams where users want to see every column.\n * Defaults to false (classic schema-relationship view: keys only).\n */\n showAllFields?: boolean;\n /** Whether to show relationship labels */\n showRelationshipLabels?: boolean;\n /** Whether to enable node dragging */\n enableDragging?: boolean;\n /** Whether to enable zoom/pan */\n enableZoom?: boolean;\n /** Initial zoom level */\n initialZoom?: number;\n /** Colors for different node states */\n colors?: ERDColorScheme;\n}\n\n/**\n * Color scheme for the ERD diagram.\n */\nexport interface ERDColorScheme {\n /** Background color for node rectangles */\n nodeBackground?: string;\n /** Border color for node rectangles */\n nodeBorder?: string;\n /** Header background color for nodes */\n nodeHeader?: string;\n /** Text color for node headers */\n nodeHeaderText?: string;\n /** Background color for primary key fields */\n primaryKeyBackground?: string;\n /** Text color for primary key fields */\n primaryKeyText?: string;\n /** Background color for foreign key fields */\n foreignKeyBackground?: string;\n /** Text color for foreign key fields */\n foreignKeyText?: string;\n /** Color for relationship links */\n linkColor?: string;\n /** Color for selected nodes */\n selectedBorder?: string;\n /** Color for highlighted nodes */\n highlightBorder?: string;\n /** Color for related nodes (when showing relationships) */\n relatedBorder?: string;\n}\n\n/**\n * Filter configuration for the ERD.\n */\nexport interface ERDFilter {\n /** Filter by schema name */\n schemaName?: string | null;\n /** Filter by node name (search) */\n nodeName?: string;\n /** Filter by node status */\n nodeStatus?: string | null;\n /** Filter by base table name (search) */\n baseTable?: string;\n /** Custom filter function */\n customFilter?: (node: ERDNode) => boolean;\n}\n\n/**\n * Event data for node selection events.\n */\nexport interface ERDNodeSelectionEvent {\n /** The selected node (null if deselected) */\n node: ERDNode | null;\n /** Previous selected node (null if none) */\n previousNode: ERDNode | null;\n /** Whether the consumer can cancel this selection */\n cancel: boolean;\n}\n\n/**\n * Event data for node click events.\n */\nexport interface ERDNodeClickEvent {\n /** The clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior (selection) */\n cancel: boolean;\n}\n\n/**\n * Event data for node double-click events.\n */\nexport interface ERDNodeDoubleClickEvent {\n /** The double-clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior */\n cancel: boolean;\n}\n\n/**\n * Event data for link click events.\n */\nexport interface ERDLinkClickEvent {\n /** The clicked link */\n link: ERDLink;\n /** Source node */\n sourceNode: ERDNode;\n /** Target node */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Whether to cancel default behavior */\n cancel: boolean;\n}\n\n/**\n * Event data for zoom change events.\n */\nexport interface ERDZoomEvent {\n /** Current zoom level */\n zoomLevel: number;\n /** X translation */\n translateX: number;\n /** Y translation */\n translateY: number;\n}\n\n/**\n * State of the ERD diagram for saving/restoring.\n * Use with `getState()` and `setState()` methods for persistence.\n *\n * @example\n * ```typescript\n * // Save state to localStorage\n * const state = erdComponent.getState();\n * localStorage.setItem('erd-state', JSON.stringify(state));\n *\n * // Restore state\n * const savedState = JSON.parse(localStorage.getItem('erd-state'));\n * erdComponent.setState(savedState);\n * ```\n */\nexport interface ERDState {\n /** ID of the currently selected node */\n selectedNodeId: string | null;\n /** IDs of highlighted nodes */\n highlightedNodeIds: string[];\n /** Current zoom level (1 = 100%) */\n zoomLevel: number;\n /** X translation (pan position) */\n translateX: number;\n /** Y translation (pan position) */\n translateY: number;\n /** Focus node ID (if in focus mode) */\n focusNodeId: string | null;\n /** Focus depth (number of relationship hops to show) */\n focusDepth: number;\n /** Node positions for restoring exact layout */\n nodePositions: Record<string, { x: number; y: number; fx?: number | null; fy?: number | null }>;\n /**\n * Active layout algorithm — persisted so a user's preferred view\n * (schema-grid vs. dagre hierarchical) survives navigation and\n * reloads. Defaults to 'schema-grid' when absent.\n */\n layoutAlgorithm?: 'schema-grid' | 'dagre';\n}\n\n/**\n * Event data for node hover events.\n * Emitted when the mouse enters a node.\n */\nexport interface ERDNodeHoverEvent {\n /** The hovered node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Nodes directly connected to this node via relationships */\n relatedNodes: ERDNode[];\n /** Position for displaying tooltips */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for link hover events.\n * Emitted when the mouse enters a relationship link.\n */\nexport interface ERDLinkHoverEvent {\n /** The hovered link */\n link: ERDLink;\n /** Source node of the relationship */\n sourceNode: ERDNode;\n /** Target node of the relationship */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Position for displaying tooltips */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on nodes.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDNodeContextMenuEvent {\n /** The right-clicked node */\n node: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on links.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDLinkContextMenuEvent {\n /** The right-clicked link */\n link: ERDLink;\n /** Source node */\n sourceNode: ERDNode;\n /** Target node */\n targetNode: ERDNode;\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n}\n\n/**\n * Event data for context menu events on the diagram background.\n * Set `cancel = true` to prevent default browser context menu.\n */\nexport interface ERDDiagramContextMenuEvent {\n /** The mouse event */\n mouseEvent: MouseEvent;\n /** Set to true to prevent default context menu */\n cancel: boolean;\n /** Screen position for showing custom context menu */\n position: { x: number; y: number };\n /** Diagram coordinates of the click */\n diagramPosition: { x: number; y: number };\n}\n\n/**\n * Event data for node drag events.\n * Set `cancel = true` in dragStart to prevent dragging.\n */\nexport interface ERDNodeDragEvent {\n /** The dragged node */\n node: ERDNode;\n /** Position when drag started */\n startPosition: { x: number; y: number };\n /** Current position during drag */\n currentPosition: { x: number; y: number };\n /** Set to true in dragStart to cancel the drag */\n cancel: boolean;\n}\n\n/**\n * Layout algorithm options for the ERD diagram.\n * - 'schema-grid': Schema-grouped rectangular bands with grid-tiled nodes (default, clean, predictable)\n * - 'force': Legacy D3 force-directed layout (dynamic, animated) — retained for compat\n * - 'dagre': Legacy Dagre hierarchical layout with orthogonal edges — retained for compat\n * - 'horizontal': Left-to-right hierarchical layout using Dagre — retained for compat\n * - 'vertical': Top-to-bottom hierarchical layout using Dagre — retained for compat\n * - 'radial': Radial layout (not yet implemented)\n */\nexport type ERDLayoutAlgorithm = 'schema-grid' | 'force' | 'dagre' | 'horizontal' | 'vertical' | 'radial';\n\n/**\n * Dagre-specific layout configuration options.\n */\nexport interface ERDDagreConfig {\n /** Direction of the graph layout. Default: 'LR' (left-to-right) */\n rankDir?: 'TB' | 'BT' | 'LR' | 'RL';\n /** Horizontal separation between nodes. Default: 50 */\n nodeSep?: number;\n /** Vertical separation between ranks/layers. Default: 100 */\n rankSep?: number;\n /** Separation between different edge paths. Default: 10 */\n edgeSep?: number;\n /** Algorithm for ranking nodes: 'network-simplex', 'tight-tree', 'longest-path'. Default: 'network-simplex' */\n ranker?: 'network-simplex' | 'tight-tree' | 'longest-path';\n /** Alignment of nodes within their rank: 'UL', 'UR', 'DL', 'DR'. Default: undefined (centered) */\n align?: 'UL' | 'UR' | 'DL' | 'DR';\n}\n\n/**\n * Extended configuration options for the ERD diagram.\n * All options are optional with sensible defaults.\n */\nexport interface ERDConfig {\n // ============================================================================\n // Node Sizing\n // ============================================================================\n\n /** Width of each node box in pixels. Default: 180 */\n nodeWidth?: number;\n /** Base height of each node box in pixels (before adding fields). Default: 60 */\n nodeBaseHeight?: number;\n /** Height per field row in pixels. Default: 20 */\n fieldHeight?: number;\n /** Maximum height of a node in pixels. Default: 300 */\n maxNodeHeight?: number;\n\n // ============================================================================\n // Force Simulation\n // ============================================================================\n\n /** Charge strength for force simulation (negative = repel). Default: -800 */\n chargeStrength?: number;\n /** Base distance between linked nodes. Default: 80 */\n linkDistance?: number;\n /** Extra padding for collision detection. Default: 20 */\n collisionPadding?: number;\n\n // ============================================================================\n // Display Options\n // ============================================================================\n\n /** Whether to show field details (PKs, FKs) in nodes. Default: true */\n showFieldDetails?: boolean;\n /** Whether to show relationship labels on links. Default: true */\n showRelationshipLabels?: boolean;\n /** Whether to show the header bar with controls. Default: true */\n showHeader?: boolean;\n /** Whether to show node count in header. Default: true */\n showNodeCount?: boolean;\n /** Whether to show a minimap for navigation. Default: false */\n showMinimap?: boolean;\n /** Whether to show a legend explaining colors. Default: false */\n showLegend?: boolean;\n\n // ============================================================================\n // Interaction Options\n // ============================================================================\n\n /** Enable node dragging. Default: true */\n enableDragging?: boolean;\n /** Enable zoom with mouse wheel. Default: true */\n enableZoom?: boolean;\n /** Enable panning by dragging background. Default: true */\n enablePan?: boolean;\n /** Minimum zoom level. Default: 0.1 */\n minZoom?: number;\n /** Maximum zoom level. Default: 4 */\n maxZoom?: number;\n /**\n * Maximum zoom level applied during fit-to-view. Default 2.5 — allows small\n * diagrams (e.g. Database Designer wizard preview with 1–3 entities) to scale\n * up enough to fill the pane without looking \"lost\", while still letting\n * manual zoom (wheel/pinch) go higher up to `maxZoom`.\n */\n maxFitZoom?: number;\n /** Initial zoom level (1 = 100%). Default: 1 */\n initialZoom?: number;\n /** Enable multi-select with Ctrl+click. Default: false */\n enableMultiSelect?: boolean;\n\n // ============================================================================\n // Animation\n // ============================================================================\n\n /** Duration of zoom/pan animations in milliseconds. Default: 750 */\n animationDuration?: number;\n /** Whether to auto-fit diagram to container on initial load. Default: true */\n fitOnLoad?: boolean;\n /**\n * Skip the D3 force simulation animation and render immediately.\n * When true, the simulation runs to completion synchronously and nodes\n * are positioned immediately without animation.\n * Default: false\n */\n skipAnimation?: boolean;\n\n // ============================================================================\n // Empty State\n // ============================================================================\n\n /** Message to show when no nodes are provided. Default: 'No entities to display' */\n emptyStateMessage?: string;\n /** Icon class for empty state. Default: 'fa-solid fa-diagram-project' */\n emptyStateIcon?: string;\n\n // ============================================================================\n // Layout\n // ============================================================================\n\n /** Layout algorithm to use. Default: 'schema-grid' */\n layoutAlgorithm?: ERDLayoutAlgorithm;\n\n /** Dagre-specific layout configuration (only used when layoutAlgorithm is 'dagre', 'horizontal', or 'vertical') */\n dagreConfig?: ERDDagreConfig;\n\n /** Draw rounded rectangular bands grouping nodes by schema. Default: true (schema-grid layout only) */\n showSchemaBands?: boolean;\n\n /** Draw crow's-foot markers at the source end of edges (many side). Default: true */\n crowsFoot?: boolean;\n\n /**\n * Max visible fields on a node before the \"+N more\" toggle kicks in.\n * Default: Infinity when `showAllFields` is true; when `showAllFields` is false,\n * only PK + FK fields are shown regardless of this value.\n */\n maxVisibleFields?: number;\n\n // ============================================================================\n // Colors\n // ============================================================================\n\n /** Color scheme for the diagram */\n colors?: ERDColorScheme;\n}\n\n/**\n * Information about a relationship for highlighting purposes.\n */\nexport interface ERDRelationshipInfo {\n /** The related node */\n node: ERDNode;\n /** The link connecting them */\n link: ERDLink;\n /** Direction of relationship from the perspective of the source node */\n direction: 'outgoing' | 'incoming';\n /** The field creating this relationship */\n field: ERDField;\n}\n"]}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Classic hierarchical (dagre) ERD layout — the "old school" option.
3
+ *
4
+ * Produces the same `ErdLayout` shape as `compute-erd-layout.ts` so the
5
+ * component's template and CSS render identical cards; only position
6
+ * (x / y) and edge routes differ. Schema bands are omitted in this mode
7
+ * — the whole point of the hierarchical layout is that the vertical/
8
+ * horizontal axis communicates relationship direction, not schema
9
+ * grouping.
10
+ *
11
+ * Implementation:
12
+ * 1. Measure every card using the same `fieldsForNode` logic the
13
+ * schema-grid uses, so card dimensions + visible fields match
14
+ * exactly.
15
+ * 2. Feed nodes + FK edges into dagre with `rankdir: 'LR'` (left-to-
16
+ * right hierarchy: sources on the left, leaves on the right).
17
+ * 3. Convert dagre's centred coords to top-left card coords.
18
+ * 4. Build orthogonal 3-segment edges (same router the schema-grid
19
+ * uses) so markers + hit targets match.
20
+ */
21
+ import type { ERDNode } from '../interfaces/erd-types';
22
+ import type { ErdLayout, ErdLayoutOptions } from './compute-erd-layout';
23
+ export interface DagreLayoutOptions extends ErdLayoutOptions {
24
+ /** Direction of the hierarchy. Default 'LR' (left-to-right). */
25
+ rankDir?: 'TB' | 'BT' | 'LR' | 'RL';
26
+ /** Horizontal separation between nodes in the same rank. Default 80. */
27
+ nodeSep?: number;
28
+ /** Separation between ranks. Default 120. */
29
+ rankSep?: number;
30
+ }
31
+ export declare function computeDagreLayout(nodes: ERDNode[], options?: DagreLayoutOptions): ErdLayout;
32
+ //# sourceMappingURL=compute-dagre-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-dagre-layout.d.ts","sourceRoot":"","sources":["../../../src/lib/layout/compute-dagre-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAA4B,MAAM,sBAAsB,CAAC;AAsBlG,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IACxD,gEAAgE;IAChE,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACpC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,SAAS,CAyEhG"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Classic hierarchical (dagre) ERD layout — the "old school" option.
3
+ *
4
+ * Produces the same `ErdLayout` shape as `compute-erd-layout.ts` so the
5
+ * component's template and CSS render identical cards; only position
6
+ * (x / y) and edge routes differ. Schema bands are omitted in this mode
7
+ * — the whole point of the hierarchical layout is that the vertical/
8
+ * horizontal axis communicates relationship direction, not schema
9
+ * grouping.
10
+ *
11
+ * Implementation:
12
+ * 1. Measure every card using the same `fieldsForNode` logic the
13
+ * schema-grid uses, so card dimensions + visible fields match
14
+ * exactly.
15
+ * 2. Feed nodes + FK edges into dagre with `rankdir: 'LR'` (left-to-
16
+ * right hierarchy: sources on the left, leaves on the right).
17
+ * 3. Convert dagre's centred coords to top-left card coords.
18
+ * 4. Build orthogonal 3-segment edges (same router the schema-grid
19
+ * uses) so markers + hit targets match.
20
+ */
21
+ import dagre from '@dagrejs/dagre';
22
+ // Mirrors the private helper in compute-erd-layout.ts — kept in sync so
23
+ // both layouts produce identical card dimensions for the same input.
24
+ function fieldsForNode(node, expanded, showAll, headerH, fieldH, moreH) {
25
+ const visibleFields = expanded || showAll
26
+ ? node.fields
27
+ : node.fields.filter(f => f.isPrimaryKey || !!f.relatedNodeId);
28
+ const hasMore = !expanded && !showAll && node.fields.length > visibleFields.length;
29
+ const rowCount = Math.max(visibleFields.length, 1);
30
+ const height = headerH + rowCount * fieldH + 8 + (hasMore ? moreH : 4);
31
+ return { visibleFields, height };
32
+ }
33
+ export function computeDagreLayout(nodes, options = {}) {
34
+ if (nodes.length === 0) {
35
+ return { nodes: [], edges: [], bands: [], totalWidth: 0, totalHeight: 0 };
36
+ }
37
+ const nodeW = options.nodeWidth ?? 220;
38
+ const headerH = options.headerHeight ?? 36;
39
+ const fieldH = options.fieldHeight ?? 22;
40
+ const moreH = options.moreToggleHeight ?? 22;
41
+ const canvasPad = options.canvasPad ?? 40;
42
+ const rankDir = options.rankDir ?? 'LR';
43
+ const nodeSep = options.nodeSep ?? 80;
44
+ const rankSep = options.rankSep ?? 120;
45
+ const expandedIds = options.expandedNodeIds ?? new Set();
46
+ const showAll = options.showAllFields ?? false;
47
+ const measured = nodes.map(n => {
48
+ const expanded = expandedIds.has(n.id) || showAll;
49
+ const { visibleFields, height } = fieldsForNode(n, expanded, showAll, headerH, fieldH, moreH);
50
+ return { node: n, visibleFields, height };
51
+ });
52
+ // Step 2: build dagre graph.
53
+ const g = new dagre.graphlib.Graph({ directed: true, multigraph: true });
54
+ g.setGraph({ rankdir: rankDir, nodesep: nodeSep, ranksep: rankSep, marginx: canvasPad, marginy: canvasPad });
55
+ g.setDefaultEdgeLabel(() => ({}));
56
+ for (const m of measured) {
57
+ g.setNode(m.node.id, { width: nodeW, height: m.height });
58
+ }
59
+ const visibleIds = new Set(measured.map(m => m.node.id));
60
+ for (const m of measured) {
61
+ for (const f of m.node.fields) {
62
+ if (!f.relatedNodeId || !visibleIds.has(f.relatedNodeId))
63
+ continue;
64
+ // Dagre doesn't love self-loops for ranking; skip — they're still
65
+ // rendered via the edge router below.
66
+ if (f.relatedNodeId === m.node.id)
67
+ continue;
68
+ g.setEdge(m.node.id, f.relatedNodeId, { fieldName: f.name }, `${m.node.id}--${f.name}--${f.relatedNodeId}`);
69
+ }
70
+ }
71
+ dagre.layout(g);
72
+ // Step 3: convert to LaidOutNode (top-left coords).
73
+ const laidOutNodes = measured.map(m => {
74
+ const { x: cx, y: cy } = g.node(m.node.id);
75
+ return {
76
+ ...m.node,
77
+ x: cx - nodeW / 2,
78
+ y: cy - m.height / 2,
79
+ width: nodeW,
80
+ height: m.height,
81
+ visibleFields: m.visibleFields,
82
+ hasMore: !showAll && !expandedIds.has(m.node.id) && m.node.fields.length > m.visibleFields.length,
83
+ };
84
+ });
85
+ // Step 4: build edges using the same orthogonal router schema-grid uses.
86
+ const edges = buildEdges(laidOutNodes, headerH, fieldH);
87
+ // Canvas size = graph bounds (dagre already accounted for margin).
88
+ const { width: totalWidth, height: totalHeight } = g.graph();
89
+ return {
90
+ nodes: laidOutNodes,
91
+ edges,
92
+ bands: [],
93
+ totalWidth: totalWidth || 0,
94
+ totalHeight: totalHeight || 0,
95
+ };
96
+ }
97
+ // ──────────────────────────────────────────────────────────────────────────
98
+ // Edge routing — same 3/5-segment router as the schema-grid layout. Kept
99
+ // as a local copy to avoid coupling the two files; the output shape of
100
+ // `LaidOutEdge` is the public contract.
101
+ // ──────────────────────────────────────────────────────────────────────────
102
+ function buildEdges(nodes, headerH, fieldH) {
103
+ const byId = new Map();
104
+ for (const n of nodes)
105
+ byId.set(n.id, n);
106
+ const edges = [];
107
+ for (const src of nodes) {
108
+ for (const f of src.fields) {
109
+ if (!f.relatedNodeId)
110
+ continue;
111
+ const tgt = byId.get(f.relatedNodeId);
112
+ if (!tgt)
113
+ continue;
114
+ const fieldIdx = src.visibleFields.findIndex(vf => vf.name === f.name);
115
+ const sourceY = fieldIdx >= 0
116
+ ? src.y + headerH + fieldIdx * fieldH + fieldH / 2
117
+ : src.y + src.height / 2;
118
+ edges.push(routeEdge({
119
+ id: `${src.id}--${f.name}--${tgt.id}`,
120
+ sourceId: src.id,
121
+ targetId: tgt.id,
122
+ sourceY,
123
+ sourceField: f,
124
+ src,
125
+ tgt,
126
+ }));
127
+ }
128
+ }
129
+ return edges;
130
+ }
131
+ function routeEdge(r) {
132
+ const { src, tgt, sourceY } = r;
133
+ const selfReference = src.id === tgt.id;
134
+ if (selfReference) {
135
+ const loopR = 18;
136
+ const sx = src.x + src.width;
137
+ const points = [
138
+ [sx, sourceY],
139
+ [sx + loopR, sourceY],
140
+ [sx + loopR, src.y - 10],
141
+ [src.x + src.width / 2, src.y - 10],
142
+ [src.x + src.width / 2, src.y],
143
+ ];
144
+ return {
145
+ id: r.id, sourceId: r.sourceId, targetId: r.targetId,
146
+ sourceY, sourceField: r.sourceField, points,
147
+ selfReference: true, goingRight: true,
148
+ };
149
+ }
150
+ const sCenterX = src.x + src.width / 2;
151
+ const tCenterX = tgt.x + tgt.width / 2;
152
+ const goingRight = tCenterX >= sCenterX;
153
+ const sx = goingRight ? src.x + src.width : src.x;
154
+ const tx = goingRight ? tgt.x : tgt.x + tgt.width;
155
+ const ty = tgt.y + 18;
156
+ const midX = goingRight
157
+ ? sx + Math.max(24, (tx - sx) / 2)
158
+ : sx - Math.max(24, (sx - tx) / 2);
159
+ const points = [
160
+ [sx, sourceY], [midX, sourceY], [midX, ty], [tx, ty],
161
+ ];
162
+ return {
163
+ id: r.id, sourceId: r.sourceId, targetId: r.targetId,
164
+ sourceY, sourceField: r.sourceField, points,
165
+ selfReference: false, goingRight,
166
+ };
167
+ }
168
+ //# sourceMappingURL=compute-dagre-layout.js.map