ngx-vflow 0.7.0 → 0.8.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.
- package/esm2022/lib/vflow/components/background/background.component.mjs +4 -4
- package/esm2022/lib/vflow/components/connection/connection.component.mjs +2 -2
- package/esm2022/lib/vflow/components/handle/handle.component.mjs +5 -5
- package/esm2022/lib/vflow/components/node/node.component.mjs +31 -82
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +12 -2
- package/esm2022/lib/vflow/directives/connection-controller.directive.mjs +91 -12
- package/esm2022/lib/vflow/directives/space-point-context.directive.mjs +11 -5
- package/esm2022/lib/vflow/interfaces/connection-settings.interface.mjs +1 -1
- package/esm2022/lib/vflow/interfaces/connection.internal.interface.mjs +2 -0
- package/esm2022/lib/vflow/models/connection.model.mjs +28 -6
- package/esm2022/lib/vflow/models/handle.model.mjs +1 -1
- package/esm2022/lib/vflow/services/flow-entities.service.mjs +2 -2
- package/esm2022/lib/vflow/services/flow-status.service.mjs +7 -7
- package/esm2022/lib/vflow/services/handle.service.mjs +1 -1
- package/esm2022/lib/vflow/types/connection-mode.type.mjs +2 -0
- package/esm2022/lib/vflow/utils/adjust-direction.mjs +30 -0
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/ngx-vflow.mjs +339 -246
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/node/node.component.d.ts +4 -12
- package/lib/vflow/components/vflow/vflow.component.d.ts +6 -0
- package/lib/vflow/directives/connection-controller.directive.d.ts +6 -0
- package/lib/vflow/directives/space-point-context.directive.d.ts +1 -0
- package/lib/vflow/interfaces/connection-settings.interface.d.ts +2 -0
- package/lib/vflow/interfaces/connection.internal.interface.d.ts +8 -0
- package/lib/vflow/models/connection.model.d.ts +5 -2
- package/lib/vflow/models/handle.model.d.ts +1 -1
- package/lib/vflow/services/flow-status.service.d.ts +7 -18
- package/lib/vflow/types/connection-mode.type.d.ts +1 -0
- package/lib/vflow/utils/adjust-direction.d.ts +11 -0
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
package/fesm2022/ngx-vflow.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { signal, Injectable, inject, ElementRef, Directive, computed, effect, untracked, Input, TemplateRef, EventEmitter, Output, DestroyRef, runInInjectionContext,
|
|
4
|
+
import { signal, Injectable, inject, ElementRef, Directive, computed, effect, untracked, Input, TemplateRef, EventEmitter, Output, DestroyRef, runInInjectionContext, Injector, Component, ChangeDetectionStrategy, HostListener, ViewChild, ContentChild, NgModule } from '@angular/core';
|
|
5
5
|
import { select } from 'd3-selection';
|
|
6
6
|
import { zoomIdentity, zoom } from 'd3-zoom';
|
|
7
|
-
import { Subject, tap, merge, BehaviorSubject, observeOn, animationFrameScheduler, switchMap, skip, map, pairwise, filter, distinctUntilChanged, asyncScheduler, zip,
|
|
7
|
+
import { Subject, tap, merge, BehaviorSubject, observeOn, animationFrameScheduler, switchMap, skip, map, pairwise, filter, distinctUntilChanged, asyncScheduler, zip, fromEvent, share, Observable, startWith } from 'rxjs';
|
|
8
8
|
import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
9
9
|
import { drag } from 'd3-drag';
|
|
10
10
|
import { path } from 'd3-path';
|
|
@@ -59,13 +59,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
59
59
|
}] });
|
|
60
60
|
|
|
61
61
|
class ConnectionModel {
|
|
62
|
-
constructor(
|
|
63
|
-
this.
|
|
64
|
-
this.curve =
|
|
65
|
-
this.type =
|
|
66
|
-
this.
|
|
62
|
+
constructor(settings) {
|
|
63
|
+
this.settings = settings;
|
|
64
|
+
this.curve = settings.curve ?? 'bezier';
|
|
65
|
+
this.type = settings.type ?? 'default';
|
|
66
|
+
this.mode = settings.mode ?? 'strict';
|
|
67
|
+
const validatorsToRun = this.getValidators(settings);
|
|
68
|
+
this.validator = (connection) => validatorsToRun.every((v) => v(connection));
|
|
69
|
+
}
|
|
70
|
+
getValidators(settings) {
|
|
71
|
+
const validators = [];
|
|
72
|
+
validators.push(notSelfValidator);
|
|
73
|
+
if (this.mode === 'loose') {
|
|
74
|
+
validators.push(hasSourceAndTargetHandleValidator);
|
|
75
|
+
}
|
|
76
|
+
if (settings.validator) {
|
|
77
|
+
validators.push(settings.validator);
|
|
78
|
+
}
|
|
79
|
+
return validators;
|
|
67
80
|
}
|
|
68
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Internal validator that not allows self connections
|
|
84
|
+
*/
|
|
85
|
+
const notSelfValidator = (connection) => {
|
|
86
|
+
return connection.source !== connection.target;
|
|
87
|
+
};
|
|
88
|
+
const hasSourceAndTargetHandleValidator = (connection) => {
|
|
89
|
+
return connection.sourceHandle !== undefined && connection.targetHandle !== undefined;
|
|
90
|
+
};
|
|
69
91
|
|
|
70
92
|
function hashCode(str) {
|
|
71
93
|
return str.split('').reduce((a, b) => {
|
|
@@ -97,7 +119,7 @@ class FlowEntitiesService {
|
|
|
97
119
|
markersMap.set(hash, e.edge.markers.end);
|
|
98
120
|
}
|
|
99
121
|
});
|
|
100
|
-
const connectionMarker = this.connection().
|
|
122
|
+
const connectionMarker = this.connection().settings.marker;
|
|
101
123
|
if (connectionMarker) {
|
|
102
124
|
const hash = hashCode(JSON.stringify(connectionMarker));
|
|
103
125
|
markersMap.set(hash, connectionMarker);
|
|
@@ -385,14 +407,14 @@ class FlowStatusService {
|
|
|
385
407
|
setIdleStatus() {
|
|
386
408
|
this.status.set({ state: 'idle', payload: null });
|
|
387
409
|
}
|
|
388
|
-
setConnectionStartStatus(
|
|
389
|
-
this.status.set({ state: 'connection-start', payload: {
|
|
410
|
+
setConnectionStartStatus(source, sourceHandle) {
|
|
411
|
+
this.status.set({ state: 'connection-start', payload: { source, sourceHandle } });
|
|
390
412
|
}
|
|
391
|
-
setConnectionValidationStatus(valid,
|
|
392
|
-
this.status.set({ state: 'connection-validation', payload: {
|
|
413
|
+
setConnectionValidationStatus(valid, source, target, sourceHandle, targetHandle) {
|
|
414
|
+
this.status.set({ state: 'connection-validation', payload: { source, target, sourceHandle, targetHandle, valid } });
|
|
393
415
|
}
|
|
394
|
-
setConnectionEndStatus(
|
|
395
|
-
this.status.set({ state: 'connection-end', payload: {
|
|
416
|
+
setConnectionEndStatus(source, target, sourceHandle, targetHandle) {
|
|
417
|
+
this.status.set({ state: 'connection-end', payload: { source, target, sourceHandle, targetHandle } });
|
|
396
418
|
}
|
|
397
419
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowStatusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
398
420
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowStatusService }); }
|
|
@@ -415,6 +437,36 @@ function batchStatusChanges(...changes) {
|
|
|
415
437
|
}
|
|
416
438
|
}
|
|
417
439
|
|
|
440
|
+
/**
|
|
441
|
+
* This function contains a hack-y behavior.
|
|
442
|
+
* If the handles are of the same type (source-source or target-target),
|
|
443
|
+
* it returns nodes where source === target and
|
|
444
|
+
* handles where sourceHandle === targetHandle
|
|
445
|
+
*
|
|
446
|
+
* This leads to that notSelfValidator returns false for these cases,
|
|
447
|
+
* exactly what we need for strict connection type
|
|
448
|
+
*/
|
|
449
|
+
function adjustDirection(connection) {
|
|
450
|
+
const result = {};
|
|
451
|
+
if (connection.sourceHandle.rawHandle.type === 'source') {
|
|
452
|
+
result.source = connection.source;
|
|
453
|
+
result.sourceHandle = connection.sourceHandle;
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
result.source = connection.target;
|
|
457
|
+
result.sourceHandle = connection.targetHandle;
|
|
458
|
+
}
|
|
459
|
+
if (connection.targetHandle.rawHandle.type === 'target') {
|
|
460
|
+
result.target = connection.target;
|
|
461
|
+
result.targetHandle = connection.targetHandle;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
result.target = connection.source;
|
|
465
|
+
result.targetHandle = connection.sourceHandle;
|
|
466
|
+
}
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
|
|
418
470
|
class ConnectionControllerDirective {
|
|
419
471
|
constructor() {
|
|
420
472
|
/**
|
|
@@ -431,18 +483,96 @@ class ConnectionControllerDirective {
|
|
|
431
483
|
this.connectEffect = effect(() => {
|
|
432
484
|
const status = this.statusService.status();
|
|
433
485
|
if (status.state === 'connection-end') {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
486
|
+
let source = status.payload.source;
|
|
487
|
+
let target = status.payload.target;
|
|
488
|
+
let sourceHandle = status.payload.sourceHandle;
|
|
489
|
+
let targetHandle = status.payload.targetHandle;
|
|
490
|
+
if (this.isStrictMode()) {
|
|
491
|
+
const adjusted = adjustDirection({
|
|
492
|
+
source: status.payload.source,
|
|
493
|
+
sourceHandle: status.payload.sourceHandle,
|
|
494
|
+
target: status.payload.target,
|
|
495
|
+
targetHandle: status.payload.targetHandle
|
|
496
|
+
});
|
|
497
|
+
source = adjusted.source;
|
|
498
|
+
target = adjusted.target;
|
|
499
|
+
sourceHandle = adjusted.sourceHandle;
|
|
500
|
+
targetHandle = adjusted.targetHandle;
|
|
501
|
+
}
|
|
502
|
+
const sourceId = source.node.id;
|
|
503
|
+
const targetId = target.node.id;
|
|
504
|
+
const sourceHandleId = sourceHandle.rawHandle.id;
|
|
505
|
+
const targetHandleId = targetHandle.rawHandle.id;
|
|
506
|
+
const connectionModel = this.flowEntitiesService.connection();
|
|
507
|
+
const connection = {
|
|
508
|
+
source: sourceId, target: targetId,
|
|
509
|
+
sourceHandle: sourceHandleId, targetHandle: targetHandleId
|
|
510
|
+
};
|
|
511
|
+
if (connectionModel.validator(connection)) {
|
|
512
|
+
this.onConnect.emit(connection);
|
|
443
513
|
}
|
|
444
514
|
}
|
|
445
515
|
}, { allowSignalWrites: true });
|
|
516
|
+
this.isStrictMode = computed(() => this.flowEntitiesService.connection().mode === 'strict');
|
|
517
|
+
}
|
|
518
|
+
startConnection(handle) {
|
|
519
|
+
this.statusService.setConnectionStartStatus(handle.parentNode, handle);
|
|
520
|
+
}
|
|
521
|
+
validateConnection(handle) {
|
|
522
|
+
const status = this.statusService.status();
|
|
523
|
+
if (status.state === 'connection-start') {
|
|
524
|
+
let source = status.payload.source;
|
|
525
|
+
let target = handle.parentNode;
|
|
526
|
+
let sourceHandle = status.payload.sourceHandle;
|
|
527
|
+
let targetHandle = handle;
|
|
528
|
+
if (this.isStrictMode()) {
|
|
529
|
+
// swap direction (if needed) according to actual source and target of strict mode
|
|
530
|
+
const adjusted = adjustDirection({
|
|
531
|
+
source: status.payload.source,
|
|
532
|
+
sourceHandle: status.payload.sourceHandle,
|
|
533
|
+
target: handle.parentNode,
|
|
534
|
+
targetHandle: handle
|
|
535
|
+
});
|
|
536
|
+
source = adjusted.source;
|
|
537
|
+
target = adjusted.target;
|
|
538
|
+
sourceHandle = adjusted.sourceHandle;
|
|
539
|
+
targetHandle = adjusted.targetHandle;
|
|
540
|
+
}
|
|
541
|
+
const valid = this.flowEntitiesService.connection().validator({
|
|
542
|
+
source: source.node.id,
|
|
543
|
+
target: target.node.id,
|
|
544
|
+
sourceHandle: sourceHandle.rawHandle.id,
|
|
545
|
+
targetHandle: targetHandle.rawHandle.id
|
|
546
|
+
});
|
|
547
|
+
// TODO: check how react flow handles highlight of handle
|
|
548
|
+
// if direction changes
|
|
549
|
+
handle.state.set(valid ? 'valid' : 'invalid');
|
|
550
|
+
// status is about how we draw connection, so we don't need
|
|
551
|
+
// swapped diretion here
|
|
552
|
+
this.statusService.setConnectionValidationStatus(valid, status.payload.source, handle.parentNode, status.payload.sourceHandle, handle);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
resetValidateConnection(targetHandle) {
|
|
556
|
+
targetHandle.state.set('idle');
|
|
557
|
+
// drop back to start status
|
|
558
|
+
const status = this.statusService.status();
|
|
559
|
+
if (status.state === 'connection-validation') {
|
|
560
|
+
this.statusService.setConnectionStartStatus(status.payload.source, status.payload.sourceHandle);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
endConnection(handle) {
|
|
564
|
+
const status = this.statusService.status();
|
|
565
|
+
if (status.state === 'connection-validation') {
|
|
566
|
+
const source = status.payload.source;
|
|
567
|
+
const sourceHandle = status.payload.sourceHandle;
|
|
568
|
+
const target = status.payload.target;
|
|
569
|
+
const targetHandle = status.payload.targetHandle;
|
|
570
|
+
batchStatusChanges(
|
|
571
|
+
// call to create connection
|
|
572
|
+
() => this.statusService.setConnectionEndStatus(source, target, sourceHandle, targetHandle),
|
|
573
|
+
// when connection created, we need go back to idle status
|
|
574
|
+
() => this.statusService.setIdleStatus());
|
|
575
|
+
}
|
|
446
576
|
}
|
|
447
577
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConnectionControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
448
578
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ConnectionControllerDirective, isStandalone: true, selector: "[connectionController]", outputs: { onConnect: "onConnect" }, ngImport: i0 }); }
|
|
@@ -1040,6 +1170,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1040
1170
|
type: Injectable
|
|
1041
1171
|
}] });
|
|
1042
1172
|
|
|
1173
|
+
class RootPointerDirective {
|
|
1174
|
+
constructor() {
|
|
1175
|
+
this.host = inject(ElementRef).nativeElement;
|
|
1176
|
+
this.initialTouch$ = new Subject();
|
|
1177
|
+
// TODO: do not emit if mouse not down
|
|
1178
|
+
this.mouseMovement$ = fromEvent(this.host, 'mousemove').pipe(map(event => ({
|
|
1179
|
+
x: event.clientX,
|
|
1180
|
+
y: event.clientY,
|
|
1181
|
+
originalEvent: event
|
|
1182
|
+
})), observeOn(animationFrameScheduler), share());
|
|
1183
|
+
this.touchMovement$ = merge(this.initialTouch$, fromEvent(this.host, 'touchmove')).pipe(tap((event) => event.preventDefault()), map((originalEvent) => {
|
|
1184
|
+
const x = originalEvent.touches[0]?.clientX ?? 0;
|
|
1185
|
+
const y = originalEvent.touches[0]?.clientY ?? 0;
|
|
1186
|
+
const target = document.elementFromPoint(x, y);
|
|
1187
|
+
return { x, y, target, originalEvent };
|
|
1188
|
+
}), observeOn(animationFrameScheduler), share());
|
|
1189
|
+
this.touchEnd$ = fromEvent(this.host, 'touchend').pipe(map((originalEvent) => {
|
|
1190
|
+
const x = originalEvent.changedTouches[0]?.clientX ?? 0;
|
|
1191
|
+
const y = originalEvent.changedTouches[0]?.clientY ?? 0;
|
|
1192
|
+
const target = document.elementFromPoint(x, y);
|
|
1193
|
+
return { x, y, target, originalEvent };
|
|
1194
|
+
}), share());
|
|
1195
|
+
this.pointerMovement$ = merge(this.mouseMovement$, this.touchMovement$);
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* We should know when user started a touch in order to not
|
|
1199
|
+
* show old touch position when connection creation is started
|
|
1200
|
+
*/
|
|
1201
|
+
setInitialTouch(event) {
|
|
1202
|
+
this.initialTouch$.next(event);
|
|
1203
|
+
}
|
|
1204
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1205
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RootPointerDirective, selector: "svg[rootPointer]", ngImport: i0 }); }
|
|
1206
|
+
}
|
|
1207
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, decorators: [{
|
|
1208
|
+
type: Directive,
|
|
1209
|
+
args: [{ selector: 'svg[rootPointer]' }]
|
|
1210
|
+
}] });
|
|
1211
|
+
|
|
1212
|
+
class SpacePointContextDirective {
|
|
1213
|
+
constructor() {
|
|
1214
|
+
this.pointerMovementDirective = inject(RootPointerDirective);
|
|
1215
|
+
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
1216
|
+
this.host = inject(ElementRef).nativeElement;
|
|
1217
|
+
/**
|
|
1218
|
+
* Signal with current mouse position in svg space
|
|
1219
|
+
*/
|
|
1220
|
+
this.svgCurrentSpacePoint = computed(() => {
|
|
1221
|
+
const movement = this.pointerMovement();
|
|
1222
|
+
if (!movement) {
|
|
1223
|
+
return { x: 0, y: 0 };
|
|
1224
|
+
}
|
|
1225
|
+
return this.documentPointToFlowPoint({
|
|
1226
|
+
x: movement.x,
|
|
1227
|
+
y: movement.y
|
|
1228
|
+
});
|
|
1229
|
+
});
|
|
1230
|
+
this.pointerMovement = toSignal(this.pointerMovementDirective.pointerMovement$);
|
|
1231
|
+
}
|
|
1232
|
+
documentPointToFlowPoint(documentPoint) {
|
|
1233
|
+
const point = this.rootSvg.createSVGPoint();
|
|
1234
|
+
point.x = documentPoint.x;
|
|
1235
|
+
point.y = documentPoint.y;
|
|
1236
|
+
return point.matrixTransform(this.host.getScreenCTM().inverse());
|
|
1237
|
+
}
|
|
1238
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpacePointContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1239
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SpacePointContextDirective, selector: "g[spacePointContext]", ngImport: i0 }); }
|
|
1240
|
+
}
|
|
1241
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpacePointContextDirective, decorators: [{
|
|
1242
|
+
type: Directive,
|
|
1243
|
+
args: [{ selector: 'g[spacePointContext]' }]
|
|
1244
|
+
}] });
|
|
1245
|
+
|
|
1043
1246
|
class HandleService {
|
|
1044
1247
|
constructor() {
|
|
1045
1248
|
this.node = signal(null);
|
|
@@ -1063,6 +1266,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1063
1266
|
type: Injectable
|
|
1064
1267
|
}] });
|
|
1065
1268
|
|
|
1269
|
+
function resizable(elems) {
|
|
1270
|
+
return new Observable((subscriber) => {
|
|
1271
|
+
let ro = new ResizeObserver((entries) => {
|
|
1272
|
+
subscriber.next(entries);
|
|
1273
|
+
});
|
|
1274
|
+
elems.forEach(e => ro.observe(e));
|
|
1275
|
+
return () => ro.disconnect();
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
function InjectionContext(target, key, descriptor) {
|
|
1280
|
+
const originalMethod = descriptor.value;
|
|
1281
|
+
descriptor.value = function (...args) {
|
|
1282
|
+
if (implementsWithInjector(this)) {
|
|
1283
|
+
return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
|
|
1284
|
+
}
|
|
1285
|
+
else {
|
|
1286
|
+
throw new Error('Class that contains decorated method must extends WithInjectorDirective class');
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
// Return the modified descriptor
|
|
1290
|
+
return descriptor;
|
|
1291
|
+
}
|
|
1292
|
+
const implementsWithInjector = (instance) => {
|
|
1293
|
+
return 'injector' in instance && 'get' in instance.injector;
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
function Microtask(target, key, descriptor) {
|
|
1297
|
+
const originalMethod = descriptor.value;
|
|
1298
|
+
descriptor.value = function (...args) {
|
|
1299
|
+
queueMicrotask(() => {
|
|
1300
|
+
originalMethod?.apply(this, args);
|
|
1301
|
+
});
|
|
1302
|
+
};
|
|
1303
|
+
// Return the modified descriptor
|
|
1304
|
+
return descriptor;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1066
1307
|
class HandleModel {
|
|
1067
1308
|
constructor(rawHandle, parentNode) {
|
|
1068
1309
|
this.rawHandle = rawHandle;
|
|
@@ -1138,43 +1379,46 @@ class HandleModel {
|
|
|
1138
1379
|
}
|
|
1139
1380
|
}
|
|
1140
1381
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
}
|
|
1164
|
-
const implementsWithInjector = (instance) => {
|
|
1165
|
-
return 'injector' in instance && 'get' in instance.injector;
|
|
1166
|
-
};
|
|
1167
|
-
|
|
1168
|
-
function Microtask(target, key, descriptor) {
|
|
1169
|
-
const originalMethod = descriptor.value;
|
|
1170
|
-
descriptor.value = function (...args) {
|
|
1171
|
-
queueMicrotask(() => {
|
|
1172
|
-
originalMethod?.apply(this, args);
|
|
1173
|
-
});
|
|
1174
|
-
};
|
|
1175
|
-
// Return the modified descriptor
|
|
1176
|
-
return descriptor;
|
|
1382
|
+
class HandleComponent {
|
|
1383
|
+
constructor() {
|
|
1384
|
+
this.injector = inject(Injector);
|
|
1385
|
+
this.handleService = inject(HandleService);
|
|
1386
|
+
this.element = inject(ElementRef).nativeElement;
|
|
1387
|
+
}
|
|
1388
|
+
ngOnInit() {
|
|
1389
|
+
this.model = new HandleModel({
|
|
1390
|
+
position: this.position,
|
|
1391
|
+
type: this.type,
|
|
1392
|
+
id: this.id,
|
|
1393
|
+
parentReference: this.element.parentElement,
|
|
1394
|
+
template: this.template
|
|
1395
|
+
}, this.handleService.node());
|
|
1396
|
+
this.handleService.createHandle(this.model);
|
|
1397
|
+
requestAnimationFrame(() => this.model.updateParent());
|
|
1398
|
+
}
|
|
1399
|
+
ngOnDestroy() {
|
|
1400
|
+
this.handleService.destroyHandle(this.model);
|
|
1401
|
+
}
|
|
1402
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1403
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HandleComponent, selector: "handle", inputs: { position: "position", type: "type", id: "id", template: "template" }, ngImport: i0, template: "", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1177
1404
|
}
|
|
1405
|
+
__decorate([
|
|
1406
|
+
InjectionContext
|
|
1407
|
+
], HandleComponent.prototype, "ngOnInit", null);
|
|
1408
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, decorators: [{
|
|
1409
|
+
type: Component,
|
|
1410
|
+
args: [{ selector: 'handle', changeDetection: ChangeDetectionStrategy.OnPush, template: "" }]
|
|
1411
|
+
}], propDecorators: { position: [{
|
|
1412
|
+
type: Input,
|
|
1413
|
+
args: [{ required: true }]
|
|
1414
|
+
}], type: [{
|
|
1415
|
+
type: Input,
|
|
1416
|
+
args: [{ required: true }]
|
|
1417
|
+
}], id: [{
|
|
1418
|
+
type: Input
|
|
1419
|
+
}], template: [{
|
|
1420
|
+
type: Input
|
|
1421
|
+
}], ngOnInit: [] } });
|
|
1178
1422
|
|
|
1179
1423
|
class HandleSizeControllerDirective {
|
|
1180
1424
|
constructor() {
|
|
@@ -1212,45 +1456,6 @@ function getChildStrokeWidth(element) {
|
|
|
1212
1456
|
return 0;
|
|
1213
1457
|
}
|
|
1214
1458
|
|
|
1215
|
-
class RootPointerDirective {
|
|
1216
|
-
constructor() {
|
|
1217
|
-
this.host = inject(ElementRef).nativeElement;
|
|
1218
|
-
this.initialTouch$ = new Subject();
|
|
1219
|
-
// TODO: do not emit if mouse not down
|
|
1220
|
-
this.mouseMovement$ = fromEvent(this.host, 'mousemove').pipe(map(event => ({
|
|
1221
|
-
x: event.clientX,
|
|
1222
|
-
y: event.clientY,
|
|
1223
|
-
originalEvent: event
|
|
1224
|
-
})), observeOn(animationFrameScheduler), share());
|
|
1225
|
-
this.touchMovement$ = merge(this.initialTouch$, fromEvent(this.host, 'touchmove')).pipe(tap((event) => event.preventDefault()), map((originalEvent) => {
|
|
1226
|
-
const x = originalEvent.touches[0]?.clientX ?? 0;
|
|
1227
|
-
const y = originalEvent.touches[0]?.clientY ?? 0;
|
|
1228
|
-
const target = document.elementFromPoint(x, y);
|
|
1229
|
-
return { x, y, target, originalEvent };
|
|
1230
|
-
}), observeOn(animationFrameScheduler), share());
|
|
1231
|
-
this.touchEnd$ = fromEvent(this.host, 'touchend').pipe(map((originalEvent) => {
|
|
1232
|
-
const x = originalEvent.changedTouches[0]?.clientX ?? 0;
|
|
1233
|
-
const y = originalEvent.changedTouches[0]?.clientY ?? 0;
|
|
1234
|
-
const target = document.elementFromPoint(x, y);
|
|
1235
|
-
return { x, y, target, originalEvent };
|
|
1236
|
-
}), share());
|
|
1237
|
-
this.pointerMovement$ = merge(this.mouseMovement$, this.touchMovement$);
|
|
1238
|
-
}
|
|
1239
|
-
/**
|
|
1240
|
-
* We should know when user started a touch in order to not
|
|
1241
|
-
* show old touch position when connection creation is started
|
|
1242
|
-
*/
|
|
1243
|
-
setInitialTouch(event) {
|
|
1244
|
-
this.initialTouch$.next(event);
|
|
1245
|
-
}
|
|
1246
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1247
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RootPointerDirective, selector: "svg[rootPointer]", ngImport: i0 }); }
|
|
1248
|
-
}
|
|
1249
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, decorators: [{
|
|
1250
|
-
type: Directive,
|
|
1251
|
-
args: [{ selector: 'svg[rootPointer]' }]
|
|
1252
|
-
}] });
|
|
1253
|
-
|
|
1254
1459
|
class PointerDirective {
|
|
1255
1460
|
constructor() {
|
|
1256
1461
|
this.hostElement = inject(ElementRef).nativeElement;
|
|
@@ -1336,28 +1541,27 @@ class NodeComponent {
|
|
|
1336
1541
|
this.handleService = inject(HandleService);
|
|
1337
1542
|
this.draggableService = inject(DraggableService);
|
|
1338
1543
|
this.flowStatusService = inject(FlowStatusService);
|
|
1339
|
-
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
1340
1544
|
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1341
1545
|
this.flowSettingsService = inject(FlowSettingsService);
|
|
1342
1546
|
this.selectionService = inject(SelectionService);
|
|
1343
1547
|
this.hostRef = inject(ElementRef);
|
|
1548
|
+
this.connectionController = inject(ConnectionControllerDirective);
|
|
1344
1549
|
this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
|
|
1345
1550
|
this.flowStatusService.status().state === 'connection-validation');
|
|
1346
1551
|
this.styleWidth = computed(() => `${this.nodeModel.size().width}px`);
|
|
1347
1552
|
this.styleHeight = computed(() => `${this.nodeModel.size().height}px`);
|
|
1348
|
-
this.subscription = new Subscription();
|
|
1349
1553
|
}
|
|
1350
1554
|
ngOnInit() {
|
|
1351
1555
|
this.handleService.node.set(this.nodeModel);
|
|
1352
1556
|
this.draggableService.toggleDraggable(this.hostRef.nativeElement, this.nodeModel);
|
|
1353
|
-
|
|
1354
|
-
.pipe(switchMap((handles) => resizable(handles.map(h => h.parentReference))
|
|
1355
|
-
|
|
1557
|
+
this.nodeModel.handles$
|
|
1558
|
+
.pipe(switchMap((handles) => resizable(handles.map(h => h.parentReference)).pipe(map(() => handles))), tap((handles) => {
|
|
1559
|
+
// TODO (performance) inspect how to avoid calls of this when flow initially rendered
|
|
1560
|
+
handles.forEach(h => h.updateParent());
|
|
1561
|
+
}), takeUntilDestroyed())
|
|
1356
1562
|
.subscribe();
|
|
1357
|
-
this.subscription.add(sub);
|
|
1358
1563
|
}
|
|
1359
1564
|
ngAfterViewInit() {
|
|
1360
|
-
this.setInitialHandles();
|
|
1361
1565
|
if (this.nodeModel.node.type === 'default') {
|
|
1362
1566
|
this.nodeModel.size.set({
|
|
1363
1567
|
width: this.nodeModel.node.width ?? NodeModel.defaultTypeSize.width,
|
|
@@ -1365,69 +1569,30 @@ class NodeComponent {
|
|
|
1365
1569
|
});
|
|
1366
1570
|
}
|
|
1367
1571
|
if (this.nodeModel.node.type === 'html-template' || this.nodeModel.isComponentType) {
|
|
1368
|
-
|
|
1572
|
+
resizable([this.htmlWrapperRef.nativeElement])
|
|
1369
1573
|
.pipe(startWith(null), tap(() => {
|
|
1370
1574
|
const width = this.htmlWrapperRef.nativeElement.clientWidth;
|
|
1371
1575
|
const height = this.htmlWrapperRef.nativeElement.clientHeight;
|
|
1372
1576
|
this.nodeModel.size.set({ width, height });
|
|
1373
|
-
})).subscribe();
|
|
1374
|
-
this.subscription.add(sub);
|
|
1577
|
+
}), takeUntilDestroyed()).subscribe();
|
|
1375
1578
|
}
|
|
1376
1579
|
}
|
|
1377
1580
|
ngOnDestroy() {
|
|
1378
1581
|
this.draggableService.destroy(this.hostRef.nativeElement);
|
|
1379
|
-
this.subscription.unsubscribe();
|
|
1380
1582
|
}
|
|
1381
1583
|
startConnection(event, handle) {
|
|
1382
1584
|
// ignore drag by stopping propagation
|
|
1383
1585
|
event.stopPropagation();
|
|
1384
|
-
this.
|
|
1586
|
+
this.connectionController.startConnection(handle);
|
|
1385
1587
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
if (status.state === 'connection-validation') {
|
|
1389
|
-
const sourceNode = status.payload.sourceNode;
|
|
1390
|
-
const targetNode = this.nodeModel;
|
|
1391
|
-
const sourceHandle = status.payload.sourceHandle;
|
|
1392
|
-
const targetHandle = status.payload.targetHandle;
|
|
1393
|
-
batchStatusChanges(
|
|
1394
|
-
// call to create connection
|
|
1395
|
-
() => this.flowStatusService.setConnectionEndStatus(sourceNode, targetNode, sourceHandle, targetHandle),
|
|
1396
|
-
// when connection created, we need go back to idle status
|
|
1397
|
-
() => this.flowStatusService.setIdleStatus());
|
|
1398
|
-
}
|
|
1588
|
+
validateConnection(handle) {
|
|
1589
|
+
this.connectionController.validateConnection(handle);
|
|
1399
1590
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
*/
|
|
1403
|
-
validateTargetHandle(targetHandle) {
|
|
1404
|
-
const status = this.flowStatusService.status();
|
|
1405
|
-
if (status.state === 'connection-start') {
|
|
1406
|
-
const sourceNode = status.payload.sourceNode;
|
|
1407
|
-
const sourceHandle = status.payload.sourceHandle;
|
|
1408
|
-
const source = sourceNode.node.id;
|
|
1409
|
-
const targetNode = this.nodeModel;
|
|
1410
|
-
const target = targetNode.node.id;
|
|
1411
|
-
const valid = this.flowEntitiesService.connection().validator({
|
|
1412
|
-
source,
|
|
1413
|
-
target,
|
|
1414
|
-
sourceHandle: sourceHandle.rawHandle.id,
|
|
1415
|
-
targetHandle: targetHandle.rawHandle.id
|
|
1416
|
-
});
|
|
1417
|
-
targetHandle.state.set(valid ? 'valid' : 'invalid');
|
|
1418
|
-
this.flowStatusService.setConnectionValidationStatus(valid, sourceNode, targetNode, sourceHandle, targetHandle);
|
|
1419
|
-
}
|
|
1591
|
+
resetValidateConnection(targetHandle) {
|
|
1592
|
+
this.connectionController.resetValidateConnection(targetHandle);
|
|
1420
1593
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
*/
|
|
1424
|
-
resetValidateTargetHandle(targetHandle) {
|
|
1425
|
-
targetHandle.state.set('idle');
|
|
1426
|
-
// drop back to start status
|
|
1427
|
-
const status = this.flowStatusService.status();
|
|
1428
|
-
if (status.state === 'connection-validation') {
|
|
1429
|
-
this.flowStatusService.setConnectionStartStatus(status.payload.sourceNode, status.payload.sourceHandle);
|
|
1430
|
-
}
|
|
1594
|
+
endConnection(handle) {
|
|
1595
|
+
this.connectionController.endConnection(handle);
|
|
1431
1596
|
}
|
|
1432
1597
|
pullNode() {
|
|
1433
1598
|
this.nodeRenderingService.pullNode(this.nodeModel);
|
|
@@ -1437,32 +1602,20 @@ class NodeComponent {
|
|
|
1437
1602
|
this.selectionService.select(this.nodeModel);
|
|
1438
1603
|
}
|
|
1439
1604
|
}
|
|
1440
|
-
setInitialHandles() {
|
|
1441
|
-
if (this.nodeModel.node.type === 'default') {
|
|
1442
|
-
this.handleService.createHandle(new HandleModel({
|
|
1443
|
-
position: this.nodeModel.sourcePosition(),
|
|
1444
|
-
type: 'source',
|
|
1445
|
-
parentReference: this.htmlWrapperRef.nativeElement
|
|
1446
|
-
}, this.nodeModel));
|
|
1447
|
-
this.handleService.createHandle(new HandleModel({
|
|
1448
|
-
position: this.nodeModel.targetPosition(),
|
|
1449
|
-
type: 'target',
|
|
1450
|
-
parentReference: this.htmlWrapperRef.nativeElement
|
|
1451
|
-
}, this.nodeModel));
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
1605
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1455
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeComponent, selector: "g[node]", inputs: { nodeModel: "nodeModel", nodeHtmlTemplate: "nodeHtmlTemplate" }, providers: [HandleService], viewQueries: [{ propertyName: "nodeContentRef", first: true, predicate: ["nodeContent"], descendants: true }, { propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true }], ngImport: i0, template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\"\n [
|
|
1606
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeComponent, selector: "g[node]", inputs: { nodeModel: "nodeModel", nodeHtmlTemplate: "nodeHtmlTemplate" }, providers: [HandleService], viewQueries: [{ propertyName: "nodeContentRef", first: true, predicate: ["nodeContent"], descendants: true }, { propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true }], ngImport: i0, template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\"\n >\n <div [outerHTML]=\"nodeModel.node.text ?? ''\"></div>\n\n <handle type=\"source\" [position]=\"nodeModel.sourcePosition()\" />\n <handle type=\"target\" [position]=\"nodeModel.targetPosition()\" />\n </div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngTemplateOutlet]=\"nodeHtmlTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { node: nodeModel.node, selected: nodeModel.selected } }\"\n [ngTemplateOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.isComponentType\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngComponentOutlet]=\"$any(nodeModel.node.type)\"\n [ngComponentOutletInputs]=\"nodeModel.componentTypeInputs()\"\n [ngComponentOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngFor=\"let handle of nodeModel.handles()\">\n <svg:circle\n *ngIf=\"!handle.template\"\n class=\"default-handle\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n r=\"5\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection(handle)\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection(handle)\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(handle); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\"\n />\n</ng-container>\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}.default-node_selected{border-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1456
1607
|
}
|
|
1457
1608
|
__decorate([
|
|
1458
|
-
|
|
1459
|
-
], NodeComponent.prototype, "
|
|
1609
|
+
InjectionContext
|
|
1610
|
+
], NodeComponent.prototype, "ngOnInit", null);
|
|
1460
1611
|
__decorate([
|
|
1612
|
+
Microtask // TODO (performance) check if we need microtask here
|
|
1613
|
+
,
|
|
1461
1614
|
InjectionContext
|
|
1462
|
-
], NodeComponent.prototype, "
|
|
1615
|
+
], NodeComponent.prototype, "ngAfterViewInit", null);
|
|
1463
1616
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, decorators: [{
|
|
1464
1617
|
type: Component,
|
|
1465
|
-
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\"\n [
|
|
1618
|
+
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [style.width]=\"styleWidth()\"\n [style.height]=\"styleHeight()\"\n [style.max-width]=\"styleWidth()\"\n [style.max-height]=\"styleHeight()\"\n >\n <div [outerHTML]=\"nodeModel.node.text ?? ''\"></div>\n\n <handle type=\"source\" [position]=\"nodeModel.sourcePosition()\" />\n <handle type=\"target\" [position]=\"nodeModel.targetPosition()\" />\n </div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngTemplateOutlet]=\"nodeHtmlTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { node: nodeModel.node, selected: nodeModel.selected } }\"\n [ngTemplateOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.isComponentType\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngComponentOutlet]=\"$any(nodeModel.node.type)\"\n [ngComponentOutletInputs]=\"nodeModel.componentTypeInputs()\"\n [ngComponentOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngFor=\"let handle of nodeModel.handles()\">\n <svg:circle\n *ngIf=\"!handle.template\"\n class=\"default-handle\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n r=\"5\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection(handle)\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection(handle)\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(handle); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\"\n />\n</ng-container>\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}.default-node_selected{border-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
|
|
1466
1619
|
}], propDecorators: { nodeModel: [{
|
|
1467
1620
|
type: Input
|
|
1468
1621
|
}], nodeHtmlTemplate: [{
|
|
@@ -1473,7 +1626,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1473
1626
|
}], htmlWrapperRef: [{
|
|
1474
1627
|
type: ViewChild,
|
|
1475
1628
|
args: ['htmlWrapper']
|
|
1476
|
-
}],
|
|
1629
|
+
}], ngOnInit: [], ngAfterViewInit: [] } });
|
|
1477
1630
|
|
|
1478
1631
|
class EdgeLabelComponent {
|
|
1479
1632
|
constructor() {
|
|
@@ -1578,34 +1731,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1578
1731
|
type: Input
|
|
1579
1732
|
}] } });
|
|
1580
1733
|
|
|
1581
|
-
class SpacePointContextDirective {
|
|
1582
|
-
constructor() {
|
|
1583
|
-
this.pointerMovementDirective = inject(RootPointerDirective);
|
|
1584
|
-
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
1585
|
-
this.host = inject(ElementRef).nativeElement;
|
|
1586
|
-
/**
|
|
1587
|
-
* Signal with current mouse position in svg space
|
|
1588
|
-
*/
|
|
1589
|
-
this.svgCurrentSpacePoint = computed(() => {
|
|
1590
|
-
const movement = this.pointerMovement();
|
|
1591
|
-
if (!movement) {
|
|
1592
|
-
return { x: 0, y: 0 };
|
|
1593
|
-
}
|
|
1594
|
-
const point = this.rootSvg.createSVGPoint();
|
|
1595
|
-
point.x = movement.x;
|
|
1596
|
-
point.y = movement.y;
|
|
1597
|
-
return point.matrixTransform(this.host.getScreenCTM().inverse());
|
|
1598
|
-
});
|
|
1599
|
-
this.pointerMovement = toSignal(this.pointerMovementDirective.pointerMovement$);
|
|
1600
|
-
}
|
|
1601
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpacePointContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1602
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SpacePointContextDirective, selector: "g[spacePointContext]", ngImport: i0 }); }
|
|
1603
|
-
}
|
|
1604
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpacePointContextDirective, decorators: [{
|
|
1605
|
-
type: Directive,
|
|
1606
|
-
args: [{ selector: 'g[spacePointContext]' }]
|
|
1607
|
-
}] });
|
|
1608
|
-
|
|
1609
1734
|
class ConnectionComponent {
|
|
1610
1735
|
constructor() {
|
|
1611
1736
|
this.flowStatusService = inject(FlowStatusService);
|
|
@@ -1643,7 +1768,7 @@ class ConnectionComponent {
|
|
|
1643
1768
|
return null;
|
|
1644
1769
|
});
|
|
1645
1770
|
this.markerUrl = computed(() => {
|
|
1646
|
-
const marker = this.model.
|
|
1771
|
+
const marker = this.model.settings.marker;
|
|
1647
1772
|
if (marker) {
|
|
1648
1773
|
return `url(#${hashCode(JSON.stringify(marker))})`;
|
|
1649
1774
|
}
|
|
@@ -1784,11 +1909,11 @@ class BackgroundComponent {
|
|
|
1784
1909
|
});
|
|
1785
1910
|
}
|
|
1786
1911
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: BackgroundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1787
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: BackgroundComponent, selector: "g[background]", inputs: { background: ["background", "background", transform] }, ngImport: i0, template: "<ng-container *ngIf=\"backgroundSignal().type === 'dots'\">\n <svg:pattern\n [attr.id]=\"patternId\"\n [attr.x]=\"x()\"\n [attr.y]=\"y()\"\n [attr.width]=\"scaledGap()\"\n [attr.height]=\"scaledGap()\"\n patternUnits=\"userSpaceOnUse\"\n >\n <svg:circle\n [attr.cx]=\"patternSize()\"\n [attr.cy]=\"patternSize()\"\n [attr.r]=\"patternSize()\"\n [attr.fill]=\"patternColor()\"\n />\n </svg:pattern>\n\n <svg:rect\n x=\"0\"\n y=\"0\"\n width=\"100%\"\n height=\"100%\"\n [attr.fill]=\"patternUrl\"\n />\n</ng-container>\n", dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
1912
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: BackgroundComponent, selector: "g[background]", inputs: { background: ["background", "background", transform] }, ngImport: i0, template: "<ng-container *ngIf=\"backgroundSignal().type === 'dots'\">\n <svg:pattern\n [attr.id]=\"patternId\"\n [attr.x]=\"x()\"\n [attr.y]=\"y()\"\n [attr.width]=\"scaledGap()\"\n [attr.height]=\"scaledGap()\"\n patternUnits=\"userSpaceOnUse\"\n >\n <svg:circle\n [attr.cx]=\"patternSize()\"\n [attr.cy]=\"patternSize()\"\n [attr.r]=\"patternSize()\"\n [attr.fill]=\"patternColor()\"\n />\n </svg:pattern>\n\n <svg:rect\n x=\"0\"\n y=\"0\"\n width=\"100%\"\n height=\"100%\"\n [attr.fill]=\"patternUrl\"\n />\n</ng-container>\n", dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1788
1913
|
}
|
|
1789
1914
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: BackgroundComponent, decorators: [{
|
|
1790
1915
|
type: Component,
|
|
1791
|
-
args: [{ selector: 'g[background]', template: "<ng-container *ngIf=\"backgroundSignal().type === 'dots'\">\n <svg:pattern\n [attr.id]=\"patternId\"\n [attr.x]=\"x()\"\n [attr.y]=\"y()\"\n [attr.width]=\"scaledGap()\"\n [attr.height]=\"scaledGap()\"\n patternUnits=\"userSpaceOnUse\"\n >\n <svg:circle\n [attr.cx]=\"patternSize()\"\n [attr.cy]=\"patternSize()\"\n [attr.r]=\"patternSize()\"\n [attr.fill]=\"patternColor()\"\n />\n </svg:pattern>\n\n <svg:rect\n x=\"0\"\n y=\"0\"\n width=\"100%\"\n height=\"100%\"\n [attr.fill]=\"patternUrl\"\n />\n</ng-container>\n" }]
|
|
1916
|
+
args: [{ selector: 'g[background]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"backgroundSignal().type === 'dots'\">\n <svg:pattern\n [attr.id]=\"patternId\"\n [attr.x]=\"x()\"\n [attr.y]=\"y()\"\n [attr.width]=\"scaledGap()\"\n [attr.height]=\"scaledGap()\"\n patternUnits=\"userSpaceOnUse\"\n >\n <svg:circle\n [attr.cx]=\"patternSize()\"\n [attr.cy]=\"patternSize()\"\n [attr.r]=\"patternSize()\"\n [attr.fill]=\"patternColor()\"\n />\n </svg:pattern>\n\n <svg:rect\n x=\"0\"\n y=\"0\"\n width=\"100%\"\n height=\"100%\"\n [attr.fill]=\"patternUrl\"\n />\n</ng-container>\n" }]
|
|
1792
1917
|
}], ctorParameters: function () { return []; }, propDecorators: { background: [{
|
|
1793
1918
|
type: Input,
|
|
1794
1919
|
args: [{ required: true, transform }]
|
|
@@ -2022,6 +2147,12 @@ class VflowComponent {
|
|
|
2022
2147
|
getDetachedEdges() {
|
|
2023
2148
|
return this.flowEntitiesService.getDetachedEdges().map(e => e.edge);
|
|
2024
2149
|
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Convert point received from document to point on the flow
|
|
2152
|
+
*/
|
|
2153
|
+
documentPointToFlowPoint(point) {
|
|
2154
|
+
return this.spacePointContext.documentPointToFlowPoint(point);
|
|
2155
|
+
}
|
|
2025
2156
|
// #endregion
|
|
2026
2157
|
trackNodes(idx, { node }) {
|
|
2027
2158
|
return node;
|
|
@@ -2041,7 +2172,7 @@ class VflowComponent {
|
|
|
2041
2172
|
SelectionService,
|
|
2042
2173
|
FlowSettingsService,
|
|
2043
2174
|
ComponentEventBusService
|
|
2044
|
-
], queries: [{ propertyName: "nodeHtmlDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true }], hostDirectives: [{ directive: ConnectionControllerDirective, outputs: ["onConnect", "onConnect"] }, { directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.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\n rootSvgRef\n rootSvgContext\n rootPointer\n class=\"root-svg\"\n #flow\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\n\n <g [background]=\"background\"/>\n\n <svg:g\n mapContext\n spacePointContext\n [minZoom]=\"minZoom\"\n [maxZoom]=\"maxZoom\"\n >\n <!-- Connection -->\n <svg:g\n connection\n [model]=\"connection\"\n [template]=\"connectionTemplateDirective?.templateRef\"\n />\n\n <!-- Edges -->\n <svg:g\n *ngFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective?.templateRef\"\n />\n\n <!-- Nodes -->\n <svg:g\n *ngFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [nodeModel]=\"model\"\n [nodeHtmlTemplate]=\"nodeHtmlDirective?.templateRef\"\n [attr.transform]=\"model.pointTransform()\"\n />\n </svg:g>\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: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["nodeModel", "nodeHtmlTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]", inputs: ["background"] }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]", inputs: ["minZoom", "maxZoom"] }, { kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2175
|
+
], queries: [{ propertyName: "nodeHtmlDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true }], hostDirectives: [{ directive: ConnectionControllerDirective, outputs: ["onConnect", "onConnect"] }, { directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.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\n rootSvgRef\n rootSvgContext\n rootPointer\n class=\"root-svg\"\n #flow\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\n\n <g [background]=\"background\"/>\n\n <svg:g\n mapContext\n spacePointContext\n [minZoom]=\"minZoom\"\n [maxZoom]=\"maxZoom\"\n >\n <!-- Connection -->\n <svg:g\n connection\n [model]=\"connection\"\n [template]=\"connectionTemplateDirective?.templateRef\"\n />\n\n <!-- Edges -->\n <svg:g\n *ngFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective?.templateRef\"\n />\n\n <!-- Nodes -->\n <svg:g\n *ngFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [nodeModel]=\"model\"\n [nodeHtmlTemplate]=\"nodeHtmlDirective?.templateRef\"\n [attr.transform]=\"model.pointTransform()\"\n />\n </svg:g>\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: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["nodeModel", "nodeHtmlTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]", inputs: ["background"] }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]", inputs: ["minZoom", "maxZoom"] }, { kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2045
2176
|
}
|
|
2046
2177
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, decorators: [{
|
|
2047
2178
|
type: Component,
|
|
@@ -2097,49 +2228,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
2097
2228
|
}], mapContext: [{
|
|
2098
2229
|
type: ViewChild,
|
|
2099
2230
|
args: [MapContextDirective]
|
|
2231
|
+
}], spacePointContext: [{
|
|
2232
|
+
type: ViewChild,
|
|
2233
|
+
args: [SpacePointContextDirective]
|
|
2100
2234
|
}] } });
|
|
2101
2235
|
|
|
2102
|
-
class HandleComponent {
|
|
2103
|
-
constructor() {
|
|
2104
|
-
this.injector = inject(Injector);
|
|
2105
|
-
this.handleService = inject(HandleService);
|
|
2106
|
-
this.element = inject(ElementRef).nativeElement;
|
|
2107
|
-
}
|
|
2108
|
-
ngOnInit() {
|
|
2109
|
-
this.model = new HandleModel({
|
|
2110
|
-
position: this.position,
|
|
2111
|
-
type: this.type,
|
|
2112
|
-
id: this.id,
|
|
2113
|
-
parentReference: this.element.parentElement,
|
|
2114
|
-
template: this.template
|
|
2115
|
-
}, this.handleService.node());
|
|
2116
|
-
this.handleService.createHandle(this.model);
|
|
2117
|
-
queueMicrotask(() => this.model.updateParent());
|
|
2118
|
-
}
|
|
2119
|
-
ngOnDestroy() {
|
|
2120
|
-
this.handleService.destroyHandle(this.model);
|
|
2121
|
-
}
|
|
2122
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2123
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HandleComponent, selector: "handle", inputs: { position: "position", type: "type", id: "id", template: "template" }, ngImport: i0, template: "" }); }
|
|
2124
|
-
}
|
|
2125
|
-
__decorate([
|
|
2126
|
-
InjectionContext
|
|
2127
|
-
], HandleComponent.prototype, "ngOnInit", null);
|
|
2128
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, decorators: [{
|
|
2129
|
-
type: Component,
|
|
2130
|
-
args: [{ selector: 'handle', template: "" }]
|
|
2131
|
-
}], propDecorators: { position: [{
|
|
2132
|
-
type: Input,
|
|
2133
|
-
args: [{ required: true }]
|
|
2134
|
-
}], type: [{
|
|
2135
|
-
type: Input,
|
|
2136
|
-
args: [{ required: true }]
|
|
2137
|
-
}], id: [{
|
|
2138
|
-
type: Input
|
|
2139
|
-
}], template: [{
|
|
2140
|
-
type: Input
|
|
2141
|
-
}], ngOnInit: [] } });
|
|
2142
|
-
|
|
2143
2236
|
class SelectableDirective {
|
|
2144
2237
|
constructor() {
|
|
2145
2238
|
this.flowSettingsService = inject(FlowSettingsService);
|