ngx-vflow 1.9.0 → 1.10.1

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 (32) hide show
  1. package/esm2022/lib/vflow/components/connection/connection.component.mjs +33 -13
  2. package/esm2022/lib/vflow/components/edge/edge.component.mjs +3 -3
  3. package/esm2022/lib/vflow/components/node/node.component.mjs +3 -3
  4. package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +8 -10
  5. package/esm2022/lib/vflow/directives/selectable.directive.mjs +3 -3
  6. package/esm2022/lib/vflow/interfaces/curve-factory.interface.mjs +2 -0
  7. package/esm2022/lib/vflow/interfaces/edge.interface.mjs +1 -1
  8. package/esm2022/lib/vflow/math/edge-path/bezier-path.mjs +12 -14
  9. package/esm2022/lib/vflow/math/edge-path/smooth-step-path.mjs +5 -5
  10. package/esm2022/lib/vflow/math/edge-path/straigh-path.mjs +7 -9
  11. package/esm2022/lib/vflow/models/edge.model.mjs +24 -8
  12. package/esm2022/lib/vflow/services/flow-entities.service.mjs +3 -1
  13. package/esm2022/lib/vflow/services/node-rendering.service.mjs +2 -2
  14. package/esm2022/public-api.mjs +2 -1
  15. package/fesm2022/ngx-vflow.mjs +89 -297
  16. package/fesm2022/ngx-vflow.mjs.map +1 -1
  17. package/lib/vflow/components/connection/connection.component.d.ts +4 -2
  18. package/lib/vflow/interfaces/curve-factory.interface.d.ts +44 -0
  19. package/lib/vflow/interfaces/edge.interface.d.ts +2 -1
  20. package/lib/vflow/math/edge-path/bezier-path.d.ts +2 -5
  21. package/lib/vflow/math/edge-path/smooth-step-path.d.ts +2 -3
  22. package/lib/vflow/math/edge-path/straigh-path.d.ts +2 -4
  23. package/lib/vflow/models/edge.model.d.ts +6 -4
  24. package/lib/vflow/services/flow-entities.service.d.ts +3 -0
  25. package/package.json +1 -1
  26. package/public-api.d.ts +1 -0
  27. package/esm2022/lib/vflow/directives/lazy-for.directive.mjs +0 -243
  28. package/esm2022/lib/vflow/interfaces/path-data.interface.mjs +0 -2
  29. package/esm2022/lib/vflow/types/using-points.type.mjs +0 -2
  30. package/lib/vflow/directives/lazy-for.directive.d.ts +0 -94
  31. package/lib/vflow/interfaces/path-data.interface.d.ts +0 -8
  32. package/lib/vflow/types/using-points.type.d.ts +0 -5
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, output, HostListener, Injector, runInInjectionContext, isDevMode, ViewContainerRef, IterableDiffers, ChangeDetectorRef, Input, contentChild, forwardRef } from '@angular/core';
2
+ import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, output, HostListener, Injector, runInInjectionContext, contentChild, Input, forwardRef } from '@angular/core';
3
3
  import { select } from 'd3-selection';
4
4
  import { zoomIdentity, zoom } from 'd3-zoom';
5
- import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith, from, bufferCount, concatMap, of, delayWhen, animationFrames, take, takeUntil, finalize } from 'rxjs';
5
+ import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith } from 'rxjs';
6
6
  import { toObservable, takeUntilDestroyed, outputFromObservable, toSignal } from '@angular/core/rxjs-interop';
7
7
  import { drag } from 'd3-drag';
8
8
  import { __decorate } from 'tslib';
@@ -117,10 +117,12 @@ class FlowEntitiesService {
117
117
  // empty arrays considered equal, other arrays may not be equal
118
118
  equal: (a, b) => (!a.length && !b.length ? true : a === b),
119
119
  });
120
+ this.rawNodes = computed(() => this.nodes().map((n) => n.rawNode));
120
121
  this.edges = signal([], {
121
122
  // empty arrays considered equal, other arrays may not be equal
122
123
  equal: (a, b) => (!a.length && !b.length ? true : a === b),
123
124
  });
125
+ this.rawEdges = computed(() => this.edges().map((e) => e.edge));
124
126
  this.validEdges = computed(() => {
125
127
  const nodes = this.nodes();
126
128
  return this.edges().filter((e) => nodes.includes(e.source()) && nodes.includes(e.target()));
@@ -1097,25 +1099,23 @@ function getPointOnLineByRatio(start, end, ratio) {
1097
1099
  };
1098
1100
  }
1099
1101
 
1100
- function straightPath(source, target, usingPoints = [false, false, false]) {
1101
- const [start, center, end] = usingPoints;
1102
- const nullPoint = { x: 0, y: 0 };
1102
+ function straightPath({ sourcePoint, targetPoint }) {
1103
1103
  return {
1104
- path: `M ${source.x},${source.y}L ${target.x},${target.y}`,
1105
- points: {
1106
- start: start ? getPointOnLineByRatio(source, target, 0.15) : nullPoint,
1107
- center: center ? getPointOnLineByRatio(source, target, 0.5) : nullPoint,
1108
- end: end ? getPointOnLineByRatio(source, target, 0.85) : nullPoint,
1104
+ path: `M ${sourcePoint.x},${sourcePoint.y}L ${targetPoint.x},${targetPoint.y}`,
1105
+ labelPoints: {
1106
+ start: getPointOnLineByRatio(sourcePoint, targetPoint, 0.15),
1107
+ center: getPointOnLineByRatio(sourcePoint, targetPoint, 0.5),
1108
+ end: getPointOnLineByRatio(sourcePoint, targetPoint, 0.85),
1109
1109
  },
1110
1110
  };
1111
1111
  }
1112
1112
 
1113
- function bezierPath(source, target, sourcePosition, targetPosition, usingPoints = [false, false, false]) {
1114
- const distanceVector = { x: source.x - target.x, y: source.y - target.y };
1115
- const sourceControl = calcControlPoint(source, sourcePosition, distanceVector);
1116
- const targetControl = calcControlPoint(target, targetPosition, distanceVector);
1117
- const path = `M${source.x},${source.y} C${sourceControl.x},${sourceControl.y} ${targetControl.x},${targetControl.y} ${target.x},${target.y}`;
1118
- return getPathData(path, source, target, sourceControl, targetControl, usingPoints);
1113
+ function bezierPath({ sourcePoint, targetPoint, sourcePosition, targetPosition, }) {
1114
+ const distanceVector = { x: sourcePoint.x - targetPoint.x, y: sourcePoint.y - targetPoint.y };
1115
+ const sourceControl = calcControlPoint(sourcePoint, sourcePosition, distanceVector);
1116
+ const targetControl = calcControlPoint(targetPoint, targetPosition, distanceVector);
1117
+ const path = `M${sourcePoint.x},${sourcePoint.y} C${sourceControl.x},${sourceControl.y} ${targetControl.x},${targetControl.y} ${targetPoint.x},${targetPoint.y}`;
1118
+ return getPathData(path, sourcePoint, targetPoint, sourceControl, targetControl);
1119
1119
  }
1120
1120
  /**
1121
1121
  * Calculate control point based on provided point
@@ -1155,15 +1155,13 @@ function calcControlPoint(point, pointPosition, distanceVector) {
1155
1155
  y: point.y - factorPoint.y * controlOffset,
1156
1156
  };
1157
1157
  }
1158
- function getPathData(path, source, target, sourceControl, targetControl, usingPoints) {
1159
- const [start, center, end] = usingPoints;
1160
- const nullPoint = { x: 0, y: 0 };
1158
+ function getPathData(path, source, target, sourceControl, targetControl) {
1161
1159
  return {
1162
1160
  path,
1163
- points: {
1164
- start: start ? getPointOnBezier(source, target, sourceControl, targetControl, 0.1) : nullPoint,
1165
- center: center ? getPointOnBezier(source, target, sourceControl, targetControl, 0.5) : nullPoint,
1166
- end: end ? getPointOnBezier(source, target, sourceControl, targetControl, 0.9) : nullPoint,
1161
+ labelPoints: {
1162
+ start: getPointOnBezier(source, target, sourceControl, targetControl, 0.1),
1163
+ center: getPointOnBezier(source, target, sourceControl, targetControl, 0.5),
1164
+ end: getPointOnBezier(source, target, sourceControl, targetControl, 0.9),
1167
1165
  },
1168
1166
  };
1169
1167
  }
@@ -1317,11 +1315,11 @@ function getBend(a, b, c, size) {
1317
1315
  const yDir = a.y < c.y ? -1 : 1;
1318
1316
  return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
1319
1317
  }
1320
- function smoothStepPath(source, target, sourcePosition, targetPosition, borderRadius = 5) {
1318
+ function smoothStepPath({ sourcePoint, targetPoint, sourcePosition, targetPosition }, borderRadius = 5) {
1321
1319
  const [points, labelX, labelY] = getPoints({
1322
- source,
1320
+ source: sourcePoint,
1323
1321
  sourcePosition,
1324
- target,
1322
+ target: targetPoint,
1325
1323
  targetPosition,
1326
1324
  offset: 20,
1327
1325
  });
@@ -1338,7 +1336,7 @@ function smoothStepPath(source, target, sourcePosition, targetPosition, borderRa
1338
1336
  }, '');
1339
1337
  return {
1340
1338
  path,
1341
- points: {
1339
+ labelPoints: {
1342
1340
  // TODO start and end points temporary unavailable for this path
1343
1341
  start: { x: labelX, y: labelY },
1344
1342
  center: { x: labelX, y: labelY },
@@ -1350,6 +1348,7 @@ function smoothStepPath(source, target, sourcePosition, targetPosition, borderRa
1350
1348
  class EdgeModel {
1351
1349
  constructor(edge) {
1352
1350
  this.edge = edge;
1351
+ this.flowEntitiesService = inject(FlowEntitiesService);
1353
1352
  this.source = signal(undefined);
1354
1353
  this.target = signal(undefined);
1355
1354
  this.selected = signal(false);
@@ -1385,22 +1384,25 @@ class EdgeModel {
1385
1384
  if (!source || !target) {
1386
1385
  return {
1387
1386
  path: '',
1388
- points: {
1387
+ labelPoints: {
1389
1388
  start: { x: 0, y: 0 },
1390
1389
  center: { x: 0, y: 0 },
1391
1390
  end: { x: 0, y: 0 },
1392
1391
  },
1393
1392
  };
1394
1393
  }
1394
+ const params = this.getPathFactoryParams(source, target);
1395
1395
  switch (this.curve) {
1396
1396
  case 'straight':
1397
- return straightPath(source.pointAbsolute(), target.pointAbsolute(), this.usingPoints);
1397
+ return straightPath(params);
1398
1398
  case 'bezier':
1399
- return bezierPath(source.pointAbsolute(), target.pointAbsolute(), source.rawHandle.position, target.rawHandle.position, this.usingPoints);
1399
+ return bezierPath(params);
1400
1400
  case 'smooth-step':
1401
- return smoothStepPath(source.pointAbsolute(), target.pointAbsolute(), source.rawHandle.position, target.rawHandle.position);
1401
+ return smoothStepPath(params);
1402
1402
  case 'step':
1403
- return smoothStepPath(source.pointAbsolute(), target.pointAbsolute(), source.rawHandle.position, target.rawHandle.position, 0);
1403
+ return smoothStepPath(params, 0);
1404
+ default:
1405
+ return this.curve(params);
1404
1406
  }
1405
1407
  });
1406
1408
  this.sourceHandle = computed(() => {
@@ -1457,7 +1459,18 @@ class EdgeModel {
1457
1459
  this.edgeLabels.center = new EdgeLabelModel(edge.edgeLabels.center);
1458
1460
  if (edge.edgeLabels?.end)
1459
1461
  this.edgeLabels.end = new EdgeLabelModel(edge.edgeLabels.end);
1460
- this.usingPoints = [!!this.edgeLabels.start, !!this.edgeLabels.center, !!this.edgeLabels.end];
1462
+ }
1463
+ getPathFactoryParams(source, target) {
1464
+ return {
1465
+ mode: 'edge',
1466
+ edge: this.edge,
1467
+ sourcePoint: source.pointAbsolute(),
1468
+ targetPoint: target.pointAbsolute(),
1469
+ sourcePosition: source.rawHandle.position,
1470
+ targetPosition: target.rawHandle.position,
1471
+ allEdges: this.flowEntitiesService.rawEdges(),
1472
+ allNodes: this.flowEntitiesService.rawNodes(),
1473
+ };
1461
1474
  }
1462
1475
  }
1463
1476
 
@@ -1728,7 +1741,7 @@ class NodeRenderingService {
1728
1741
  constructor() {
1729
1742
  this.flowEntitiesService = inject(FlowEntitiesService);
1730
1743
  this.nodes = computed(() => {
1731
- return this.flowEntitiesService.nodes().sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder());
1744
+ return [...this.flowEntitiesService.nodes().sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder())];
1732
1745
  });
1733
1746
  this.groups = computed(() => {
1734
1747
  return this.nodes().filter((n) => isGroupNode(n));
@@ -2269,14 +2282,14 @@ class EdgeComponent {
2269
2282
  this.connectionController?.startReconnection(handle, this.model());
2270
2283
  }
2271
2284
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2272
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2285
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (click)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n @if (model().path().labelPoints?.start; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().edgeLabels.center; as label) {\n @if (model().path().labelPoints?.center; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().edgeLabels.end; as label) {\n @if (model().path().labelPoints?.end; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2273
2286
  }
2274
2287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, decorators: [{
2275
2288
  type: Component,
2276
2289
  args: [{ standalone: true, selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2277
2290
  class: 'selectable',
2278
2291
  '[style.visibility]': 'isReconnecting() ? "hidden" : "visible"',
2279
- }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2292
+ }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (click)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n @if (model().path().labelPoints?.start; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().edgeLabels.center; as label) {\n @if (model().path().labelPoints?.center; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().edgeLabels.end; as label) {\n @if (model().path().labelPoints?.end; as point) {\n <svg:g edgeLabel [model]=\"label\" [point]=\"point\" [edgeModel]=\"model()\" [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n }\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2280
2293
  }] });
2281
2294
 
2282
2295
  class HandleService {
@@ -2864,7 +2877,7 @@ class NodeComponent {
2864
2877
  }
2865
2878
  }
2866
2879
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2867
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, nodeSvgTemplate: { classPropertyName: "nodeSvgTemplate", publicName: "nodeSvgTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], ngImport: i0, template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }, { kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ResizableComponent, selector: "[resizable]", inputs: ["resizable", "resizerColor", "gap"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: NodeHandlesControllerDirective, selector: "[nodeHandlesController]" }, { kind: "directive", type: NodeResizeControllerDirective, selector: "[nodeResizeController]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2880
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, nodeSvgTemplate: { classPropertyName: "nodeSvgTemplate", publicName: "nodeSvgTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], ngImport: i0, template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (click)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (click)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (click)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }, { kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ResizableComponent, selector: "[resizable]", inputs: ["resizable", "resizerColor", "gap"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: NodeHandlesControllerDirective, selector: "[nodeHandlesController]" }, { kind: "directive", type: NodeResizeControllerDirective, selector: "[nodeResizeController]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2868
2881
  }
2869
2882
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, decorators: [{
2870
2883
  type: Component,
@@ -2880,32 +2893,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2880
2893
  HandleSizeControllerDirective,
2881
2894
  NodeHandlesControllerDirective,
2882
2895
  NodeResizeControllerDirective,
2883
- ], template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
2896
+ ], template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (click)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (click)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (click)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (click)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
2884
2897
  }] });
2885
2898
 
2886
2899
  class ConnectionComponent {
2887
2900
  constructor() {
2888
- this.model = input.required();
2889
- this.template = input();
2890
2901
  this.flowStatusService = inject(FlowStatusService);
2891
2902
  this.spacePointContext = inject(SpacePointContextDirective);
2903
+ this.flowEntitiesService = inject(FlowEntitiesService);
2904
+ this.model = input.required();
2905
+ this.template = input();
2892
2906
  this.path = computed(() => {
2893
2907
  const status = this.flowStatusService.status();
2908
+ const curve = this.model().curve;
2894
2909
  if (status.state === 'connection-start' || status.state === 'reconnection-start') {
2895
2910
  const sourceHandle = status.payload.sourceHandle;
2896
2911
  const sourcePoint = sourceHandle.pointAbsolute();
2897
2912
  const sourcePosition = sourceHandle.rawHandle.position;
2898
2913
  const targetPoint = this.spacePointContext.svgCurrentSpacePoint();
2899
2914
  const targetPosition = getOppositePostion(sourceHandle.rawHandle.position);
2900
- switch (this.model().curve) {
2915
+ const params = this.getPathFactoryParams(sourcePoint, targetPoint, sourcePosition, targetPosition);
2916
+ switch (curve) {
2901
2917
  case 'straight':
2902
- return straightPath(sourcePoint, targetPoint).path;
2918
+ return straightPath(params).path;
2903
2919
  case 'bezier':
2904
- return bezierPath(sourcePoint, targetPoint, sourcePosition, targetPosition).path;
2920
+ return bezierPath(params).path;
2905
2921
  case 'smooth-step':
2906
- return smoothStepPath(sourcePoint, targetPoint, sourcePosition, targetPosition).path;
2922
+ return smoothStepPath(params).path;
2907
2923
  case 'step':
2908
- return smoothStepPath(sourcePoint, targetPoint, sourcePosition, targetPosition, 0).path;
2924
+ return smoothStepPath(params, 0).path;
2925
+ default:
2926
+ return curve(params).path;
2909
2927
  }
2910
2928
  }
2911
2929
  if (status.state === 'connection-validation' || status.state === 'reconnection-validation') {
@@ -2920,15 +2938,18 @@ class ConnectionComponent {
2920
2938
  const targetPosition = status.payload.valid
2921
2939
  ? targetHandle.rawHandle.position
2922
2940
  : getOppositePostion(sourceHandle.rawHandle.position);
2923
- switch (this.model().curve) {
2941
+ const params = this.getPathFactoryParams(sourcePoint, targetPoint, sourcePosition, targetPosition);
2942
+ switch (curve) {
2924
2943
  case 'straight':
2925
- return straightPath(sourcePoint, targetPoint).path;
2944
+ return straightPath(params).path;
2926
2945
  case 'bezier':
2927
- return bezierPath(sourcePoint, targetPoint, sourcePosition, targetPosition).path;
2946
+ return bezierPath(params).path;
2928
2947
  case 'smooth-step':
2929
- return smoothStepPath(sourcePoint, targetPoint, sourcePosition, targetPosition).path;
2948
+ return smoothStepPath(params).path;
2930
2949
  case 'step':
2931
- return smoothStepPath(sourcePoint, targetPoint, sourcePosition, targetPosition, 0).path;
2950
+ return smoothStepPath(params, 0).path;
2951
+ default:
2952
+ return curve(params).path;
2932
2953
  }
2933
2954
  }
2934
2955
  return null;
@@ -2951,6 +2972,17 @@ class ConnectionComponent {
2951
2972
  },
2952
2973
  };
2953
2974
  }
2975
+ getPathFactoryParams(sourcePoint, targetPoint, sourcePosition, targetPosition) {
2976
+ return {
2977
+ mode: 'connection',
2978
+ sourcePoint,
2979
+ targetPoint,
2980
+ sourcePosition,
2981
+ targetPosition,
2982
+ allEdges: this.flowEntitiesService.rawEdges(),
2983
+ allNodes: this.flowEntitiesService.rawNodes(),
2984
+ };
2985
+ }
2954
2986
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2955
2987
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: ConnectionComponent, isStandalone: true, selector: "g[connection]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2956
2988
  @if (model().type === 'default') {
@@ -3232,245 +3264,6 @@ function getSpacePoints(point, groups) {
3232
3264
  return result;
3233
3265
  }
3234
3266
 
3235
- /** Enum with lazy render directive state */
3236
- var LazyForState;
3237
- (function (LazyForState) {
3238
- /** Directive is in idle state */
3239
- LazyForState["idle"] = "idle";
3240
- /** Directive is rendering */
3241
- LazyForState["rendering"] = "rendering";
3242
- })(LazyForState || (LazyForState = {}));
3243
- /**
3244
- * Context for an element in lazyFor
3245
- */
3246
- class LazyForContextModel {
3247
- /** Whether the element is first */
3248
- get first() {
3249
- return this.index === 0;
3250
- }
3251
- /** Whether the element is last */
3252
- get last() {
3253
- return this.index === this.count - 1;
3254
- }
3255
- /** Whether the element is even */
3256
- get even() {
3257
- return this.index % 2 === 0;
3258
- }
3259
- /** Whether the element is odd */
3260
- get odd() {
3261
- return !this.even;
3262
- }
3263
- constructor($implicit, lazyFor, index, count) {
3264
- this.$implicit = $implicit;
3265
- this.lazyFor = lazyFor;
3266
- this.index = index;
3267
- this.count = count;
3268
- }
3269
- }
3270
- class LazyForDirective {
3271
- /**
3272
- * Asserts the correct type of the context for the template that `lazyFor` will render.
3273
- *
3274
- * The presence of this method is a signal to the Ivy template type-check compiler that the
3275
- * `lazyFor` structural directive renders its template with a specific context type.
3276
- */
3277
- static ngTemplateContextGuard(dir, ctx) {
3278
- return true;
3279
- }
3280
- //#region INPUTS
3281
- /** Setter for the array to be rendered by the directive */
3282
- set lazyForOf(lazyFor) {
3283
- this._lazyFor = lazyFor;
3284
- this._lazyForDirty = true;
3285
- }
3286
- /**
3287
- * Input - setter for TrackBy function
3288
- * @description is required
3289
- */
3290
- set lazyForTrackBy(fn) {
3291
- if (isDevMode() && fn !== null && typeof fn !== 'function') {
3292
- console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
3293
- `See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
3294
- }
3295
- this._trackByFn = fn;
3296
- }
3297
- /**
3298
- * Setter for the number of items that will be rendered per frame
3299
- * @param value number of items that will be rendered per frame
3300
- */
3301
- set lazyForItemsPerFrame(value) {
3302
- if (value <= 0) {
3303
- if (isDevMode()) {
3304
- console.warn('Items per frame parameter cannot be lower than 0! Input value was ignored');
3305
- }
3306
- return;
3307
- }
3308
- this._itemsPerFrame = value;
3309
- }
3310
- /** Setter for array item template */
3311
- set lazyForTemplate(value) {
3312
- if (value) {
3313
- this._template = value;
3314
- }
3315
- }
3316
- /** Getter for TrackBy function */
3317
- get lazyForTrackBy() {
3318
- return this._trackByFn;
3319
- }
3320
- //#endregion
3321
- constructor() {
3322
- this._template = inject(TemplateRef);
3323
- this._viewContainer = inject(ViewContainerRef);
3324
- this._differs = inject(IterableDiffers);
3325
- this._cdr = inject(ChangeDetectorRef);
3326
- this._destroyRef$ = inject(DestroyRef);
3327
- //#region PROPERTIES
3328
- /** Array for rendering */
3329
- this._lazyFor = null;
3330
- /** lazyFor initialization flag */
3331
- this._lazyForDirty = true;
3332
- /** Differ for tracking changes in input array */
3333
- this._differ = null;
3334
- /** Number of items to be rendered per frame */
3335
- this._itemsPerFrame = 5;
3336
- /** Directive state */
3337
- this._lazyForState = LazyForState.idle;
3338
- //#endregion
3339
- //#region RXJS
3340
- /** Private subject for stopping dynamic render process */
3341
- this._rerenderUnsub$ = new Subject();
3342
- this._destroyRef$.onDestroy(() => this._viewContainer.clear());
3343
- }
3344
- /** ngDoCheck hook */
3345
- ngDoCheck() {
3346
- if (this._lazyForDirty) {
3347
- this._lazyForDirty = false;
3348
- const value = this._lazyFor;
3349
- if (!this._differ && value) {
3350
- this._differ = this._differs.find(value).create(this.lazyForTrackBy);
3351
- }
3352
- }
3353
- if (this._differ) {
3354
- let changes = this._differ.diff(this._lazyFor);
3355
- if (changes) {
3356
- if (this._lazyForState === LazyForState.rendering) {
3357
- /**
3358
- * If the array changed during an active render process
3359
- * Need to clear container of all views
3360
- * And restart rendering from the beginning.
3361
- */
3362
- this._rerenderUnsub$.next();
3363
- changes = this._differ.diff([]);
3364
- changes = this._differ.diff(this._lazyFor);
3365
- this._viewContainer.clear();
3366
- if (changes) {
3367
- this.applyChanges(changes);
3368
- }
3369
- }
3370
- else {
3371
- this.applyChanges(changes);
3372
- }
3373
- }
3374
- }
3375
- }
3376
- /**
3377
- * Apply changes detected by differ
3378
- * @param changes changes
3379
- */
3380
- applyChanges(changes) {
3381
- const itemDataListToRender = [];
3382
- changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
3383
- const itemToPush = {
3384
- item: { ...item },
3385
- adjustedPreviousIndex,
3386
- currentIndex,
3387
- };
3388
- itemDataListToRender.push(itemToPush);
3389
- });
3390
- this.performLazyRender(itemDataListToRender, changes);
3391
- }
3392
- /**
3393
- * Perform lazy rendering
3394
- * @param itemDataListToRender list of items to render
3395
- * @param changes changes
3396
- */
3397
- performLazyRender(itemDataListToRender, changes) {
3398
- this.updateLazyForState(LazyForState.rendering);
3399
- this._rerenderUnsub$.next();
3400
- from(itemDataListToRender)
3401
- .pipe(bufferCount(this._itemsPerFrame), concatMap((itemList) => of(itemList).pipe(delayWhen(() => animationFrames()))), tap((itemList) => {
3402
- for (let i = 0; i < itemList.length; i++) {
3403
- const data = itemList[i];
3404
- if (data.item.previousIndex === null) {
3405
- this._viewContainer.createEmbeddedView(this._template, new LazyForContextModel(data.item.item, this._lazyFor, -1, -1), data.currentIndex === null ? undefined : data.currentIndex);
3406
- }
3407
- else if (data.currentIndex === null) {
3408
- this._viewContainer.remove(data.adjustedPreviousIndex === null ? undefined : data.adjustedPreviousIndex);
3409
- }
3410
- else if (data.adjustedPreviousIndex !== null) {
3411
- const view = this._viewContainer.get(data.adjustedPreviousIndex);
3412
- this._viewContainer.move(view, data.currentIndex);
3413
- this.applyViewChange(view, data.item);
3414
- }
3415
- }
3416
- this.updateViewContext();
3417
- this._cdr.markForCheck();
3418
- }),
3419
- /** Using take we automatically unsubscribe from the stream when rendering is complete */
3420
- take(Math.ceil(itemDataListToRender.length / this._itemsPerFrame)), takeUntil(this._rerenderUnsub$), takeUntilDestroyed(this._destroyRef$), finalize(() => {
3421
- changes.forEachIdentityChange((record) => {
3422
- const viewRef = (this._viewContainer.get(record.currentIndex));
3423
- this.applyViewChange(viewRef, record);
3424
- });
3425
- this.updateLazyForState(LazyForState.idle);
3426
- }))
3427
- .subscribe();
3428
- }
3429
- /** Update context (without implicit$) for elements inside view */
3430
- updateViewContext() {
3431
- for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
3432
- const viewRef = (this._viewContainer.get(i));
3433
- const context = viewRef.context;
3434
- context.index = i;
3435
- context.count = ilen;
3436
- context.lazyFor = this._lazyFor;
3437
- }
3438
- }
3439
- /**
3440
- * Apply implicit$ context
3441
- * @param view view
3442
- * @param record data
3443
- */
3444
- applyViewChange(view, record) {
3445
- view.context.$implicit = record.item;
3446
- }
3447
- /**
3448
- * Update directive state
3449
- * @param stateToSet state to set
3450
- */
3451
- updateLazyForState(stateToSet) {
3452
- this._lazyForState = stateToSet;
3453
- }
3454
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3455
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: LazyForDirective, isStandalone: true, selector: "[lazyFor][lazyForOf]", inputs: { lazyForOf: "lazyForOf", lazyForTrackBy: "lazyForTrackBy", lazyForItemsPerFrame: "lazyForItemsPerFrame", lazyForTemplate: "lazyForTemplate" }, ngImport: i0 }); }
3456
- }
3457
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, decorators: [{
3458
- type: Directive,
3459
- args: [{
3460
- selector: '[lazyFor][lazyForOf]',
3461
- standalone: true,
3462
- }]
3463
- }], ctorParameters: () => [], propDecorators: { lazyForOf: [{
3464
- type: Input
3465
- }], lazyForTrackBy: [{
3466
- type: Input,
3467
- args: [{ required: true }]
3468
- }], lazyForItemsPerFrame: [{
3469
- type: Input
3470
- }], lazyForTemplate: [{
3471
- type: Input
3472
- }] } });
3473
-
3474
3267
  const changesControllerHostDirective = {
3475
3268
  directive: ChangesControllerDirective,
3476
3269
  outputs: [
@@ -3521,10 +3314,10 @@ class VflowComponent {
3521
3314
  this.optimization = input({
3522
3315
  detachedGroupsLayer: false,
3523
3316
  });
3524
- this.nodeModels = computed(() => this.nodeRenderingService.nodes());
3525
- this.groups = computed(() => this.nodeRenderingService.groups());
3526
- this.nonGroups = computed(() => this.nodeRenderingService.nonGroups());
3527
- this.edgeModels = computed(() => this.edgeRenderingService.edges());
3317
+ this.nodeModels = this.nodeRenderingService.nodes;
3318
+ this.groups = this.nodeRenderingService.groups;
3319
+ this.nonGroups = this.nodeRenderingService.nonGroups;
3320
+ this.edgeModels = this.edgeRenderingService.edges;
3528
3321
  // #endregion
3529
3322
  // #region OUTPUTS
3530
3323
  /**
@@ -3785,7 +3578,7 @@ class VflowComponent {
3785
3578
  ComponentEventBusService,
3786
3579
  KeyboardService,
3787
3580
  OverlaysService,
3788
- ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n <svg:g\n *lazyFor=\"let model of groups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nonGroups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: LazyForDirective, selector: "[lazyFor][lazyForOf]", inputs: ["lazyForOf", "lazyForTrackBy", "lazyForItemsPerFrame", "lazyForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3581
+ ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3789
3582
  }
3790
3583
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, decorators: [{
3791
3584
  type: Component,
@@ -3816,8 +3609,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3816
3609
  NodeComponent,
3817
3610
  EdgeComponent,
3818
3611
  NgTemplateOutlet,
3819
- LazyForDirective,
3820
- ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n <svg:g\n *lazyFor=\"let model of groups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nonGroups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
3612
+ ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
3821
3613
  }], propDecorators: { view: [{
3822
3614
  type: Input
3823
3615
  }], minZoom: [{
@@ -3900,7 +3692,7 @@ class SelectableDirective {
3900
3692
  return null;
3901
3693
  }
3902
3694
  getEvent$() {
3903
- return merge(fromEvent(this.host.nativeElement, 'mousedown'), fromEvent(this.host.nativeElement, 'touchstart'));
3695
+ return fromEvent(this.host.nativeElement, 'click');
3904
3696
  }
3905
3697
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3906
3698
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectableDirective, isStandalone: true, selector: "[selectable]", ngImport: i0 }); }