ngx-vflow 1.0.7 → 1.1.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 (47) hide show
  1. package/esm2022/lib/vflow/components/edge-label/edge-label.component.mjs +15 -11
  2. package/esm2022/lib/vflow/components/node/node.component.mjs +18 -49
  3. package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +3 -3
  4. package/esm2022/lib/vflow/directives/changes-controller.directive.mjs +55 -1
  5. package/esm2022/lib/vflow/directives/node-handles-controller.directive.mjs +33 -0
  6. package/esm2022/lib/vflow/directives/node-resize-controller.directive.mjs +35 -0
  7. package/esm2022/lib/vflow/directives/selectable.directive.mjs +2 -2
  8. package/esm2022/lib/vflow/models/handle.model.mjs +33 -33
  9. package/esm2022/lib/vflow/models/node.model.mjs +30 -67
  10. package/esm2022/lib/vflow/public-components/handle/handle.component.mjs +3 -3
  11. package/esm2022/lib/vflow/public-components/resizable/resizable.component.mjs +4 -3
  12. package/esm2022/lib/vflow/services/draggable.service.mjs +2 -2
  13. package/esm2022/lib/vflow/services/handle.service.mjs +1 -1
  14. package/esm2022/lib/vflow/testing-utils/component-mocks/handle-mock.component.mjs +22 -0
  15. package/esm2022/lib/vflow/testing-utils/component-mocks/minimap-mock.component.mjs +22 -0
  16. package/esm2022/lib/vflow/testing-utils/component-mocks/node-toolbar-mock.component.mjs +19 -0
  17. package/esm2022/lib/vflow/testing-utils/component-mocks/resizable-mock.component.mjs +21 -0
  18. package/esm2022/lib/vflow/testing-utils/component-mocks/vflow-mock.component.mjs +251 -0
  19. package/esm2022/lib/vflow/testing-utils/directive-mocks/connection-controller-mock.directive.mjs +15 -0
  20. package/esm2022/lib/vflow/testing-utils/directive-mocks/drag-handle-mock.directive.mjs +11 -0
  21. package/esm2022/lib/vflow/testing-utils/directive-mocks/selectable-mock.directive.mjs +14 -0
  22. package/esm2022/lib/vflow/testing-utils/directive-mocks/template-mock.directive.mjs +87 -0
  23. package/esm2022/lib/vflow/testing-utils/provide-custom-node-mocks.mjs +9 -8
  24. package/esm2022/lib/vflow/testing-utils/vflow-mocks.mjs +26 -0
  25. package/esm2022/public-api.mjs +11 -1
  26. package/fesm2022/ngx-vflow.mjs +699 -189
  27. package/fesm2022/ngx-vflow.mjs.map +1 -1
  28. package/lib/vflow/components/edge-label/edge-label.component.d.ts +2 -0
  29. package/lib/vflow/components/node/node.component.d.ts +5 -11
  30. package/lib/vflow/directives/changes-controller.directive.d.ts +54 -0
  31. package/lib/vflow/directives/node-handles-controller.directive.d.ts +11 -0
  32. package/lib/vflow/directives/node-resize-controller.directive.d.ts +11 -0
  33. package/lib/vflow/models/handle.model.d.ts +8 -23
  34. package/lib/vflow/models/node.model.d.ts +17 -13
  35. package/lib/vflow/services/handle.service.d.ts +1 -1
  36. package/lib/vflow/testing-utils/component-mocks/handle-mock.component.d.ts +11 -0
  37. package/lib/vflow/testing-utils/component-mocks/minimap-mock.component.d.ts +10 -0
  38. package/lib/vflow/testing-utils/component-mocks/node-toolbar-mock.component.d.ts +7 -0
  39. package/lib/vflow/testing-utils/component-mocks/resizable-mock.component.d.ts +8 -0
  40. package/lib/vflow/testing-utils/component-mocks/vflow-mock.component.d.ts +48 -0
  41. package/lib/vflow/testing-utils/directive-mocks/connection-controller-mock.directive.d.ts +7 -0
  42. package/lib/vflow/testing-utils/directive-mocks/drag-handle-mock.directive.d.ts +5 -0
  43. package/lib/vflow/testing-utils/directive-mocks/selectable-mock.directive.d.ts +5 -0
  44. package/lib/vflow/testing-utils/directive-mocks/template-mock.directive.d.ts +32 -0
  45. package/lib/vflow/testing-utils/vflow-mocks.d.ts +10 -0
  46. package/package.json +1 -1
  47. package/public-api.d.ts +10 -0
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, viewChild, Component, ChangeDetectionStrategy, Injector, runInInjectionContext, output, HostListener, NgZone, contentChild, Input, forwardRef } from '@angular/core';
2
+ import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, Injector, output, HostListener, 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, observeOn, animationFrameScheduler, skip, map, pairwise, filter, distinctUntilChanged, asyncScheduler, zip, share, startWith, of } from 'rxjs';
6
- import { toObservable, takeUntilDestroyed, toSignal, outputFromObservable } from '@angular/core/rxjs-interop';
5
+ import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith, of } from 'rxjs';
6
+ import { toObservable, takeUntilDestroyed, outputFromObservable, toSignal } from '@angular/core/rxjs-interop';
7
7
  import { drag } from 'd3-drag';
8
8
  import { __decorate } from 'tslib';
9
9
  import { NgTemplateOutlet, NgComponentOutlet, KeyValuePipe } from '@angular/common';
@@ -545,7 +545,7 @@ function moveNode(model, point) {
545
545
  point.y = Math.min(parent.size().height - model.size().height, point.y);
546
546
  point.y = Math.max(0, point.y);
547
547
  }
548
- model.setPoint(point, true);
548
+ model.setPoint(point);
549
549
  }
550
550
 
551
551
  class EdgeTemplateDirective {
@@ -827,26 +827,29 @@ function isTemplateDynamicGroupNode(node) {
827
827
  return node.type === 'template-group';
828
828
  }
829
829
 
830
- // TODO bad naming around points
831
830
  class NodeModel {
832
831
  static { this.defaultWidth = 100; }
833
832
  static { this.defaultHeight = 50; }
834
833
  static { this.defaultColor = '#1b262c'; }
835
834
  constructor(node) {
836
835
  this.node = node;
837
- this.flowSettingsService = inject(FlowSettingsService);
838
836
  this.entitiesService = inject(FlowEntitiesService);
839
- this.internalPoint = this.createInternalPointSignal();
840
- this.throttledPoint$ = toObservable(this.internalPoint).pipe(observeOn(animationFrameScheduler));
841
- this.notThrottledPoint$ = new Subject();
842
- this.point = toSignal(merge(this.throttledPoint$, this.notThrottledPoint$), {
843
- initialValue: this.internalPoint(),
844
- });
845
- this.point$ = this.throttledPoint$;
846
- this.size = signal({ width: 0, height: 0 });
837
+ this.point = this.createInternalPointSignal();
838
+ this.point$ = toObservable(this.point);
839
+ this.width = this.createWidthSignal(NodeModel.defaultWidth);
840
+ this.width$ = toObservable(this.width);
841
+ this.height = this.createHeightSignal(NodeModel.defaultHeight);
842
+ this.height$ = toObservable(this.height);
843
+ /**
844
+ * @deprecated use width or height signals
845
+ */
846
+ this.size = computed(() => ({ width: this.width(), height: this.height() }));
847
+ /**
848
+ * @deprecated use width$ or height$
849
+ */
847
850
  this.size$ = toObservable(this.size);
848
- this.width = computed(() => this.size().width);
849
- this.height = computed(() => this.size().height);
851
+ this.styleWidth = computed(() => `${this.width()}px`);
852
+ this.styleHeight = computed(() => `${this.height()}px`);
850
853
  this.renderOrder = signal(0);
851
854
  this.selected = signal(false);
852
855
  this.selected$ = toObservable(this.selected);
@@ -916,56 +919,8 @@ class NodeModel {
916
919
  }
917
920
  }
918
921
  }
919
- setPoint(point, throttle) {
920
- if (throttle) {
921
- this.internalPoint.set(point);
922
- }
923
- else {
924
- this.notThrottledPoint$.next(point);
925
- }
926
- }
927
- /**
928
- * TODO find the way to implement this better
929
- */
930
- linkDefaultNodeSizeWithModelSize() {
931
- const node = this.node;
932
- switch (node.type) {
933
- case 'default':
934
- case 'default-group':
935
- case 'template-group': {
936
- if (isDynamicNode(node)) {
937
- effect(() => {
938
- this.size.set({
939
- width: node.width?.() ?? NodeModel.defaultWidth,
940
- height: node.height?.() ?? NodeModel.defaultHeight,
941
- });
942
- }, { allowSignalWrites: true });
943
- }
944
- else {
945
- this.size.set({
946
- width: node.width ?? NodeModel.defaultWidth,
947
- height: node.height ?? NodeModel.defaultHeight,
948
- });
949
- }
950
- }
951
- }
952
- if (node.type === 'html-template' || this.isComponentType) {
953
- if (isDynamicNode(node)) {
954
- effect(() => {
955
- if (node.width && node.height) {
956
- this.size.set({
957
- width: node.width(),
958
- height: node.height(),
959
- });
960
- }
961
- }, { allowSignalWrites: true });
962
- }
963
- else {
964
- if (node.width && node.height) {
965
- this.size.set({ width: node.width, height: node.height });
966
- }
967
- }
968
- }
922
+ setPoint(point) {
923
+ this.point.set(point);
969
924
  }
970
925
  createTextSignal() {
971
926
  const node = this.node;
@@ -982,6 +937,16 @@ class NodeModel {
982
937
  createInternalPointSignal() {
983
938
  return isDynamicNode(this.node) ? this.node.point : signal({ x: this.node.point.x, y: this.node.point.y });
984
939
  }
940
+ createWidthSignal(defaultValue) {
941
+ return isDynamicNode(this.node)
942
+ ? (this.node.width ?? signal(defaultValue))
943
+ : signal(this.node.width ?? defaultValue);
944
+ }
945
+ createHeightSignal(defaultValue) {
946
+ return isDynamicNode(this.node)
947
+ ? (this.node.height ?? signal(defaultValue))
948
+ : signal(this.node.height ?? defaultValue);
949
+ }
985
950
  }
986
951
 
987
952
  class EdgeLabelModel {
@@ -1451,37 +1416,67 @@ class ChangesControllerDirective {
1451
1416
  this.onNodesChangePosition = outputFromObservable(this.nodeChangesOfType('position'), {
1452
1417
  alias: 'onNodesChange.position',
1453
1418
  });
1419
+ /**
1420
+ * @deprecated use `onNodesChange.position` instead
1421
+ */
1454
1422
  this.onNodesChangePositionSignle = outputFromObservable(this.singleChange(this.nodeChangesOfType('position')), { alias: 'onNodesChange.position.single' });
1423
+ /**
1424
+ * @deprecated use `onNodesChange.position` instead
1425
+ */
1455
1426
  this.onNodesChangePositionMany = outputFromObservable(this.manyChanges(this.nodeChangesOfType('position')), { alias: 'onNodesChange.position.many' });
1456
1427
  this.onNodesChangeSize = outputFromObservable(this.nodeChangesOfType('size'), {
1457
1428
  alias: 'onNodesChange.size',
1458
1429
  });
1430
+ /**
1431
+ * @deprecated use `onNodesChange.size` instead
1432
+ */
1459
1433
  this.onNodesChangeSizeSingle = outputFromObservable(this.singleChange(this.nodeChangesOfType('size')), {
1460
1434
  alias: 'onNodesChange.size.single',
1461
1435
  });
1436
+ /**
1437
+ * @deprecated use `onNodesChange.size` instead
1438
+ */
1462
1439
  this.onNodesChangeSizeMany = outputFromObservable(this.manyChanges(this.nodeChangesOfType('size')), {
1463
1440
  alias: 'onNodesChange.size.many',
1464
1441
  });
1465
1442
  this.onNodesChangeAdd = outputFromObservable(this.nodeChangesOfType('add'), {
1466
1443
  alias: 'onNodesChange.add',
1467
1444
  });
1445
+ /**
1446
+ * @deprecated use `onNodesChange.add` instead
1447
+ */
1468
1448
  this.onNodesChangeAddSingle = outputFromObservable(this.singleChange(this.nodeChangesOfType('add')), {
1469
1449
  alias: 'onNodesChange.add.single',
1470
1450
  });
1451
+ /**
1452
+ * @deprecated use `onNodesChange.add` instead
1453
+ */
1471
1454
  this.onNodesChangeAddMany = outputFromObservable(this.manyChanges(this.nodeChangesOfType('add')), {
1472
1455
  alias: 'onNodesChange.add.many',
1473
1456
  });
1474
1457
  this.onNodesChangeRemove = outputFromObservable(this.nodeChangesOfType('remove'), {
1475
1458
  alias: 'onNodesChange.remove',
1476
1459
  });
1460
+ /**
1461
+ * @deprecated use `onNodesChange.remove` instead
1462
+ */
1477
1463
  this.onNodesChangeRemoveSingle = outputFromObservable(this.singleChange(this.nodeChangesOfType('remove')), { alias: 'onNodesChange.remove.single' });
1464
+ /**
1465
+ * @deprecated use `onNodesChange.remove` instead
1466
+ */
1478
1467
  this.onNodesChangeRemoveMany = outputFromObservable(this.manyChanges(this.nodeChangesOfType('remove')), {
1479
1468
  alias: 'onNodesChange.remove.many',
1480
1469
  });
1481
1470
  this.onNodesChangeSelect = outputFromObservable(this.nodeChangesOfType('select'), {
1482
1471
  alias: 'onNodesChange.select',
1483
1472
  });
1473
+ /**
1474
+ * @deprecated use `onNodesChange.select` instead
1475
+ */
1484
1476
  this.onNodesChangeSelectSingle = outputFromObservable(this.singleChange(this.nodeChangesOfType('select')), { alias: 'onNodesChange.select.single' });
1477
+ /**
1478
+ * @deprecated use `onNodesChange.select` instead
1479
+ */
1485
1480
  this.onNodesChangeSelectMany = outputFromObservable(this.manyChanges(this.nodeChangesOfType('select')), {
1486
1481
  alias: 'onNodesChange.select.many',
1487
1482
  });
@@ -1492,32 +1487,56 @@ class ChangesControllerDirective {
1492
1487
  this.onNodesChangeDetached = outputFromObservable(this.edgeChangesOfType('detached'), {
1493
1488
  alias: 'onEdgesChange.detached',
1494
1489
  });
1490
+ /**
1491
+ * @deprecated use `onEdgesChange.detached` instead
1492
+ */
1495
1493
  this.onNodesChangeDetachedSingle = outputFromObservable(this.singleChange(this.edgeChangesOfType('detached')), { alias: 'onEdgesChange.detached.single' });
1494
+ /**
1495
+ * @deprecated use `onEdgesChange.detached` instead
1496
+ */
1496
1497
  this.onNodesChangeDetachedMany = outputFromObservable(this.manyChanges(this.edgeChangesOfType('detached')), { alias: 'onEdgesChange.detached.many' });
1497
1498
  this.onEdgesChangeAdd = outputFromObservable(this.edgeChangesOfType('add'), {
1498
1499
  alias: 'onEdgesChange.add',
1499
1500
  });
1501
+ /**
1502
+ * @deprecated use `onEdgesChange.add` instead
1503
+ */
1500
1504
  this.onEdgeChangeAddSingle = outputFromObservable(this.singleChange(this.edgeChangesOfType('add')), {
1501
1505
  alias: 'onEdgesChange.add.single',
1502
1506
  });
1507
+ /**
1508
+ * @deprecated use `onEdgesChange.add` instead
1509
+ */
1503
1510
  this.onEdgeChangeAddMany = outputFromObservable(this.manyChanges(this.edgeChangesOfType('add')), {
1504
1511
  alias: 'onEdgesChange.add.many',
1505
1512
  });
1506
1513
  this.onEdgeChangeRemove = outputFromObservable(this.edgeChangesOfType('remove'), {
1507
1514
  alias: 'onEdgesChange.remove',
1508
1515
  });
1516
+ /**
1517
+ * @deprecated use `onEdgesChange.remove` instead
1518
+ */
1509
1519
  this.onEdgeChangeRemoveSingle = outputFromObservable(this.singleChange(this.edgeChangesOfType('remove')), {
1510
1520
  alias: 'onEdgesChange.remove.single',
1511
1521
  });
1522
+ /**
1523
+ * @deprecated use `onEdgesChange.remove` instead
1524
+ */
1512
1525
  this.onEdgeChangeRemoveMany = outputFromObservable(this.manyChanges(this.edgeChangesOfType('remove')), {
1513
1526
  alias: 'onEdgesChange.remove.many',
1514
1527
  });
1515
1528
  this.onEdgeChangeSelect = outputFromObservable(this.edgeChangesOfType('select'), {
1516
1529
  alias: 'onEdgesChange.select',
1517
1530
  });
1531
+ /**
1532
+ * @deprecated use `onEdgesChange.select` instead
1533
+ */
1518
1534
  this.onEdgeChangeSelectSingle = outputFromObservable(this.singleChange(this.edgeChangesOfType('select')), {
1519
1535
  alias: 'onEdgesChange.select.single',
1520
1536
  });
1537
+ /**
1538
+ * @deprecated use `onEdgesChange.select` instead
1539
+ */
1521
1540
  this.onEdgeChangeSelectMany = outputFromObservable(this.manyChanges(this.edgeChangesOfType('select')), {
1522
1541
  alias: 'onEdgesChange.select.many',
1523
1542
  });
@@ -1719,8 +1738,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1719
1738
  type: Injectable
1720
1739
  }], propDecorators: { addToolbar: [], removeToolbar: [] } });
1721
1740
 
1741
+ function resizable(elems, zone) {
1742
+ return new Observable((subscriber) => {
1743
+ const ro = new ResizeObserver((entries) => {
1744
+ zone.run(() => subscriber.next(entries));
1745
+ });
1746
+ elems.forEach((e) => ro.observe(e));
1747
+ return () => ro.disconnect();
1748
+ });
1749
+ }
1750
+
1722
1751
  class EdgeLabelComponent {
1723
1752
  constructor() {
1753
+ this.zone = inject(NgZone);
1754
+ this.destroyRef = inject(DestroyRef);
1724
1755
  // TODO: too many inputs
1725
1756
  this.model = input.required();
1726
1757
  this.edgeModel = input.required();
@@ -1745,9 +1776,13 @@ class EdgeLabelComponent {
1745
1776
  // this is a fix for visual artifact in chrome that for some reason adresses only for edge label.
1746
1777
  // the bug reproduces if edgeLabelWrapperRef size fully matched the size of parent foreignObject
1747
1778
  const MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME = 2;
1748
- const width = this.edgeLabelWrapperRef().nativeElement.clientWidth + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
1749
- const height = this.edgeLabelWrapperRef().nativeElement.clientHeight + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
1750
- this.model().size.set({ width, height });
1779
+ resizable([this.edgeLabelWrapperRef().nativeElement], this.zone)
1780
+ .pipe(startWith(null), tap(() => {
1781
+ const width = this.edgeLabelWrapperRef().nativeElement.clientWidth + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
1782
+ const height = this.edgeLabelWrapperRef().nativeElement.clientHeight + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
1783
+ this.model().size.set({ width, height });
1784
+ }), takeUntilDestroyed(this.destroyRef))
1785
+ .subscribe();
1751
1786
  }
1752
1787
  getLabelContext() {
1753
1788
  return {
@@ -1760,13 +1795,10 @@ class EdgeLabelComponent {
1760
1795
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1761
1796
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeLabelComponent, isStandalone: true, selector: "g[edgeLabel]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeModel: { classPropertyName: "edgeModel", publicName: "edgeModel", isSignal: true, isRequired: true, transformFunction: null }, point: { classPropertyName: "point", publicName: "point", isSignal: true, isRequired: false, transformFunction: null }, htmlTemplate: { classPropertyName: "htmlTemplate", publicName: "htmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "edgeLabelWrapperRef", first: true, predicate: ["edgeLabelWrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (model().edgeLabel.type === 'html-template' && htmlTemplate()) {\n @if (htmlTemplate(); as htmlTemplate) {\n <svg:foreignObject\n [attr.x]=\"edgeLabelPoint().x\"\n [attr.y]=\"edgeLabelPoint().y\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\">\n <div #edgeLabelWrapper class=\"edge-label-wrapper\">\n <ng-container *ngTemplateOutlet=\"htmlTemplate; context: getLabelContext()\" />\n </div>\n </svg:foreignObject>\n }\n}\n", styles: [".edge-label-wrapper{width:max-content;margin-top:1px;margin-left:1px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1762
1797
  }
1763
- __decorate([
1764
- Microtask
1765
- ], EdgeLabelComponent.prototype, "ngAfterViewInit", null);
1766
1798
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeLabelComponent, decorators: [{
1767
1799
  type: Component,
1768
1800
  args: [{ standalone: true, selector: 'g[edgeLabel]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet], template: "@if (model().edgeLabel.type === 'html-template' && htmlTemplate()) {\n @if (htmlTemplate(); as htmlTemplate) {\n <svg:foreignObject\n [attr.x]=\"edgeLabelPoint().x\"\n [attr.y]=\"edgeLabelPoint().y\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\">\n <div #edgeLabelWrapper class=\"edge-label-wrapper\">\n <ng-container *ngTemplateOutlet=\"htmlTemplate; context: getLabelContext()\" />\n </div>\n </svg:foreignObject>\n }\n}\n", styles: [".edge-label-wrapper{width:max-content;margin-top:1px;margin-left:1px}\n"] }]
1769
- }], propDecorators: { ngAfterViewInit: [] } });
1801
+ }] });
1770
1802
 
1771
1803
  class EdgeComponent {
1772
1804
  constructor() {
@@ -1838,33 +1870,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1838
1870
  type: Injectable
1839
1871
  }], propDecorators: { createHandle: [] } });
1840
1872
 
1841
- function resizable(elems, zone) {
1842
- return new Observable((subscriber) => {
1843
- const ro = new ResizeObserver((entries) => {
1844
- zone.run(() => subscriber.next(entries));
1845
- });
1846
- elems.forEach((e) => ro.observe(e));
1847
- return () => ro.disconnect();
1848
- });
1849
- }
1850
-
1851
- function InjectionContext(target, key, descriptor) {
1852
- const originalMethod = descriptor.value;
1853
- descriptor.value = function (...args) {
1854
- if (implementsWithInjector(this)) {
1855
- return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
1856
- }
1857
- else {
1858
- throw new Error('Class that contains decorated method must extends WithInjectorDirective class');
1859
- }
1860
- };
1861
- // Return the modified descriptor
1862
- return descriptor;
1863
- }
1864
- const implementsWithInjector = (instance) => {
1865
- return 'injector' in instance && 'get' in instance.injector;
1866
- };
1867
-
1868
1873
  /**
1869
1874
  * This function contains a hack-y behavior.
1870
1875
  * If the handles are of the same type (source-source or target-target),
@@ -2193,8 +2198,9 @@ class ResizableComponent {
2193
2198
  return;
2194
2199
  const offset = calcOffset(event.movementX, event.movementY, this.zoom());
2195
2200
  const { x, y, width, height } = constrainRect(applyResize(this.resizeSide, this.model, offset), this.model, this.resizeSide, this.minWidth, this.minHeight);
2196
- this.model.setPoint({ x, y }, false);
2197
- this.model.size.set({ width, height });
2201
+ this.model.setPoint({ x, y });
2202
+ this.model.width.set(width);
2203
+ this.model.height.set(height);
2198
2204
  }
2199
2205
  endResize() {
2200
2206
  this.resizeSide = null;
@@ -2355,26 +2361,43 @@ class HandleModel {
2355
2361
  width: 10 + 2 * this.strokeWidth,
2356
2362
  height: 10 + 2 * this.strokeWidth,
2357
2363
  });
2358
- this.offset = computed(() => {
2364
+ this.pointAbsolute = computed(() => {
2365
+ return {
2366
+ x: this.parentNode.globalPoint().x + this.hostOffset().x + this.sizeOffset().x,
2367
+ y: this.parentNode.globalPoint().y + this.hostOffset().y + this.sizeOffset().y,
2368
+ };
2369
+ });
2370
+ this.state = signal('idle');
2371
+ this.updateHostSizeAndPosition$ = new Subject();
2372
+ this.hostSize = toSignal(this.updateHostSizeAndPosition$.pipe(map(() => this.getHostSize())), {
2373
+ initialValue: { width: 0, height: 0 },
2374
+ });
2375
+ this.hostPosition = toSignal(this.updateHostSizeAndPosition$.pipe(map(() => ({
2376
+ x: this.hostReference instanceof HTMLElement ? this.hostReference.offsetLeft : 0, // for now just 0 for group nodes
2377
+ y: this.hostReference instanceof HTMLElement ? this.hostReference.offsetTop : 0, // for now just 0 for group nodes
2378
+ }))), {
2379
+ initialValue: { x: 0, y: 0 },
2380
+ });
2381
+ this.hostOffset = computed(() => {
2359
2382
  switch (this.rawHandle.position) {
2360
2383
  case 'left':
2361
2384
  return {
2362
2385
  x: 0,
2363
- y: this.parentPosition().y + this.parentSize().height / 2,
2386
+ y: this.hostPosition().y + this.hostSize().height / 2,
2364
2387
  };
2365
2388
  case 'right':
2366
2389
  return {
2367
2390
  x: this.parentNode.size().width,
2368
- y: this.parentPosition().y + this.parentSize().height / 2,
2391
+ y: this.hostPosition().y + this.hostSize().height / 2,
2369
2392
  };
2370
2393
  case 'top':
2371
2394
  return {
2372
- x: this.parentPosition().x + this.parentSize().width / 2,
2395
+ x: this.hostPosition().x + this.hostSize().width / 2,
2373
2396
  y: 0,
2374
2397
  };
2375
2398
  case 'bottom':
2376
2399
  return {
2377
- x: this.parentPosition().x + this.parentSize().width / 2,
2400
+ x: this.hostPosition().x + this.hostSize().width / 2,
2378
2401
  y: this.parentNode.size().height,
2379
2402
  };
2380
2403
  }
@@ -2391,50 +2414,50 @@ class HandleModel {
2391
2414
  return { x: 0, y: this.size().height / 2 };
2392
2415
  }
2393
2416
  });
2394
- this.pointAbsolute = computed(() => {
2395
- return {
2396
- x: this.parentNode.globalPoint().x + this.offset().x + this.sizeOffset().x,
2397
- y: this.parentNode.globalPoint().y + this.offset().y + this.sizeOffset().y,
2398
- };
2399
- });
2400
- this.state = signal('idle');
2401
- this.updateParentSizeAndPosition$ = new Subject();
2402
- this.parentSize = toSignal(this.updateParentSizeAndPosition$.pipe(map(() => this.getParentSize())), {
2403
- initialValue: { width: 0, height: 0 },
2404
- });
2405
- this.parentPosition = toSignal(this.updateParentSizeAndPosition$.pipe(map(() => ({
2406
- x: this.parentReference instanceof HTMLElement ? this.parentReference.offsetLeft : 0, // for now just 0 for group nodes
2407
- y: this.parentReference instanceof HTMLElement ? this.parentReference.offsetTop : 0, // for now just 0 for group nodes
2408
- }))), {
2409
- initialValue: { x: 0, y: 0 },
2410
- });
2411
- this.parentReference = this.rawHandle.parentReference;
2417
+ this.hostReference = this.rawHandle.hostReference;
2412
2418
  this.template = this.rawHandle.template;
2413
2419
  this.templateContext = {
2414
2420
  $implicit: {
2415
- point: this.offset,
2421
+ point: this.hostOffset,
2416
2422
  state: this.state,
2417
2423
  node: this.parentNode.node,
2418
2424
  },
2419
2425
  };
2420
2426
  }
2421
- updateParent() {
2422
- this.updateParentSizeAndPosition$.next();
2427
+ updateHost() {
2428
+ this.updateHostSizeAndPosition$.next();
2423
2429
  }
2424
- getParentSize() {
2425
- if (this.parentReference instanceof HTMLElement) {
2430
+ getHostSize() {
2431
+ if (this.hostReference instanceof HTMLElement) {
2426
2432
  return {
2427
- width: this.parentReference.offsetWidth,
2428
- height: this.parentReference.offsetHeight,
2433
+ width: this.hostReference.offsetWidth,
2434
+ height: this.hostReference.offsetHeight,
2429
2435
  };
2430
2436
  }
2431
- else if (this.parentReference instanceof SVGGraphicsElement) {
2432
- return this.parentReference.getBBox();
2437
+ else if (this.hostReference instanceof SVGGraphicsElement) {
2438
+ return this.hostReference.getBBox();
2433
2439
  }
2434
2440
  return { width: 0, height: 0 };
2435
2441
  }
2436
2442
  }
2437
2443
 
2444
+ function InjectionContext(target, key, descriptor) {
2445
+ const originalMethod = descriptor.value;
2446
+ descriptor.value = function (...args) {
2447
+ if (implementsWithInjector(this)) {
2448
+ return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
2449
+ }
2450
+ else {
2451
+ throw new Error('Class that contains decorated method must extends WithInjectorDirective class');
2452
+ }
2453
+ };
2454
+ // Return the modified descriptor
2455
+ return descriptor;
2456
+ }
2457
+ const implementsWithInjector = (instance) => {
2458
+ return 'injector' in instance && 'get' in instance.injector;
2459
+ };
2460
+
2438
2461
  class HandleComponent {
2439
2462
  constructor() {
2440
2463
  this.injector = inject(Injector);
@@ -2462,11 +2485,11 @@ class HandleComponent {
2462
2485
  position: this.position(),
2463
2486
  type: this.type(),
2464
2487
  id: this.id(),
2465
- parentReference: this.element.parentElement,
2488
+ hostReference: this.element.parentElement,
2466
2489
  template: this.template(),
2467
2490
  }, node);
2468
2491
  this.handleService.createHandle(this.model);
2469
- requestAnimationFrame(() => this.model.updateParent());
2492
+ requestAnimationFrame(() => this.model.updateHost());
2470
2493
  this.destroyRef.onDestroy(() => this.handleService.destroyHandle(this.model));
2471
2494
  }
2472
2495
  }
@@ -2481,6 +2504,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2481
2504
  args: [{ standalone: true, selector: 'handle', changeDetection: ChangeDetectionStrategy.OnPush, template: "" }]
2482
2505
  }], propDecorators: { ngOnInit: [] } });
2483
2506
 
2507
+ class NodeHandlesControllerDirective {
2508
+ constructor() {
2509
+ this.nodeAccessor = inject(NodeAccessorService);
2510
+ this.zone = inject(NgZone);
2511
+ this.destroyRef = inject(DestroyRef);
2512
+ this.hostElementRef = inject(ElementRef);
2513
+ }
2514
+ ngOnInit() {
2515
+ const model = this.nodeAccessor.model();
2516
+ model.handles$
2517
+ .pipe(switchMap((handles) => resizable([...handles.map((h) => h.hostReference), this.hostElementRef.nativeElement], this.zone).pipe(map(() => handles))), tap((handles) => {
2518
+ // TODO (performance) inspect how to avoid calls of this when flow initially rendered
2519
+ handles.forEach((h) => h.updateHost());
2520
+ }), takeUntilDestroyed(this.destroyRef))
2521
+ .subscribe();
2522
+ }
2523
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeHandlesControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2524
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeHandlesControllerDirective, isStandalone: true, selector: "[nodeHandlesController]", ngImport: i0 }); }
2525
+ }
2526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeHandlesControllerDirective, decorators: [{
2527
+ type: Directive,
2528
+ args: [{
2529
+ selector: '[nodeHandlesController]',
2530
+ standalone: true,
2531
+ }]
2532
+ }] });
2533
+
2534
+ class NodeResizeControllerDirective {
2535
+ constructor() {
2536
+ this.nodeAccessor = inject(NodeAccessorService);
2537
+ this.zone = inject(NgZone);
2538
+ this.destroyRef = inject(DestroyRef);
2539
+ this.hostElementRef = inject(ElementRef);
2540
+ }
2541
+ ngOnInit() {
2542
+ const model = this.nodeAccessor.model();
2543
+ resizable([this.hostElementRef.nativeElement], this.zone)
2544
+ .pipe(startWith(null), filter(() => !model.resizing()), tap(() => {
2545
+ const width = this.hostElementRef.nativeElement.clientWidth;
2546
+ const height = this.hostElementRef.nativeElement.clientHeight;
2547
+ model.width.set(width);
2548
+ model.height.set(height);
2549
+ }), takeUntilDestroyed(this.destroyRef))
2550
+ .subscribe();
2551
+ }
2552
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeResizeControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2553
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeResizeControllerDirective, isStandalone: true, selector: "[nodeResizeController]", ngImport: i0 }); }
2554
+ }
2555
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeResizeControllerDirective, decorators: [{
2556
+ type: Directive,
2557
+ args: [{
2558
+ selector: '[nodeResizeController]',
2559
+ standalone: true,
2560
+ }]
2561
+ }] });
2562
+
2484
2563
  class NodeComponent {
2485
2564
  constructor() {
2486
2565
  this.injector = inject(Injector);
@@ -2493,50 +2572,26 @@ class NodeComponent {
2493
2572
  this.hostRef = inject(ElementRef);
2494
2573
  this.nodeAccessor = inject(NodeAccessorService);
2495
2574
  this.overlaysService = inject(OverlaysService);
2496
- this.zone = inject(NgZone);
2497
2575
  // TODO remove dependency from this directive
2498
2576
  this.connectionController = inject(ConnectionControllerDirective, { optional: true });
2499
- this.nodeModel = input.required();
2577
+ this.model = input.required();
2500
2578
  this.nodeTemplate = input();
2501
2579
  this.groupNodeTemplate = input();
2502
- this.htmlWrapperRef = viewChild.required('htmlWrapper');
2503
2580
  this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
2504
2581
  this.flowStatusService.status().state === 'connection-validation');
2505
- this.styleWidth = computed(() => `${this.nodeModel().size().width}px`);
2506
- this.styleHeight = computed(() => `${this.nodeModel().size().height}px`);
2507
- this.toolbar = computed(() => this.overlaysService.nodeToolbars().get(this.nodeModel()));
2582
+ this.toolbar = computed(() => this.overlaysService.nodeToolbars().get(this.model()));
2508
2583
  }
2509
2584
  ngOnInit() {
2510
- this.nodeAccessor.model.set(this.nodeModel());
2511
- this.handleService.node.set(this.nodeModel());
2585
+ this.nodeAccessor.model.set(this.model());
2586
+ this.handleService.node.set(this.model());
2512
2587
  effect(() => {
2513
- if (this.nodeModel().draggable()) {
2514
- this.draggableService.enable(this.hostRef.nativeElement, this.nodeModel());
2588
+ if (this.model().draggable()) {
2589
+ this.draggableService.enable(this.hostRef.nativeElement, this.model());
2515
2590
  }
2516
2591
  else {
2517
2592
  this.draggableService.disable(this.hostRef.nativeElement);
2518
2593
  }
2519
- });
2520
- this.nodeModel()
2521
- .handles$.pipe(switchMap((handles) => resizable(handles.map((h) => h.parentReference), this.zone).pipe(map(() => handles))), tap((handles) => {
2522
- // TODO (performance) inspect how to avoid calls of this when flow initially rendered
2523
- handles.forEach((h) => h.updateParent());
2524
- }), takeUntilDestroyed())
2525
- .subscribe();
2526
- }
2527
- ngAfterViewInit() {
2528
- this.nodeModel().linkDefaultNodeSizeWithModelSize();
2529
- if (this.nodeModel().node.type === 'html-template' || this.nodeModel().isComponentType) {
2530
- resizable([this.htmlWrapperRef().nativeElement], this.zone)
2531
- .pipe(startWith(null), tap(() => this.nodeModel()
2532
- .handles()
2533
- .forEach((h) => h.updateParent())), filter(() => !this.nodeModel().resizing()), tap(() => {
2534
- const width = this.htmlWrapperRef().nativeElement.clientWidth;
2535
- const height = this.htmlWrapperRef().nativeElement.clientHeight;
2536
- this.nodeModel().size.set({ width, height });
2537
- }), takeUntilDestroyed())
2538
- .subscribe();
2539
- }
2594
+ }, { injector: this.injector });
2540
2595
  }
2541
2596
  ngOnDestroy() {
2542
2597
  this.draggableService.destroy(this.hostRef.nativeElement);
@@ -2556,22 +2611,16 @@ class NodeComponent {
2556
2611
  this.connectionController?.endConnection();
2557
2612
  }
2558
2613
  pullNode() {
2559
- this.nodeRenderingService.pullNode(this.nodeModel());
2614
+ this.nodeRenderingService.pullNode(this.model());
2560
2615
  }
2561
2616
  selectNode() {
2562
2617
  if (this.flowSettingsService.entitiesSelectable()) {
2563
- this.selectionService.select(this.nodeModel());
2618
+ this.selectionService.select(this.model());
2564
2619
  }
2565
2620
  }
2566
2621
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2567
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { nodeModel: { classPropertyName: "nodeModel", publicName: "nodeModel", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], viewQueries: [{ propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Default node -->\n@if (nodeModel().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n #htmlWrapper\n [selected]=\"nodeModel().selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\">\n <div [outerHTML]=\"nodeModel().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (nodeModel().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode()\">\n <div #htmlWrapper class=\"wrapper\" [style.width]=\"styleWidth()\" [style.height]=\"styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: { node: nodeModel().node, selected: nodeModel().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (nodeModel().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode()\">\n <div #htmlWrapper class=\"wrapper\" [style.width]=\"styleWidth()\" [style.height]=\"styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(nodeModel().node.type)\"\n [ngComponentOutletInputs]=\"nodeModel().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (nodeModel().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"nodeModel().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"nodeModel().color()\"\n [class.default-group-node_selected]=\"nodeModel().selected()\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n [style.stroke]=\"nodeModel().color()\"\n [style.fill]=\"nodeModel().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (nodeModel().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: nodeModel().node,\n selected: nodeModel().selected,\n width: nodeModel().width,\n height: nodeModel().height,\n },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (nodeModel().resizerTemplate(); as template) {\n @if (nodeModel().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of nodeModel().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().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]=\"nodeModel().magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2622
+ 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 }, 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().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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]=\"{\n $implicit: { node: model().node, selected: model().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.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().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: model().node,\n selected: model().selected,\n width: model().width,\n height: model().height,\n },\n }\"\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@if (toolbar(); as 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 }); }
2568
2623
  }
2569
- __decorate([
2570
- InjectionContext
2571
- ], NodeComponent.prototype, "ngOnInit", null);
2572
- __decorate([
2573
- InjectionContext
2574
- ], NodeComponent.prototype, "ngAfterViewInit", null);
2575
2624
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, decorators: [{
2576
2625
  type: Component,
2577
2626
  args: [{ standalone: true, selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService, NodeAccessorService], host: {
@@ -2584,8 +2633,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2584
2633
  NgComponentOutlet,
2585
2634
  ResizableComponent,
2586
2635
  HandleSizeControllerDirective,
2587
- ], template: "<!-- Default node -->\n@if (nodeModel().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n #htmlWrapper\n [selected]=\"nodeModel().selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\">\n <div [outerHTML]=\"nodeModel().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (nodeModel().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode()\">\n <div #htmlWrapper class=\"wrapper\" [style.width]=\"styleWidth()\" [style.height]=\"styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: { node: nodeModel().node, selected: nodeModel().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (nodeModel().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n (pointerStart)=\"pullNode()\">\n <div #htmlWrapper class=\"wrapper\" [style.width]=\"styleWidth()\" [style.height]=\"styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(nodeModel().node.type)\"\n [ngComponentOutletInputs]=\"nodeModel().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (nodeModel().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"nodeModel().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"nodeModel().color()\"\n [class.default-group-node_selected]=\"nodeModel().selected()\"\n [attr.width]=\"nodeModel().size().width\"\n [attr.height]=\"nodeModel().size().height\"\n [style.stroke]=\"nodeModel().color()\"\n [style.fill]=\"nodeModel().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (nodeModel().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: nodeModel().node,\n selected: nodeModel().selected,\n width: nodeModel().width,\n height: nodeModel().height,\n },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (nodeModel().resizerTemplate(); as template) {\n @if (nodeModel().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of nodeModel().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().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]=\"nodeModel().magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as 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"] }]
2588
- }], propDecorators: { ngOnInit: [], ngAfterViewInit: [] } });
2636
+ NodeHandlesControllerDirective,
2637
+ NodeResizeControllerDirective,
2638
+ ], template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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]=\"{\n $implicit: { node: model().node, selected: model().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\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().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.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().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: model().node,\n selected: model().selected,\n width: model().width,\n height: model().height,\n },\n }\"\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@if (toolbar(); as 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"] }]
2639
+ }] });
2589
2640
 
2590
2641
  class ConnectionComponent {
2591
2642
  constructor() {
@@ -3179,7 +3230,7 @@ class VflowComponent {
3179
3230
  ComponentEventBusService,
3180
3231
  KeyboardService,
3181
3232
  OverlaysService,
3182
- ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, 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 [nodeModel]=\"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 [nodeModel]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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 <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [nodeModel]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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: ["nodeModel", "nodeTemplate", "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 }); }
3233
+ ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, 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 [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 <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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", "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 }); }
3183
3234
  }
3184
3235
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, decorators: [{
3185
3236
  type: Component,
@@ -3209,7 +3260,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3209
3260
  NodeComponent,
3210
3261
  EdgeComponent,
3211
3262
  NgTemplateOutlet,
3212
- ], 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 [nodeModel]=\"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 [nodeModel]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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 <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [nodeModel]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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"] }]
3263
+ ], 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 [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 <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.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"] }]
3213
3264
  }], propDecorators: { view: [{
3214
3265
  type: Input
3215
3266
  }], minZoom: [{
@@ -3274,7 +3325,7 @@ class SelectableDirective {
3274
3325
  }
3275
3326
  entity() {
3276
3327
  if (this.parentNode) {
3277
- return this.parentNode.nodeModel();
3328
+ return this.parentNode.model();
3278
3329
  }
3279
3330
  else if (this.parentEdge) {
3280
3331
  return this.parentEdge.model();
@@ -3521,6 +3572,14 @@ function provideCustomNodeMocks() {
3521
3572
  pushEvent: () => { },
3522
3573
  },
3523
3574
  },
3575
+ {
3576
+ provide: NodeAccessorService,
3577
+ useFactory: () => ({
3578
+ model: signal(mockModel()),
3579
+ }),
3580
+ },
3581
+ FlowEntitiesService,
3582
+ // TODO: mocks below should be removed after the major release
3524
3583
  {
3525
3584
  provide: HandleService,
3526
3585
  useFactory: () => ({
@@ -3549,12 +3608,6 @@ function provideCustomNodeMocks() {
3549
3608
  documentPointToFlowPoint: (point) => point,
3550
3609
  },
3551
3610
  },
3552
- {
3553
- provide: NodeAccessorService,
3554
- useFactory: () => ({
3555
- model: signal(mockModel()),
3556
- }),
3557
- },
3558
3611
  {
3559
3612
  provide: SelectionService,
3560
3613
  useValue: {
@@ -3562,16 +3615,473 @@ function provideCustomNodeMocks() {
3562
3615
  },
3563
3616
  },
3564
3617
  FlowSettingsService,
3565
- FlowEntitiesService,
3566
3618
  ViewportService,
3567
3619
  ];
3568
3620
  }
3569
3621
 
3622
+ class EdgeTemplateMockDirective {
3623
+ constructor() {
3624
+ this.templateRef = inject(TemplateRef);
3625
+ }
3626
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3627
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: EdgeTemplateMockDirective, isStandalone: true, selector: "ng-template[edge]", ngImport: i0 }); }
3628
+ }
3629
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeTemplateMockDirective, decorators: [{
3630
+ type: Directive,
3631
+ args: [{
3632
+ standalone: true,
3633
+ selector: 'ng-template[edge]',
3634
+ }]
3635
+ }] });
3636
+ class ConnectionTemplateMockDirective {
3637
+ constructor() {
3638
+ this.templateRef = inject(TemplateRef);
3639
+ }
3640
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3641
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionTemplateMockDirective, isStandalone: true, selector: "ng-template[connection]", ngImport: i0 }); }
3642
+ }
3643
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionTemplateMockDirective, decorators: [{
3644
+ type: Directive,
3645
+ args: [{
3646
+ standalone: true,
3647
+ selector: 'ng-template[connection]',
3648
+ }]
3649
+ }] });
3650
+ class EdgeLabelHtmlTemplateMockDirective {
3651
+ constructor() {
3652
+ this.templateRef = inject(TemplateRef);
3653
+ }
3654
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeLabelHtmlTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3655
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: EdgeLabelHtmlTemplateMockDirective, isStandalone: true, selector: "ng-template[edgeLabelHtml]", ngImport: i0 }); }
3656
+ }
3657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeLabelHtmlTemplateMockDirective, decorators: [{
3658
+ type: Directive,
3659
+ args: [{
3660
+ standalone: true,
3661
+ selector: 'ng-template[edgeLabelHtml]',
3662
+ }]
3663
+ }] });
3664
+ class NodeHtmlTemplateMockDirective {
3665
+ constructor() {
3666
+ this.templateRef = inject(TemplateRef);
3667
+ }
3668
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeHtmlTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3669
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeHtmlTemplateMockDirective, isStandalone: true, selector: "ng-template[nodeHtml]", ngImport: i0 }); }
3670
+ }
3671
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeHtmlTemplateMockDirective, decorators: [{
3672
+ type: Directive,
3673
+ args: [{
3674
+ standalone: true,
3675
+ selector: 'ng-template[nodeHtml]',
3676
+ }]
3677
+ }] });
3678
+ class GroupNodeTemplateMockDirective {
3679
+ constructor() {
3680
+ this.templateRef = inject(TemplateRef);
3681
+ }
3682
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupNodeTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3683
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: GroupNodeTemplateMockDirective, isStandalone: true, selector: "ng-template[groupNode]", ngImport: i0 }); }
3684
+ }
3685
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupNodeTemplateMockDirective, decorators: [{
3686
+ type: Directive,
3687
+ args: [{
3688
+ standalone: true,
3689
+ selector: 'ng-template[groupNode]',
3690
+ }]
3691
+ }] });
3692
+ class HandleTemplateMockDirective {
3693
+ constructor() {
3694
+ this.templateRef = inject(TemplateRef);
3695
+ }
3696
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3697
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: HandleTemplateMockDirective, isStandalone: true, selector: "ng-template[handle]", ngImport: i0 }); }
3698
+ }
3699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleTemplateMockDirective, decorators: [{
3700
+ type: Directive,
3701
+ args: [{
3702
+ standalone: true,
3703
+ selector: 'ng-template[handle]',
3704
+ }]
3705
+ }] });
3706
+
3707
+ class VflowMockComponent {
3708
+ constructor() {
3709
+ this.nodes = input.required();
3710
+ this.edges = input.required();
3711
+ this.view = input([400, 400]);
3712
+ this.minZoom = input(0.5);
3713
+ this.maxZoom = input(3);
3714
+ this.background = input('#fff');
3715
+ this.optimization = input({
3716
+ detachedGroupsLayer: false,
3717
+ });
3718
+ this.entitiesSelectable = input(true);
3719
+ this.keyboardShortcuts = input({
3720
+ multiSelection: null,
3721
+ });
3722
+ this.connection = input();
3723
+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
3724
+ this.onComponentNodeEvent = output();
3725
+ this.nodeTemplateDirective = contentChild(NodeHtmlTemplateMockDirective);
3726
+ this.groupNodeTemplateDirective = contentChild(GroupNodeTemplateMockDirective);
3727
+ this.edgeTemplateDirective = contentChild(EdgeTemplateMockDirective);
3728
+ this.edgeLabelHtmlDirective = contentChild(EdgeLabelHtmlTemplateMockDirective);
3729
+ this.connectionTemplateDirective = contentChild(ConnectionTemplateMockDirective);
3730
+ this.viewport = signal({
3731
+ x: 0,
3732
+ y: 0,
3733
+ zoom: 1,
3734
+ });
3735
+ this.nodesChange = signal([]);
3736
+ this.edgesChange = signal([]);
3737
+ this.viewportChange$ = toObservable(this.viewport);
3738
+ this.nodesChange$ = toObservable(this.nodesChange);
3739
+ this.edgesChange$ = toObservable(this.edgesChange);
3740
+ }
3741
+ viewportTo(viewport) {
3742
+ this.viewport.set(viewport);
3743
+ }
3744
+ zoomTo(zoom) {
3745
+ this.viewport.update((prev) => ({ ...prev, zoom }));
3746
+ }
3747
+ panTo(point) {
3748
+ this.viewport.update((prev) => ({ ...prev, x: point.x, y: point.y }));
3749
+ }
3750
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3751
+ fitView(options) { }
3752
+ documentPointToFlowPoint(point) {
3753
+ return point;
3754
+ }
3755
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3756
+ getNode(id) {
3757
+ return this.nodes().find((node) => node.id === id);
3758
+ }
3759
+ getDetachedEdges() {
3760
+ return [];
3761
+ }
3762
+ createSignal(value) {
3763
+ return signal(value);
3764
+ }
3765
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3766
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: VflowMockComponent, isStandalone: true, selector: "vflow", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: true, transformFunction: null }, edges: { classPropertyName: "edges", publicName: "edges", isSignal: true, isRequired: true, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: true, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: true, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null }, optimization: { classPropertyName: "optimization", publicName: "optimization", isSignal: true, isRequired: false, transformFunction: null }, entitiesSelectable: { classPropertyName: "entitiesSelectable", publicName: "entitiesSelectable", isSignal: true, isRequired: false, transformFunction: null }, keyboardShortcuts: { classPropertyName: "keyboardShortcuts", publicName: "keyboardShortcuts", isSignal: true, isRequired: false, transformFunction: null }, connection: { classPropertyName: "connection", publicName: "connection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateMockDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
3767
+ <ng-content />
3768
+
3769
+ @for (node of nodes(); track $index) {
3770
+ @if (node.type === 'html-template') {
3771
+ <ng-component
3772
+ [ngTemplateOutlet]="nodeTemplateDirective()?.templateRef ?? null"
3773
+ [ngTemplateOutletContext]="{
3774
+ $implicit: {
3775
+ node: node,
3776
+ selected: createSignal(false),
3777
+ },
3778
+ }" />
3779
+ }
3780
+
3781
+ @if (node.type === 'template-group') {
3782
+ <ng-component
3783
+ [ngTemplateOutlet]="groupNodeTemplateDirective()?.templateRef ?? null"
3784
+ [ngTemplateOutletContext]="{
3785
+ $implicit: {
3786
+ node: node,
3787
+ selected: createSignal(false),
3788
+ width: createSignal(node.width),
3789
+ height: createSignal(node.height),
3790
+ },
3791
+ }" />
3792
+ }
3793
+ }
3794
+
3795
+ @for (edge of edges(); track $index) {
3796
+ @if (edge.type === 'template') {
3797
+ <ng-component
3798
+ [ngTemplateOutlet]="edgeTemplateDirective()?.templateRef ?? null"
3799
+ [ngTemplateOutletContext]="{
3800
+ $implicit: {
3801
+ edge: edge,
3802
+ selected: createSignal(false),
3803
+ path: createSignal(''),
3804
+ markerStart: createSignal(''),
3805
+ markerEnd: createSignal(''),
3806
+ },
3807
+ }" />
3808
+
3809
+ @if (edge.edgeLabels?.start) {
3810
+ <ng-component
3811
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3812
+ [ngTemplateOutletContext]="{
3813
+ $implicit: {
3814
+ edge: edge,
3815
+ },
3816
+ }" />
3817
+ }
3818
+
3819
+ @if (edge.edgeLabels?.center) {
3820
+ <ng-component
3821
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3822
+ [ngTemplateOutletContext]="{
3823
+ $implicit: {
3824
+ edge: edge,
3825
+ label: edge.edgeLabels?.center,
3826
+ },
3827
+ }" />
3828
+ }
3829
+
3830
+ @if (edge.edgeLabels?.end) {
3831
+ <ng-component
3832
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3833
+ [ngTemplateOutletContext]="{
3834
+ $implicit: {
3835
+ edge: edge,
3836
+ label: edge.edgeLabels?.end,
3837
+ },
3838
+ }" />
3839
+ }
3840
+ }
3841
+ }
3842
+
3843
+ @if (connection()?.type === 'template') {
3844
+ <ng-component
3845
+ [ngTemplateOutlet]="connectionTemplateDirective()?.templateRef ?? null"
3846
+ [ngTemplateOutletContext]="{
3847
+ $implicit: {
3848
+ path: createSignal(''),
3849
+ marker: createSignal(''),
3850
+ },
3851
+ }" />
3852
+ }
3853
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3854
+ }
3855
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowMockComponent, decorators: [{
3856
+ type: Component,
3857
+ args: [{
3858
+ selector: 'vflow',
3859
+ template: `
3860
+ <ng-content />
3861
+
3862
+ @for (node of nodes(); track $index) {
3863
+ @if (node.type === 'html-template') {
3864
+ <ng-component
3865
+ [ngTemplateOutlet]="nodeTemplateDirective()?.templateRef ?? null"
3866
+ [ngTemplateOutletContext]="{
3867
+ $implicit: {
3868
+ node: node,
3869
+ selected: createSignal(false),
3870
+ },
3871
+ }" />
3872
+ }
3873
+
3874
+ @if (node.type === 'template-group') {
3875
+ <ng-component
3876
+ [ngTemplateOutlet]="groupNodeTemplateDirective()?.templateRef ?? null"
3877
+ [ngTemplateOutletContext]="{
3878
+ $implicit: {
3879
+ node: node,
3880
+ selected: createSignal(false),
3881
+ width: createSignal(node.width),
3882
+ height: createSignal(node.height),
3883
+ },
3884
+ }" />
3885
+ }
3886
+ }
3887
+
3888
+ @for (edge of edges(); track $index) {
3889
+ @if (edge.type === 'template') {
3890
+ <ng-component
3891
+ [ngTemplateOutlet]="edgeTemplateDirective()?.templateRef ?? null"
3892
+ [ngTemplateOutletContext]="{
3893
+ $implicit: {
3894
+ edge: edge,
3895
+ selected: createSignal(false),
3896
+ path: createSignal(''),
3897
+ markerStart: createSignal(''),
3898
+ markerEnd: createSignal(''),
3899
+ },
3900
+ }" />
3901
+
3902
+ @if (edge.edgeLabels?.start) {
3903
+ <ng-component
3904
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3905
+ [ngTemplateOutletContext]="{
3906
+ $implicit: {
3907
+ edge: edge,
3908
+ },
3909
+ }" />
3910
+ }
3911
+
3912
+ @if (edge.edgeLabels?.center) {
3913
+ <ng-component
3914
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3915
+ [ngTemplateOutletContext]="{
3916
+ $implicit: {
3917
+ edge: edge,
3918
+ label: edge.edgeLabels?.center,
3919
+ },
3920
+ }" />
3921
+ }
3922
+
3923
+ @if (edge.edgeLabels?.end) {
3924
+ <ng-component
3925
+ [ngTemplateOutlet]="edgeLabelHtmlDirective()?.templateRef ?? null"
3926
+ [ngTemplateOutletContext]="{
3927
+ $implicit: {
3928
+ edge: edge,
3929
+ label: edge.edgeLabels?.end,
3930
+ },
3931
+ }" />
3932
+ }
3933
+ }
3934
+ }
3935
+
3936
+ @if (connection()?.type === 'template') {
3937
+ <ng-component
3938
+ [ngTemplateOutlet]="connectionTemplateDirective()?.templateRef ?? null"
3939
+ [ngTemplateOutletContext]="{
3940
+ $implicit: {
3941
+ path: createSignal(''),
3942
+ marker: createSignal(''),
3943
+ },
3944
+ }" />
3945
+ }
3946
+ `,
3947
+ changeDetection: ChangeDetectionStrategy.OnPush,
3948
+ standalone: true,
3949
+ imports: [NgTemplateOutlet],
3950
+ }]
3951
+ }] });
3952
+
3953
+ class HandleMockComponent {
3954
+ constructor() {
3955
+ this.position = input.required();
3956
+ this.type = input.required();
3957
+ this.id = input();
3958
+ this.template = input();
3959
+ }
3960
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3961
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: HandleMockComponent, isStandalone: true, selector: "handle", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3962
+ }
3963
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleMockComponent, decorators: [{
3964
+ type: Component,
3965
+ args: [{
3966
+ selector: 'handle',
3967
+ template: '',
3968
+ changeDetection: ChangeDetectionStrategy.OnPush,
3969
+ standalone: true,
3970
+ }]
3971
+ }] });
3972
+
3973
+ class ResizableMockComponent {
3974
+ constructor() {
3975
+ this.resizable = input();
3976
+ this.resizerColor = input('#2e414c');
3977
+ this.gap = input(1.5);
3978
+ }
3979
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizableMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3980
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: ResizableMockComponent, isStandalone: true, selector: "[resizable]", inputs: { resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, resizerColor: { classPropertyName: "resizerColor", publicName: "resizerColor", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<ng-content />', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3981
+ }
3982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizableMockComponent, decorators: [{
3983
+ type: Component,
3984
+ args: [{
3985
+ selector: '[resizable]',
3986
+ template: '<ng-content />',
3987
+ standalone: true,
3988
+ changeDetection: ChangeDetectionStrategy.OnPush,
3989
+ }]
3990
+ }] });
3991
+
3992
+ class MiniMapMockComponent {
3993
+ constructor() {
3994
+ this.maskColor = input(`rgba(215, 215, 215, 0.6)`);
3995
+ this.strokeColor = input(`rgb(200, 200, 200)`);
3996
+ this.position = input('bottom-right');
3997
+ this.scaleOnHover = input(false);
3998
+ }
3999
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MiniMapMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4000
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: MiniMapMockComponent, isStandalone: true, selector: "mini-map", inputs: { maskColor: { classPropertyName: "maskColor", publicName: "maskColor", isSignal: true, isRequired: false, transformFunction: null }, strokeColor: { classPropertyName: "strokeColor", publicName: "strokeColor", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, scaleOnHover: { classPropertyName: "scaleOnHover", publicName: "scaleOnHover", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4001
+ }
4002
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MiniMapMockComponent, decorators: [{
4003
+ type: Component,
4004
+ args: [{
4005
+ selector: 'mini-map',
4006
+ template: '',
4007
+ standalone: true,
4008
+ changeDetection: ChangeDetectionStrategy.OnPush,
4009
+ }]
4010
+ }] });
4011
+
4012
+ class NodeToolbarMockComponent {
4013
+ constructor() {
4014
+ this.position = input('top');
4015
+ }
4016
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeToolbarMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4017
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: NodeToolbarMockComponent, isStandalone: true, selector: "node-toolbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<ng-content />', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4018
+ }
4019
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeToolbarMockComponent, decorators: [{
4020
+ type: Component,
4021
+ args: [{
4022
+ selector: 'node-toolbar',
4023
+ template: '<ng-content />',
4024
+ standalone: true,
4025
+ changeDetection: ChangeDetectionStrategy.OnPush,
4026
+ }]
4027
+ }] });
4028
+
4029
+ class ConnectionControllerMockDirective {
4030
+ constructor() {
4031
+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
4032
+ this.onConnect = output();
4033
+ }
4034
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4035
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionControllerMockDirective, isStandalone: true, selector: "[onConnect]", outputs: { onConnect: "onConnect" }, ngImport: i0 }); }
4036
+ }
4037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerMockDirective, decorators: [{
4038
+ type: Directive,
4039
+ args: [{ selector: '[onConnect]', standalone: true }]
4040
+ }] });
4041
+
4042
+ class DragHandleMockDirective {
4043
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DragHandleMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4044
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: DragHandleMockDirective, isStandalone: true, selector: "[dragHandle]", ngImport: i0 }); }
4045
+ }
4046
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DragHandleMockDirective, decorators: [{
4047
+ type: Directive,
4048
+ args: [{ selector: '[dragHandle]', standalone: true }]
4049
+ }] });
4050
+
4051
+ class SelectableMockDirective {
4052
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4053
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectableMockDirective, isStandalone: true, selector: "[selectable]", ngImport: i0 }); }
4054
+ }
4055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableMockDirective, decorators: [{
4056
+ type: Directive,
4057
+ args: [{
4058
+ selector: '[selectable]',
4059
+ standalone: true,
4060
+ }]
4061
+ }] });
4062
+
4063
+ const VflowMocks = [
4064
+ VflowMockComponent,
4065
+ HandleMockComponent,
4066
+ ResizableMockComponent,
4067
+ SelectableMockDirective,
4068
+ MiniMapMockComponent,
4069
+ NodeToolbarMockComponent,
4070
+ DragHandleMockDirective,
4071
+ ConnectionControllerMockDirective,
4072
+ NodeHtmlTemplateMockDirective,
4073
+ GroupNodeTemplateMockDirective,
4074
+ EdgeLabelHtmlTemplateMockDirective,
4075
+ EdgeTemplateMockDirective,
4076
+ ConnectionTemplateMockDirective,
4077
+ HandleTemplateMockDirective,
4078
+ ];
4079
+
3570
4080
  // Standalone Util
3571
4081
 
3572
4082
  /**
3573
4083
  * Generated bundle index. Do not edit.
3574
4084
  */
3575
4085
 
3576
- export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, CustomDynamicNodeComponent, CustomNodeComponent, DragHandleDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, GroupNodeTemplateDirective, HandleComponent, HandleTemplateDirective, MiniMapComponent, NodeHtmlTemplateDirective, NodeToolbarComponent, NodeToolbarWrapperDirective, ResizableComponent, SelectableDirective, Vflow, VflowComponent, isComponentDynamicNode, isComponentStaticNode, isDefaultDynamicGroupNode, isDefaultDynamicNode, isDefaultStaticGroupNode, isDefaultStaticNode, isDynamicNode, isStaticNode, isTemplateDynamicGroupNode, isTemplateDynamicNode, isTemplateStaticGroupNode, isTemplateStaticNode, provideCustomNodeMocks };
4086
+ export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionControllerMockDirective, ConnectionTemplateDirective, ConnectionTemplateMockDirective, CustomDynamicNodeComponent, CustomNodeComponent, DragHandleDirective, DragHandleMockDirective, EdgeLabelHtmlTemplateDirective, EdgeLabelHtmlTemplateMockDirective, EdgeTemplateDirective, EdgeTemplateMockDirective, GroupNodeTemplateDirective, GroupNodeTemplateMockDirective, HandleComponent, HandleMockComponent, HandleTemplateDirective, HandleTemplateMockDirective, MiniMapComponent, MiniMapMockComponent, NodeHtmlTemplateDirective, NodeHtmlTemplateMockDirective, NodeToolbarComponent, NodeToolbarMockComponent, NodeToolbarWrapperDirective, ResizableComponent, ResizableMockComponent, SelectableDirective, SelectableMockDirective, Vflow, VflowComponent, VflowMockComponent, VflowMocks, isComponentDynamicNode, isComponentStaticNode, isDefaultDynamicGroupNode, isDefaultDynamicNode, isDefaultStaticGroupNode, isDefaultStaticNode, isDynamicNode, isStaticNode, isTemplateDynamicGroupNode, isTemplateDynamicNode, isTemplateStaticGroupNode, isTemplateStaticNode, provideCustomNodeMocks };
3577
4087
  //# sourceMappingURL=ngx-vflow.mjs.map