ngx-vflow 0.3.0 → 0.5.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/edge/edge.component.mjs +18 -6
- package/esm2022/lib/vflow/components/handle/handle.component.mjs +7 -7
- package/esm2022/lib/vflow/components/node/node.component.mjs +23 -8
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +63 -22
- package/esm2022/lib/vflow/decorators/run-in-injection-context.decorator.mjs +6 -14
- package/esm2022/lib/vflow/directives/changes-controller.directive.mjs +115 -14
- package/esm2022/lib/vflow/directives/map-context.directive.mjs +31 -4
- package/esm2022/lib/vflow/directives/pointer.directive.mjs +84 -0
- package/esm2022/lib/vflow/directives/root-pointer.directive.mjs +42 -0
- package/esm2022/lib/vflow/directives/root-svg-context.directive.mjs +5 -2
- package/esm2022/lib/vflow/directives/selectable.directive.mjs +39 -0
- package/esm2022/lib/vflow/directives/space-point-context.directive.mjs +10 -6
- package/esm2022/lib/vflow/interfaces/flow-entity.interface.mjs +2 -0
- package/esm2022/lib/vflow/interfaces/template-context.interface.mjs +1 -1
- package/esm2022/lib/vflow/models/edge.model.mjs +3 -1
- package/esm2022/lib/vflow/models/node.model.mjs +9 -12
- package/esm2022/lib/vflow/services/edge-changes.service.mjs +6 -2
- package/esm2022/lib/vflow/services/flow-entities.service.mjs +5 -1
- package/esm2022/lib/vflow/services/flow-settings.service.mjs +25 -0
- package/esm2022/lib/vflow/services/node-changes.service.mjs +7 -3
- package/esm2022/lib/vflow/services/node-rendering.service.mjs +22 -0
- package/esm2022/lib/vflow/services/selection.service.mjs +45 -0
- package/esm2022/lib/vflow/types/edge-change.type.mjs +1 -1
- package/esm2022/lib/vflow/types/node-change.type.mjs +1 -1
- package/esm2022/lib/vflow/vflow.module.mjs +15 -4
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/ngx-vflow.mjs +582 -161
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/edge/edge.component.d.ts +5 -2
- package/lib/vflow/components/handle/handle.component.d.ts +4 -3
- package/lib/vflow/components/node/node.component.d.ts +10 -4
- package/lib/vflow/components/vflow/vflow.component.d.ts +12 -6
- package/lib/vflow/decorators/run-in-injection-context.decorator.d.ts +2 -5
- package/lib/vflow/directives/changes-controller.directive.d.ts +35 -9
- package/lib/vflow/directives/map-context.directive.d.ts +5 -0
- package/lib/vflow/directives/pointer.directive.d.ts +21 -0
- package/lib/vflow/directives/root-pointer.directive.d.ts +40 -0
- package/lib/vflow/directives/selectable.directive.d.ts +11 -0
- package/lib/vflow/directives/space-point-context.directive.d.ts +13 -3
- package/lib/vflow/interfaces/flow-entity.interface.d.ts +4 -0
- package/lib/vflow/interfaces/template-context.interface.d.ts +1 -0
- package/lib/vflow/models/edge.model.d.ts +8 -20
- package/lib/vflow/models/node.model.d.ts +6 -9
- package/lib/vflow/services/edge-changes.service.d.ts +5 -0
- package/lib/vflow/services/flow-entities.service.d.ts +5 -2
- package/lib/vflow/services/flow-settings.service.d.ts +20 -0
- package/lib/vflow/services/node-changes.service.d.ts +5 -0
- package/lib/vflow/services/node-rendering.service.d.ts +9 -0
- package/lib/vflow/services/selection.service.d.ts +19 -0
- package/lib/vflow/types/edge-change.type.d.ts +5 -1
- package/lib/vflow/types/node-change.type.d.ts +5 -1
- package/lib/vflow/vflow.module.d.ts +6 -3
- package/package.json +3 -3
- package/public-api.d.ts +1 -0
- package/esm2022/lib/vflow/models/flow.model.mjs +0 -18
- package/lib/vflow/models/flow.model.d.ts +0 -16
package/fesm2022/ngx-vflow.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
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, effect, Input, TemplateRef,
|
|
4
|
+
import { signal, Injectable, inject, ElementRef, Directive, computed, effect, Input, TemplateRef, EventEmitter, Output, untracked, runInInjectionContext, HostListener, Injector, NgZone, Component, ChangeDetectionStrategy, 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, switchMap, merge, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, Observable, fromEvent, animationFrameScheduler, share, Subscription, startWith } from 'rxjs';
|
|
8
|
+
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
7
9
|
import { drag } from 'd3-drag';
|
|
8
|
-
import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
9
|
-
import { switchMap, merge, skip, map, pairwise, filter, observeOn, asyncScheduler, zip, distinctUntilChanged, tap, Subject, Observable, Subscription, startWith, fromEvent } from 'rxjs';
|
|
10
10
|
import { path } from 'd3-path';
|
|
11
11
|
import { __decorate } from 'tslib';
|
|
12
12
|
|
|
@@ -58,13 +58,123 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
58
58
|
}]
|
|
59
59
|
}] });
|
|
60
60
|
|
|
61
|
+
class ConnectionModel {
|
|
62
|
+
constructor(connection) {
|
|
63
|
+
this.connection = connection;
|
|
64
|
+
this.curve = connection.curve ?? 'bezier';
|
|
65
|
+
this.type = connection.type ?? 'default';
|
|
66
|
+
this.validator = connection.validator ?? (() => true);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function hashCode(str) {
|
|
71
|
+
return str.split('').reduce((a, b) => {
|
|
72
|
+
a = ((a << 5) - a) + b.charCodeAt(0);
|
|
73
|
+
return a & a;
|
|
74
|
+
}, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class FlowEntitiesService {
|
|
78
|
+
constructor() {
|
|
79
|
+
this.nodes = signal([], {
|
|
80
|
+
// empty arrays considered equal, other arrays may not be equal
|
|
81
|
+
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
82
|
+
});
|
|
83
|
+
this.edges = signal([], {
|
|
84
|
+
// empty arrays considered equal, other arrays may not be equal
|
|
85
|
+
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
86
|
+
});
|
|
87
|
+
this.connection = signal(new ConnectionModel({}));
|
|
88
|
+
this.markers = computed(() => {
|
|
89
|
+
const markersMap = new Map();
|
|
90
|
+
this.validEdges().forEach(e => {
|
|
91
|
+
if (e.edge.markers?.start) {
|
|
92
|
+
const hash = hashCode(JSON.stringify(e.edge.markers.start));
|
|
93
|
+
markersMap.set(hash, e.edge.markers.start);
|
|
94
|
+
}
|
|
95
|
+
if (e.edge.markers?.end) {
|
|
96
|
+
const hash = hashCode(JSON.stringify(e.edge.markers.end));
|
|
97
|
+
markersMap.set(hash, e.edge.markers.end);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const connectionMarker = this.connection().connection.marker;
|
|
101
|
+
if (connectionMarker) {
|
|
102
|
+
const hash = hashCode(JSON.stringify(connectionMarker));
|
|
103
|
+
markersMap.set(hash, connectionMarker);
|
|
104
|
+
}
|
|
105
|
+
return markersMap;
|
|
106
|
+
});
|
|
107
|
+
this.validEdges = computed(() => {
|
|
108
|
+
const nodes = this.nodes();
|
|
109
|
+
return this.edges().filter(e => nodes.includes(e.source()) && nodes.includes(e.target()));
|
|
110
|
+
});
|
|
111
|
+
this.entities = computed(() => [
|
|
112
|
+
...this.nodes(),
|
|
113
|
+
...this.edges()
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
getNode(id) {
|
|
117
|
+
return this.nodes().find(({ node }) => node.id === id);
|
|
118
|
+
}
|
|
119
|
+
getDetachedEdges() {
|
|
120
|
+
return this.edges().filter(e => e.detached());
|
|
121
|
+
}
|
|
122
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
123
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService }); }
|
|
124
|
+
}
|
|
125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, decorators: [{
|
|
126
|
+
type: Injectable
|
|
127
|
+
}] });
|
|
128
|
+
|
|
129
|
+
class SelectionService {
|
|
130
|
+
constructor() {
|
|
131
|
+
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
132
|
+
this.viewport$ = new Subject();
|
|
133
|
+
this.resetSelection = this.viewport$.pipe(tap(({ start, end, target }) => {
|
|
134
|
+
if (start && end) {
|
|
135
|
+
const delta = SelectionService.delta;
|
|
136
|
+
const diffX = Math.abs(end.x - start.x);
|
|
137
|
+
const diffY = Math.abs(end.y - start.y);
|
|
138
|
+
// click (not drag)
|
|
139
|
+
const isClick = diffX < delta && diffY < delta;
|
|
140
|
+
// do not reset if event chain contains selectable elems
|
|
141
|
+
const isNotSelectable = !target.closest('.selectable');
|
|
142
|
+
if (isClick && isNotSelectable) {
|
|
143
|
+
this.select(null);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}), takeUntilDestroyed()).subscribe();
|
|
147
|
+
}
|
|
148
|
+
static { this.delta = 6; }
|
|
149
|
+
setViewport(viewport) {
|
|
150
|
+
this.viewport$.next(viewport);
|
|
151
|
+
}
|
|
152
|
+
select(entity) {
|
|
153
|
+
// undo select for previously selected nodes
|
|
154
|
+
this.flowEntitiesService.entities()
|
|
155
|
+
.filter(n => n.selected)
|
|
156
|
+
.forEach(n => n.selected.set(false));
|
|
157
|
+
if (entity) {
|
|
158
|
+
// select passed entity
|
|
159
|
+
entity.selected.set(true);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
163
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService }); }
|
|
164
|
+
}
|
|
165
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService, decorators: [{
|
|
166
|
+
type: Injectable
|
|
167
|
+
}] });
|
|
168
|
+
|
|
61
169
|
class MapContextDirective {
|
|
62
170
|
constructor() {
|
|
63
171
|
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
64
172
|
this.host = inject(ElementRef).nativeElement;
|
|
173
|
+
this.selectionService = inject(SelectionService);
|
|
65
174
|
this.viewportService = inject(ViewportService);
|
|
66
175
|
this.rootSvgSelection = select(this.rootSvg);
|
|
67
176
|
this.zoomableSelection = select(this.host);
|
|
177
|
+
this.viewportForSelection = {};
|
|
68
178
|
// under the hood this effect triggers handleZoom, so error throws without this flag
|
|
69
179
|
// TODO: hack with timer fixes wrong node scaling (handle positions not matched with content size)
|
|
70
180
|
this.manualViewportChangeEffect = effect(() => setTimeout(() => {
|
|
@@ -91,15 +201,32 @@ class MapContextDirective {
|
|
|
91
201
|
}), { allowSignalWrites: true });
|
|
92
202
|
this.handleZoom = ({ transform }) => {
|
|
93
203
|
// update public signal for user to read
|
|
94
|
-
this.viewportService.readableViewport.set(
|
|
204
|
+
this.viewportService.readableViewport.set(mapTransformToViewportState(transform));
|
|
95
205
|
this.zoomableSelection.attr('transform', transform.toString());
|
|
96
206
|
};
|
|
97
207
|
}
|
|
98
208
|
ngOnInit() {
|
|
99
209
|
this.zoomBehavior = zoom()
|
|
100
210
|
.scaleExtent([this.minZoom, this.maxZoom])
|
|
101
|
-
.on('
|
|
102
|
-
|
|
211
|
+
.on('start', (event) => this.onD3zoomStart(event))
|
|
212
|
+
.on('zoom', (event) => this.handleZoom(event))
|
|
213
|
+
.on('end', (event) => this.onD3zoomEnd(event));
|
|
214
|
+
this.rootSvgSelection
|
|
215
|
+
.call(this.zoomBehavior)
|
|
216
|
+
.on('dblclick.zoom', null);
|
|
217
|
+
}
|
|
218
|
+
onD3zoomStart({ transform }) {
|
|
219
|
+
this.viewportForSelection = {
|
|
220
|
+
start: mapTransformToViewportState(transform)
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
onD3zoomEnd({ transform, sourceEvent }) {
|
|
224
|
+
this.viewportForSelection = {
|
|
225
|
+
...this.viewportForSelection,
|
|
226
|
+
end: mapTransformToViewportState(transform),
|
|
227
|
+
target: evTarget(sourceEvent)
|
|
228
|
+
};
|
|
229
|
+
this.selectionService.setViewport(this.viewportForSelection);
|
|
103
230
|
}
|
|
104
231
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MapContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
105
232
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: MapContextDirective, selector: "g[mapContext]", inputs: { minZoom: "minZoom", maxZoom: "maxZoom" }, ngImport: i0 }); }
|
|
@@ -112,6 +239,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
112
239
|
}], maxZoom: [{
|
|
113
240
|
type: Input
|
|
114
241
|
}] } });
|
|
242
|
+
const mapTransformToViewportState = (transform) => ({ zoom: transform.k, x: transform.x, y: transform.y });
|
|
243
|
+
const evTarget = (anyEvent) => {
|
|
244
|
+
if (anyEvent instanceof Event && anyEvent.target instanceof Element) {
|
|
245
|
+
return anyEvent.target;
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
};
|
|
115
249
|
|
|
116
250
|
const round = (num) => Math.round(num * 100) / 100;
|
|
117
251
|
|
|
@@ -243,23 +377,6 @@ function addNodesToEdges(nodes, edges) {
|
|
|
243
377
|
});
|
|
244
378
|
}
|
|
245
379
|
|
|
246
|
-
class FlowModel {
|
|
247
|
-
constructor() {
|
|
248
|
-
/**
|
|
249
|
-
* Global setting with handle positions. Nodes derive this value
|
|
250
|
-
*
|
|
251
|
-
* @deprecated
|
|
252
|
-
*/
|
|
253
|
-
this.handlePositions = signal({ source: 'right', target: 'left' });
|
|
254
|
-
/**
|
|
255
|
-
* @see {VflowComponent.view}
|
|
256
|
-
*/
|
|
257
|
-
this.view = signal([400, 400]);
|
|
258
|
-
this.flowWidth = computed(() => this.view() === 'auto' ? '100%' : this.view()[0]);
|
|
259
|
-
this.flowHeight = computed(() => this.view() === 'auto' ? '100%' : this.view()[1]);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
380
|
class FlowStatusService {
|
|
264
381
|
constructor() {
|
|
265
382
|
this.status = signal({ state: 'idle', payload: null });
|
|
@@ -297,70 +414,6 @@ function batchStatusChanges(...changes) {
|
|
|
297
414
|
}
|
|
298
415
|
}
|
|
299
416
|
|
|
300
|
-
class ConnectionModel {
|
|
301
|
-
constructor(connection) {
|
|
302
|
-
this.connection = connection;
|
|
303
|
-
this.curve = connection.curve ?? 'bezier';
|
|
304
|
-
this.type = connection.type ?? 'default';
|
|
305
|
-
this.validator = connection.validator ?? (() => true);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function hashCode(str) {
|
|
310
|
-
return str.split('').reduce((a, b) => {
|
|
311
|
-
a = ((a << 5) - a) + b.charCodeAt(0);
|
|
312
|
-
return a & a;
|
|
313
|
-
}, 0);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
class FlowEntitiesService {
|
|
317
|
-
constructor() {
|
|
318
|
-
this.nodes = signal([], {
|
|
319
|
-
// empty arrays considered equal, other arrays may not be equal
|
|
320
|
-
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
321
|
-
});
|
|
322
|
-
this.edges = signal([], {
|
|
323
|
-
// empty arrays considered equal, other arrays may not be equal
|
|
324
|
-
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
325
|
-
});
|
|
326
|
-
this.connection = signal(new ConnectionModel({}));
|
|
327
|
-
this.markers = computed(() => {
|
|
328
|
-
const markersMap = new Map();
|
|
329
|
-
this.validEdges().forEach(e => {
|
|
330
|
-
if (e.edge.markers?.start) {
|
|
331
|
-
const hash = hashCode(JSON.stringify(e.edge.markers.start));
|
|
332
|
-
markersMap.set(hash, e.edge.markers.start);
|
|
333
|
-
}
|
|
334
|
-
if (e.edge.markers?.end) {
|
|
335
|
-
const hash = hashCode(JSON.stringify(e.edge.markers.end));
|
|
336
|
-
markersMap.set(hash, e.edge.markers.end);
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
const connectionMarker = this.connection().connection.marker;
|
|
340
|
-
if (connectionMarker) {
|
|
341
|
-
const hash = hashCode(JSON.stringify(connectionMarker));
|
|
342
|
-
markersMap.set(hash, connectionMarker);
|
|
343
|
-
}
|
|
344
|
-
return markersMap;
|
|
345
|
-
});
|
|
346
|
-
this.validEdges = computed(() => {
|
|
347
|
-
const nodes = this.nodes();
|
|
348
|
-
return this.edges().filter(e => nodes.includes(e.source()) && nodes.includes(e.target()));
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
getNode(id) {
|
|
352
|
-
return this.nodes().find(({ node }) => node.id === id);
|
|
353
|
-
}
|
|
354
|
-
getDetachedEdges() {
|
|
355
|
-
return this.edges().filter(e => e.detached());
|
|
356
|
-
}
|
|
357
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
358
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService }); }
|
|
359
|
-
}
|
|
360
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, decorators: [{
|
|
361
|
-
type: Injectable
|
|
362
|
-
}] });
|
|
363
|
-
|
|
364
417
|
class ConnectionControllerDirective {
|
|
365
418
|
constructor() {
|
|
366
419
|
/**
|
|
@@ -403,16 +456,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
403
456
|
type: Output
|
|
404
457
|
}] } });
|
|
405
458
|
|
|
459
|
+
class FlowSettingsService {
|
|
460
|
+
constructor() {
|
|
461
|
+
this.entitiesSelectable = signal(true);
|
|
462
|
+
/**
|
|
463
|
+
* Global setting with handle positions. Nodes derive this value
|
|
464
|
+
*
|
|
465
|
+
* @deprecated
|
|
466
|
+
*/
|
|
467
|
+
this.handlePositions = signal({ source: 'right', target: 'left' });
|
|
468
|
+
/**
|
|
469
|
+
* @see {VflowComponent.view}
|
|
470
|
+
*/
|
|
471
|
+
this.view = signal([400, 400]);
|
|
472
|
+
this.flowWidth = computed(() => this.view() === 'auto' ? '100%' : this.view()[0]);
|
|
473
|
+
this.flowHeight = computed(() => this.view() === 'auto' ? '100%' : this.view()[1]);
|
|
474
|
+
}
|
|
475
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
476
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService }); }
|
|
477
|
+
}
|
|
478
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService, decorators: [{
|
|
479
|
+
type: Injectable
|
|
480
|
+
}] });
|
|
481
|
+
|
|
406
482
|
class NodeModel {
|
|
407
483
|
constructor(node) {
|
|
408
484
|
this.node = node;
|
|
485
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
409
486
|
this.point = signal({ x: 0, y: 0 });
|
|
410
487
|
this.point$ = toObservable(this.point);
|
|
411
488
|
this.size = signal({ width: 0, height: 0 });
|
|
489
|
+
this.renderOrder = signal(0);
|
|
490
|
+
this.selected = signal(false);
|
|
491
|
+
this.selected$ = toObservable(this.selected);
|
|
412
492
|
this.pointTransform = computed(() => `translate(${this.point().x}, ${this.point().y})`);
|
|
413
493
|
// Now source and handle positions derived from parent flow
|
|
414
|
-
this.sourcePosition = computed(() => this.
|
|
415
|
-
this.targetPosition = computed(() => this.
|
|
494
|
+
this.sourcePosition = computed(() => this.flowSettingsService.handlePositions().source);
|
|
495
|
+
this.targetPosition = computed(() => this.flowSettingsService.handlePositions().target);
|
|
416
496
|
this.handles = signal([]);
|
|
417
497
|
this.handles$ = toObservable(this.handles);
|
|
418
498
|
this.draggable = true;
|
|
@@ -422,14 +502,6 @@ class NodeModel {
|
|
|
422
502
|
if (isDefined(node.draggable))
|
|
423
503
|
this.draggable = node.draggable;
|
|
424
504
|
}
|
|
425
|
-
/**
|
|
426
|
-
* Bind parent flow model to node
|
|
427
|
-
*
|
|
428
|
-
* @param flow parent flow
|
|
429
|
-
*/
|
|
430
|
-
bindFlow(flow) {
|
|
431
|
-
this.flow = flow;
|
|
432
|
-
}
|
|
433
505
|
}
|
|
434
506
|
|
|
435
507
|
class EdgeLabelModel {
|
|
@@ -547,6 +619,8 @@ class EdgeModel {
|
|
|
547
619
|
this.edge = edge;
|
|
548
620
|
this.source = signal(undefined);
|
|
549
621
|
this.target = signal(undefined);
|
|
622
|
+
this.selected = signal(false);
|
|
623
|
+
this.selected$ = toObservable(this.selected);
|
|
550
624
|
this.detached = computed(() => {
|
|
551
625
|
const source = this.source();
|
|
552
626
|
const target = this.target();
|
|
@@ -671,7 +745,11 @@ class NodesChangeService {
|
|
|
671
745
|
.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 }))));
|
|
672
746
|
this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes)
|
|
673
747
|
.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 }))));
|
|
674
|
-
this.
|
|
748
|
+
this.nodeSelectedChange$ = toObservable(this.entitiesService.nodes)
|
|
749
|
+
.pipe(switchMap((nodes) => merge(...nodes.map(node => node.selected$.pipe(distinctUntilChanged(), skip(1), map(() => node))))), map((changedNode) => [
|
|
750
|
+
{ type: 'select', id: changedNode.node.id, selected: changedNode.selected() }
|
|
751
|
+
]));
|
|
752
|
+
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$, this.nodeSelectedChange$).pipe(
|
|
675
753
|
// this fixes a bug when on fire node event change,
|
|
676
754
|
// you can't get valid list of detached edges
|
|
677
755
|
observeOn(asyncScheduler));
|
|
@@ -708,7 +786,11 @@ class EdgeChangesService {
|
|
|
708
786
|
.pipe(pairwise(), map(([oldList, newList]) => {
|
|
709
787
|
return oldList.filter(edge => !newList.includes(edge));
|
|
710
788
|
}), filter(edges => !!edges.length), map((edges) => edges.map(({ edge }) => ({ type: 'remove', id: edge.id }))));
|
|
711
|
-
this.
|
|
789
|
+
this.edgeSelectChange$ = toObservable(this.entitiesService.edges)
|
|
790
|
+
.pipe(switchMap((edges) => merge(...edges.map(edge => edge.selected$.pipe(distinctUntilChanged(), skip(1), map(() => edge))))), map((changedEdge) => [
|
|
791
|
+
{ type: 'select', id: changedEdge.edge.id, selected: changedEdge.selected() }
|
|
792
|
+
]));
|
|
793
|
+
this.changes$ = merge(this.edgeDetachedChange$, this.edgeAddChange$, this.edgeRemoveChange$, this.edgeSelectChange$)
|
|
712
794
|
.pipe(
|
|
713
795
|
// this fixes the case when user gets 'deteched' changes
|
|
714
796
|
// and tries to delete these edges inside stream
|
|
@@ -730,20 +812,50 @@ class ChangesControllerDirective {
|
|
|
730
812
|
/**
|
|
731
813
|
* Watch nodes change
|
|
732
814
|
*/
|
|
733
|
-
this.onNodesChange =
|
|
815
|
+
this.onNodesChange = this.nodesChangeService.changes$;
|
|
816
|
+
this.onNodesChangePosition = this.nodeChangesOfType('position');
|
|
817
|
+
this.onNodesChangePositionSignle = this.singleChange(this.nodeChangesOfType('position'));
|
|
818
|
+
this.onNodesChangePositionMany = this.manyChanges(this.nodeChangesOfType('position'));
|
|
819
|
+
this.onNodesChangeAdd = this.nodeChangesOfType('add');
|
|
820
|
+
this.onNodesChangeAddSingle = this.singleChange(this.nodeChangesOfType('add'));
|
|
821
|
+
this.onNodesChangeAddMany = this.manyChanges(this.nodeChangesOfType('add'));
|
|
822
|
+
this.onNodesChangeRemove = this.nodeChangesOfType('remove');
|
|
823
|
+
this.onNodesChangeRemoveSingle = this.singleChange(this.nodeChangesOfType('remove'));
|
|
824
|
+
this.onNodesChangeRemoveMany = this.manyChanges(this.nodeChangesOfType('remove'));
|
|
825
|
+
this.onNodesChangeSelect = this.nodeChangesOfType('select');
|
|
826
|
+
this.onNodesChangeSelectSingle = this.singleChange(this.nodeChangesOfType('select'));
|
|
827
|
+
this.onNodesChangeSelectMany = this.manyChanges(this.nodeChangesOfType('select'));
|
|
734
828
|
/**
|
|
735
|
-
* Watch
|
|
829
|
+
* Watch edges change
|
|
736
830
|
*/
|
|
737
|
-
this.onEdgesChange =
|
|
738
|
-
this.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
this.
|
|
742
|
-
|
|
743
|
-
|
|
831
|
+
this.onEdgesChange = this.edgesChangeService.changes$;
|
|
832
|
+
this.onNodesChangeDetached = this.edgeChangesOfType('detached');
|
|
833
|
+
this.onNodesChangeDetachedSingle = this.singleChange(this.edgeChangesOfType('detached'));
|
|
834
|
+
this.onNodesChangeDetachedMany = this.manyChanges(this.edgeChangesOfType('detached'));
|
|
835
|
+
this.onEdgesChangeAdd = this.edgeChangesOfType('add');
|
|
836
|
+
this.onEdgeChangeAddSingle = this.singleChange(this.edgeChangesOfType('add'));
|
|
837
|
+
this.onEdgeChangeAddMany = this.manyChanges(this.edgeChangesOfType('add'));
|
|
838
|
+
this.onEdgeChangeRemove = this.edgeChangesOfType('remove');
|
|
839
|
+
this.onEdgeChangeRemoveSingle = this.singleChange(this.edgeChangesOfType('remove'));
|
|
840
|
+
this.onEdgeChangeRemoveMany = this.manyChanges(this.edgeChangesOfType('remove'));
|
|
841
|
+
this.onEdgeChangeSelect = this.edgeChangesOfType('select');
|
|
842
|
+
this.onEdgeChangeSelectSingle = this.singleChange(this.edgeChangesOfType('select'));
|
|
843
|
+
this.onEdgeChangeSelectMany = this.manyChanges(this.edgeChangesOfType('select'));
|
|
844
|
+
}
|
|
845
|
+
nodeChangesOfType(type) {
|
|
846
|
+
return this.nodesChangeService.changes$.pipe(map(changes => changes.filter((c) => c.type === type)), filter(changes => !!changes.length));
|
|
847
|
+
}
|
|
848
|
+
edgeChangesOfType(type) {
|
|
849
|
+
return this.edgesChangeService.changes$.pipe(map(changes => changes.filter((c) => c.type === type)), filter(changes => !!changes.length));
|
|
850
|
+
}
|
|
851
|
+
singleChange(changes$) {
|
|
852
|
+
return changes$.pipe(filter(changes => changes.length === 1), map(([first]) => first));
|
|
853
|
+
}
|
|
854
|
+
manyChanges(changes$) {
|
|
855
|
+
return changes$.pipe(filter(changes => changes.length > 1));
|
|
744
856
|
}
|
|
745
857
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ChangesControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
746
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ChangesControllerDirective, isStandalone: true, selector: "[changesController]", outputs: { onNodesChange: "onNodesChange", onEdgesChange: "onEdgesChange" }, ngImport: i0 }); }
|
|
858
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ChangesControllerDirective, isStandalone: true, selector: "[changesController]", outputs: { onNodesChange: "onNodesChange", onNodesChangePosition: "onNodesChange.position", onNodesChangePositionSignle: "onNodesChange.position.single", onNodesChangePositionMany: "onNodesChange.position.many", onNodesChangeAdd: "onNodesChange.add", onNodesChangeAddSingle: "onNodesChange.add.single", onNodesChangeAddMany: "onNodesChange.add.many", onNodesChangeRemove: "onNodesChange.remove", onNodesChangeRemoveSingle: "onNodesChange.remove.single", onNodesChangeRemoveMany: "onNodesChange.remove.many", onNodesChangeSelect: "onNodesChange.select", onNodesChangeSelectSingle: "onNodesChange.select.single", onNodesChangeSelectMany: "onNodesChange.select.many", onEdgesChange: "onEdgesChange", onNodesChangeDetached: "onEdgesChange.detached", onNodesChangeDetachedSingle: "onEdgesChange.detached.single", onNodesChangeDetachedMany: "onEdgesChange.detached.many", onEdgesChangeAdd: "onEdgesChange.add", onEdgeChangeAddSingle: "onEdgesChange.add.single", onEdgeChangeAddMany: "onEdgesChange.add.many", onEdgeChangeRemove: "onEdgesChange.remove", onEdgeChangeRemoveSingle: "onEdgesChange.remove.single", onEdgeChangeRemoveMany: "onEdgesChange.remove.many", onEdgeChangeSelect: "onEdgesChange.select", onEdgeChangeSelectSingle: "onEdgesChange.select.single", onEdgeChangeSelectMany: "onEdgesChange.select.many" }, ngImport: i0 }); }
|
|
747
859
|
}
|
|
748
860
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ChangesControllerDirective, decorators: [{
|
|
749
861
|
type: Directive,
|
|
@@ -753,10 +865,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
753
865
|
}]
|
|
754
866
|
}], propDecorators: { onNodesChange: [{
|
|
755
867
|
type: Output
|
|
868
|
+
}], onNodesChangePosition: [{
|
|
869
|
+
type: Output,
|
|
870
|
+
args: ['onNodesChange.position']
|
|
871
|
+
}], onNodesChangePositionSignle: [{
|
|
872
|
+
type: Output,
|
|
873
|
+
args: ['onNodesChange.position.single']
|
|
874
|
+
}], onNodesChangePositionMany: [{
|
|
875
|
+
type: Output,
|
|
876
|
+
args: ['onNodesChange.position.many']
|
|
877
|
+
}], onNodesChangeAdd: [{
|
|
878
|
+
type: Output,
|
|
879
|
+
args: ['onNodesChange.add']
|
|
880
|
+
}], onNodesChangeAddSingle: [{
|
|
881
|
+
type: Output,
|
|
882
|
+
args: ['onNodesChange.add.single']
|
|
883
|
+
}], onNodesChangeAddMany: [{
|
|
884
|
+
type: Output,
|
|
885
|
+
args: ['onNodesChange.add.many']
|
|
886
|
+
}], onNodesChangeRemove: [{
|
|
887
|
+
type: Output,
|
|
888
|
+
args: ['onNodesChange.remove']
|
|
889
|
+
}], onNodesChangeRemoveSingle: [{
|
|
890
|
+
type: Output,
|
|
891
|
+
args: ['onNodesChange.remove.single']
|
|
892
|
+
}], onNodesChangeRemoveMany: [{
|
|
893
|
+
type: Output,
|
|
894
|
+
args: ['onNodesChange.remove.many']
|
|
895
|
+
}], onNodesChangeSelect: [{
|
|
896
|
+
type: Output,
|
|
897
|
+
args: ['onNodesChange.select']
|
|
898
|
+
}], onNodesChangeSelectSingle: [{
|
|
899
|
+
type: Output,
|
|
900
|
+
args: ['onNodesChange.select.single']
|
|
901
|
+
}], onNodesChangeSelectMany: [{
|
|
902
|
+
type: Output,
|
|
903
|
+
args: ['onNodesChange.select.many']
|
|
756
904
|
}], onEdgesChange: [{
|
|
757
905
|
type: Output
|
|
906
|
+
}], onNodesChangeDetached: [{
|
|
907
|
+
type: Output,
|
|
908
|
+
args: ['onEdgesChange.detached']
|
|
909
|
+
}], onNodesChangeDetachedSingle: [{
|
|
910
|
+
type: Output,
|
|
911
|
+
args: ['onEdgesChange.detached.single']
|
|
912
|
+
}], onNodesChangeDetachedMany: [{
|
|
913
|
+
type: Output,
|
|
914
|
+
args: ['onEdgesChange.detached.many']
|
|
915
|
+
}], onEdgesChangeAdd: [{
|
|
916
|
+
type: Output,
|
|
917
|
+
args: ['onEdgesChange.add']
|
|
918
|
+
}], onEdgeChangeAddSingle: [{
|
|
919
|
+
type: Output,
|
|
920
|
+
args: ['onEdgesChange.add.single']
|
|
921
|
+
}], onEdgeChangeAddMany: [{
|
|
922
|
+
type: Output,
|
|
923
|
+
args: ['onEdgesChange.add.many']
|
|
924
|
+
}], onEdgeChangeRemove: [{
|
|
925
|
+
type: Output,
|
|
926
|
+
args: ['onEdgesChange.remove']
|
|
927
|
+
}], onEdgeChangeRemoveSingle: [{
|
|
928
|
+
type: Output,
|
|
929
|
+
args: ['onEdgesChange.remove.single']
|
|
930
|
+
}], onEdgeChangeRemoveMany: [{
|
|
931
|
+
type: Output,
|
|
932
|
+
args: ['onEdgesChange.remove.many']
|
|
933
|
+
}], onEdgeChangeSelect: [{
|
|
934
|
+
type: Output,
|
|
935
|
+
args: ['onEdgesChange.select']
|
|
936
|
+
}], onEdgeChangeSelectSingle: [{
|
|
937
|
+
type: Output,
|
|
938
|
+
args: ['onEdgesChange.select.single']
|
|
939
|
+
}], onEdgeChangeSelectMany: [{
|
|
940
|
+
type: Output,
|
|
941
|
+
args: ['onEdgesChange.select.many']
|
|
758
942
|
}] } });
|
|
759
943
|
|
|
944
|
+
class NodeRenderingService {
|
|
945
|
+
constructor() {
|
|
946
|
+
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
947
|
+
this.nodes = computed(() => {
|
|
948
|
+
return this.flowEntitiesService.nodes()
|
|
949
|
+
.sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder());
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
pullNode(node) {
|
|
953
|
+
const maxOrder = Math.max(...this.flowEntitiesService.nodes().map((n) => n.renderOrder()));
|
|
954
|
+
node.renderOrder.set(maxOrder + 1);
|
|
955
|
+
}
|
|
956
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
957
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService }); }
|
|
958
|
+
}
|
|
959
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService, decorators: [{
|
|
960
|
+
type: Injectable
|
|
961
|
+
}] });
|
|
962
|
+
|
|
760
963
|
class HandleService {
|
|
761
964
|
constructor() {
|
|
762
965
|
this.node = signal(null);
|
|
@@ -868,7 +1071,7 @@ function resizable(elems, zone) {
|
|
|
868
1071
|
function InjectionContext(target, key, descriptor) {
|
|
869
1072
|
const originalMethod = descriptor.value;
|
|
870
1073
|
descriptor.value = function (...args) {
|
|
871
|
-
if (this
|
|
1074
|
+
if (implementsWithInjector(this)) {
|
|
872
1075
|
return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
|
|
873
1076
|
}
|
|
874
1077
|
else {
|
|
@@ -878,16 +1081,9 @@ function InjectionContext(target, key, descriptor) {
|
|
|
878
1081
|
// Return the modified descriptor
|
|
879
1082
|
return descriptor;
|
|
880
1083
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
}
|
|
885
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WithInjectorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
886
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: WithInjectorDirective, ngImport: i0 }); }
|
|
887
|
-
}
|
|
888
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WithInjectorDirective, decorators: [{
|
|
889
|
-
type: Directive
|
|
890
|
-
}] });
|
|
1084
|
+
const implementsWithInjector = (instance) => {
|
|
1085
|
+
return 'injector' in instance && 'get' in instance.injector;
|
|
1086
|
+
};
|
|
891
1087
|
|
|
892
1088
|
function Microtask(target, key, descriptor) {
|
|
893
1089
|
const originalMethod = descriptor.value;
|
|
@@ -936,14 +1132,135 @@ function getChildStrokeWidth(element) {
|
|
|
936
1132
|
return 0;
|
|
937
1133
|
}
|
|
938
1134
|
|
|
939
|
-
class
|
|
1135
|
+
class RootPointerDirective {
|
|
940
1136
|
constructor() {
|
|
941
|
-
|
|
1137
|
+
this.host = inject(ElementRef).nativeElement;
|
|
1138
|
+
this.initialTouch$ = new Subject();
|
|
1139
|
+
// TODO: do not emit if mouse not down
|
|
1140
|
+
this.mouseMovement$ = fromEvent(this.host, 'mousemove').pipe(map(event => ({
|
|
1141
|
+
x: event.clientX,
|
|
1142
|
+
y: event.clientY,
|
|
1143
|
+
originalEvent: event
|
|
1144
|
+
})), observeOn(animationFrameScheduler), share());
|
|
1145
|
+
this.touchMovement$ = merge(this.initialTouch$, fromEvent(this.host, 'touchmove')).pipe(tap((event) => event.preventDefault()), map((originalEvent) => {
|
|
1146
|
+
const x = originalEvent.touches[0]?.clientX ?? 0;
|
|
1147
|
+
const y = originalEvent.touches[0]?.clientY ?? 0;
|
|
1148
|
+
const target = document.elementFromPoint(x, y);
|
|
1149
|
+
return { x, y, target, originalEvent };
|
|
1150
|
+
}), observeOn(animationFrameScheduler), share());
|
|
1151
|
+
this.touchEnd$ = fromEvent(this.host, 'touchend').pipe(map((originalEvent) => {
|
|
1152
|
+
const x = originalEvent.changedTouches[0]?.clientX ?? 0;
|
|
1153
|
+
const y = originalEvent.changedTouches[0]?.clientY ?? 0;
|
|
1154
|
+
const target = document.elementFromPoint(x, y);
|
|
1155
|
+
return { x, y, target, originalEvent };
|
|
1156
|
+
}), share());
|
|
1157
|
+
this.pointerMovement$ = merge(this.mouseMovement$, this.touchMovement$);
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* We should know when user started a touch in order to not
|
|
1161
|
+
* show old touch position when connection creation is started
|
|
1162
|
+
*/
|
|
1163
|
+
setInitialTouch(event) {
|
|
1164
|
+
this.initialTouch$.next(event);
|
|
1165
|
+
}
|
|
1166
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1167
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RootPointerDirective, selector: "svg[rootPointer]", ngImport: i0 }); }
|
|
1168
|
+
}
|
|
1169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootPointerDirective, decorators: [{
|
|
1170
|
+
type: Directive,
|
|
1171
|
+
args: [{ selector: 'svg[rootPointer]' }]
|
|
1172
|
+
}] });
|
|
1173
|
+
|
|
1174
|
+
class PointerDirective {
|
|
1175
|
+
constructor() {
|
|
1176
|
+
this.hostElement = inject(ElementRef).nativeElement;
|
|
1177
|
+
this.pointerMovementDirective = inject(RootPointerDirective);
|
|
1178
|
+
this.pointerOver = new EventEmitter();
|
|
1179
|
+
this.pointerOut = new EventEmitter();
|
|
1180
|
+
this.pointerStart = new EventEmitter();
|
|
1181
|
+
this.pointerEnd = new EventEmitter();
|
|
1182
|
+
this.wasPointerOver = false;
|
|
1183
|
+
// TODO check if i could avoid global touch end
|
|
1184
|
+
this.touchEnd = this.pointerMovementDirective.touchEnd$
|
|
1185
|
+
.pipe(filter(({ target }) => target === this.hostElement), tap(({ originalEvent }) => this.pointerEnd.emit(originalEvent)), takeUntilDestroyed())
|
|
1186
|
+
.subscribe();
|
|
1187
|
+
this.touchOverOut = this.pointerMovementDirective.touchMovement$
|
|
1188
|
+
.pipe(tap(({ target, originalEvent }) => {
|
|
1189
|
+
this.handleTouchOverAndOut(target, originalEvent);
|
|
1190
|
+
}), takeUntilDestroyed())
|
|
1191
|
+
.subscribe();
|
|
1192
|
+
}
|
|
1193
|
+
onPointerStart(event) {
|
|
1194
|
+
this.pointerStart.emit(event);
|
|
1195
|
+
if (event instanceof TouchEvent) {
|
|
1196
|
+
this.pointerMovementDirective.setInitialTouch(event);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
onPointerEnd(event) {
|
|
1200
|
+
this.pointerEnd.emit(event);
|
|
1201
|
+
}
|
|
1202
|
+
onMouseOver(event) {
|
|
1203
|
+
this.pointerOver.emit(event);
|
|
1204
|
+
}
|
|
1205
|
+
onMouseOut(event) {
|
|
1206
|
+
this.pointerOut.emit(event);
|
|
1207
|
+
}
|
|
1208
|
+
// TODO: dirty imperative implementation
|
|
1209
|
+
handleTouchOverAndOut(target, event) {
|
|
1210
|
+
if (target === this.hostElement) {
|
|
1211
|
+
this.pointerOver.emit(event);
|
|
1212
|
+
this.wasPointerOver = true;
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
// should not emit before pointerOver
|
|
1216
|
+
if (this.wasPointerOver) {
|
|
1217
|
+
this.pointerOut.emit(event);
|
|
1218
|
+
}
|
|
1219
|
+
this.wasPointerOver = false;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PointerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1223
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: { pointerOver: "pointerOver", pointerOut: "pointerOut", pointerStart: "pointerStart", pointerEnd: "pointerEnd" }, host: { listeners: { "mousedown": "onPointerStart($event)", "touchstart": "onPointerStart($event)", "mouseup": "onPointerEnd($event)", "mouseover": "onMouseOver($event)", "mouseout": "onMouseOut($event)" } }, ngImport: i0 }); }
|
|
1224
|
+
}
|
|
1225
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PointerDirective, decorators: [{
|
|
1226
|
+
type: Directive,
|
|
1227
|
+
args: [{ selector: '[pointerStart], [pointerEnd], [pointerOver], [pointerOut]' }]
|
|
1228
|
+
}], propDecorators: { pointerOver: [{
|
|
1229
|
+
type: Output
|
|
1230
|
+
}], pointerOut: [{
|
|
1231
|
+
type: Output
|
|
1232
|
+
}], pointerStart: [{
|
|
1233
|
+
type: Output
|
|
1234
|
+
}], pointerEnd: [{
|
|
1235
|
+
type: Output
|
|
1236
|
+
}], onPointerStart: [{
|
|
1237
|
+
type: HostListener,
|
|
1238
|
+
args: ['mousedown', ['$event']]
|
|
1239
|
+
}, {
|
|
1240
|
+
type: HostListener,
|
|
1241
|
+
args: ['touchstart', ['$event']]
|
|
1242
|
+
}], onPointerEnd: [{
|
|
1243
|
+
type: HostListener,
|
|
1244
|
+
args: ['mouseup', ['$event']]
|
|
1245
|
+
}], onMouseOver: [{
|
|
1246
|
+
type: HostListener,
|
|
1247
|
+
args: ['mouseover', ['$event']]
|
|
1248
|
+
}], onMouseOut: [{
|
|
1249
|
+
type: HostListener,
|
|
1250
|
+
args: ['mouseout', ['$event']]
|
|
1251
|
+
}] } });
|
|
1252
|
+
|
|
1253
|
+
class NodeComponent {
|
|
1254
|
+
constructor() {
|
|
1255
|
+
this.injector = inject(Injector);
|
|
942
1256
|
this.handleService = inject(HandleService);
|
|
943
1257
|
this.zone = inject(NgZone);
|
|
944
1258
|
this.draggableService = inject(DraggableService);
|
|
945
1259
|
this.flowStatusService = inject(FlowStatusService);
|
|
946
1260
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
1261
|
+
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1262
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1263
|
+
this.selectionService = inject(SelectionService);
|
|
947
1264
|
this.hostRef = inject(ElementRef);
|
|
948
1265
|
this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
|
|
949
1266
|
this.flowStatusService.status().state === 'connection-validation');
|
|
@@ -1029,6 +1346,14 @@ class NodeComponent extends WithInjectorDirective {
|
|
|
1029
1346
|
this.flowStatusService.setConnectionStartStatus(status.payload.sourceNode, status.payload.sourceHandle);
|
|
1030
1347
|
}
|
|
1031
1348
|
}
|
|
1349
|
+
pullNode() {
|
|
1350
|
+
this.nodeRenderingService.pullNode(this.nodeModel);
|
|
1351
|
+
}
|
|
1352
|
+
selectNode() {
|
|
1353
|
+
if (this.flowSettingsService.entitiesSelectable()) {
|
|
1354
|
+
this.selectionService.select(this.nodeModel);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1032
1357
|
setInitialHandles() {
|
|
1033
1358
|
if (this.nodeModel.node.type === 'default') {
|
|
1034
1359
|
this.handleService.createHandle(new HandleModel({
|
|
@@ -1043,8 +1368,8 @@ class NodeComponent extends WithInjectorDirective {
|
|
|
1043
1368
|
}, this.nodeModel));
|
|
1044
1369
|
}
|
|
1045
1370
|
}
|
|
1046
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps:
|
|
1047
|
-
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 }],
|
|
1371
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1372
|
+
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 width=\"100\"\n height=\"50\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [innerHTML]=\"nodeModel.node.text ?? ''\"\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<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)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (pointerEnd)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (pointerStart)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (pointerEnd)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"handle.rawHandle.type === 'target' && showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(); resetValidateTargetHandle(handle)\"\n (pointerOver)=\"validateTargetHandle(handle)\"\n (pointerOut)=\"resetValidateTargetHandle(handle)\"\n />\n</ng-container>\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;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.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: "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 }); }
|
|
1048
1373
|
}
|
|
1049
1374
|
__decorate([
|
|
1050
1375
|
Microtask
|
|
@@ -1054,7 +1379,7 @@ __decorate([
|
|
|
1054
1379
|
], NodeComponent.prototype, "setInitialHandles", null);
|
|
1055
1380
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, decorators: [{
|
|
1056
1381
|
type: Component,
|
|
1057
|
-
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n>\n <div
|
|
1382
|
+
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [innerHTML]=\"nodeModel.node.text ?? ''\"\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<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)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (pointerEnd)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (pointerStart)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (pointerEnd)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"handle.rawHandle.type === 'target' && showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (pointerEnd)=\"endConnection(); resetValidateTargetHandle(handle)\"\n (pointerOver)=\"validateTargetHandle(handle)\"\n (pointerOut)=\"resetValidateTargetHandle(handle)\"\n />\n</ng-container>\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;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"] }]
|
|
1058
1383
|
}], propDecorators: { nodeModel: [{
|
|
1059
1384
|
type: Input
|
|
1060
1385
|
}], nodeHtmlTemplate: [{
|
|
@@ -1125,6 +1450,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1125
1450
|
|
|
1126
1451
|
class EdgeComponent {
|
|
1127
1452
|
constructor() {
|
|
1453
|
+
this.injector = inject(Injector);
|
|
1454
|
+
this.selectionService = inject(SelectionService);
|
|
1455
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1128
1456
|
this.markerStartUrl = computed(() => {
|
|
1129
1457
|
const marker = this.model.edge.markers?.start;
|
|
1130
1458
|
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
@@ -1133,7 +1461,6 @@ class EdgeComponent {
|
|
|
1133
1461
|
const marker = this.model.edge.markers?.end;
|
|
1134
1462
|
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
1135
1463
|
});
|
|
1136
|
-
this.defaultColor = 'rgb(177, 177, 183)';
|
|
1137
1464
|
}
|
|
1138
1465
|
ngOnInit() {
|
|
1139
1466
|
this.edgeContext = {
|
|
@@ -1142,16 +1469,24 @@ class EdgeComponent {
|
|
|
1142
1469
|
edge: this.model.edge,
|
|
1143
1470
|
path: computed(() => this.model.path().path),
|
|
1144
1471
|
markerStart: this.markerStartUrl,
|
|
1145
|
-
markerEnd: this.markerEndUrl
|
|
1472
|
+
markerEnd: this.markerEndUrl,
|
|
1473
|
+
selected: this.model.selected.asReadonly()
|
|
1146
1474
|
}
|
|
1147
1475
|
};
|
|
1148
1476
|
}
|
|
1477
|
+
onEdgeMouseDown() {
|
|
1478
|
+
if (this.flowSettingsService.entitiesSelectable()) {
|
|
1479
|
+
this.selectionService.select(this.model);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1149
1482
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1150
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EdgeComponent, selector: "g[edge]", inputs: { model: "model", edgeTemplate: "edgeTemplate", edgeLabelHtmlTemplate: "edgeLabelHtmlTemplate" }, ngImport: i0, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n
|
|
1483
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EdgeComponent, selector: "g[edge]", inputs: { model: "model", edgeTemplate: "edgeTemplate", edgeLabelHtmlTemplate: "edgeLabelHtmlTemplate" }, host: { classAttribute: "selectable" }, ngImport: i0, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n (mousedown)=\"onEdgeMouseDown()\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n class=\"edge\"\n [class.edge_selected]=\"model.selected()\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\"\n ></ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.start as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.start\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.center as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.center\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.end as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.end\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"], dependencies: [{ 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: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1151
1484
|
}
|
|
1152
1485
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, decorators: [{
|
|
1153
1486
|
type: Component,
|
|
1154
|
-
args: [{ selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1487
|
+
args: [{ selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1488
|
+
'class': 'selectable'
|
|
1489
|
+
}, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n (mousedown)=\"onEdgeMouseDown()\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n class=\"edge\"\n [class.edge_selected]=\"model.selected()\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\"\n ></ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.start as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.start\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.center as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.center\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.end as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.end\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"] }]
|
|
1155
1490
|
}], propDecorators: { model: [{
|
|
1156
1491
|
type: Input
|
|
1157
1492
|
}], edgeTemplate: [{
|
|
@@ -1162,19 +1497,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1162
1497
|
|
|
1163
1498
|
class SpacePointContextDirective {
|
|
1164
1499
|
constructor() {
|
|
1500
|
+
this.pointerMovementDirective = inject(RootPointerDirective);
|
|
1501
|
+
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
1502
|
+
this.host = inject(ElementRef).nativeElement;
|
|
1165
1503
|
/**
|
|
1166
1504
|
* Signal with current mouse position in svg space
|
|
1167
1505
|
*/
|
|
1168
1506
|
this.svgCurrentSpacePoint = computed(() => {
|
|
1169
|
-
const movement = this.
|
|
1507
|
+
const movement = this.pointerMovement();
|
|
1508
|
+
if (!movement) {
|
|
1509
|
+
return { x: 0, y: 0 };
|
|
1510
|
+
}
|
|
1170
1511
|
const point = this.rootSvg.createSVGPoint();
|
|
1171
1512
|
point.x = movement.x;
|
|
1172
1513
|
point.y = movement.y;
|
|
1173
1514
|
return point.matrixTransform(this.host.getScreenCTM().inverse());
|
|
1174
1515
|
});
|
|
1175
|
-
this.
|
|
1176
|
-
this.host = inject(ElementRef).nativeElement;
|
|
1177
|
-
this.mouseMovement = toSignal(fromEvent(this.rootSvg, 'mousemove').pipe(map(event => ({ x: event.clientX, y: event.clientY }))), { initialValue: { x: 0, y: 0 } });
|
|
1516
|
+
this.pointerMovement = toSignal(this.pointerMovementDirective.pointerMovement$);
|
|
1178
1517
|
}
|
|
1179
1518
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SpacePointContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1180
1519
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SpacePointContextDirective, selector: "g[spacePointContext]", ngImport: i0 }); }
|
|
@@ -1325,7 +1664,7 @@ class RootSvgContextDirective {
|
|
|
1325
1664
|
}
|
|
1326
1665
|
}
|
|
1327
1666
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootSvgContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1328
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RootSvgContextDirective, selector: "svg[rootSvgContext]", host: { listeners: { "document:mouseup": "resetConnection()" } }, ngImport: i0 }); }
|
|
1667
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: RootSvgContextDirective, selector: "svg[rootSvgContext]", host: { listeners: { "document:mouseup": "resetConnection()", "document:touchend": "resetConnection()" } }, ngImport: i0 }); }
|
|
1329
1668
|
}
|
|
1330
1669
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RootSvgContextDirective, decorators: [{
|
|
1331
1670
|
type: Directive,
|
|
@@ -1333,6 +1672,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1333
1672
|
}], propDecorators: { resetConnection: [{
|
|
1334
1673
|
type: HostListener,
|
|
1335
1674
|
args: ['document:mouseup']
|
|
1675
|
+
}, {
|
|
1676
|
+
type: HostListener,
|
|
1677
|
+
args: ['document:touchend']
|
|
1336
1678
|
}] } });
|
|
1337
1679
|
|
|
1338
1680
|
const connectionControllerHostDirective = {
|
|
@@ -1341,7 +1683,34 @@ const connectionControllerHostDirective = {
|
|
|
1341
1683
|
};
|
|
1342
1684
|
const changesControllerHostDirective = {
|
|
1343
1685
|
directive: ChangesControllerDirective,
|
|
1344
|
-
outputs: [
|
|
1686
|
+
outputs: [
|
|
1687
|
+
'onNodesChange',
|
|
1688
|
+
'onNodesChange.position',
|
|
1689
|
+
'onNodesChange.position.single',
|
|
1690
|
+
'onNodesChange.position.many',
|
|
1691
|
+
'onNodesChange.add',
|
|
1692
|
+
'onNodesChange.add.single',
|
|
1693
|
+
'onNodesChange.add.many',
|
|
1694
|
+
'onNodesChange.remove',
|
|
1695
|
+
'onNodesChange.remove.single',
|
|
1696
|
+
'onNodesChange.remove.many',
|
|
1697
|
+
'onNodesChange.select',
|
|
1698
|
+
'onNodesChange.select.single',
|
|
1699
|
+
'onNodesChange.select.many',
|
|
1700
|
+
'onEdgesChange',
|
|
1701
|
+
'onEdgesChange.detached',
|
|
1702
|
+
'onEdgesChange.detached.single',
|
|
1703
|
+
'onEdgesChange.detached.many',
|
|
1704
|
+
'onEdgesChange.add',
|
|
1705
|
+
'onEdgesChange.add.single',
|
|
1706
|
+
'onEdgesChange.add.many',
|
|
1707
|
+
'onEdgesChange.remove',
|
|
1708
|
+
'onEdgesChange.remove.single',
|
|
1709
|
+
'onEdgesChange.remove.many',
|
|
1710
|
+
'onEdgesChange.select',
|
|
1711
|
+
'onEdgesChange.select.single',
|
|
1712
|
+
'onEdgesChange.select.many',
|
|
1713
|
+
]
|
|
1345
1714
|
};
|
|
1346
1715
|
class VflowComponent {
|
|
1347
1716
|
constructor() {
|
|
@@ -1350,6 +1719,8 @@ class VflowComponent {
|
|
|
1350
1719
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
1351
1720
|
this.nodesChangeService = inject(NodesChangeService);
|
|
1352
1721
|
this.edgesChangeService = inject(EdgeChangesService);
|
|
1722
|
+
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1723
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1353
1724
|
this.injector = inject(Injector);
|
|
1354
1725
|
/**
|
|
1355
1726
|
* Minimum zoom value
|
|
@@ -1363,6 +1734,8 @@ class VflowComponent {
|
|
|
1363
1734
|
* Background color for flow
|
|
1364
1735
|
*/
|
|
1365
1736
|
this.background = '#FFFFFF';
|
|
1737
|
+
this.nodeModels = computed(() => this.nodeRenderingService.nodes());
|
|
1738
|
+
this.edgeModels = computed(() => this.flowEntitiesService.validEdges());
|
|
1366
1739
|
// #endregion
|
|
1367
1740
|
// #region SIGNAL_API
|
|
1368
1741
|
/**
|
|
@@ -1389,12 +1762,12 @@ class VflowComponent {
|
|
|
1389
1762
|
*/
|
|
1390
1763
|
this.nodesChange$ = this.nodesChangeService.changes$;
|
|
1391
1764
|
/**
|
|
1392
|
-
* Observable with
|
|
1765
|
+
* Observable with edges change
|
|
1393
1766
|
*/
|
|
1394
1767
|
this.edgesChange$ = this.edgesChangeService.changes$;
|
|
1395
1768
|
// #endregion
|
|
1396
|
-
|
|
1397
|
-
this.
|
|
1769
|
+
this.flowWidth = this.flowSettingsService.flowWidth;
|
|
1770
|
+
this.flowHeight = this.flowSettingsService.flowHeight;
|
|
1398
1771
|
this.markers = this.flowEntitiesService.markers;
|
|
1399
1772
|
}
|
|
1400
1773
|
// #endregion
|
|
@@ -1407,7 +1780,7 @@ class VflowComponent {
|
|
|
1407
1780
|
* - 'auto' to compute size based on parent element size
|
|
1408
1781
|
*/
|
|
1409
1782
|
set view(view) {
|
|
1410
|
-
this.
|
|
1783
|
+
this.flowSettingsService.view.set(view);
|
|
1411
1784
|
}
|
|
1412
1785
|
/**
|
|
1413
1786
|
* Object that controls flow direction.
|
|
@@ -1418,7 +1791,13 @@ class VflowComponent {
|
|
|
1418
1791
|
* @deprecated
|
|
1419
1792
|
*/
|
|
1420
1793
|
set handlePositions(handlePositions) {
|
|
1421
|
-
this.
|
|
1794
|
+
this.flowSettingsService.handlePositions.set(handlePositions);
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Global rule if you can or can't select entities
|
|
1798
|
+
*/
|
|
1799
|
+
set entitiesSelectable(value) {
|
|
1800
|
+
this.flowSettingsService.entitiesSelectable.set(value);
|
|
1422
1801
|
}
|
|
1423
1802
|
/**
|
|
1424
1803
|
* Settings for connection (it renders when user tries to create edge between nodes)
|
|
@@ -1434,23 +1813,19 @@ class VflowComponent {
|
|
|
1434
1813
|
*/
|
|
1435
1814
|
set nodes(newNodes) {
|
|
1436
1815
|
const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.nodes(newNodes, this.flowEntitiesService.nodes()));
|
|
1437
|
-
// TODO better to solve this by DI
|
|
1438
|
-
bindFlowToNodes(this.flowModel, newModels);
|
|
1439
1816
|
// quick and dirty binding nodes to edges
|
|
1440
1817
|
addNodesToEdges(newModels, this.flowEntitiesService.edges());
|
|
1441
1818
|
this.flowEntitiesService.nodes.set(newModels);
|
|
1442
1819
|
}
|
|
1443
|
-
get nodeModels() { return this.flowEntitiesService.nodes(); }
|
|
1444
1820
|
/**
|
|
1445
1821
|
* Edges to render
|
|
1446
1822
|
*/
|
|
1447
1823
|
set edges(newEdges) {
|
|
1448
1824
|
const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.edges(newEdges, this.flowEntitiesService.edges()));
|
|
1449
1825
|
// quick and dirty binding nodes to edges
|
|
1450
|
-
addNodesToEdges(this.nodeModels, newModels);
|
|
1826
|
+
addNodesToEdges(this.nodeModels(), newModels);
|
|
1451
1827
|
this.flowEntitiesService.edges.set(newModels);
|
|
1452
1828
|
}
|
|
1453
|
-
get edgeModels() { return this.flowEntitiesService.validEdges(); }
|
|
1454
1829
|
// #region METHODS_API
|
|
1455
1830
|
/**
|
|
1456
1831
|
* Change viewport to specified state
|
|
@@ -1498,14 +1873,17 @@ class VflowComponent {
|
|
|
1498
1873
|
return edge;
|
|
1499
1874
|
}
|
|
1500
1875
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1501
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: VflowComponent, selector: "vflow", inputs: { view: "view", minZoom: "minZoom", maxZoom: "maxZoom", handlePositions: "handlePositions", background: "background", connection: ["connection", "connection", (settings) => new ConnectionModel(settings)], nodes: "nodes", edges: "edges" }, providers: [
|
|
1876
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: VflowComponent, selector: "vflow", inputs: { view: "view", minZoom: "minZoom", maxZoom: "maxZoom", handlePositions: "handlePositions", background: "background", entitiesSelectable: "entitiesSelectable", connection: ["connection", "connection", (settings) => new ConnectionModel(settings)], nodes: "nodes", edges: "edges" }, providers: [
|
|
1502
1877
|
DraggableService,
|
|
1503
1878
|
ViewportService,
|
|
1504
1879
|
FlowStatusService,
|
|
1505
1880
|
FlowEntitiesService,
|
|
1506
1881
|
NodesChangeService,
|
|
1507
|
-
EdgeChangesService
|
|
1508
|
-
|
|
1882
|
+
EdgeChangesService,
|
|
1883
|
+
NodeRenderingService,
|
|
1884
|
+
SelectionService,
|
|
1885
|
+
FlowSettingsService
|
|
1886
|
+
], 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 [style.backgroundColor]=\"background\"\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\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: "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 }); }
|
|
1509
1887
|
}
|
|
1510
1888
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, decorators: [{
|
|
1511
1889
|
type: Component,
|
|
@@ -1515,11 +1893,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1515
1893
|
FlowStatusService,
|
|
1516
1894
|
FlowEntitiesService,
|
|
1517
1895
|
NodesChangeService,
|
|
1518
|
-
EdgeChangesService
|
|
1896
|
+
EdgeChangesService,
|
|
1897
|
+
NodeRenderingService,
|
|
1898
|
+
SelectionService,
|
|
1899
|
+
FlowSettingsService
|
|
1519
1900
|
], hostDirectives: [
|
|
1520
1901
|
connectionControllerHostDirective,
|
|
1521
1902
|
changesControllerHostDirective
|
|
1522
|
-
], template: "<svg:svg\n rootSvgRef\n rootSvgContext\n class=\"root-svg\"\n #flow\n [style.backgroundColor]=\"background\"\n [attr.width]=\"
|
|
1903
|
+
], template: "<svg:svg\n rootSvgRef\n rootSvgContext\n rootPointer\n class=\"root-svg\"\n #flow\n [style.backgroundColor]=\"background\"\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\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"] }]
|
|
1523
1904
|
}], propDecorators: { view: [{
|
|
1524
1905
|
type: Input
|
|
1525
1906
|
}], minZoom: [{
|
|
@@ -1530,6 +1911,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1530
1911
|
type: Input
|
|
1531
1912
|
}], background: [{
|
|
1532
1913
|
type: Input
|
|
1914
|
+
}], entitiesSelectable: [{
|
|
1915
|
+
type: Input
|
|
1533
1916
|
}], connection: [{
|
|
1534
1917
|
type: Input,
|
|
1535
1918
|
args: [{ transform: (settings) => new ConnectionModel(settings) }]
|
|
@@ -1554,13 +1937,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1554
1937
|
type: ViewChild,
|
|
1555
1938
|
args: [MapContextDirective]
|
|
1556
1939
|
}] } });
|
|
1557
|
-
function bindFlowToNodes(flow, nodes) {
|
|
1558
|
-
nodes.forEach(n => n.bindFlow(flow));
|
|
1559
|
-
}
|
|
1560
1940
|
|
|
1561
|
-
class HandleComponent
|
|
1941
|
+
class HandleComponent {
|
|
1562
1942
|
constructor() {
|
|
1563
|
-
|
|
1943
|
+
this.injector = inject(Injector);
|
|
1564
1944
|
this.handleService = inject(HandleService);
|
|
1565
1945
|
this.element = inject(ElementRef).nativeElement;
|
|
1566
1946
|
}
|
|
@@ -1578,8 +1958,8 @@ class HandleComponent extends WithInjectorDirective {
|
|
|
1578
1958
|
ngOnDestroy() {
|
|
1579
1959
|
this.handleService.destroyHandle(this.model);
|
|
1580
1960
|
}
|
|
1581
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps:
|
|
1582
|
-
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" },
|
|
1961
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1962
|
+
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: "" }); }
|
|
1583
1963
|
}
|
|
1584
1964
|
__decorate([
|
|
1585
1965
|
InjectionContext
|
|
@@ -1599,6 +1979,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1599
1979
|
type: Input
|
|
1600
1980
|
}], ngOnInit: [] } });
|
|
1601
1981
|
|
|
1982
|
+
class SelectableDirective {
|
|
1983
|
+
constructor() {
|
|
1984
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1985
|
+
this.selectionService = inject(SelectionService);
|
|
1986
|
+
this.parentEdge = inject(EdgeComponent, { optional: true });
|
|
1987
|
+
this.parentNode = inject(NodeComponent, { optional: true });
|
|
1988
|
+
}
|
|
1989
|
+
onMousedown() {
|
|
1990
|
+
const entity = this.entity();
|
|
1991
|
+
if (entity && this.flowSettingsService.entitiesSelectable()) {
|
|
1992
|
+
this.selectionService.select(entity);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
entity() {
|
|
1996
|
+
if (this.parentNode) {
|
|
1997
|
+
return this.parentNode.nodeModel;
|
|
1998
|
+
}
|
|
1999
|
+
else if (this.parentEdge) {
|
|
2000
|
+
return this.parentEdge.model;
|
|
2001
|
+
}
|
|
2002
|
+
return null;
|
|
2003
|
+
}
|
|
2004
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2005
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SelectableDirective, selector: "[selectable]", host: { listeners: { "mousedown": "onMousedown()" } }, ngImport: i0 }); }
|
|
2006
|
+
}
|
|
2007
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectableDirective, decorators: [{
|
|
2008
|
+
type: Directive,
|
|
2009
|
+
args: [{ selector: '[selectable]' }]
|
|
2010
|
+
}], propDecorators: { onMousedown: [{
|
|
2011
|
+
type: HostListener,
|
|
2012
|
+
args: ['mousedown']
|
|
2013
|
+
}] } });
|
|
2014
|
+
|
|
1602
2015
|
const components = [
|
|
1603
2016
|
VflowComponent,
|
|
1604
2017
|
NodeComponent,
|
|
@@ -1613,7 +2026,10 @@ const directives = [
|
|
|
1613
2026
|
MapContextDirective,
|
|
1614
2027
|
RootSvgReferenceDirective,
|
|
1615
2028
|
RootSvgContextDirective,
|
|
1616
|
-
HandleSizeControllerDirective
|
|
2029
|
+
HandleSizeControllerDirective,
|
|
2030
|
+
SelectableDirective,
|
|
2031
|
+
PointerDirective,
|
|
2032
|
+
RootPointerDirective
|
|
1617
2033
|
];
|
|
1618
2034
|
const templateDirectives = [
|
|
1619
2035
|
NodeHtmlTemplateDirective,
|
|
@@ -1634,12 +2050,16 @@ class VflowModule {
|
|
|
1634
2050
|
MapContextDirective,
|
|
1635
2051
|
RootSvgReferenceDirective,
|
|
1636
2052
|
RootSvgContextDirective,
|
|
1637
|
-
HandleSizeControllerDirective,
|
|
2053
|
+
HandleSizeControllerDirective,
|
|
2054
|
+
SelectableDirective,
|
|
2055
|
+
PointerDirective,
|
|
2056
|
+
RootPointerDirective, NodeHtmlTemplateDirective,
|
|
1638
2057
|
EdgeLabelHtmlTemplateDirective,
|
|
1639
2058
|
EdgeTemplateDirective,
|
|
1640
2059
|
ConnectionTemplateDirective,
|
|
1641
2060
|
HandleTemplateDirective], imports: [CommonModule], exports: [VflowComponent,
|
|
1642
|
-
HandleComponent,
|
|
2061
|
+
HandleComponent,
|
|
2062
|
+
SelectableDirective, NodeHtmlTemplateDirective,
|
|
1643
2063
|
EdgeLabelHtmlTemplateDirective,
|
|
1644
2064
|
EdgeTemplateDirective,
|
|
1645
2065
|
ConnectionTemplateDirective,
|
|
@@ -1653,6 +2073,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1653
2073
|
exports: [
|
|
1654
2074
|
VflowComponent,
|
|
1655
2075
|
HandleComponent,
|
|
2076
|
+
SelectableDirective,
|
|
1656
2077
|
...templateDirectives
|
|
1657
2078
|
],
|
|
1658
2079
|
declarations: [...components, ...directives, ...templateDirectives],
|
|
@@ -1665,5 +2086,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1665
2086
|
* Generated bundle index. Do not edit.
|
|
1666
2087
|
*/
|
|
1667
2088
|
|
|
1668
|
-
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, VflowComponent, VflowModule };
|
|
2089
|
+
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, SelectableDirective, VflowComponent, VflowModule };
|
|
1669
2090
|
//# sourceMappingURL=ngx-vflow.mjs.map
|