ngx-vflow 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/esm2022/lib/vflow/components/custom-node-base/custom-node-base.component.mjs +2 -2
  2. package/esm2022/lib/vflow/components/node/node.component.mjs +5 -4
  3. package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +11 -10
  4. package/esm2022/lib/vflow/directives/connection-controller.directive.mjs +5 -5
  5. package/esm2022/lib/vflow/directives/node-resize-controller.directive.mjs +4 -1
  6. package/esm2022/lib/vflow/directives/template.directive.mjs +18 -1
  7. package/esm2022/lib/vflow/interfaces/node.interface.mjs +7 -1
  8. package/esm2022/lib/vflow/interfaces/template-context.interface.mjs +1 -1
  9. package/esm2022/lib/vflow/models/handle.model.mjs +2 -2
  10. package/esm2022/lib/vflow/models/node.model.mjs +48 -70
  11. package/esm2022/lib/vflow/public-components/minimap/minimap.component.mjs +5 -5
  12. package/esm2022/lib/vflow/public-components/resizable/resizable.component.mjs +105 -44
  13. package/esm2022/lib/vflow/services/draggable.service.mjs +2 -4
  14. package/esm2022/lib/vflow/services/flow-entities.service.mjs +2 -2
  15. package/esm2022/lib/vflow/services/node-changes.service.mjs +6 -6
  16. package/esm2022/lib/vflow/services/overlays.service.mjs +4 -3
  17. package/esm2022/lib/vflow/services/viewport.service.mjs +2 -2
  18. package/esm2022/lib/vflow/testing-utils/directive-mocks/template-mock.directive.mjs +15 -1
  19. package/esm2022/lib/vflow/utils/add-nodes-to-edges.mjs +2 -2
  20. package/esm2022/lib/vflow/utils/align-number.mjs +4 -0
  21. package/esm2022/lib/vflow/utils/identity-checker/reference-identity-checker.mjs +31 -0
  22. package/esm2022/lib/vflow/utils/is-group-node.mjs +2 -2
  23. package/esm2022/lib/vflow/utils/to-unified-node.mjs +24 -0
  24. package/esm2022/lib/vflow/vflow.mjs +5 -4
  25. package/fesm2022/ngx-vflow.mjs +269 -165
  26. package/fesm2022/ngx-vflow.mjs.map +1 -1
  27. package/lib/vflow/components/node/node.component.d.ts +3 -2
  28. package/lib/vflow/components/vflow/vflow.component.d.ts +4 -3
  29. package/lib/vflow/directives/node-resize-controller.directive.d.ts +3 -0
  30. package/lib/vflow/directives/template.directive.d.ts +7 -1
  31. package/lib/vflow/interfaces/node.interface.d.ts +16 -2
  32. package/lib/vflow/interfaces/template-context.interface.d.ts +8 -0
  33. package/lib/vflow/models/node.model.d.ts +13 -17
  34. package/lib/vflow/public-components/minimap/minimap.component.d.ts +1 -1
  35. package/lib/vflow/public-components/resizable/resizable.component.d.ts +2 -0
  36. package/lib/vflow/services/overlays.service.d.ts +2 -2
  37. package/lib/vflow/testing-utils/directive-mocks/template-mock.directive.d.ts +5 -0
  38. package/lib/vflow/utils/align-number.d.ts +1 -0
  39. package/lib/vflow/utils/{reference-keeper.d.ts → identity-checker/reference-identity-checker.d.ts} +5 -5
  40. package/lib/vflow/utils/to-unified-node.d.ts +2 -0
  41. package/lib/vflow/vflow.d.ts +4 -4
  42. package/package.json +1 -1
  43. package/esm2022/lib/vflow/utils/reference-keeper.mjs +0 -31
@@ -120,7 +120,7 @@ class FlowEntitiesService {
120
120
  this.minimap = signal(null);
121
121
  }
122
122
  getNode(id) {
123
- return this.nodes().find(({ node }) => node.id === id);
123
+ return this.nodes().find(({ rawNode }) => rawNode.id === id);
124
124
  }
125
125
  getDetachedEdges() {
126
126
  return this.edges().filter((e) => e.detached());
@@ -217,7 +217,7 @@ class ViewportService {
217
217
  this.entitiesService.nodes()
218
218
  : // Otherwise fit to specific nodes
219
219
  nodeIds
220
- .map((nodeId) => this.entitiesService.nodes().find(({ node }) => node.id === nodeId))
220
+ .map((nodeId) => this.entitiesService.nodes().find(({ rawNode }) => rawNode.id === nodeId))
221
221
  .filter((node) => !!node);
222
222
  }
223
223
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -459,6 +459,10 @@ const evTarget = (anyEvent) => {
459
459
 
460
460
  const round = (num) => Math.round(num * 100) / 100;
461
461
 
462
+ function align(num, constant) {
463
+ return Math.ceil(num / constant) * constant;
464
+ }
465
+
462
466
  class DraggableService {
463
467
  constructor() {
464
468
  this.entitiesService = inject(FlowEntitiesService);
@@ -568,9 +572,6 @@ class DraggableService {
568
572
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DraggableService, decorators: [{
569
573
  type: Injectable
570
574
  }] });
571
- function align(num, constant) {
572
- return Math.ceil(num / constant) * constant;
573
- }
574
575
 
575
576
  class EdgeTemplateDirective {
576
577
  constructor() {
@@ -640,6 +641,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
640
641
  selector: 'ng-template[nodeHtml]',
641
642
  }]
642
643
  }] });
644
+ class NodeSvgTemplateDirective {
645
+ constructor() {
646
+ this.templateRef = inject(TemplateRef);
647
+ }
648
+ static ngTemplateContextGuard(dir, ctx) {
649
+ return true;
650
+ }
651
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeSvgTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
652
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeSvgTemplateDirective, isStandalone: true, selector: "ng-template[nodeSvg]", ngImport: i0 }); }
653
+ }
654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeSvgTemplateDirective, decorators: [{
655
+ type: Directive,
656
+ args: [{
657
+ standalone: true,
658
+ selector: 'ng-template[nodeSvg]',
659
+ }]
660
+ }] });
643
661
  class GroupNodeTemplateDirective {
644
662
  constructor() {
645
663
  this.templateRef = inject(TemplateRef);
@@ -674,7 +692,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
674
692
 
675
693
  function addNodesToEdges(nodes, edges) {
676
694
  const nodesById = nodes.reduce((acc, n) => {
677
- acc[n.node.id] = n;
695
+ acc[n.rawNode.id] = n;
678
696
  return acc;
679
697
  }, {});
680
698
  edges.forEach((e) => {
@@ -775,7 +793,7 @@ class CustomNodeBaseComponent {
775
793
  }
776
794
  return merge(...Array.from(emittersOrRefs.keys()).map((emitter) => emitter.pipe(tap((event) => {
777
795
  this.eventBus.pushEvent({
778
- nodeId: this.nodeService.model()?.node.id ?? '',
796
+ nodeId: this.nodeService.model()?.rawNode.id ?? '',
779
797
  eventName: emittersOrRefs.get(emitter),
780
798
  eventPayload: event,
781
799
  });
@@ -859,6 +877,12 @@ function isTemplateStaticNode(node) {
859
877
  function isTemplateDynamicNode(node) {
860
878
  return node.type === 'html-template';
861
879
  }
880
+ function isSvgTemplateStaticNode(node) {
881
+ return node.type === 'svg-template';
882
+ }
883
+ function isSvgTemplateDynamicNode(node) {
884
+ return node.type === 'html-template';
885
+ }
862
886
  function isDefaultStaticNode(node) {
863
887
  return node.type === 'default';
864
888
  }
@@ -882,18 +906,40 @@ function isTemplateDynamicGroupNode(node) {
882
906
  // the bug reproduces if edgeLabelWrapperRef size fully matched the size of parent foreignObject
883
907
  const MAGIC_NUMBER_TO_FIX_GLITCH_IN_CHROME = 2;
884
908
 
909
+ function toUnifiedNode(node) {
910
+ if (isDynamicNode(node)) {
911
+ return node;
912
+ }
913
+ return {
914
+ ...toSignalProperties(node),
915
+ // non-signal props below
916
+ id: node.id,
917
+ // TODO this actually of incorrect type for component nodes
918
+ type: node.type,
919
+ };
920
+ }
921
+ function toSignalProperties(obj) {
922
+ const newObj = {};
923
+ for (const key in obj) {
924
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
925
+ newObj[key] = signal(obj[key]);
926
+ }
927
+ }
928
+ return newObj;
929
+ }
930
+
885
931
  class NodeModel {
886
932
  static { this.defaultWidth = 100; }
887
933
  static { this.defaultHeight = 50; }
888
934
  static { this.defaultColor = '#1b262c'; }
889
- constructor(node) {
890
- this.node = node;
935
+ constructor(rawNode) {
936
+ this.rawNode = rawNode;
891
937
  this.entitiesService = inject(FlowEntitiesService);
892
- this.point = this.createInternalPointSignal();
938
+ this.point = signal({ x: 0, y: 0 });
893
939
  this.point$ = toObservable(this.point);
894
- this.width = this.createWidthSignal(NodeModel.defaultWidth);
940
+ this.width = signal(NodeModel.defaultWidth);
895
941
  this.width$ = toObservable(this.width);
896
- this.height = this.createHeightSignal(NodeModel.defaultHeight);
942
+ this.height = signal(NodeModel.defaultHeight);
897
943
  this.height$ = toObservable(this.height);
898
944
  /**
899
945
  * @deprecated use width or height signals
@@ -929,15 +975,15 @@ class NodeModel {
929
975
  // disabled for configuration for now
930
976
  this.magnetRadius = 20;
931
977
  // TODO: not sure if we need to statically store it
932
- this.isComponentType = isComponentStaticNode(this.node) || isComponentDynamicNode(this.node);
978
+ this.isComponentType = isComponentStaticNode(this.rawNode) || isComponentDynamicNode(this.rawNode);
933
979
  // Default node specific thing
934
- this.text = this.createTextSignal();
980
+ this.text = signal('');
935
981
  // Component node specific thing
936
982
  this.componentTypeInputs = {
937
- node: this.node,
983
+ node: this.rawNode,
938
984
  };
939
- this.parent = computed(() => this.entitiesService.nodes().find((n) => n.node.id === this.parentId()) ?? null);
940
- this.children = computed(() => this.entitiesService.nodes().filter((n) => n.parentId() === this.node.id));
985
+ this.parent = computed(() => this.entitiesService.nodes().find((n) => n.rawNode.id === this.parentId()) ?? null);
986
+ this.children = computed(() => this.entitiesService.nodes().filter((n) => n.parentId() === this.rawNode.id));
941
987
  this.color = signal(NodeModel.defaultColor);
942
988
  this.resizable = signal(false);
943
989
  this.resizing = signal(false);
@@ -946,50 +992,53 @@ class NodeModel {
946
992
  $implicit: {},
947
993
  };
948
994
  this.parentId = signal(null);
949
- if (isDefined(node.draggable)) {
950
- if (isDynamicNode(node)) {
951
- this.draggable = node.draggable;
952
- }
953
- else {
954
- this.draggable.set(node.draggable);
955
- }
995
+ const internalNode = toUnifiedNode(rawNode);
996
+ if (internalNode.point) {
997
+ this.point = internalNode.point;
956
998
  }
957
- if (isDefined(node.parentId)) {
958
- if (isDynamicNode(node)) {
959
- this.parentId = node.parentId;
960
- }
961
- else {
962
- this.parentId.set(node.parentId);
963
- }
999
+ if (internalNode.width) {
1000
+ this.width = internalNode.width;
964
1001
  }
965
- if (node.type === 'default-group' && node.color) {
966
- if (isDynamicNode(node)) {
967
- this.color = node.color;
968
- }
969
- else {
970
- this.color.set(node.color);
971
- }
1002
+ if (internalNode.height) {
1003
+ this.height = internalNode.height;
972
1004
  }
973
- if (node.type === 'default-group' && node.resizable) {
974
- if (isDynamicNode(node)) {
975
- this.resizable = node.resizable;
976
- }
977
- else {
978
- this.resizable.set(node.resizable);
979
- }
1005
+ if (internalNode.draggable) {
1006
+ this.draggable = internalNode.draggable;
1007
+ }
1008
+ if (internalNode.parentId) {
1009
+ this.parentId = internalNode.parentId;
1010
+ }
1011
+ if (internalNode.type === 'default-group' && internalNode.color) {
1012
+ this.color = internalNode.color;
1013
+ }
1014
+ if (internalNode.type === 'default-group' && internalNode.resizable) {
1015
+ this.resizable = internalNode.resizable;
1016
+ }
1017
+ if (internalNode.type === 'default' && internalNode.text) {
1018
+ this.text = internalNode.text;
980
1019
  }
981
- if (node.type === 'html-template') {
1020
+ if (internalNode.type === 'html-template') {
982
1021
  this.context = {
983
1022
  $implicit: {
984
- node: node,
1023
+ node: rawNode,
985
1024
  selected: this.selected,
986
1025
  },
987
1026
  };
988
1027
  }
989
- else if (node.type === 'template-group') {
1028
+ if (internalNode.type === 'svg-template') {
990
1029
  this.context = {
991
1030
  $implicit: {
992
- node: node,
1031
+ node: rawNode,
1032
+ selected: this.selected,
1033
+ width: this.width,
1034
+ height: this.height,
1035
+ },
1036
+ };
1037
+ }
1038
+ if (internalNode.type === 'template-group') {
1039
+ this.context = {
1040
+ $implicit: {
1041
+ node: rawNode,
993
1042
  selected: this.selected.asReadonly(),
994
1043
  width: this.width,
995
1044
  height: this.height,
@@ -1000,31 +1049,6 @@ class NodeModel {
1000
1049
  setPoint(point) {
1001
1050
  this.point.set(point);
1002
1051
  }
1003
- createTextSignal() {
1004
- const node = this.node;
1005
- if (node.type === 'default') {
1006
- if (isDynamicNode(node)) {
1007
- return node.text ?? signal('');
1008
- }
1009
- else {
1010
- return signal(node.text ?? '');
1011
- }
1012
- }
1013
- return signal('');
1014
- }
1015
- createInternalPointSignal() {
1016
- return isDynamicNode(this.node) ? this.node.point : signal({ x: this.node.point.x, y: this.node.point.y });
1017
- }
1018
- createWidthSignal(defaultValue) {
1019
- return isDynamicNode(this.node)
1020
- ? (this.node.width ?? signal(defaultValue))
1021
- : signal(this.node.width ?? defaultValue);
1022
- }
1023
- createHeightSignal(defaultValue) {
1024
- return isDynamicNode(this.node)
1025
- ? (this.node.height ?? signal(defaultValue))
1026
- : signal(this.node.height ?? defaultValue);
1027
- }
1028
1052
  }
1029
1053
 
1030
1054
  class EdgeLabelModel {
@@ -1410,13 +1434,13 @@ class EdgeModel {
1410
1434
  }
1411
1435
  }
1412
1436
 
1413
- class ReferenceKeeper {
1437
+ class ReferenceIdentityChecker {
1414
1438
  /**
1415
1439
  * Create new models for new node references and keep old models for old node references
1416
1440
  */
1417
1441
  static nodes(newNodes, oldNodeModels) {
1418
1442
  const oldNodesMap = new Map();
1419
- oldNodeModels.forEach((model) => oldNodesMap.set(model.node, model));
1443
+ oldNodeModels.forEach((model) => oldNodesMap.set(model.rawNode, model));
1420
1444
  return newNodes.map((newNode) => {
1421
1445
  if (oldNodesMap.has(newNode))
1422
1446
  return oldNodesMap.get(newNode);
@@ -1453,12 +1477,12 @@ class NodesChangeService {
1453
1477
  return this.entitiesService
1454
1478
  .nodes()
1455
1479
  .filter((node) => node === changedNode || node.selected())
1456
- .map((node) => ({ type: 'position', id: node.node.id, point: node.point() }));
1480
+ .map((node) => ({ type: 'position', id: node.rawNode.id, point: node.point() }));
1457
1481
  }));
1458
- this.nodeSizeChange$ = toObservable(this.entitiesService.nodes).pipe(switchMap((nodes) => merge(...nodes.map((node) => node.size$.pipe(skip(1), map(() => node))))), map((changedNode) => [{ type: 'size', id: changedNode.node.id, size: changedNode.size() }]));
1459
- this.nodeAddChange$ = toObservable(this.entitiesService.nodes).pipe(pairwise(), map(([oldList, newList]) => newList.filter((node) => !oldList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map((node) => ({ type: 'add', id: node.node.id }))));
1460
- this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes).pipe(pairwise(), map(([oldList, newList]) => oldList.filter((node) => !newList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map((node) => ({ type: 'remove', id: node.node.id }))));
1461
- this.nodeSelectedChange$ = toObservable(this.entitiesService.nodes).pipe(switchMap((nodes) => merge(...nodes.map((node) => node.selected$.pipe(distinctUntilChanged(), skip(1), map(() => node))))), map((changedNode) => [{ type: 'select', id: changedNode.node.id, selected: changedNode.selected() }]));
1482
+ this.nodeSizeChange$ = toObservable(this.entitiesService.nodes).pipe(switchMap((nodes) => merge(...nodes.map((node) => node.size$.pipe(skip(1), map(() => node))))), map((changedNode) => [{ type: 'size', id: changedNode.rawNode.id, size: changedNode.size() }]));
1483
+ this.nodeAddChange$ = toObservable(this.entitiesService.nodes).pipe(pairwise(), map(([oldList, newList]) => newList.filter((node) => !oldList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map((node) => ({ type: 'add', id: node.rawNode.id }))));
1484
+ this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes).pipe(pairwise(), map(([oldList, newList]) => oldList.filter((node) => !newList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map((node) => ({ type: 'remove', id: node.rawNode.id }))));
1485
+ this.nodeSelectedChange$ = toObservable(this.entitiesService.nodes).pipe(switchMap((nodes) => merge(...nodes.map((node) => node.selected$.pipe(distinctUntilChanged(), skip(1), map(() => node))))), map((changedNode) => [{ type: 'select', id: changedNode.rawNode.id, selected: changedNode.selected() }]));
1462
1486
  this.changes$ = merge(this.nodesPositionChange$, this.nodeSizeChange$, this.nodeAddChange$, this.nodeRemoveChange$, this.nodeSelectedChange$).pipe(
1463
1487
  // this fixes a bug when on fire node event change,
1464
1488
  // you can't get valid list of detached edges
@@ -1669,7 +1693,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1669
1693
  }] });
1670
1694
 
1671
1695
  function isGroupNode(node) {
1672
- return node.node.type === 'default-group' || node.node.type === 'template-group';
1696
+ return node.rawNode.type === 'default-group' || node.rawNode.type === 'template-group';
1673
1697
  }
1674
1698
 
1675
1699
  class NodeRenderingService {
@@ -1816,10 +1840,11 @@ function Microtask(target, key, descriptor) {
1816
1840
  class OverlaysService {
1817
1841
  constructor() {
1818
1842
  this.toolbars = signal([]);
1819
- this.nodeToolbars = computed(() => {
1843
+ this.nodeToolbarsMap = computed(() => {
1820
1844
  const map = new Map();
1821
1845
  this.toolbars().forEach((toolbar) => {
1822
- map.set(toolbar.node, toolbar);
1846
+ const existing = map.get(toolbar.node) ?? [];
1847
+ map.set(toolbar.node, [...existing, toolbar]);
1823
1848
  });
1824
1849
  return map;
1825
1850
  });
@@ -2002,8 +2027,8 @@ class ConnectionControllerDirective {
2002
2027
  targetHandle = adjusted.targetHandle;
2003
2028
  }
2004
2029
  const valid = this.flowEntitiesService.connection().validator({
2005
- source: source.node.id,
2006
- target: target.node.id,
2030
+ source: source.rawNode.id,
2031
+ target: target.rawNode.id,
2007
2032
  sourceHandle: sourceHandle.rawHandle.id,
2008
2033
  targetHandle: targetHandle.rawHandle.id,
2009
2034
  });
@@ -2068,8 +2093,8 @@ function statusToConnection(status, isStrictMode) {
2068
2093
  sourceHandle = adjusted.sourceHandle;
2069
2094
  targetHandle = adjusted.targetHandle;
2070
2095
  }
2071
- const sourceId = source.node.id;
2072
- const targetId = target.node.id;
2096
+ const sourceId = source.rawNode.id;
2097
+ const targetId = target.rawNode.id;
2073
2098
  const sourceHandleId = sourceHandle.rawHandle.id;
2074
2099
  const targetHandleId = targetHandle.rawHandle.id;
2075
2100
  return {
@@ -2319,6 +2344,7 @@ class ResizableComponent {
2319
2344
  this.rootPointer = inject(RootPointerDirective);
2320
2345
  this.viewportService = inject(ViewportService);
2321
2346
  this.spacePointContext = inject(SpacePointContextDirective);
2347
+ this.settingsService = inject(FlowSettingsService);
2322
2348
  this.hostRef = inject(ElementRef);
2323
2349
  this.resizable = input();
2324
2350
  this.resizerColor = input('#2e414c');
@@ -2363,7 +2389,7 @@ class ResizableComponent {
2363
2389
  if (!this.resizeSide)
2364
2390
  return;
2365
2391
  const offset = calcOffset(event.movementX, event.movementY, this.zoom());
2366
- const resized = applyResize(this.resizeSide, this.model, offset, this.getDistanceToEdge(event));
2392
+ const resized = this.applyResize(this.resizeSide, this.model, offset, this.getDistanceToEdge(event));
2367
2393
  const { x, y, width, height } = constrainRect(resized, this.model, this.resizeSide, this.minWidth, this.minHeight);
2368
2394
  this.model.setPoint({ x, y });
2369
2395
  this.model.width.set(width);
@@ -2383,6 +2409,104 @@ class ResizableComponent {
2383
2409
  bottom: flowPoint.y - (y + this.model.height()),
2384
2410
  };
2385
2411
  }
2412
+ applyResize(side, model, offset, distanceToEdge) {
2413
+ const { x, y } = model.point();
2414
+ const width = model.width();
2415
+ const height = model.height();
2416
+ const [snapX, snapY] = this.settingsService.snapGrid();
2417
+ switch (side) {
2418
+ case 'left': {
2419
+ const movementX = offset.x + distanceToEdge.left;
2420
+ const newX = align(x + movementX, snapX);
2421
+ const deltaX = newX - x;
2422
+ return {
2423
+ x: newX,
2424
+ y,
2425
+ width: width - deltaX,
2426
+ height,
2427
+ };
2428
+ }
2429
+ case 'right': {
2430
+ const movementX = offset.x + distanceToEdge.right;
2431
+ const newWidth = align(width + movementX, snapX);
2432
+ return {
2433
+ x,
2434
+ y,
2435
+ width: newWidth,
2436
+ height,
2437
+ };
2438
+ }
2439
+ case 'top': {
2440
+ const movementY = offset.y + distanceToEdge.top;
2441
+ const newY = align(y + movementY, snapY);
2442
+ const deltaY = newY - y;
2443
+ return {
2444
+ x,
2445
+ y: newY,
2446
+ width,
2447
+ height: height - deltaY,
2448
+ };
2449
+ }
2450
+ case 'bottom': {
2451
+ const movementY = offset.y + distanceToEdge.bottom;
2452
+ const newHeight = align(height + movementY, snapY);
2453
+ return {
2454
+ x,
2455
+ y,
2456
+ width,
2457
+ height: newHeight,
2458
+ };
2459
+ }
2460
+ case 'top-left': {
2461
+ const movementX = offset.x + distanceToEdge.left;
2462
+ const movementY = offset.y + distanceToEdge.top;
2463
+ const newX = align(x + movementX, snapX);
2464
+ const newY = align(y + movementY, snapY);
2465
+ const deltaX = newX - x;
2466
+ const deltaY = newY - y;
2467
+ return {
2468
+ x: newX,
2469
+ y: newY,
2470
+ width: width - deltaX,
2471
+ height: height - deltaY,
2472
+ };
2473
+ }
2474
+ case 'top-right': {
2475
+ const movementX = offset.x + distanceToEdge.right;
2476
+ const movementY = offset.y + distanceToEdge.top;
2477
+ const newY = align(y + movementY, snapY);
2478
+ const deltaY = newY - y;
2479
+ return {
2480
+ x,
2481
+ y: newY,
2482
+ width: align(width + movementX, snapX),
2483
+ height: height - deltaY,
2484
+ };
2485
+ }
2486
+ case 'bottom-left': {
2487
+ const movementX = offset.x + distanceToEdge.left;
2488
+ const movementY = offset.y + distanceToEdge.bottom;
2489
+ const newX = align(x + movementX, snapX);
2490
+ const deltaX = newX - x;
2491
+ return {
2492
+ x: newX,
2493
+ y,
2494
+ width: width - deltaX,
2495
+ height: align(height + movementY, snapY),
2496
+ };
2497
+ }
2498
+ case 'bottom-right': {
2499
+ const movementX = offset.x + distanceToEdge.right;
2500
+ const movementY = offset.y + distanceToEdge.bottom;
2501
+ return {
2502
+ x,
2503
+ y,
2504
+ width: align(width + movementX, snapX),
2505
+ height: align(height + movementY, snapY),
2506
+ };
2507
+ }
2508
+ }
2509
+ }
2386
2510
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2387
2511
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "17.3.12", type: ResizableComponent, 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 } }, viewQueries: [{ propertyName: "resizer", first: true, predicate: ["resizer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #resizer>\n <svg:g>\n <!-- top line -->\n <svg:line\n class=\"top\"\n stroke-width=\"2\"\n [attr.x1]=\"lineGap\"\n [attr.y1]=\"-gap()\"\n [attr.x2]=\"model.size().width - lineGap\"\n [attr.y2]=\"-gap()\"\n [attr.stroke]=\"resizerColor()\"\n (pointerStart)=\"startResize('top', $event)\" />\n <!-- Left line -->\n <svg:line\n class=\"left\"\n stroke-width=\"2\"\n [attr.x1]=\"-gap()\"\n [attr.y1]=\"lineGap\"\n [attr.x2]=\"-gap()\"\n [attr.y2]=\"model.size().height - lineGap\"\n [attr.stroke]=\"resizerColor()\"\n (pointerStart)=\"startResize('left', $event)\" />\n <!-- Bottom line -->\n <svg:line\n class=\"bottom\"\n stroke-width=\"2\"\n [attr.x1]=\"lineGap\"\n [attr.y1]=\"model.size().height + gap()\"\n [attr.x2]=\"model.size().width - lineGap\"\n [attr.y2]=\"model.size().height + gap()\"\n [attr.stroke]=\"resizerColor()\"\n (pointerStart)=\"startResize('bottom', $event)\" />\n <!-- Right line -->\n <svg:line\n class=\"right\"\n stroke-width=\"2\"\n [attr.x1]=\"model.size().width + gap()\"\n [attr.y1]=\"lineGap\"\n [attr.x2]=\"model.size().width + gap()\"\n [attr.y2]=\"model.size().height - lineGap\"\n [attr.stroke]=\"resizerColor()\"\n (pointerStart)=\"startResize('right', $event)\" />\n\n <!-- Top Left -->\n <svg:rect\n class=\"top-left\"\n [attr.x]=\"-(handleSize / 2) - gap()\"\n [attr.y]=\"-(handleSize / 2) - gap()\"\n [attr.width]=\"handleSize\"\n [attr.height]=\"handleSize\"\n [attr.fill]=\"resizerColor()\"\n (pointerStart)=\"startResize('top-left', $event)\" />\n\n <!-- Top right -->\n <svg:rect\n class=\"top-right\"\n [attr.x]=\"model.size().width - handleSize / 2 + gap()\"\n [attr.y]=\"-(handleSize / 2) - gap()\"\n [attr.width]=\"handleSize\"\n [attr.height]=\"handleSize\"\n [attr.fill]=\"resizerColor()\"\n (pointerStart)=\"startResize('top-right', $event)\" />\n\n <!-- Bottom left -->\n <svg:rect\n class=\"bottom-left\"\n [attr.x]=\"-(handleSize / 2) - gap()\"\n [attr.y]=\"model.size().height - handleSize / 2 + gap()\"\n [attr.width]=\"handleSize\"\n [attr.height]=\"handleSize\"\n [attr.fill]=\"resizerColor()\"\n (pointerStart)=\"startResize('bottom-left', $event)\" />\n\n <!-- Bottom right -->\n <svg:rect\n class=\"bottom-right\"\n [attr.x]=\"model.size().width - handleSize / 2 + gap()\"\n [attr.y]=\"model.size().height - handleSize / 2 + gap()\"\n [attr.width]=\"handleSize\"\n [attr.height]=\"handleSize\"\n [attr.fill]=\"resizerColor()\"\n (pointerStart)=\"startResize('bottom-right', $event)\" />\n </svg:g>\n</ng-template>\n\n<ng-content />\n", styles: [".top{cursor:n-resize}.left{cursor:w-resize}.right{cursor:e-resize}.bottom{cursor:s-resize}.top-left{cursor:nw-resize}.top-right{cursor:ne-resize}.bottom-left{cursor:sw-resize}.bottom-right{cursor:se-resize}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2388
2512
  }
@@ -2395,50 +2519,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2395
2519
  }], ctorParameters: () => [], propDecorators: { ngAfterViewInit: [] } });
2396
2520
  function calcOffset(movementX, movementY, zoom) {
2397
2521
  return {
2398
- offsetX: round(movementX / zoom),
2399
- offsetY: round(movementY / zoom),
2522
+ x: round(movementX / zoom),
2523
+ y: round(movementY / zoom),
2400
2524
  };
2401
2525
  }
2402
- function applyResize(side, model, offset, distanceToEdge) {
2403
- const { offsetX, offsetY } = offset;
2404
- const { x, y } = model.point();
2405
- const width = model.width();
2406
- const height = model.height();
2407
- // Handle each case of resizing (top, bottom, left, right, corners)
2408
- switch (side) {
2409
- case 'left':
2410
- return { x: x + offsetX + distanceToEdge.left, y, width: width - offsetX - distanceToEdge.left, height };
2411
- case 'right':
2412
- return { x, y, width: width + offsetX + distanceToEdge.right, height };
2413
- case 'top':
2414
- return { x, y: y + offsetY + distanceToEdge.top, width, height: height - offsetY - distanceToEdge.top };
2415
- case 'bottom':
2416
- return { x, y, width, height: height + offsetY + distanceToEdge.bottom };
2417
- case 'top-left':
2418
- return {
2419
- x: x + offsetX + distanceToEdge.left,
2420
- y: y + offsetY + distanceToEdge.top,
2421
- width: width - offsetX - distanceToEdge.left,
2422
- height: height - offsetY - distanceToEdge.top,
2423
- };
2424
- case 'top-right':
2425
- return {
2426
- x,
2427
- y: y + offsetY + distanceToEdge.top,
2428
- width: width + offsetX + distanceToEdge.right,
2429
- height: height - offsetY - distanceToEdge.top,
2430
- };
2431
- case 'bottom-left':
2432
- return {
2433
- x: x + offsetX + distanceToEdge.left,
2434
- y,
2435
- width: width - offsetX - distanceToEdge.left,
2436
- height: height + offsetY + distanceToEdge.bottom,
2437
- };
2438
- case 'bottom-right':
2439
- return { x, y, width: width + offsetX + distanceToEdge.right, height: height + offsetY + distanceToEdge.bottom };
2440
- }
2441
- }
2442
2526
  function constrainRect(rect, model, side, minWidth, minHeight) {
2443
2527
  let { x, y, width, height } = rect;
2444
2528
  // 1. Prevent negative dimensions
@@ -2568,7 +2652,7 @@ class HandleModel {
2568
2652
  $implicit: {
2569
2653
  point: this.hostOffset,
2570
2654
  state: this.state,
2571
- node: this.parentNode.node,
2655
+ node: this.parentNode.rawNode,
2572
2656
  },
2573
2657
  };
2574
2658
  }
@@ -2661,6 +2745,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2661
2745
  }]
2662
2746
  }] });
2663
2747
 
2748
+ /**
2749
+ * Only suitable for HTML nodes
2750
+ */
2664
2751
  class NodeResizeControllerDirective {
2665
2752
  constructor() {
2666
2753
  this.nodeAccessor = inject(NodeAccessorService);
@@ -2706,12 +2793,13 @@ class NodeComponent {
2706
2793
  this.connectionController = inject(ConnectionControllerDirective, { optional: true });
2707
2794
  this.model = input.required();
2708
2795
  this.nodeTemplate = input();
2796
+ this.nodeSvgTemplate = input();
2709
2797
  this.groupNodeTemplate = input();
2710
2798
  this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
2711
2799
  this.flowStatusService.status().state === 'connection-validation' ||
2712
2800
  this.flowStatusService.status().state === 'reconnection-start' ||
2713
2801
  this.flowStatusService.status().state === 'reconnection-validation');
2714
- this.toolbar = computed(() => this.overlaysService.nodeToolbars().get(this.model()));
2802
+ this.toolbars = computed(() => this.overlaysService.nodeToolbarsMap().get(this.model()));
2715
2803
  }
2716
2804
  ngOnInit() {
2717
2805
  this.nodeAccessor.model.set(this.model());
@@ -2753,7 +2841,7 @@ class NodeComponent {
2753
2841
  }
2754
2842
  }
2755
2843
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2756
- 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().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().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]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@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 }); }
2844
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, nodeSvgTemplate: { classPropertyName: "nodeSvgTemplate", publicName: "nodeSvgTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], ngImport: i0, template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }, { kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ResizableComponent, selector: "[resizable]", inputs: ["resizable", "resizerColor", "gap"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: NodeHandlesControllerDirective, selector: "[nodeHandlesController]" }, { kind: "directive", type: NodeResizeControllerDirective, selector: "[nodeResizeController]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2757
2845
  }
2758
2846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, decorators: [{
2759
2847
  type: Component,
@@ -2769,7 +2857,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2769
2857
  HandleSizeControllerDirective,
2770
2858
  NodeHandlesControllerDirective,
2771
2859
  NodeResizeControllerDirective,
2772
- ], template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().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]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@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"] }]
2860
+ ], template: "<!-- Default node -->\n@if (model().rawNode.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- HTML Template node -->\n@if (model().rawNode.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- SVG Template node -->\n@if (model().rawNode.type === 'svg-template' && nodeSvgTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeSvgTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().rawNode.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().rawNode.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().rawNode.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@for (toolbar of toolbars(); track toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
2773
2861
  }] });
2774
2862
 
2775
2863
  class ConnectionComponent {
@@ -3161,6 +3249,7 @@ class VflowComponent {
3161
3249
  // #endregion
3162
3250
  // #region TEMPLATES
3163
3251
  this.nodeTemplateDirective = contentChild(NodeHtmlTemplateDirective);
3252
+ this.nodeSvgTemplateDirective = contentChild(NodeSvgTemplateDirective);
3164
3253
  this.groupNodeTemplateDirective = contentChild(GroupNodeTemplateDirective);
3165
3254
  this.edgeTemplateDirective = contentChild(EdgeTemplateDirective);
3166
3255
  this.edgeLabelHtmlDirective = contentChild(EdgeLabelHtmlTemplateDirective);
@@ -3279,7 +3368,7 @@ class VflowComponent {
3279
3368
  * Nodes to render
3280
3369
  */
3281
3370
  set nodes(newNodes) {
3282
- const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.nodes(newNodes, this.flowEntitiesService.nodes()));
3371
+ const newModels = runInInjectionContext(this.injector, () => ReferenceIdentityChecker.nodes(newNodes, this.flowEntitiesService.nodes()));
3283
3372
  // quick and dirty binding nodes to edges
3284
3373
  addNodesToEdges(newModels, this.flowEntitiesService.edges());
3285
3374
  this.flowEntitiesService.nodes.set(newModels);
@@ -3288,7 +3377,7 @@ class VflowComponent {
3288
3377
  * Edges to render
3289
3378
  */
3290
3379
  set edges(newEdges) {
3291
- const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.edges(newEdges, this.flowEntitiesService.edges()));
3380
+ const newModels = runInInjectionContext(this.injector, () => ReferenceIdentityChecker.edges(newEdges, this.flowEntitiesService.edges()));
3292
3381
  // quick and dirty binding nodes to edges
3293
3382
  addNodesToEdges(this.nodeModels(), newModels);
3294
3383
  this.flowEntitiesService.edges.set(newModels);
@@ -3342,7 +3431,7 @@ class VflowComponent {
3342
3431
  * @param id node id
3343
3432
  */
3344
3433
  getNode(id) {
3345
- return this.flowEntitiesService.getNode(id)?.node;
3434
+ return this.flowEntitiesService.getNode(id)?.rawNode;
3346
3435
  }
3347
3436
  /**
3348
3437
  * Sync method to get detached edges
@@ -3357,7 +3446,7 @@ class VflowComponent {
3357
3446
  return this.spacePointContext().documentPointToFlowPoint(point);
3358
3447
  }
3359
3448
  // #endregion
3360
- trackNodes(idx, { node }) {
3449
+ trackNodes(idx, { rawNode: node }) {
3361
3450
  return node;
3362
3451
  }
3363
3452
  trackEdges(idx, { edge }) {
@@ -3365,7 +3454,7 @@ class VflowComponent {
3365
3454
  }
3366
3455
  setInitialNodesOrder() {
3367
3456
  this.nodeModels().forEach((model) => {
3368
- switch (model.node.type) {
3457
+ switch (model.rawNode.type) {
3369
3458
  case 'default-group':
3370
3459
  case 'template-group': {
3371
3460
  this.nodeRenderingService.pullNode(model);
@@ -3388,7 +3477,7 @@ class VflowComponent {
3388
3477
  ComponentEventBusService,
3389
3478
  KeyboardService,
3390
3479
  OverlaysService,
3391
- ], 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 }); }
3480
+ ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3392
3481
  }
3393
3482
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, decorators: [{
3394
3483
  type: Component,
@@ -3419,7 +3508,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3419
3508
  NodeComponent,
3420
3509
  EdgeComponent,
3421
3510
  NgTemplateOutlet,
3422
- ], 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"] }]
3511
+ ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
3423
3512
  }], propDecorators: { view: [{
3424
3513
  type: Input
3425
3514
  }], minZoom: [{
@@ -3609,15 +3698,15 @@ class MiniMapComponent {
3609
3698
  model.template.set(this.minimap());
3610
3699
  this.entitiesService.minimap.set(model);
3611
3700
  }
3612
- trackNodes(idx, { node }) {
3613
- return node;
3701
+ trackNodes(idx, { rawNode }) {
3702
+ return rawNode;
3614
3703
  }
3615
3704
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MiniMapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3616
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MiniMapComponent, 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 } }, viewQueries: [{ propertyName: "minimap", first: true, predicate: ["minimap"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #minimap>\n <svg:rect\n fill=\"none\"\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n [attr.stroke]=\"strokeColor()\" />\n\n <svg:svg\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n (mouseover)=\"hovered.set(true)\"\n (mouseleave)=\"hovered.set(false)\">\n <svg:rect [attr.width]=\"minimapWidth()\" [attr.height]=\"minimapHeight()\" [attr.fill]=\"maskColor()\" />\n\n <svg:g [attr.transform]=\"minimapTransform()\">\n <svg:rect\n [attr.fill]=\"viewportColor()\"\n [attr.transform]=\"viewportTransform()\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\" />\n\n @for (model of entitiesService.nodes(); track trackNodes($index, model)) {\n <ng-container>\n @if (model.node.type === 'default' || model.node.type === 'html-template' || model.isComponentType) {\n <svg:foreignObject\n [attr.transform]=\"model.pointTransform()\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <default-node\n [selected]=\"model.selected()\"\n [style.width.px]=\"model.size().width\"\n [style.height.px]=\"model.size().height\"\n [style.max-width.px]=\"model.size().width\"\n [style.max-height.px]=\"model.size().height\">\n <div [outerHTML]=\"model.text()\"></div>\n </default-node>\n </svg:foreignObject>\n }\n @if (model.node.type === 'default-group' || model.node.type === 'template-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [attr.transform]=\"model.pointTransform()\"\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 }\n </ng-container>\n }\n </svg:g>\n </svg:svg>\n</ng-template>\n", styles: [".default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}\n"], dependencies: [{ kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3705
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MiniMapComponent, 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 } }, viewQueries: [{ propertyName: "minimap", first: true, predicate: ["minimap"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #minimap>\n <svg:rect\n fill=\"none\"\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n [attr.stroke]=\"strokeColor()\" />\n\n <svg:svg\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n (mouseover)=\"hovered.set(true)\"\n (mouseleave)=\"hovered.set(false)\">\n <svg:rect [attr.width]=\"minimapWidth()\" [attr.height]=\"minimapHeight()\" [attr.fill]=\"maskColor()\" />\n\n <svg:g [attr.transform]=\"minimapTransform()\">\n <svg:rect\n [attr.fill]=\"viewportColor()\"\n [attr.transform]=\"viewportTransform()\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\" />\n\n @for (model of entitiesService.nodes(); track trackNodes($index, model)) {\n <ng-container>\n @if (model.rawNode.type === 'default' || model.rawNode.type === 'html-template' || model.isComponentType) {\n <svg:foreignObject\n [attr.transform]=\"model.pointTransform()\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <default-node\n [selected]=\"model.selected()\"\n [style.width.px]=\"model.size().width\"\n [style.height.px]=\"model.size().height\"\n [style.max-width.px]=\"model.size().width\"\n [style.max-height.px]=\"model.size().height\">\n <div [outerHTML]=\"model.text()\"></div>\n </default-node>\n </svg:foreignObject>\n }\n @if (model.rawNode.type === 'default-group' || model.rawNode.type === 'template-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [attr.transform]=\"model.pointTransform()\"\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 }\n </ng-container>\n }\n </svg:g>\n </svg:svg>\n</ng-template>\n", styles: [".default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}\n"], dependencies: [{ kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3617
3706
  }
3618
3707
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MiniMapComponent, decorators: [{
3619
3708
  type: Component,
3620
- args: [{ standalone: true, selector: 'mini-map', imports: [DefaultNodeComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #minimap>\n <svg:rect\n fill=\"none\"\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n [attr.stroke]=\"strokeColor()\" />\n\n <svg:svg\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n (mouseover)=\"hovered.set(true)\"\n (mouseleave)=\"hovered.set(false)\">\n <svg:rect [attr.width]=\"minimapWidth()\" [attr.height]=\"minimapHeight()\" [attr.fill]=\"maskColor()\" />\n\n <svg:g [attr.transform]=\"minimapTransform()\">\n <svg:rect\n [attr.fill]=\"viewportColor()\"\n [attr.transform]=\"viewportTransform()\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\" />\n\n @for (model of entitiesService.nodes(); track trackNodes($index, model)) {\n <ng-container>\n @if (model.node.type === 'default' || model.node.type === 'html-template' || model.isComponentType) {\n <svg:foreignObject\n [attr.transform]=\"model.pointTransform()\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <default-node\n [selected]=\"model.selected()\"\n [style.width.px]=\"model.size().width\"\n [style.height.px]=\"model.size().height\"\n [style.max-width.px]=\"model.size().width\"\n [style.max-height.px]=\"model.size().height\">\n <div [outerHTML]=\"model.text()\"></div>\n </default-node>\n </svg:foreignObject>\n }\n @if (model.node.type === 'default-group' || model.node.type === 'template-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [attr.transform]=\"model.pointTransform()\"\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 }\n </ng-container>\n }\n </svg:g>\n </svg:svg>\n</ng-template>\n", styles: [".default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}\n"] }]
3709
+ args: [{ standalone: true, selector: 'mini-map', imports: [DefaultNodeComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #minimap>\n <svg:rect\n fill=\"none\"\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n [attr.stroke]=\"strokeColor()\" />\n\n <svg:svg\n [attr.x]=\"minimapPoint().x\"\n [attr.y]=\"minimapPoint().y\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\"\n (mouseover)=\"hovered.set(true)\"\n (mouseleave)=\"hovered.set(false)\">\n <svg:rect [attr.width]=\"minimapWidth()\" [attr.height]=\"minimapHeight()\" [attr.fill]=\"maskColor()\" />\n\n <svg:g [attr.transform]=\"minimapTransform()\">\n <svg:rect\n [attr.fill]=\"viewportColor()\"\n [attr.transform]=\"viewportTransform()\"\n [attr.width]=\"minimapWidth()\"\n [attr.height]=\"minimapHeight()\" />\n\n @for (model of entitiesService.nodes(); track trackNodes($index, model)) {\n <ng-container>\n @if (model.rawNode.type === 'default' || model.rawNode.type === 'html-template' || model.isComponentType) {\n <svg:foreignObject\n [attr.transform]=\"model.pointTransform()\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <default-node\n [selected]=\"model.selected()\"\n [style.width.px]=\"model.size().width\"\n [style.height.px]=\"model.size().height\"\n [style.max-width.px]=\"model.size().width\"\n [style.max-height.px]=\"model.size().height\">\n <div [outerHTML]=\"model.text()\"></div>\n </default-node>\n </svg:foreignObject>\n }\n @if (model.rawNode.type === 'default-group' || model.rawNode.type === 'template-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [attr.transform]=\"model.pointTransform()\"\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 }\n </ng-container>\n }\n </svg:g>\n </svg:svg>\n</ng-template>\n", styles: [".default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}\n"] }]
3621
3710
  }] });
3622
3711
 
3623
3712
  class ToolbarModel {
@@ -3712,24 +3801,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3712
3801
  }]
3713
3802
  }] });
3714
3803
 
3715
- const Vflow = [
3716
- VflowComponent,
3717
- HandleComponent,
3718
- ResizableComponent,
3719
- SelectableDirective,
3720
- MiniMapComponent,
3721
- NodeToolbarComponent,
3722
- CustomTemplateEdgeComponent,
3723
- DragHandleDirective,
3724
- ConnectionControllerDirective,
3725
- NodeHtmlTemplateDirective,
3726
- GroupNodeTemplateDirective,
3727
- EdgeLabelHtmlTemplateDirective,
3728
- EdgeTemplateDirective,
3729
- ConnectionTemplateDirective,
3730
- HandleTemplateDirective,
3731
- ];
3732
-
3733
3804
  class CustomTemplateEdgeComponent {
3734
3805
  constructor() {
3735
3806
  this.edge = inject(EdgeComponent);
@@ -3754,6 +3825,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3754
3825
  }, template: "<ng-content />\n\n<svg:path #interactiveEdge class=\"interactive-edge\" [attr.d]=\"context.path()\" />\n", styles: [".interactive-edge{fill:none;stroke-width:20;stroke:transparent}\n"] }]
3755
3826
  }] });
3756
3827
 
3828
+ const Vflow = [
3829
+ VflowComponent,
3830
+ HandleComponent,
3831
+ ResizableComponent,
3832
+ SelectableDirective,
3833
+ MiniMapComponent,
3834
+ NodeToolbarComponent,
3835
+ CustomTemplateEdgeComponent,
3836
+ DragHandleDirective,
3837
+ ConnectionControllerDirective,
3838
+ NodeHtmlTemplateDirective,
3839
+ NodeSvgTemplateDirective,
3840
+ GroupNodeTemplateDirective,
3841
+ EdgeLabelHtmlTemplateDirective,
3842
+ EdgeTemplateDirective,
3843
+ ConnectionTemplateDirective,
3844
+ HandleTemplateDirective,
3845
+ ];
3846
+
3757
3847
  const mockModel = () => new NodeModel({ id: 'mock', type: 'default', point: { x: 0, y: 0 } });
3758
3848
  function provideCustomNodeMocks() {
3759
3849
  return [
@@ -3866,6 +3956,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3866
3956
  selector: 'ng-template[nodeHtml]',
3867
3957
  }]
3868
3958
  }] });
3959
+ class NodeSvgTemplateMockDirective {
3960
+ constructor() {
3961
+ this.templateRef = inject(TemplateRef);
3962
+ }
3963
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeSvgTemplateMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3964
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeSvgTemplateMockDirective, isStandalone: true, selector: "ng-template[nodeSvg]", ngImport: i0 }); }
3965
+ }
3966
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeSvgTemplateMockDirective, decorators: [{
3967
+ type: Directive,
3968
+ args: [{
3969
+ standalone: true,
3970
+ selector: 'ng-template[nodeSvg]',
3971
+ }]
3972
+ }] });
3869
3973
  class GroupNodeTemplateMockDirective {
3870
3974
  constructor() {
3871
3975
  this.templateRef = inject(TemplateRef);
@@ -4325,5 +4429,5 @@ const VflowMocks = [
4325
4429
  * Generated bundle index. Do not edit.
4326
4430
  */
4327
4431
 
4328
- export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionControllerMockDirective, ConnectionTemplateDirective, ConnectionTemplateMockDirective, CustomDynamicNodeComponent, CustomNodeComponent, CustomTemplateEdgeComponent, 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 };
4432
+ export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionControllerMockDirective, ConnectionTemplateDirective, ConnectionTemplateMockDirective, CustomDynamicNodeComponent, CustomNodeComponent, CustomTemplateEdgeComponent, DragHandleDirective, DragHandleMockDirective, EdgeLabelHtmlTemplateDirective, EdgeLabelHtmlTemplateMockDirective, EdgeTemplateDirective, EdgeTemplateMockDirective, GroupNodeTemplateDirective, GroupNodeTemplateMockDirective, HandleComponent, HandleMockComponent, HandleTemplateDirective, HandleTemplateMockDirective, MiniMapComponent, MiniMapMockComponent, NodeHtmlTemplateDirective, NodeHtmlTemplateMockDirective, NodeSvgTemplateDirective, NodeSvgTemplateMockDirective, NodeToolbarComponent, NodeToolbarMockComponent, NodeToolbarWrapperDirective, ResizableComponent, ResizableMockComponent, SelectableDirective, SelectableMockDirective, Vflow, VflowComponent, VflowMockComponent, VflowMocks, isComponentDynamicNode, isComponentStaticNode, isDefaultDynamicGroupNode, isDefaultDynamicNode, isDefaultStaticGroupNode, isDefaultStaticNode, isDynamicNode, isStaticNode, isSvgTemplateDynamicNode, isSvgTemplateStaticNode, isTemplateDynamicGroupNode, isTemplateDynamicNode, isTemplateStaticGroupNode, isTemplateStaticNode, provideCustomNodeMocks };
4329
4433
  //# sourceMappingURL=ngx-vflow.mjs.map