@ngx-km/graph 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,7 @@ Angular 19+ library for creating interactive graph visualizations with custom no
8
8
  - Automatic graph layout (hierarchical, force-directed, stress)
9
9
  - Obstacle-aware path routing between nodes
10
10
  - Infinite canvas with pan and zoom
11
+ - Animated viewport transitions with configurable easing
11
12
  - Draggable nodes with position tracking
12
13
  - Custom labels on paths (pill components)
13
14
  - Fully type-safe API
@@ -117,13 +118,13 @@ export class MyNodeComponent {
117
118
  @ViewChild(GraphComponent) graph!: GraphComponent;
118
119
 
119
120
  // Fit all content to viewport
120
- this.graph.fitToView(fitZoom?: boolean, padding?: number);
121
+ this.graph.fitToView(fitZoom?: boolean, padding?: number, options?: ViewportAnimationOptions);
121
122
 
122
123
  // Center viewport on a specific node
123
- this.graph.centerOnNode(nodeId: string);
124
+ this.graph.centerOnNode(nodeId: string, options?: ViewportAnimationOptions);
124
125
 
125
126
  // Scroll node into view with minimal pan
126
- this.graph.scrollToNode(nodeId: string, padding?: number);
127
+ this.graph.scrollToNode(nodeId: string, padding?: number, options?: ViewportAnimationOptions);
127
128
 
128
129
  // Check if node is visible in viewport
129
130
  this.graph.isNodeVisible(nodeId: string, padding?: number): boolean;
@@ -132,6 +133,66 @@ this.graph.isNodeVisible(nodeId: string, padding?: number): boolean;
132
133
  this.graph.recalculateLayout();
133
134
  ```
134
135
 
136
+ ### Animated Viewport Transitions
137
+
138
+ All viewport methods support smooth animated transitions:
139
+
140
+ ```typescript
141
+ import { ViewportAnimationOptions } from '@ngx-km/graph';
142
+
143
+ // Animate with default settings (300ms, ease-out)
144
+ this.graph.centerOnNode('node-1', { animated: true });
145
+
146
+ // Custom duration and easing
147
+ this.graph.fitToView(true, 40, {
148
+ animated: true,
149
+ duration: 500,
150
+ easing: 'ease-in-out',
151
+ });
152
+
153
+ // Instant (no animation)
154
+ this.graph.scrollToNode('node-2', 40, { animated: false });
155
+ ```
156
+
157
+ #### ViewportAnimationOptions
158
+
159
+ | Property | Type | Default | Description |
160
+ |----------|------|---------|-------------|
161
+ | `animated` | `boolean` | `false` | Enable animated transition |
162
+ | `duration` | `number` | `300` | Animation duration in milliseconds |
163
+ | `easing` | `EasingName \| EasingFunction` | `'ease-out'` | Easing function |
164
+
165
+ #### Built-in Easing Functions
166
+
167
+ | Name | Description |
168
+ |------|-------------|
169
+ | `'linear'` | Constant speed |
170
+ | `'ease-out'` | Fast start, slow end (default) |
171
+ | `'ease-in'` | Slow start, fast end |
172
+ | `'ease-in-out'` | Slow start and end |
173
+
174
+ #### Custom Easing Functions
175
+
176
+ You can provide a custom easing function:
177
+
178
+ ```typescript
179
+ // Custom bounce easing
180
+ this.graph.centerOnNode('node-1', {
181
+ animated: true,
182
+ duration: 600,
183
+ easing: (t: number) => {
184
+ const n1 = 7.5625;
185
+ const d1 = 2.75;
186
+ if (t < 1 / d1) return n1 * t * t;
187
+ if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;
188
+ if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;
189
+ return n1 * (t -= 2.625 / d1) * t + 0.984375;
190
+ },
191
+ });
192
+ ```
193
+
194
+ **Note:** Animations are automatically cancelled when the user starts panning or zooming.
195
+
135
196
  ## Interfaces
136
197
 
137
198
  ### GraphNode
@@ -153,13 +214,85 @@ interface GraphRelationship<T = unknown> {
153
214
  id: string; // Unique identifier
154
215
  sourceId: string; // Source node ID
155
216
  targetId: string; // Target node ID
156
- type?: 'one-way' | 'two-way'; // Arrow direction
217
+ type?: 'one-way' | 'two-way'; // Arrow direction (default: 'one-way')
157
218
  data?: T; // Data passed to pill component
158
219
  sourceAnchorSide?: 'top' | 'right' | 'bottom' | 'left';
159
220
  targetAnchorSide?: 'top' | 'right' | 'bottom' | 'left';
160
221
  }
161
222
  ```
162
223
 
224
+ ## Relationship Types
225
+
226
+ Relationships support two arrow modes:
227
+
228
+ | Type | Description | Visual |
229
+ |------|-------------|--------|
230
+ | `'one-way'` | Arrow on target end only (default) | A ───→ B |
231
+ | `'two-way'` | Arrows on both ends (bidirectional) | A ←──→ B |
232
+
233
+ ### One-Way Relationships (Default)
234
+
235
+ One-way relationships show a single arrow pointing from source to target. This is the default when `type` is omitted:
236
+
237
+ ```typescript
238
+ const relationships: GraphRelationship[] = [
239
+ // Explicit one-way
240
+ { id: 'e1', sourceId: 'A', targetId: 'B', type: 'one-way' },
241
+
242
+ // Implicit one-way (type defaults to 'one-way')
243
+ { id: 'e2', sourceId: 'B', targetId: 'C' },
244
+ ];
245
+ ```
246
+
247
+ ### Two-Way Relationships (Bidirectional)
248
+
249
+ Two-way relationships show arrows on both ends, indicating a bidirectional connection:
250
+
251
+ ```typescript
252
+ const relationships: GraphRelationship[] = [
253
+ // Bidirectional relationship
254
+ { id: 'e1', sourceId: 'A', targetId: 'B', type: 'two-way' },
255
+
256
+ // Mixed: some one-way, some two-way
257
+ { id: 'e2', sourceId: 'B', targetId: 'C', type: 'one-way' },
258
+ { id: 'e3', sourceId: 'C', targetId: 'D', type: 'two-way' },
259
+ ];
260
+ ```
261
+
262
+ ### Complete Example with Mixed Relationship Types
263
+
264
+ ```typescript
265
+ import { Component } from '@angular/core';
266
+ import { GraphComponent, GraphNode, GraphRelationship } from '@ngx-km/graph';
267
+ import { NodeComponent } from './node.component';
268
+
269
+ @Component({
270
+ selector: 'app-network',
271
+ standalone: true,
272
+ imports: [GraphComponent],
273
+ template: `
274
+ <ngx-graph [nodes]="nodes" [relationships]="relationships" />
275
+ `,
276
+ })
277
+ export class NetworkComponent {
278
+ nodes: GraphNode[] = [
279
+ { id: 'server', component: NodeComponent, data: { label: 'Server' } },
280
+ { id: 'client1', component: NodeComponent, data: { label: 'Client 1' } },
281
+ { id: 'client2', component: NodeComponent, data: { label: 'Client 2' } },
282
+ { id: 'database', component: NodeComponent, data: { label: 'Database' } },
283
+ ];
284
+
285
+ relationships: GraphRelationship[] = [
286
+ // Bidirectional: Server communicates both ways with clients
287
+ { id: 'r1', sourceId: 'server', targetId: 'client1', type: 'two-way' },
288
+ { id: 'r2', sourceId: 'server', targetId: 'client2', type: 'two-way' },
289
+
290
+ // One-way: Server writes to database
291
+ { id: 'r3', sourceId: 'server', targetId: 'database', type: 'one-way' },
292
+ ];
293
+ }
294
+ ```
295
+
163
296
  ## Configuration
164
297
 
165
298
  ### Full Configuration Example
@@ -213,6 +346,8 @@ const config: GraphConfig = {
213
346
  | `layered` | Hierarchical structures, flowcharts, org charts |
214
347
  | `force` | Networks, social graphs, unstructured data |
215
348
  | `stress` | General purpose, good edge length consistency |
349
+ | `radial` | Radial tree structures, centered hierarchies |
350
+ | `tree` | Simple tree structures, file systems |
216
351
 
217
352
  ### Path Types
218
353
 
@@ -1,7 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injector, viewChild, input, output, signal, computed, effect, Component } from '@angular/core';
3
- import { NgComponentOutlet } from '@angular/common';
4
3
  import { GridComponent } from '@ngx-km/grid';
4
+ export { DEFAULT_ANIMATION_DURATION, DEFAULT_EASING, EASING_FUNCTIONS } from '@ngx-km/grid';
5
+ import { NgComponentOutlet } from '@angular/common';
5
6
  import { LayoutService } from '@ngx-km/layout';
6
7
  import { PathFindingService } from '@ngx-km/path-finding';
7
8
 
@@ -36,12 +37,17 @@ const DEFAULT_GRAPH_PATH_CONFIG = {
36
37
  */
37
38
  const DEFAULT_GRAPH_LAYOUT_CONFIG = {
38
39
  algorithm: 'layered',
39
- direction: 'DOWN',
40
40
  nodeSpacing: 50,
41
- layerSpacing: 100,
42
41
  autoLayout: true,
43
42
  preservePositions: true,
44
43
  fitPadding: 40,
44
+ layered: {
45
+ direction: 'DOWN',
46
+ layerSpacing: 100,
47
+ },
48
+ tree: {
49
+ direction: 'DOWN',
50
+ },
45
51
  };
46
52
  /**
47
53
  * Default graph configuration
@@ -200,9 +206,10 @@ class GraphComponent {
200
206
  * Centers content in the viewport, optionally zooming out to fit everything
201
207
  * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)
202
208
  * @param padding Padding around content in pixels (default: 40)
209
+ * @param options Animation options
203
210
  */
204
- fitToView(fitZoom = false, padding = 40) {
205
- this.gridRef()?.fitToView(fitZoom, padding);
211
+ fitToView(fitZoom = false, padding = 40, options) {
212
+ this.gridRef()?.fitToView(fitZoom, padding, options);
206
213
  }
207
214
  /**
208
215
  * Check if a node is fully visible in the viewport
@@ -216,18 +223,20 @@ class GraphComponent {
216
223
  /**
217
224
  * Center viewport on a specific node (no zoom change)
218
225
  * @param nodeId The node ID to center on
226
+ * @param options Animation options
219
227
  */
220
- centerOnNode(nodeId) {
221
- this.gridRef()?.centerOnElement(nodeId);
228
+ centerOnNode(nodeId, options) {
229
+ this.gridRef()?.centerOnElement(nodeId, options);
222
230
  }
223
231
  /**
224
232
  * Scroll node into view with minimal pan
225
233
  * Only pans if node is not fully visible
226
234
  * @param nodeId The node ID to scroll into view
227
235
  * @param padding Padding from viewport edges (default: 40)
236
+ * @param options Animation options
228
237
  */
229
- scrollToNode(nodeId, padding = 40) {
230
- this.gridRef()?.scrollToElement(nodeId, padding);
238
+ scrollToNode(nodeId, padding = 40, options) {
239
+ this.gridRef()?.scrollToElement(nodeId, padding, options);
231
240
  }
232
241
  // Private methods
233
242
  async runLayout() {
@@ -249,6 +258,10 @@ class GraphComponent {
249
258
  id: rel.id,
250
259
  sourceId: rel.sourceId,
251
260
  targetId: rel.targetId,
261
+ type: rel.type === 'two-way' ? 'bidirectional' : 'directed',
262
+ // Pass algorithm-specific edge hints
263
+ layered: rel.layered,
264
+ force: rel.force,
252
265
  }));
253
266
  try {
254
267
  const result = await this.layoutService.calculateLayout({
@@ -256,9 +269,12 @@ class GraphComponent {
256
269
  edges: layoutEdges,
257
270
  options: {
258
271
  algorithm: layoutCfg.algorithm,
259
- direction: layoutCfg.direction,
260
272
  nodeSpacing: layoutCfg.nodeSpacing,
261
- layerSpacing: layoutCfg.layerSpacing,
273
+ layered: layoutCfg.layered,
274
+ tree: layoutCfg.tree,
275
+ force: layoutCfg.force,
276
+ stress: layoutCfg.stress,
277
+ radial: layoutCfg.radial,
262
278
  },
263
279
  });
264
280
  // Update all positions from layout result
@@ -324,6 +340,11 @@ class GraphComponent {
324
340
  this.calculatedPaths.set(result.paths);
325
341
  }
326
342
  // Path rendering helpers
343
+ /** Check if a relationship is two-way/bidirectional */
344
+ isTwoWay(relationshipId) {
345
+ const rel = this.relationships().find(r => r.id === relationshipId);
346
+ return rel?.type === 'two-way';
347
+ }
327
348
  getArrowPoints() {
328
349
  const size = this.pathConfig().arrowSize;
329
350
  return `0,0 ${size},${size / 2} 0,${size}`;
@@ -439,7 +460,7 @@ class GraphComponent {
439
460
  [attr.id]="'arrow-' + path.relationshipId"
440
461
  [attr.markerWidth]="pathConfig().arrowSize"
441
462
  [attr.markerHeight]="pathConfig().arrowSize"
442
- [attr.refX]="pathConfig().arrowSize"
463
+ [attr.refX]="pathConfig().arrowSize - 1"
443
464
  [attr.refY]="pathConfig().arrowSize / 2"
444
465
  orient="auto-start-reverse"
445
466
  markerUnits="userSpaceOnUse"
@@ -460,6 +481,7 @@ class GraphComponent {
460
481
  [attr.stroke-width]="pathConfig().strokeWidth"
461
482
  [attr.stroke-dasharray]="getStrokeDasharray()"
462
483
  [attr.marker-end]="'url(#arrow-' + path.relationshipId + ')'"
484
+ [attr.marker-start]="isTwoWay(path.relationshipId) ? 'url(#arrow-' + path.relationshipId + ')' : null"
463
485
  stroke-linecap="round"
464
486
  stroke-linejoin="round"
465
487
  />
@@ -508,7 +530,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
508
530
  [attr.id]="'arrow-' + path.relationshipId"
509
531
  [attr.markerWidth]="pathConfig().arrowSize"
510
532
  [attr.markerHeight]="pathConfig().arrowSize"
511
- [attr.refX]="pathConfig().arrowSize"
533
+ [attr.refX]="pathConfig().arrowSize - 1"
512
534
  [attr.refY]="pathConfig().arrowSize / 2"
513
535
  orient="auto-start-reverse"
514
536
  markerUnits="userSpaceOnUse"
@@ -529,6 +551,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
529
551
  [attr.stroke-width]="pathConfig().strokeWidth"
530
552
  [attr.stroke-dasharray]="getStrokeDasharray()"
531
553
  [attr.marker-end]="'url(#arrow-' + path.relationshipId + ')'"
554
+ [attr.marker-start]="isTwoWay(path.relationshipId) ? 'url(#arrow-' + path.relationshipId + ')' : null"
532
555
  stroke-linecap="round"
533
556
  stroke-linejoin="round"
534
557
  />
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-km-graph.mjs","sources":["../../../../libs/ngx-km-graph/src/lib/models/graph.models.ts","../../../../libs/ngx-km-graph/src/lib/components/graph.component.ts","../../../../libs/ngx-km-graph/src/index.ts","../../../../libs/ngx-km-graph/src/ngx-km-graph.ts"],"sourcesContent":["import { Type, InjectionToken, Signal } from '@angular/core';\nimport type { GridConfig } from '@ngx-km/grid';\nimport type { LayoutAlgorithm, LayoutDirection } from '@ngx-km/layout';\nimport type { PathType } from '@ngx-km/path-finding';\nimport type { StrokePattern, ArrowStyle, ArrowPosition } from '@ngx-km/path-drawing';\n\n/**\n * Injection token for accessing node data in dynamically rendered node components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRAPH_NODE_DATA = new InjectionToken<unknown>('GRAPH_NODE_DATA');\n\n/**\n * Injection token for accessing relationship data in dynamically rendered pill components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRAPH_RELATIONSHIP_DATA = new InjectionToken<unknown>('GRAPH_RELATIONSHIP_DATA');\n\n/**\n * Type alias for data that can be either a plain value or a Signal.\n * Use Signal<T> when you need the component to reactively update based on data changes.\n */\nexport type ReactiveData<T> = T | Signal<T>;\n\n// ============================================================================\n// Node Definitions\n// ============================================================================\n\n/**\n * Definition for a node in the graph\n * @template T Type of the data passed to the node component\n */\nexport interface GraphNode<T = unknown> {\n /** Unique identifier for this node */\n id: string;\n /** Angular component class to render for this node */\n component: Type<unknown>;\n /**\n * Data to pass to the node component via GRAPH_NODE_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** Optional initial X position (used when preservePositions is true) */\n x?: number;\n /** Optional initial Y position (used when preservePositions is true) */\n y?: number;\n}\n\n/**\n * Internal node representation with resolved position\n */\nexport interface GraphNodeInternal<T = unknown> extends GraphNode<T> {\n /** Resolved X position in world space */\n x: number;\n /** Resolved Y position in world space */\n y: number;\n /** Rendered width (tracked after render) */\n width?: number;\n /** Rendered height (tracked after render) */\n height?: number;\n}\n\n// ============================================================================\n// Relationship Definitions\n// ============================================================================\n\n/**\n * Type of relationship (affects path drawing)\n * - 'one-way': Arrow on target end only\n * - 'two-way': Arrows on both ends\n */\nexport type RelationshipType = 'one-way' | 'two-way';\n\n/**\n * Definition for a relationship (edge) between nodes\n * @template T Type of the data passed to the pill component\n */\nexport interface GraphRelationship<T = unknown> {\n /** Unique identifier for this relationship */\n id: string;\n /** ID of the source node */\n sourceId: string;\n /** ID of the target node */\n targetId: string;\n /** Type of relationship (default: 'one-way') */\n type?: RelationshipType;\n /**\n * Data to pass to the pill component via GRAPH_RELATIONSHIP_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** Optional: Force specific source anchor side */\n sourceAnchorSide?: 'top' | 'right' | 'bottom' | 'left';\n /** Optional: Force specific target anchor side */\n targetAnchorSide?: 'top' | 'right' | 'bottom' | 'left';\n}\n\n// ============================================================================\n// Path Configuration\n// ============================================================================\n\n/**\n * Configuration for path rendering\n */\nexport interface GraphPathConfig {\n /** Path routing type (default: 'orthogonal') */\n pathType?: PathType;\n /** Stroke color for paths (default: '#6366f1') */\n strokeColor?: string;\n /** Stroke width in pixels (default: 2) */\n strokeWidth?: number;\n /** Stroke pattern (default: 'solid') */\n strokePattern?: StrokePattern;\n /** Stroke opacity 0-1 (default: 1) */\n strokeOpacity?: number;\n /** Corner radius for orthogonal paths (default: 0) */\n cornerRadius?: number;\n /** Arrow head style (default: 'filled') */\n arrowStyle?: ArrowStyle;\n /** Arrow head size in pixels (default: 10) */\n arrowSize?: number;\n /** Padding around nodes for obstacle avoidance (default: 20) */\n obstaclePadding?: number;\n /** Spacing between connection points on same side (default: 15) */\n anchorSpacing?: number;\n /** Whether to spread multiple anchors on same side (default: true) */\n spreadAnchors?: boolean;\n}\n\n/**\n * Default path configuration\n */\nexport const DEFAULT_GRAPH_PATH_CONFIG: Required<GraphPathConfig> = {\n pathType: 'orthogonal',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n strokePattern: 'solid',\n strokeOpacity: 1,\n cornerRadius: 0,\n arrowStyle: 'filled',\n arrowSize: 10,\n obstaclePadding: 20,\n anchorSpacing: 15,\n spreadAnchors: true,\n};\n\n// ============================================================================\n// Layout Configuration\n// ============================================================================\n\n/**\n * Configuration for automatic layout\n */\nexport interface GraphLayoutConfig {\n /** Layout algorithm to use (default: 'layered') */\n algorithm?: LayoutAlgorithm;\n /** Layout direction (default: 'DOWN') */\n direction?: LayoutDirection;\n /** Spacing between nodes in pixels (default: 50) */\n nodeSpacing?: number;\n /** Spacing between layers in pixels (default: 100) */\n layerSpacing?: number;\n /** Whether to run layout automatically on init (default: true) */\n autoLayout?: boolean;\n /** Whether to preserve manually moved node positions on data update (default: true) */\n preservePositions?: boolean;\n /** Padding around content when fitting to view after layout (default: 40) */\n fitPadding?: number;\n}\n\n/**\n * Default layout configuration\n */\nexport const DEFAULT_GRAPH_LAYOUT_CONFIG: Required<GraphLayoutConfig> = {\n algorithm: 'layered',\n direction: 'DOWN',\n nodeSpacing: 50,\n layerSpacing: 100,\n autoLayout: true,\n preservePositions: true,\n fitPadding: 40,\n};\n\n// ============================================================================\n// Main Graph Configuration\n// ============================================================================\n\n/**\n * Main configuration for the graph component\n * Combines grid, layout, and path configurations\n */\nexport interface GraphConfig {\n /** Grid configuration (pan, zoom, background, etc.) */\n grid?: Partial<GridConfig>;\n /** Layout configuration (algorithm, spacing, etc.) */\n layout?: GraphLayoutConfig;\n /** Path rendering configuration (colors, arrows, etc.) */\n paths?: GraphPathConfig;\n /** Component to render at path midpoints (optional) */\n pillComponent?: Type<unknown>;\n}\n\n/**\n * Default graph configuration\n */\nexport const DEFAULT_GRAPH_CONFIG: GraphConfig = {\n grid: {\n dimensionMode: 'full',\n backgroundMode: 'dots',\n cellSize: 20,\n panEnabled: true,\n zoomEnabled: true,\n dragEnabled: true,\n },\n layout: DEFAULT_GRAPH_LAYOUT_CONFIG,\n paths: DEFAULT_GRAPH_PATH_CONFIG,\n};\n\n// ============================================================================\n// Events\n// ============================================================================\n\n/**\n * Event emitted when a node is selected\n */\nexport interface NodeSelectEvent<T = unknown> {\n /** The selected node */\n node: GraphNode<T>;\n}\n\n/**\n * Event emitted when a node position changes\n */\nexport interface NodePositionChangeEvent {\n /** Node ID */\n nodeId: string;\n /** New X position */\n x: number;\n /** New Y position */\n y: number;\n /** Previous X position */\n previousX: number;\n /** Previous Y position */\n previousY: number;\n}\n\n/**\n * Event emitted when a relationship is selected\n */\nexport interface RelationshipSelectEvent<T = unknown> {\n /** The selected relationship */\n relationship: GraphRelationship<T>;\n}\n","import {\n Component,\n input,\n output,\n computed,\n signal,\n effect,\n inject,\n Injector,\n viewChild,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport {\n GridComponent,\n GridConfig,\n GridElement,\n RenderedElement,\n ElementPositionChange,\n ViewportState,\n} from '@ngx-km/grid';\nimport { LayoutService, LayoutNode, LayoutEdge } from '@ngx-km/layout';\nimport {\n PathFindingService,\n PathNode,\n PathRelationship,\n CalculatedPath,\n PathFindingInput,\n} from '@ngx-km/path-finding';\nimport {\n GraphConfig,\n GraphNode,\n GraphRelationship,\n NodePositionChangeEvent,\n DEFAULT_GRAPH_CONFIG,\n DEFAULT_GRAPH_LAYOUT_CONFIG,\n DEFAULT_GRAPH_PATH_CONFIG,\n GRAPH_RELATIONSHIP_DATA,\n} from '../models/graph.models';\n\n/** Internal node with position */\ninterface InternalNode<T> {\n id: string;\n component: GraphNode<T>['component'];\n data: T | undefined;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n@Component({\n selector: 'ngx-graph',\n standalone: true,\n imports: [GridComponent, NgComponentOutlet],\n template: `\n <div class=\"graph-wrapper\" [class.layout-ready]=\"layoutReady()\">\n <ngx-grid\n #gridRef\n [config]=\"gridConfig()\"\n [elements]=\"gridElements()\"\n (viewportChange)=\"onViewportChange($event)\"\n (elementsRendered)=\"onElementsRendered($event)\"\n (elementPositionChange)=\"onElementPositionChange($event)\"\n />\n <!-- SVG layer for paths -->\n <svg\n class=\"paths-layer\"\n xmlns=\"http://www.w3.org/2000/svg\"\n [style.transform]=\"pathsTransform()\"\n >\n <defs>\n @for (path of calculatedPaths(); track path.relationshipId) {\n <marker\n [attr.id]=\"'arrow-' + path.relationshipId\"\n [attr.markerWidth]=\"pathConfig().arrowSize\"\n [attr.markerHeight]=\"pathConfig().arrowSize\"\n [attr.refX]=\"pathConfig().arrowSize\"\n [attr.refY]=\"pathConfig().arrowSize / 2\"\n orient=\"auto-start-reverse\"\n markerUnits=\"userSpaceOnUse\"\n >\n <polygon\n [attr.points]=\"getArrowPoints()\"\n [attr.fill]=\"pathConfig().strokeColor\"\n />\n </marker>\n }\n </defs>\n\n @for (path of calculatedPaths(); track path.relationshipId) {\n <path\n [attr.d]=\"getPathD(path)\"\n fill=\"none\"\n [attr.stroke]=\"pathConfig().strokeColor\"\n [attr.stroke-width]=\"pathConfig().strokeWidth\"\n [attr.stroke-dasharray]=\"getStrokeDasharray()\"\n [attr.marker-end]=\"'url(#arrow-' + path.relationshipId + ')'\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n }\n </svg>\n <!-- Pills layer - rendered at path midpoints -->\n @if (pillComponent()) {\n <div class=\"pills-layer\" [style.transform]=\"pathsTransform()\">\n @for (path of calculatedPaths(); track path.relationshipId) {\n <div\n class=\"pill-wrapper\"\n [style.left.px]=\"path.midpoint.x\"\n [style.top.px]=\"path.midpoint.y\"\n >\n <ng-container\n *ngComponentOutlet=\"pillComponent()!; injector: createPillInjector(path.relationshipId)\"\n />\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .graph-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n /* Hide nodes and paths until layout is ready to prevent flash */\n .graph-wrapper:not(.layout-ready) ::ng-deep .grid-viewport,\n .graph-wrapper:not(.layout-ready) .paths-layer,\n .graph-wrapper:not(.layout-ready) .pills-layer {\n opacity: 0;\n }\n .paths-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n transform-origin: 0 0;\n }\n .pills-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n transform-origin: 0 0;\n }\n .pill-wrapper {\n position: absolute;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n }\n `],\n})\nexport class GraphComponent<TNode = unknown, TRelationship = unknown> {\n private readonly layoutService = inject(LayoutService);\n private readonly pathFindingService = inject(PathFindingService);\n private readonly injector = inject(Injector);\n private readonly gridRef = viewChild<GridComponent>('gridRef');\n\n // Inputs\n nodes = input<GraphNode<TNode>[]>([]);\n relationships = input<GraphRelationship<TRelationship>[]>([]);\n config = input<GraphConfig>(DEFAULT_GRAPH_CONFIG);\n\n // Outputs\n nodePositionChange = output<NodePositionChangeEvent>();\n viewportChange = output<ViewportState>();\n\n // Internal state - single source of truth for positions\n private nodePositions = signal<Map<string, { x: number; y: number }>>(new Map());\n private nodeDimensions = signal<Map<string, { width: number; height: number }>>(new Map());\n private viewport = signal<ViewportState>({ x: 0, y: 0, zoom: 1 });\n calculatedPaths = signal<CalculatedPath[]>([]);\n\n /** Whether initial layout has completed - used to prevent flash of unstyled nodes */\n layoutReady = signal<boolean>(false);\n\n // Computed configs\n gridConfig = computed((): GridConfig => ({\n dimensionMode: 'full',\n backgroundMode: 'dots',\n cellSize: 20,\n panEnabled: true,\n zoomEnabled: true,\n dragEnabled: true,\n ...this.config().grid,\n }));\n\n layoutConfig = computed(() => ({\n ...DEFAULT_GRAPH_LAYOUT_CONFIG,\n ...this.config().layout,\n }));\n\n pathConfig = computed(() => ({\n ...DEFAULT_GRAPH_PATH_CONFIG,\n ...this.config().paths,\n }));\n\n /** Pill component to render at path midpoints */\n pillComponent = computed(() => this.config().pillComponent);\n\n // Grid elements - combines input nodes with their positions\n gridElements = computed((): GridElement<TNode>[] => {\n const inputNodes = this.nodes();\n const positions = this.nodePositions();\n\n return inputNodes.map((node, index) => {\n const pos = positions.get(node.id);\n // Default grid position if not set\n const cols = Math.ceil(Math.sqrt(inputNodes.length));\n const defaultX = (index % cols) * 200;\n const defaultY = Math.floor(index / cols) * 150;\n\n return {\n id: node.id,\n component: node.component,\n data: node.data,\n x: pos?.x ?? node.x ?? defaultX,\n y: pos?.y ?? node.y ?? defaultY,\n };\n });\n });\n\n pathsTransform = computed(() => {\n const vp = this.viewport();\n return `translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom})`;\n });\n\n constructor() {\n // Run initial layout when nodes change\n effect(() => {\n const inputNodes = this.nodes();\n const layoutCfg = this.layoutConfig();\n\n if (inputNodes.length === 0) {\n // No nodes - mark as ready immediately\n this.layoutReady.set(true);\n return;\n }\n\n if (!layoutCfg.autoLayout) {\n // Auto-layout disabled - show nodes at their provided positions immediately\n this.layoutReady.set(true);\n return;\n }\n\n // Check if we have positions for all nodes\n const positions = this.nodePositions();\n const needsLayout = inputNodes.some(n => !positions.has(n.id));\n\n if (needsLayout) {\n // Reset layoutReady when new nodes need positioning\n this.layoutReady.set(false);\n this.runLayout();\n }\n });\n\n // Recalculate paths when relationships or positions change\n effect(() => {\n const relationships = this.relationships();\n const positions = this.nodePositions();\n const dimensions = this.nodeDimensions();\n\n if (relationships.length > 0 && positions.size > 0) {\n this.calculatePaths();\n }\n });\n }\n\n // Event handlers\n onViewportChange(viewport: ViewportState): void {\n this.viewport.set(viewport);\n this.viewportChange.emit(viewport);\n }\n\n onElementsRendered(elements: RenderedElement[]): void {\n const dims = new Map(this.nodeDimensions());\n let changed = false;\n\n elements.forEach(el => {\n const existing = dims.get(el.id);\n if (!existing || existing.width !== el.width || existing.height !== el.height) {\n dims.set(el.id, { width: el.width, height: el.height });\n changed = true;\n }\n });\n\n if (changed) {\n this.nodeDimensions.set(dims);\n this.calculatePaths();\n }\n }\n\n onElementPositionChange(change: ElementPositionChange): void {\n // Update position\n const positions = new Map(this.nodePositions());\n positions.set(change.id, { x: change.x, y: change.y });\n this.nodePositions.set(positions);\n\n // Emit event\n this.nodePositionChange.emit({\n nodeId: change.id,\n x: change.x,\n y: change.y,\n previousX: change.previousX,\n previousY: change.previousY,\n });\n\n // Recalculate paths\n this.calculatePaths();\n }\n\n // Public method to force re-layout\n recalculateLayout(): void {\n this.runLayout();\n }\n\n /**\n * Fit all graph content to view\n * Centers content in the viewport, optionally zooming out to fit everything\n * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)\n * @param padding Padding around content in pixels (default: 40)\n */\n fitToView(fitZoom = false, padding = 40): void {\n this.gridRef()?.fitToView(fitZoom, padding);\n }\n\n /**\n * Check if a node is fully visible in the viewport\n * @param nodeId The node ID to check\n * @param padding Padding from viewport edges (default: 0)\n * @returns true if node is fully visible, false otherwise\n */\n isNodeVisible(nodeId: string, padding = 0): boolean {\n return this.gridRef()?.isElementVisible(nodeId, padding) ?? false;\n }\n\n /**\n * Center viewport on a specific node (no zoom change)\n * @param nodeId The node ID to center on\n */\n centerOnNode(nodeId: string): void {\n this.gridRef()?.centerOnElement(nodeId);\n }\n\n /**\n * Scroll node into view with minimal pan\n * Only pans if node is not fully visible\n * @param nodeId The node ID to scroll into view\n * @param padding Padding from viewport edges (default: 40)\n */\n scrollToNode(nodeId: string, padding = 40): void {\n this.gridRef()?.scrollToElement(nodeId, padding);\n }\n\n // Private methods\n private async runLayout(): Promise<void> {\n const inputNodes = this.nodes();\n const relationships = this.relationships();\n const layoutCfg = this.layoutConfig();\n const dimensions = this.nodeDimensions();\n\n if (inputNodes.length === 0) return;\n\n const layoutNodes: LayoutNode[] = inputNodes.map(node => {\n const dim = dimensions.get(node.id);\n return {\n id: node.id,\n width: dim?.width ?? 150,\n height: dim?.height ?? 80,\n };\n });\n\n const layoutEdges: LayoutEdge[] = relationships.map(rel => ({\n id: rel.id,\n sourceId: rel.sourceId,\n targetId: rel.targetId,\n }));\n\n try {\n const result = await this.layoutService.calculateLayout({\n nodes: layoutNodes,\n edges: layoutEdges,\n options: {\n algorithm: layoutCfg.algorithm,\n direction: layoutCfg.direction,\n nodeSpacing: layoutCfg.nodeSpacing,\n layerSpacing: layoutCfg.layerSpacing,\n },\n });\n\n // Update all positions from layout result\n const positions = new Map<string, { x: number; y: number }>();\n result.nodes.forEach(n => {\n positions.set(n.id, { x: n.x, y: n.y });\n });\n this.nodePositions.set(positions);\n\n // Recalculate paths\n this.calculatePaths();\n\n // Fit to view and then show nodes (use requestAnimationFrame to ensure DOM is updated)\n requestAnimationFrame(() => {\n this.fitToView(true, layoutCfg.fitPadding ?? 40);\n // Mark layout as ready after fit (shows nodes and paths)\n this.layoutReady.set(true);\n });\n } catch (error) {\n console.error('Layout calculation failed:', error);\n // Still mark as ready on error so user can see something\n this.layoutReady.set(true);\n }\n }\n\n private calculatePaths(): void {\n const inputNodes = this.nodes();\n const relationships = this.relationships();\n const positions = this.nodePositions();\n const dimensions = this.nodeDimensions();\n const pathCfg = this.pathConfig();\n\n if (inputNodes.length === 0 || relationships.length === 0) {\n this.calculatedPaths.set([]);\n return;\n }\n\n const pfNodes: PathNode[] = inputNodes.map(node => {\n const pos = positions.get(node.id);\n const dim = dimensions.get(node.id);\n return {\n id: node.id,\n x: pos?.x ?? 0,\n y: pos?.y ?? 0,\n width: dim?.width ?? 150,\n height: dim?.height ?? 80,\n };\n });\n\n const pfRelationships: PathRelationship[] = relationships.map(rel => ({\n id: rel.id,\n sourceId: rel.sourceId,\n targetId: rel.targetId,\n sourceAnchor: rel.sourceAnchorSide,\n targetAnchor: rel.targetAnchorSide,\n }));\n\n const input: PathFindingInput = {\n nodes: pfNodes,\n relationships: pfRelationships,\n options: {\n pathType: pathCfg.pathType,\n obstaclePadding: pathCfg.obstaclePadding,\n anchorSpacing: pathCfg.anchorSpacing,\n spreadAnchors: pathCfg.spreadAnchors,\n },\n };\n\n const result = this.pathFindingService.calculatePaths(input);\n this.calculatedPaths.set(result.paths);\n }\n\n // Path rendering helpers\n getArrowPoints(): string {\n const size = this.pathConfig().arrowSize;\n return `0,0 ${size},${size / 2} 0,${size}`;\n }\n\n getStrokeDasharray(): string {\n const pattern = this.pathConfig().strokePattern;\n switch (pattern) {\n case 'dashed': return '8,4';\n case 'dotted': return '2,4';\n default: return '';\n }\n }\n\n getPathD(path: CalculatedPath): string {\n const waypoints = path.waypoints;\n if (!waypoints || waypoints.length === 0) return '';\n\n const cfg = this.pathConfig();\n\n if (cfg.pathType === 'bezier') {\n return this.generateBezierPath(waypoints);\n } else if (cfg.pathType === 'straight') {\n return this.generateStraightPath(waypoints);\n } else {\n return this.generateOrthogonalPath(waypoints, cfg.cornerRadius);\n }\n }\n\n private generateOrthogonalPath(\n waypoints: { x: number; y: number; isControlPoint?: boolean }[],\n cornerRadius: number\n ): string {\n const points = waypoints.filter(w => !w.isControlPoint);\n if (points.length === 0) return '';\n\n if (cornerRadius === 0 || points.length < 3) {\n return points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ');\n }\n\n let path = `M ${points[0].x} ${points[0].y}`;\n\n for (let i = 1; i < points.length - 1; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n const next = points[i + 1];\n\n const dx1 = curr.x - prev.x;\n const dy1 = curr.y - prev.y;\n const dx2 = next.x - curr.x;\n const dy2 = next.y - curr.y;\n\n const dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);\n const dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);\n\n if (dist1 === 0 || dist2 === 0) {\n path += ` L ${curr.x} ${curr.y}`;\n continue;\n }\n\n const r = Math.min(cornerRadius, dist1 / 2, dist2 / 2);\n\n const startX = curr.x - (dx1 / dist1) * r;\n const startY = curr.y - (dy1 / dist1) * r;\n const endX = curr.x + (dx2 / dist2) * r;\n const endY = curr.y + (dy2 / dist2) * r;\n\n path += ` L ${startX} ${startY}`;\n path += ` Q ${curr.x} ${curr.y}, ${endX} ${endY}`;\n }\n\n const last = points[points.length - 1];\n path += ` L ${last.x} ${last.y}`;\n\n return path;\n }\n\n private generateBezierPath(waypoints: { x: number; y: number }[]): string {\n if (waypoints.length < 2) return '';\n if (waypoints.length === 4) {\n const [start, cp1, cp2, end] = waypoints;\n return `M ${start.x} ${start.y} C ${cp1.x} ${cp1.y}, ${cp2.x} ${cp2.y}, ${end.x} ${end.y}`;\n }\n if (waypoints.length === 3) {\n const [start, cp, end] = waypoints;\n return `M ${start.x} ${start.y} Q ${cp.x} ${cp.y}, ${end.x} ${end.y}`;\n }\n return this.generateStraightPath(waypoints);\n }\n\n private generateStraightPath(waypoints: { x: number; y: number }[]): string {\n if (waypoints.length < 2) return '';\n const start = waypoints[0];\n const end = waypoints[waypoints.length - 1];\n return `M ${start.x} ${start.y} L ${end.x} ${end.y}`;\n }\n\n // Pill rendering helpers\n\n /** Create an injector for a pill component, passing the relationship data */\n createPillInjector(relationshipId: string): Injector {\n const relationship = this.relationships().find(r => r.id === relationshipId);\n return Injector.create({\n providers: [\n { provide: GRAPH_RELATIONSHIP_DATA, useValue: relationship?.data },\n ],\n parent: this.injector,\n });\n }\n}\n","// Models - Types\nexport type {\n GraphNode,\n GraphNodeInternal,\n GraphRelationship,\n RelationshipType,\n ReactiveData,\n GraphPathConfig,\n GraphLayoutConfig,\n GraphConfig,\n NodeSelectEvent,\n NodePositionChangeEvent,\n RelationshipSelectEvent,\n} from './lib/models/graph.models';\n\n// Models - Values\nexport {\n GRAPH_NODE_DATA,\n GRAPH_RELATIONSHIP_DATA,\n DEFAULT_GRAPH_PATH_CONFIG,\n DEFAULT_GRAPH_LAYOUT_CONFIG,\n DEFAULT_GRAPH_CONFIG,\n} from './lib/models/graph.models';\n\n// Components\nexport { GraphComponent } from './lib/components/graph.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngx-km-graph.mjs","sources":["../../../../libs/ngx-km-graph/src/lib/models/graph.models.ts","../../../../libs/ngx-km-graph/src/lib/components/graph.component.ts","../../../../libs/ngx-km-graph/src/index.ts","../../../../libs/ngx-km-graph/src/ngx-km-graph.ts"],"sourcesContent":["import { Type, InjectionToken, Signal } from '@angular/core';\nimport type { GridConfig } from '@ngx-km/grid';\nimport type {\n LayoutAlgorithm,\n LayoutDirection,\n LayeredLayoutOptions,\n ForceLayoutOptions,\n StressLayoutOptions,\n RadialLayoutOptions,\n TreeLayoutOptions,\n LayeredEdgeHint,\n ForceEdgeHint,\n} from '@ngx-km/layout';\nimport type { PathType } from '@ngx-km/path-finding';\nimport type { StrokePattern, ArrowStyle, ArrowPosition } from '@ngx-km/path-drawing';\n\n/**\n * Injection token for accessing node data in dynamically rendered node components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRAPH_NODE_DATA = new InjectionToken<unknown>('GRAPH_NODE_DATA');\n\n/**\n * Injection token for accessing relationship data in dynamically rendered pill components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRAPH_RELATIONSHIP_DATA = new InjectionToken<unknown>('GRAPH_RELATIONSHIP_DATA');\n\n/**\n * Type alias for data that can be either a plain value or a Signal.\n * Use Signal<T> when you need the component to reactively update based on data changes.\n */\nexport type ReactiveData<T> = T | Signal<T>;\n\n// ============================================================================\n// Node Definitions\n// ============================================================================\n\n/**\n * Definition for a node in the graph\n * @template T Type of the data passed to the node component\n */\nexport interface GraphNode<T = unknown> {\n /** Unique identifier for this node */\n id: string;\n /** Angular component class to render for this node */\n component: Type<unknown>;\n /**\n * Data to pass to the node component via GRAPH_NODE_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** Optional initial X position (used when preservePositions is true) */\n x?: number;\n /** Optional initial Y position (used when preservePositions is true) */\n y?: number;\n}\n\n/**\n * Internal node representation with resolved position\n */\nexport interface GraphNodeInternal<T = unknown> extends GraphNode<T> {\n /** Resolved X position in world space */\n x: number;\n /** Resolved Y position in world space */\n y: number;\n /** Rendered width (tracked after render) */\n width?: number;\n /** Rendered height (tracked after render) */\n height?: number;\n}\n\n// ============================================================================\n// Relationship Definitions\n// ============================================================================\n\n/**\n * Type of relationship (affects path drawing)\n * - 'one-way': Arrow on target end only\n * - 'two-way': Arrows on both ends\n */\nexport type RelationshipType = 'one-way' | 'two-way';\n\n/**\n * Definition for a relationship (edge) between nodes\n * @template T Type of the data passed to the pill component\n */\nexport interface GraphRelationship<T = unknown> {\n /** Unique identifier for this relationship */\n id: string;\n /** ID of the source node */\n sourceId: string;\n /** ID of the target node */\n targetId: string;\n /** Type of relationship (default: 'one-way') */\n type?: RelationshipType;\n /**\n * Data to pass to the pill component via GRAPH_RELATIONSHIP_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** Optional: Force specific source anchor side */\n sourceAnchorSide?: 'top' | 'right' | 'bottom' | 'left';\n /** Optional: Force specific target anchor side */\n targetAnchorSide?: 'top' | 'right' | 'bottom' | 'left';\n\n // ---- Algorithm-specific layout hints ----\n\n /** Hints for layered layout algorithm (e.g., association for same-layer placement) */\n layered?: LayeredEdgeHint;\n /** Hints for force layout algorithm (e.g., edge strength, ideal length) */\n force?: ForceEdgeHint;\n}\n\n// ============================================================================\n// Path Configuration\n// ============================================================================\n\n/**\n * Configuration for path rendering\n */\nexport interface GraphPathConfig {\n /** Path routing type (default: 'orthogonal') */\n pathType?: PathType;\n /** Stroke color for paths (default: '#6366f1') */\n strokeColor?: string;\n /** Stroke width in pixels (default: 2) */\n strokeWidth?: number;\n /** Stroke pattern (default: 'solid') */\n strokePattern?: StrokePattern;\n /** Stroke opacity 0-1 (default: 1) */\n strokeOpacity?: number;\n /** Corner radius for orthogonal paths (default: 0) */\n cornerRadius?: number;\n /** Arrow head style (default: 'filled') */\n arrowStyle?: ArrowStyle;\n /** Arrow head size in pixels (default: 10) */\n arrowSize?: number;\n /** Padding around nodes for obstacle avoidance (default: 20) */\n obstaclePadding?: number;\n /** Spacing between connection points on same side (default: 15) */\n anchorSpacing?: number;\n /** Whether to spread multiple anchors on same side (default: true) */\n spreadAnchors?: boolean;\n}\n\n/**\n * Default path configuration\n */\nexport const DEFAULT_GRAPH_PATH_CONFIG: Required<GraphPathConfig> = {\n pathType: 'orthogonal',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n strokePattern: 'solid',\n strokeOpacity: 1,\n cornerRadius: 0,\n arrowStyle: 'filled',\n arrowSize: 10,\n obstaclePadding: 20,\n anchorSpacing: 15,\n spreadAnchors: true,\n};\n\n// ============================================================================\n// Layout Configuration\n// ============================================================================\n\n/**\n * Configuration for automatic layout\n */\nexport interface GraphLayoutConfig {\n /** Layout algorithm to use (default: 'layered') */\n algorithm?: LayoutAlgorithm;\n\n // ---- Common options ----\n\n /** Spacing between nodes in pixels (default: 50) */\n nodeSpacing?: number;\n /** Whether to run layout automatically on init (default: true) */\n autoLayout?: boolean;\n /** Whether to preserve manually moved node positions on data update (default: true) */\n preservePositions?: boolean;\n /** Padding around content when fitting to view after layout (default: 40) */\n fitPadding?: number;\n\n // ---- Algorithm-specific options ----\n\n /** Options for layered (hierarchical) layout */\n layered?: LayeredLayoutOptions;\n /** Options for force-directed layout */\n force?: ForceLayoutOptions;\n /** Options for stress layout */\n stress?: StressLayoutOptions;\n /** Options for radial layout */\n radial?: RadialLayoutOptions;\n /** Options for tree layout */\n tree?: TreeLayoutOptions;\n}\n\n/**\n * Default layout configuration\n */\nexport const DEFAULT_GRAPH_LAYOUT_CONFIG: GraphLayoutConfig = {\n algorithm: 'layered',\n nodeSpacing: 50,\n autoLayout: true,\n preservePositions: true,\n fitPadding: 40,\n layered: {\n direction: 'DOWN',\n layerSpacing: 100,\n },\n tree: {\n direction: 'DOWN',\n },\n};\n\n// ============================================================================\n// Main Graph Configuration\n// ============================================================================\n\n/**\n * Main configuration for the graph component\n * Combines grid, layout, and path configurations\n */\nexport interface GraphConfig {\n /** Grid configuration (pan, zoom, background, etc.) */\n grid?: Partial<GridConfig>;\n /** Layout configuration (algorithm, spacing, etc.) */\n layout?: GraphLayoutConfig;\n /** Path rendering configuration (colors, arrows, etc.) */\n paths?: GraphPathConfig;\n /** Component to render at path midpoints (optional) */\n pillComponent?: Type<unknown>;\n}\n\n/**\n * Default graph configuration\n */\nexport const DEFAULT_GRAPH_CONFIG: GraphConfig = {\n grid: {\n dimensionMode: 'full',\n backgroundMode: 'dots',\n cellSize: 20,\n panEnabled: true,\n zoomEnabled: true,\n dragEnabled: true,\n },\n layout: DEFAULT_GRAPH_LAYOUT_CONFIG,\n paths: DEFAULT_GRAPH_PATH_CONFIG,\n};\n\n// ============================================================================\n// Events\n// ============================================================================\n\n/**\n * Event emitted when a node is selected\n */\nexport interface NodeSelectEvent<T = unknown> {\n /** The selected node */\n node: GraphNode<T>;\n}\n\n/**\n * Event emitted when a node position changes\n */\nexport interface NodePositionChangeEvent {\n /** Node ID */\n nodeId: string;\n /** New X position */\n x: number;\n /** New Y position */\n y: number;\n /** Previous X position */\n previousX: number;\n /** Previous Y position */\n previousY: number;\n}\n\n/**\n * Event emitted when a relationship is selected\n */\nexport interface RelationshipSelectEvent<T = unknown> {\n /** The selected relationship */\n relationship: GraphRelationship<T>;\n}\n","import {\n Component,\n input,\n output,\n computed,\n signal,\n effect,\n inject,\n Injector,\n viewChild,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport {\n GridComponent,\n GridConfig,\n GridElement,\n RenderedElement,\n ElementPositionChange,\n ViewportState,\n ViewportAnimationOptions,\n} from '@ngx-km/grid';\nimport { LayoutService, LayoutNode, LayoutEdge } from '@ngx-km/layout';\nimport {\n PathFindingService,\n PathNode,\n PathRelationship,\n CalculatedPath,\n PathFindingInput,\n} from '@ngx-km/path-finding';\nimport {\n GraphConfig,\n GraphNode,\n GraphRelationship,\n NodePositionChangeEvent,\n DEFAULT_GRAPH_CONFIG,\n DEFAULT_GRAPH_LAYOUT_CONFIG,\n DEFAULT_GRAPH_PATH_CONFIG,\n GRAPH_RELATIONSHIP_DATA,\n} from '../models/graph.models';\n\n/** Internal node with position */\ninterface InternalNode<T> {\n id: string;\n component: GraphNode<T>['component'];\n data: T | undefined;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n@Component({\n selector: 'ngx-graph',\n standalone: true,\n imports: [GridComponent, NgComponentOutlet],\n template: `\n <div class=\"graph-wrapper\" [class.layout-ready]=\"layoutReady()\">\n <ngx-grid\n #gridRef\n [config]=\"gridConfig()\"\n [elements]=\"gridElements()\"\n (viewportChange)=\"onViewportChange($event)\"\n (elementsRendered)=\"onElementsRendered($event)\"\n (elementPositionChange)=\"onElementPositionChange($event)\"\n />\n <!-- SVG layer for paths -->\n <svg\n class=\"paths-layer\"\n xmlns=\"http://www.w3.org/2000/svg\"\n [style.transform]=\"pathsTransform()\"\n >\n <defs>\n @for (path of calculatedPaths(); track path.relationshipId) {\n <marker\n [attr.id]=\"'arrow-' + path.relationshipId\"\n [attr.markerWidth]=\"pathConfig().arrowSize\"\n [attr.markerHeight]=\"pathConfig().arrowSize\"\n [attr.refX]=\"pathConfig().arrowSize - 1\"\n [attr.refY]=\"pathConfig().arrowSize / 2\"\n orient=\"auto-start-reverse\"\n markerUnits=\"userSpaceOnUse\"\n >\n <polygon\n [attr.points]=\"getArrowPoints()\"\n [attr.fill]=\"pathConfig().strokeColor\"\n />\n </marker>\n }\n </defs>\n\n @for (path of calculatedPaths(); track path.relationshipId) {\n <path\n [attr.d]=\"getPathD(path)\"\n fill=\"none\"\n [attr.stroke]=\"pathConfig().strokeColor\"\n [attr.stroke-width]=\"pathConfig().strokeWidth\"\n [attr.stroke-dasharray]=\"getStrokeDasharray()\"\n [attr.marker-end]=\"'url(#arrow-' + path.relationshipId + ')'\"\n [attr.marker-start]=\"isTwoWay(path.relationshipId) ? 'url(#arrow-' + path.relationshipId + ')' : null\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n }\n </svg>\n <!-- Pills layer - rendered at path midpoints -->\n @if (pillComponent()) {\n <div class=\"pills-layer\" [style.transform]=\"pathsTransform()\">\n @for (path of calculatedPaths(); track path.relationshipId) {\n <div\n class=\"pill-wrapper\"\n [style.left.px]=\"path.midpoint.x\"\n [style.top.px]=\"path.midpoint.y\"\n >\n <ng-container\n *ngComponentOutlet=\"pillComponent()!; injector: createPillInjector(path.relationshipId)\"\n />\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .graph-wrapper {\n position: relative;\n width: 100%;\n height: 100%;\n }\n /* Hide nodes and paths until layout is ready to prevent flash */\n .graph-wrapper:not(.layout-ready) ::ng-deep .grid-viewport,\n .graph-wrapper:not(.layout-ready) .paths-layer,\n .graph-wrapper:not(.layout-ready) .pills-layer {\n opacity: 0;\n }\n .paths-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n transform-origin: 0 0;\n }\n .pills-layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow: visible;\n pointer-events: none;\n transform-origin: 0 0;\n }\n .pill-wrapper {\n position: absolute;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n }\n `],\n})\nexport class GraphComponent<TNode = unknown, TRelationship = unknown> {\n private readonly layoutService = inject(LayoutService);\n private readonly pathFindingService = inject(PathFindingService);\n private readonly injector = inject(Injector);\n private readonly gridRef = viewChild<GridComponent>('gridRef');\n\n // Inputs\n nodes = input<GraphNode<TNode>[]>([]);\n relationships = input<GraphRelationship<TRelationship>[]>([]);\n config = input<GraphConfig>(DEFAULT_GRAPH_CONFIG);\n\n // Outputs\n nodePositionChange = output<NodePositionChangeEvent>();\n viewportChange = output<ViewportState>();\n\n // Internal state - single source of truth for positions\n private nodePositions = signal<Map<string, { x: number; y: number }>>(new Map());\n private nodeDimensions = signal<Map<string, { width: number; height: number }>>(new Map());\n private viewport = signal<ViewportState>({ x: 0, y: 0, zoom: 1 });\n calculatedPaths = signal<CalculatedPath[]>([]);\n\n /** Whether initial layout has completed - used to prevent flash of unstyled nodes */\n layoutReady = signal<boolean>(false);\n\n // Computed configs\n gridConfig = computed((): GridConfig => ({\n dimensionMode: 'full',\n backgroundMode: 'dots',\n cellSize: 20,\n panEnabled: true,\n zoomEnabled: true,\n dragEnabled: true,\n ...this.config().grid,\n }));\n\n layoutConfig = computed(() => ({\n ...DEFAULT_GRAPH_LAYOUT_CONFIG,\n ...this.config().layout,\n }));\n\n pathConfig = computed(() => ({\n ...DEFAULT_GRAPH_PATH_CONFIG,\n ...this.config().paths,\n }));\n\n /** Pill component to render at path midpoints */\n pillComponent = computed(() => this.config().pillComponent);\n\n // Grid elements - combines input nodes with their positions\n gridElements = computed((): GridElement<TNode>[] => {\n const inputNodes = this.nodes();\n const positions = this.nodePositions();\n\n return inputNodes.map((node, index) => {\n const pos = positions.get(node.id);\n // Default grid position if not set\n const cols = Math.ceil(Math.sqrt(inputNodes.length));\n const defaultX = (index % cols) * 200;\n const defaultY = Math.floor(index / cols) * 150;\n\n return {\n id: node.id,\n component: node.component,\n data: node.data,\n x: pos?.x ?? node.x ?? defaultX,\n y: pos?.y ?? node.y ?? defaultY,\n };\n });\n });\n\n pathsTransform = computed(() => {\n const vp = this.viewport();\n return `translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom})`;\n });\n\n constructor() {\n // Run initial layout when nodes change\n effect(() => {\n const inputNodes = this.nodes();\n const layoutCfg = this.layoutConfig();\n\n if (inputNodes.length === 0) {\n // No nodes - mark as ready immediately\n this.layoutReady.set(true);\n return;\n }\n\n if (!layoutCfg.autoLayout) {\n // Auto-layout disabled - show nodes at their provided positions immediately\n this.layoutReady.set(true);\n return;\n }\n\n // Check if we have positions for all nodes\n const positions = this.nodePositions();\n const needsLayout = inputNodes.some(n => !positions.has(n.id));\n\n if (needsLayout) {\n // Reset layoutReady when new nodes need positioning\n this.layoutReady.set(false);\n this.runLayout();\n }\n });\n\n // Recalculate paths when relationships or positions change\n effect(() => {\n const relationships = this.relationships();\n const positions = this.nodePositions();\n const dimensions = this.nodeDimensions();\n\n if (relationships.length > 0 && positions.size > 0) {\n this.calculatePaths();\n }\n });\n }\n\n // Event handlers\n onViewportChange(viewport: ViewportState): void {\n this.viewport.set(viewport);\n this.viewportChange.emit(viewport);\n }\n\n onElementsRendered(elements: RenderedElement[]): void {\n const dims = new Map(this.nodeDimensions());\n let changed = false;\n\n elements.forEach(el => {\n const existing = dims.get(el.id);\n if (!existing || existing.width !== el.width || existing.height !== el.height) {\n dims.set(el.id, { width: el.width, height: el.height });\n changed = true;\n }\n });\n\n if (changed) {\n this.nodeDimensions.set(dims);\n this.calculatePaths();\n }\n }\n\n onElementPositionChange(change: ElementPositionChange): void {\n // Update position\n const positions = new Map(this.nodePositions());\n positions.set(change.id, { x: change.x, y: change.y });\n this.nodePositions.set(positions);\n\n // Emit event\n this.nodePositionChange.emit({\n nodeId: change.id,\n x: change.x,\n y: change.y,\n previousX: change.previousX,\n previousY: change.previousY,\n });\n\n // Recalculate paths\n this.calculatePaths();\n }\n\n // Public method to force re-layout\n recalculateLayout(): void {\n this.runLayout();\n }\n\n /**\n * Fit all graph content to view\n * Centers content in the viewport, optionally zooming out to fit everything\n * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)\n * @param padding Padding around content in pixels (default: 40)\n * @param options Animation options\n */\n fitToView(fitZoom = false, padding = 40, options?: ViewportAnimationOptions): void {\n this.gridRef()?.fitToView(fitZoom, padding, options);\n }\n\n /**\n * Check if a node is fully visible in the viewport\n * @param nodeId The node ID to check\n * @param padding Padding from viewport edges (default: 0)\n * @returns true if node is fully visible, false otherwise\n */\n isNodeVisible(nodeId: string, padding = 0): boolean {\n return this.gridRef()?.isElementVisible(nodeId, padding) ?? false;\n }\n\n /**\n * Center viewport on a specific node (no zoom change)\n * @param nodeId The node ID to center on\n * @param options Animation options\n */\n centerOnNode(nodeId: string, options?: ViewportAnimationOptions): void {\n this.gridRef()?.centerOnElement(nodeId, options);\n }\n\n /**\n * Scroll node into view with minimal pan\n * Only pans if node is not fully visible\n * @param nodeId The node ID to scroll into view\n * @param padding Padding from viewport edges (default: 40)\n * @param options Animation options\n */\n scrollToNode(nodeId: string, padding = 40, options?: ViewportAnimationOptions): void {\n this.gridRef()?.scrollToElement(nodeId, padding, options);\n }\n\n // Private methods\n private async runLayout(): Promise<void> {\n const inputNodes = this.nodes();\n const relationships = this.relationships();\n const layoutCfg = this.layoutConfig();\n const dimensions = this.nodeDimensions();\n\n if (inputNodes.length === 0) return;\n\n const layoutNodes: LayoutNode[] = inputNodes.map(node => {\n const dim = dimensions.get(node.id);\n return {\n id: node.id,\n width: dim?.width ?? 150,\n height: dim?.height ?? 80,\n };\n });\n\n const layoutEdges: LayoutEdge[] = relationships.map(rel => ({\n id: rel.id,\n sourceId: rel.sourceId,\n targetId: rel.targetId,\n type: rel.type === 'two-way' ? 'bidirectional' : 'directed',\n // Pass algorithm-specific edge hints\n layered: rel.layered,\n force: rel.force,\n }));\n\n try {\n const result = await this.layoutService.calculateLayout({\n nodes: layoutNodes,\n edges: layoutEdges,\n options: {\n algorithm: layoutCfg.algorithm,\n nodeSpacing: layoutCfg.nodeSpacing,\n layered: layoutCfg.layered,\n tree: layoutCfg.tree,\n force: layoutCfg.force,\n stress: layoutCfg.stress,\n radial: layoutCfg.radial,\n },\n });\n\n // Update all positions from layout result\n const positions = new Map<string, { x: number; y: number }>();\n result.nodes.forEach(n => {\n positions.set(n.id, { x: n.x, y: n.y });\n });\n this.nodePositions.set(positions);\n\n // Recalculate paths\n this.calculatePaths();\n\n // Fit to view and then show nodes (use requestAnimationFrame to ensure DOM is updated)\n requestAnimationFrame(() => {\n this.fitToView(true, layoutCfg.fitPadding ?? 40);\n // Mark layout as ready after fit (shows nodes and paths)\n this.layoutReady.set(true);\n });\n } catch (error) {\n console.error('Layout calculation failed:', error);\n // Still mark as ready on error so user can see something\n this.layoutReady.set(true);\n }\n }\n\n private calculatePaths(): void {\n const inputNodes = this.nodes();\n const relationships = this.relationships();\n const positions = this.nodePositions();\n const dimensions = this.nodeDimensions();\n const pathCfg = this.pathConfig();\n\n if (inputNodes.length === 0 || relationships.length === 0) {\n this.calculatedPaths.set([]);\n return;\n }\n\n const pfNodes: PathNode[] = inputNodes.map(node => {\n const pos = positions.get(node.id);\n const dim = dimensions.get(node.id);\n return {\n id: node.id,\n x: pos?.x ?? 0,\n y: pos?.y ?? 0,\n width: dim?.width ?? 150,\n height: dim?.height ?? 80,\n };\n });\n\n const pfRelationships: PathRelationship[] = relationships.map(rel => ({\n id: rel.id,\n sourceId: rel.sourceId,\n targetId: rel.targetId,\n sourceAnchor: rel.sourceAnchorSide,\n targetAnchor: rel.targetAnchorSide,\n }));\n\n const input: PathFindingInput = {\n nodes: pfNodes,\n relationships: pfRelationships,\n options: {\n pathType: pathCfg.pathType,\n obstaclePadding: pathCfg.obstaclePadding,\n anchorSpacing: pathCfg.anchorSpacing,\n spreadAnchors: pathCfg.spreadAnchors,\n },\n };\n\n const result = this.pathFindingService.calculatePaths(input);\n this.calculatedPaths.set(result.paths);\n }\n\n // Path rendering helpers\n /** Check if a relationship is two-way/bidirectional */\n isTwoWay(relationshipId: string): boolean {\n const rel = this.relationships().find(r => r.id === relationshipId);\n return rel?.type === 'two-way';\n }\n\n getArrowPoints(): string {\n const size = this.pathConfig().arrowSize;\n return `0,0 ${size},${size / 2} 0,${size}`;\n }\n\n getStrokeDasharray(): string {\n const pattern = this.pathConfig().strokePattern;\n switch (pattern) {\n case 'dashed': return '8,4';\n case 'dotted': return '2,4';\n default: return '';\n }\n }\n\n getPathD(path: CalculatedPath): string {\n const waypoints = path.waypoints;\n if (!waypoints || waypoints.length === 0) return '';\n\n const cfg = this.pathConfig();\n\n if (cfg.pathType === 'bezier') {\n return this.generateBezierPath(waypoints);\n } else if (cfg.pathType === 'straight') {\n return this.generateStraightPath(waypoints);\n } else {\n return this.generateOrthogonalPath(waypoints, cfg.cornerRadius);\n }\n }\n\n private generateOrthogonalPath(\n waypoints: { x: number; y: number; isControlPoint?: boolean }[],\n cornerRadius: number\n ): string {\n const points = waypoints.filter(w => !w.isControlPoint);\n if (points.length === 0) return '';\n\n if (cornerRadius === 0 || points.length < 3) {\n return points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ');\n }\n\n let path = `M ${points[0].x} ${points[0].y}`;\n\n for (let i = 1; i < points.length - 1; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n const next = points[i + 1];\n\n const dx1 = curr.x - prev.x;\n const dy1 = curr.y - prev.y;\n const dx2 = next.x - curr.x;\n const dy2 = next.y - curr.y;\n\n const dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);\n const dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);\n\n if (dist1 === 0 || dist2 === 0) {\n path += ` L ${curr.x} ${curr.y}`;\n continue;\n }\n\n const r = Math.min(cornerRadius, dist1 / 2, dist2 / 2);\n\n const startX = curr.x - (dx1 / dist1) * r;\n const startY = curr.y - (dy1 / dist1) * r;\n const endX = curr.x + (dx2 / dist2) * r;\n const endY = curr.y + (dy2 / dist2) * r;\n\n path += ` L ${startX} ${startY}`;\n path += ` Q ${curr.x} ${curr.y}, ${endX} ${endY}`;\n }\n\n const last = points[points.length - 1];\n path += ` L ${last.x} ${last.y}`;\n\n return path;\n }\n\n private generateBezierPath(waypoints: { x: number; y: number }[]): string {\n if (waypoints.length < 2) return '';\n if (waypoints.length === 4) {\n const [start, cp1, cp2, end] = waypoints;\n return `M ${start.x} ${start.y} C ${cp1.x} ${cp1.y}, ${cp2.x} ${cp2.y}, ${end.x} ${end.y}`;\n }\n if (waypoints.length === 3) {\n const [start, cp, end] = waypoints;\n return `M ${start.x} ${start.y} Q ${cp.x} ${cp.y}, ${end.x} ${end.y}`;\n }\n return this.generateStraightPath(waypoints);\n }\n\n private generateStraightPath(waypoints: { x: number; y: number }[]): string {\n if (waypoints.length < 2) return '';\n const start = waypoints[0];\n const end = waypoints[waypoints.length - 1];\n return `M ${start.x} ${start.y} L ${end.x} ${end.y}`;\n }\n\n // Pill rendering helpers\n\n /** Create an injector for a pill component, passing the relationship data */\n createPillInjector(relationshipId: string): Injector {\n const relationship = this.relationships().find(r => r.id === relationshipId);\n return Injector.create({\n providers: [\n { provide: GRAPH_RELATIONSHIP_DATA, useValue: relationship?.data },\n ],\n parent: this.injector,\n });\n }\n}\n","// Models - Types\nexport type {\n GraphNode,\n GraphNodeInternal,\n GraphRelationship,\n RelationshipType,\n ReactiveData,\n GraphPathConfig,\n GraphLayoutConfig,\n GraphConfig,\n NodeSelectEvent,\n NodePositionChangeEvent,\n RelationshipSelectEvent,\n} from './lib/models/graph.models';\n\n// Models - Values\nexport {\n GRAPH_NODE_DATA,\n GRAPH_RELATIONSHIP_DATA,\n DEFAULT_GRAPH_PATH_CONFIG,\n DEFAULT_GRAPH_LAYOUT_CONFIG,\n DEFAULT_GRAPH_CONFIG,\n} from './lib/models/graph.models';\n\n// Re-export animation types from grid for convenience\nexport type {\n ViewportAnimationOptions,\n EasingFunction,\n EasingName,\n} from '@ngx-km/grid';\nexport {\n EASING_FUNCTIONS,\n DEFAULT_ANIMATION_DURATION,\n DEFAULT_EASING,\n} from '@ngx-km/grid';\n\n// Re-export layout types for convenience\nexport type {\n LayoutAlgorithm,\n LayoutDirection,\n LayeredLayoutOptions,\n ForceLayoutOptions,\n StressLayoutOptions,\n RadialLayoutOptions,\n TreeLayoutOptions,\n LayeredEdgeType,\n LayeredEdgeHint,\n ForceEdgeHint,\n} from '@ngx-km/layout';\n\n// Components\nexport { GraphComponent } from './lib/components/graph.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { Type, Signal, InjectionToken, Injector } from '@angular/core';
3
- import { GridConfig, ViewportState, GridElement, RenderedElement, ElementPositionChange } from '@ngx-km/grid';
3
+ import { GridConfig, ViewportState, GridElement, RenderedElement, ElementPositionChange, ViewportAnimationOptions } from '@ngx-km/grid';
4
+ export { DEFAULT_ANIMATION_DURATION, DEFAULT_EASING, EASING_FUNCTIONS, EasingFunction, EasingName, ViewportAnimationOptions } from '@ngx-km/grid';
4
5
  import * as _ngx_km_layout from '@ngx-km/layout';
5
- import { LayoutAlgorithm, LayoutDirection } from '@ngx-km/layout';
6
+ import { LayeredEdgeHint, ForceEdgeHint, LayoutAlgorithm, LayeredLayoutOptions, ForceLayoutOptions, StressLayoutOptions, RadialLayoutOptions, TreeLayoutOptions } from '@ngx-km/layout';
7
+ export { ForceEdgeHint, ForceLayoutOptions, LayeredEdgeHint, LayeredEdgeType, LayeredLayoutOptions, LayoutAlgorithm, LayoutDirection, RadialLayoutOptions, StressLayoutOptions, TreeLayoutOptions } from '@ngx-km/layout';
6
8
  import * as _ngx_km_path_finding from '@ngx-km/path-finding';
7
9
  import { PathType, CalculatedPath } from '@ngx-km/path-finding';
8
10
  import * as _ngx_km_path_drawing from '@ngx-km/path-drawing';
@@ -85,6 +87,10 @@ interface GraphRelationship<T = unknown> {
85
87
  sourceAnchorSide?: 'top' | 'right' | 'bottom' | 'left';
86
88
  /** Optional: Force specific target anchor side */
87
89
  targetAnchorSide?: 'top' | 'right' | 'bottom' | 'left';
90
+ /** Hints for layered layout algorithm (e.g., association for same-layer placement) */
91
+ layered?: LayeredEdgeHint;
92
+ /** Hints for force layout algorithm (e.g., edge strength, ideal length) */
93
+ force?: ForceEdgeHint;
88
94
  }
89
95
  /**
90
96
  * Configuration for path rendering
@@ -123,23 +129,29 @@ declare const DEFAULT_GRAPH_PATH_CONFIG: Required<GraphPathConfig>;
123
129
  interface GraphLayoutConfig {
124
130
  /** Layout algorithm to use (default: 'layered') */
125
131
  algorithm?: LayoutAlgorithm;
126
- /** Layout direction (default: 'DOWN') */
127
- direction?: LayoutDirection;
128
132
  /** Spacing between nodes in pixels (default: 50) */
129
133
  nodeSpacing?: number;
130
- /** Spacing between layers in pixels (default: 100) */
131
- layerSpacing?: number;
132
134
  /** Whether to run layout automatically on init (default: true) */
133
135
  autoLayout?: boolean;
134
136
  /** Whether to preserve manually moved node positions on data update (default: true) */
135
137
  preservePositions?: boolean;
136
138
  /** Padding around content when fitting to view after layout (default: 40) */
137
139
  fitPadding?: number;
140
+ /** Options for layered (hierarchical) layout */
141
+ layered?: LayeredLayoutOptions;
142
+ /** Options for force-directed layout */
143
+ force?: ForceLayoutOptions;
144
+ /** Options for stress layout */
145
+ stress?: StressLayoutOptions;
146
+ /** Options for radial layout */
147
+ radial?: RadialLayoutOptions;
148
+ /** Options for tree layout */
149
+ tree?: TreeLayoutOptions;
138
150
  }
139
151
  /**
140
152
  * Default layout configuration
141
153
  */
142
- declare const DEFAULT_GRAPH_LAYOUT_CONFIG: Required<GraphLayoutConfig>;
154
+ declare const DEFAULT_GRAPH_LAYOUT_CONFIG: GraphLayoutConfig;
143
155
  /**
144
156
  * Main configuration for the graph component
145
157
  * Combines grid, layout, and path configurations
@@ -206,13 +218,16 @@ declare class GraphComponent<TNode = unknown, TRelationship = unknown> {
206
218
  layoutReady: _angular_core.WritableSignal<boolean>;
207
219
  gridConfig: _angular_core.Signal<GridConfig>;
208
220
  layoutConfig: _angular_core.Signal<{
209
- algorithm: _ngx_km_layout.LayoutAlgorithm;
210
- direction: _ngx_km_layout.LayoutDirection;
211
- nodeSpacing: number;
212
- layerSpacing: number;
213
- autoLayout: boolean;
214
- preservePositions: boolean;
215
- fitPadding: number;
221
+ algorithm?: _ngx_km_layout.LayoutAlgorithm;
222
+ nodeSpacing?: number;
223
+ autoLayout?: boolean;
224
+ preservePositions?: boolean;
225
+ fitPadding?: number;
226
+ layered?: _ngx_km_layout.LayeredLayoutOptions;
227
+ force?: _ngx_km_layout.ForceLayoutOptions;
228
+ stress?: _ngx_km_layout.StressLayoutOptions;
229
+ radial?: _ngx_km_layout.RadialLayoutOptions;
230
+ tree?: _ngx_km_layout.TreeLayoutOptions;
216
231
  }>;
217
232
  pathConfig: _angular_core.Signal<{
218
233
  pathType: _ngx_km_path_finding.PathType;
@@ -241,8 +256,9 @@ declare class GraphComponent<TNode = unknown, TRelationship = unknown> {
241
256
  * Centers content in the viewport, optionally zooming out to fit everything
242
257
  * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)
243
258
  * @param padding Padding around content in pixels (default: 40)
259
+ * @param options Animation options
244
260
  */
245
- fitToView(fitZoom?: boolean, padding?: number): void;
261
+ fitToView(fitZoom?: boolean, padding?: number, options?: ViewportAnimationOptions): void;
246
262
  /**
247
263
  * Check if a node is fully visible in the viewport
248
264
  * @param nodeId The node ID to check
@@ -253,17 +269,21 @@ declare class GraphComponent<TNode = unknown, TRelationship = unknown> {
253
269
  /**
254
270
  * Center viewport on a specific node (no zoom change)
255
271
  * @param nodeId The node ID to center on
272
+ * @param options Animation options
256
273
  */
257
- centerOnNode(nodeId: string): void;
274
+ centerOnNode(nodeId: string, options?: ViewportAnimationOptions): void;
258
275
  /**
259
276
  * Scroll node into view with minimal pan
260
277
  * Only pans if node is not fully visible
261
278
  * @param nodeId The node ID to scroll into view
262
279
  * @param padding Padding from viewport edges (default: 40)
280
+ * @param options Animation options
263
281
  */
264
- scrollToNode(nodeId: string, padding?: number): void;
282
+ scrollToNode(nodeId: string, padding?: number, options?: ViewportAnimationOptions): void;
265
283
  private runLayout;
266
284
  private calculatePaths;
285
+ /** Check if a relationship is two-way/bidirectional */
286
+ isTwoWay(relationshipId: string): boolean;
267
287
  getArrowPoints(): string;
268
288
  getStrokeDasharray(): string;
269
289
  getPathD(path: CalculatedPath): string;
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@ngx-km/graph",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "dependencies": {
5
- "@ngx-km/grid": "^0.0.2",
6
- "@ngx-km/layout": "^0.0.2",
5
+ "@ngx-km/grid": "^0.0.3",
6
+ "@ngx-km/layout": "^0.0.3",
7
7
  "@ngx-km/path-finding": "^0.0.2",
8
8
  "@ngx-km/path-drawing": "^0.0.2",
9
9
  "tslib": "^2.3.0"