ngx-vflow 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/vflow/components/background/background.component.mjs +66 -0
- package/esm2022/lib/vflow/components/handle/handle.component.mjs +1 -1
- package/esm2022/lib/vflow/components/node/node.component.mjs +14 -10
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +29 -14
- package/esm2022/lib/vflow/directives/map-context.directive.mjs +7 -6
- package/esm2022/lib/vflow/interfaces/component-node-event.interface.mjs +2 -0
- package/esm2022/lib/vflow/interfaces/node.interface.mjs +1 -1
- package/esm2022/lib/vflow/models/node.model.mjs +25 -5
- package/esm2022/lib/vflow/public-components/custom-node.component.mjs +51 -0
- package/esm2022/lib/vflow/services/component-event-bus.service.mjs +18 -0
- package/esm2022/lib/vflow/services/draggable.service.mjs +2 -2
- package/esm2022/lib/vflow/services/selection.service.mjs +2 -2
- package/esm2022/lib/vflow/types/background.type.mjs +2 -0
- package/esm2022/lib/vflow/utils/id.mjs +5 -0
- package/esm2022/lib/vflow/utils/resizable.mjs +3 -3
- package/esm2022/lib/vflow/vflow.module.mjs +6 -3
- package/esm2022/public-api.mjs +4 -1
- package/fesm2022/ngx-vflow.mjs +195 -32
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/background/background.component.d.ts +20 -0
- package/lib/vflow/components/node/node.component.d.ts +8 -8
- package/lib/vflow/components/vflow/vflow.component.d.ts +11 -3
- package/lib/vflow/directives/space-point-context.directive.d.ts +3 -3
- package/lib/vflow/interfaces/component-node-event.interface.d.ts +32 -0
- package/lib/vflow/interfaces/node.interface.d.ts +9 -1
- package/lib/vflow/models/node.model.d.ts +14 -1
- package/lib/vflow/public-components/custom-node.component.d.ts +20 -0
- package/lib/vflow/services/component-event-bus.service.d.ts +9 -0
- package/lib/vflow/services/selection.service.d.ts +4 -1
- package/lib/vflow/types/background.type.d.ts +24 -0
- package/lib/vflow/utils/id.d.ts +1 -0
- package/lib/vflow/utils/resizable.d.ts +1 -2
- package/lib/vflow/vflow.module.d.ts +12 -11
- package/package.json +1 -1
- package/public-api.d.ts +3 -0
package/fesm2022/ngx-vflow.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
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, Input, TemplateRef, EventEmitter, Output,
|
|
4
|
+
import { signal, Injectable, inject, ElementRef, Directive, computed, effect, untracked, Input, TemplateRef, EventEmitter, Output, DestroyRef, runInInjectionContext, HostListener, Injector, 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,
|
|
8
|
-
import { takeUntilDestroyed,
|
|
7
|
+
import { Subject, tap, merge, BehaviorSubject, observeOn, animationFrameScheduler, switchMap, skip, map, pairwise, filter, distinctUntilChanged, asyncScheduler, zip, Observable, fromEvent, share, Subscription, startWith } from 'rxjs';
|
|
8
|
+
import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
9
9
|
import { drag } from 'd3-drag';
|
|
10
10
|
import { path } from 'd3-path';
|
|
11
11
|
import { __decorate } from 'tslib';
|
|
@@ -131,7 +131,7 @@ class SelectionService {
|
|
|
131
131
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
132
132
|
this.viewport$ = new Subject();
|
|
133
133
|
this.resetSelection = this.viewport$.pipe(tap(({ start, end, target }) => {
|
|
134
|
-
if (start && end) {
|
|
134
|
+
if (start && end && target) {
|
|
135
135
|
const delta = SelectionService.delta;
|
|
136
136
|
const diffX = Math.abs(end.x - start.x);
|
|
137
137
|
const diffY = Math.abs(end.y - start.y);
|
|
@@ -176,8 +176,7 @@ class MapContextDirective {
|
|
|
176
176
|
this.zoomableSelection = select(this.host);
|
|
177
177
|
this.viewportForSelection = {};
|
|
178
178
|
// under the hood this effect triggers handleZoom, so error throws without this flag
|
|
179
|
-
|
|
180
|
-
this.manualViewportChangeEffect = effect(() => setTimeout(() => {
|
|
179
|
+
this.manualViewportChangeEffect = effect(() => {
|
|
181
180
|
const viewport = this.viewportService.writableViewport();
|
|
182
181
|
const state = viewport.state;
|
|
183
182
|
if (viewport.changeType === 'initial') {
|
|
@@ -190,7 +189,9 @@ class MapContextDirective {
|
|
|
190
189
|
}
|
|
191
190
|
// If only pan provided
|
|
192
191
|
if ((isDefined(state.x) && isDefined(state.y)) && !isDefined(state.zoom)) {
|
|
193
|
-
|
|
192
|
+
// remain same zoom value
|
|
193
|
+
const zoom = untracked(this.viewportService.readableViewport).zoom;
|
|
194
|
+
this.rootSvgSelection.call(this.zoomBehavior.transform, zoomIdentity.translate(state.x, state.y).scale(zoom));
|
|
194
195
|
return;
|
|
195
196
|
}
|
|
196
197
|
// If whole viewort state provided
|
|
@@ -198,7 +199,7 @@ class MapContextDirective {
|
|
|
198
199
|
this.rootSvgSelection.call(this.zoomBehavior.transform, zoomIdentity.translate(state.x, state.y).scale(state.zoom));
|
|
199
200
|
return;
|
|
200
201
|
}
|
|
201
|
-
}
|
|
202
|
+
}, { allowSignalWrites: true });
|
|
202
203
|
this.handleZoom = ({ transform }) => {
|
|
203
204
|
// update public signal for user to read
|
|
204
205
|
this.viewportService.readableViewport.set(mapTransformToViewportState(transform));
|
|
@@ -287,7 +288,7 @@ class DraggableService {
|
|
|
287
288
|
deltaY = model.point().y - event.y;
|
|
288
289
|
})
|
|
289
290
|
.on('drag', (event) => {
|
|
290
|
-
model.
|
|
291
|
+
model.setPoint({
|
|
291
292
|
x: round(event.x + deltaX),
|
|
292
293
|
y: round(event.y + deltaY)
|
|
293
294
|
});
|
|
@@ -479,12 +480,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
479
480
|
type: Injectable
|
|
480
481
|
}] });
|
|
481
482
|
|
|
483
|
+
class ComponentEventBusService {
|
|
484
|
+
constructor() {
|
|
485
|
+
this._event$ = new Subject();
|
|
486
|
+
this.event$ = this._event$.asObservable();
|
|
487
|
+
}
|
|
488
|
+
pushEvent(event) {
|
|
489
|
+
this._event$.next(event);
|
|
490
|
+
}
|
|
491
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ComponentEventBusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
492
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ComponentEventBusService }); }
|
|
493
|
+
}
|
|
494
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ComponentEventBusService, decorators: [{
|
|
495
|
+
type: Injectable
|
|
496
|
+
}] });
|
|
497
|
+
|
|
498
|
+
class CustomNodeComponent {
|
|
499
|
+
constructor() {
|
|
500
|
+
this.eventBus = inject(ComponentEventBusService);
|
|
501
|
+
this.destroyRef = inject(DestroyRef);
|
|
502
|
+
/**
|
|
503
|
+
* Signal with selected state of node
|
|
504
|
+
*/
|
|
505
|
+
this.selected = signal(false);
|
|
506
|
+
}
|
|
507
|
+
set _selected(value) {
|
|
508
|
+
this.selected.set(value);
|
|
509
|
+
}
|
|
510
|
+
ngOnInit() {
|
|
511
|
+
this.trackEvents();
|
|
512
|
+
}
|
|
513
|
+
trackEvents() {
|
|
514
|
+
const props = Object.getOwnPropertyNames(this);
|
|
515
|
+
const emitters = new Map();
|
|
516
|
+
for (const prop of props) {
|
|
517
|
+
const field = this[prop];
|
|
518
|
+
if (field instanceof EventEmitter) {
|
|
519
|
+
emitters.set(field, prop);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
merge(...Array.from(emitters.keys()).map(emitter => emitter.pipe(tap((event) => {
|
|
523
|
+
this.eventBus.pushEvent({
|
|
524
|
+
nodeId: this.node.id,
|
|
525
|
+
eventName: emitters.get(emitter),
|
|
526
|
+
eventPayload: event
|
|
527
|
+
});
|
|
528
|
+
}))))
|
|
529
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
530
|
+
.subscribe();
|
|
531
|
+
}
|
|
532
|
+
;
|
|
533
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CustomNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
534
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: CustomNodeComponent, inputs: { node: "node", _selected: "_selected" }, ngImport: i0 }); }
|
|
535
|
+
}
|
|
536
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CustomNodeComponent, decorators: [{
|
|
537
|
+
type: Directive
|
|
538
|
+
}], propDecorators: { node: [{
|
|
539
|
+
type: Input
|
|
540
|
+
}], _selected: [{
|
|
541
|
+
type: Input
|
|
542
|
+
}] } });
|
|
543
|
+
|
|
482
544
|
class NodeModel {
|
|
545
|
+
static { this.defaultTypeSize = {
|
|
546
|
+
width: 100,
|
|
547
|
+
height: 50
|
|
548
|
+
}; }
|
|
483
549
|
constructor(node) {
|
|
484
550
|
this.node = node;
|
|
485
551
|
this.flowSettingsService = inject(FlowSettingsService);
|
|
486
|
-
this.
|
|
487
|
-
this.
|
|
552
|
+
this.internalPoint$ = new BehaviorSubject({ x: 0, y: 0 });
|
|
553
|
+
this.throttledPoint$ = this.internalPoint$.pipe(observeOn(animationFrameScheduler));
|
|
554
|
+
this.point = toSignal(this.throttledPoint$, {
|
|
555
|
+
initialValue: this.internalPoint$.getValue()
|
|
556
|
+
});
|
|
557
|
+
this.point$ = this.throttledPoint$;
|
|
488
558
|
this.size = signal({ width: 0, height: 0 });
|
|
489
559
|
this.renderOrder = signal(0);
|
|
490
560
|
this.selected = signal(false);
|
|
@@ -498,10 +568,20 @@ class NodeModel {
|
|
|
498
568
|
this.draggable = true;
|
|
499
569
|
// disabled for configuration for now
|
|
500
570
|
this.magnetRadius = 20;
|
|
501
|
-
this.
|
|
571
|
+
this.isComponentType = CustomNodeComponent.isPrototypeOf(this.node.type);
|
|
572
|
+
this.componentTypeInputs = computed(() => {
|
|
573
|
+
return {
|
|
574
|
+
node: this.node,
|
|
575
|
+
_selected: this.selected()
|
|
576
|
+
};
|
|
577
|
+
});
|
|
578
|
+
this.setPoint(node.point);
|
|
502
579
|
if (isDefined(node.draggable))
|
|
503
580
|
this.draggable = node.draggable;
|
|
504
581
|
}
|
|
582
|
+
setPoint(point) {
|
|
583
|
+
this.internalPoint$.next(point);
|
|
584
|
+
}
|
|
505
585
|
}
|
|
506
586
|
|
|
507
587
|
class EdgeLabelModel {
|
|
@@ -1058,10 +1138,10 @@ class HandleModel {
|
|
|
1058
1138
|
}
|
|
1059
1139
|
}
|
|
1060
1140
|
|
|
1061
|
-
function resizable(elems
|
|
1141
|
+
function resizable(elems) {
|
|
1062
1142
|
return new Observable((subscriber) => {
|
|
1063
1143
|
let ro = new ResizeObserver((entries) => {
|
|
1064
|
-
|
|
1144
|
+
subscriber.next(entries);
|
|
1065
1145
|
});
|
|
1066
1146
|
elems.forEach(e => ro.observe(e));
|
|
1067
1147
|
return () => ro.disconnect();
|
|
@@ -1254,7 +1334,6 @@ class NodeComponent {
|
|
|
1254
1334
|
constructor() {
|
|
1255
1335
|
this.injector = inject(Injector);
|
|
1256
1336
|
this.handleService = inject(HandleService);
|
|
1257
|
-
this.zone = inject(NgZone);
|
|
1258
1337
|
this.draggableService = inject(DraggableService);
|
|
1259
1338
|
this.flowStatusService = inject(FlowStatusService);
|
|
1260
1339
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
@@ -1264,13 +1343,15 @@ class NodeComponent {
|
|
|
1264
1343
|
this.hostRef = inject(ElementRef);
|
|
1265
1344
|
this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
|
|
1266
1345
|
this.flowStatusService.status().state === 'connection-validation');
|
|
1346
|
+
this.styleWidth = computed(() => `${this.nodeModel.size().width}px`);
|
|
1347
|
+
this.styleHeight = computed(() => `${this.nodeModel.size().height}px`);
|
|
1267
1348
|
this.subscription = new Subscription();
|
|
1268
1349
|
}
|
|
1269
1350
|
ngOnInit() {
|
|
1270
1351
|
this.handleService.node.set(this.nodeModel);
|
|
1271
1352
|
this.draggableService.toggleDraggable(this.hostRef.nativeElement, this.nodeModel);
|
|
1272
1353
|
const sub = this.nodeModel.handles$
|
|
1273
|
-
.pipe(switchMap((handles) => resizable(handles.map(h => h.parentReference)
|
|
1354
|
+
.pipe(switchMap((handles) => resizable(handles.map(h => h.parentReference))
|
|
1274
1355
|
.pipe(map(() => handles))), tap((handles) => handles.forEach(h => h.updateParent())))
|
|
1275
1356
|
.subscribe();
|
|
1276
1357
|
this.subscription.add(sub);
|
|
@@ -1278,11 +1359,13 @@ class NodeComponent {
|
|
|
1278
1359
|
ngAfterViewInit() {
|
|
1279
1360
|
this.setInitialHandles();
|
|
1280
1361
|
if (this.nodeModel.node.type === 'default') {
|
|
1281
|
-
|
|
1282
|
-
|
|
1362
|
+
this.nodeModel.size.set({
|
|
1363
|
+
width: this.nodeModel.node.width ?? NodeModel.defaultTypeSize.width,
|
|
1364
|
+
height: this.nodeModel.node.height ?? NodeModel.defaultTypeSize.height
|
|
1365
|
+
});
|
|
1283
1366
|
}
|
|
1284
|
-
if (this.nodeModel.node.type === 'html-template') {
|
|
1285
|
-
const sub = resizable([this.htmlWrapperRef.nativeElement]
|
|
1367
|
+
if (this.nodeModel.node.type === 'html-template' || this.nodeModel.isComponentType) {
|
|
1368
|
+
const sub = resizable([this.htmlWrapperRef.nativeElement])
|
|
1286
1369
|
.pipe(startWith(null), tap(() => {
|
|
1287
1370
|
const width = this.htmlWrapperRef.nativeElement.clientWidth;
|
|
1288
1371
|
const height = this.htmlWrapperRef.nativeElement.clientHeight;
|
|
@@ -1369,7 +1452,7 @@ class NodeComponent {
|
|
|
1369
1452
|
}
|
|
1370
1453
|
}
|
|
1371
1454
|
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=\"
|
|
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 [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<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)=\"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", 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: "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 }); }
|
|
1373
1456
|
}
|
|
1374
1457
|
__decorate([
|
|
1375
1458
|
Microtask
|
|
@@ -1379,7 +1462,7 @@ __decorate([
|
|
|
1379
1462
|
], NodeComponent.prototype, "setInitialHandles", null);
|
|
1380
1463
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, decorators: [{
|
|
1381
1464
|
type: Component,
|
|
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=\"
|
|
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 [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<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)=\"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", 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"] }]
|
|
1383
1466
|
}], propDecorators: { nodeModel: [{
|
|
1384
1467
|
type: Input
|
|
1385
1468
|
}], nodeHtmlTemplate: [{
|
|
@@ -1651,6 +1734,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1651
1734
|
args: [{ required: true }]
|
|
1652
1735
|
}] } });
|
|
1653
1736
|
|
|
1737
|
+
function id() {
|
|
1738
|
+
const randomLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
|
1739
|
+
return randomLetter + Date.now();
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
const defaultBg = '#fff';
|
|
1743
|
+
const defaultGap = 20;
|
|
1744
|
+
const defaultDotSize = 2;
|
|
1745
|
+
const defaultDotColor = 'rgb(177, 177, 183)';
|
|
1746
|
+
class BackgroundComponent {
|
|
1747
|
+
set background(value) {
|
|
1748
|
+
this.backgroundSignal.set(value);
|
|
1749
|
+
}
|
|
1750
|
+
constructor() {
|
|
1751
|
+
this.viewportService = inject(ViewportService);
|
|
1752
|
+
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
1753
|
+
this.backgroundSignal = signal({ type: 'solid', color: defaultBg });
|
|
1754
|
+
this.scaledGap = computed(() => {
|
|
1755
|
+
const background = this.backgroundSignal();
|
|
1756
|
+
if (background.type === 'dots') {
|
|
1757
|
+
const zoom = this.viewportService.readableViewport().zoom;
|
|
1758
|
+
return zoom * (background.gap ?? defaultGap);
|
|
1759
|
+
}
|
|
1760
|
+
return 0;
|
|
1761
|
+
});
|
|
1762
|
+
this.x = computed(() => this.viewportService.readableViewport().x % this.scaledGap());
|
|
1763
|
+
this.y = computed(() => this.viewportService.readableViewport().y % this.scaledGap());
|
|
1764
|
+
this.patternColor = computed(() => this.backgroundSignal().color ?? defaultDotColor);
|
|
1765
|
+
this.patternSize = computed(() => {
|
|
1766
|
+
const background = this.backgroundSignal();
|
|
1767
|
+
if (background.type === 'dots') {
|
|
1768
|
+
return (this.viewportService.readableViewport().zoom * (background.size ?? defaultDotSize)) / 2;
|
|
1769
|
+
}
|
|
1770
|
+
return 0;
|
|
1771
|
+
});
|
|
1772
|
+
// Without ID there will be pattern collision for several flows on the page
|
|
1773
|
+
// Later pattern ID may be exposed to API
|
|
1774
|
+
this.patternId = id();
|
|
1775
|
+
this.patternUrl = `url(#${this.patternId})`;
|
|
1776
|
+
effect(() => {
|
|
1777
|
+
const background = this.backgroundSignal();
|
|
1778
|
+
if (background.type === 'dots') {
|
|
1779
|
+
this.rootSvg.style.backgroundColor = background.backgroundColor ?? defaultBg;
|
|
1780
|
+
}
|
|
1781
|
+
if (background.type === 'solid') {
|
|
1782
|
+
this.rootSvg.style.backgroundColor = background.color;
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
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"] }] }); }
|
|
1788
|
+
}
|
|
1789
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: BackgroundComponent, decorators: [{
|
|
1790
|
+
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" }]
|
|
1792
|
+
}], ctorParameters: function () { return []; }, propDecorators: { background: [{
|
|
1793
|
+
type: Input,
|
|
1794
|
+
args: [{ required: true, transform }]
|
|
1795
|
+
}] } });
|
|
1796
|
+
function transform(background) {
|
|
1797
|
+
return typeof background === 'string'
|
|
1798
|
+
? { type: 'solid', color: background }
|
|
1799
|
+
: background;
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1654
1802
|
// TODO: too general purpose nane
|
|
1655
1803
|
class RootSvgContextDirective {
|
|
1656
1804
|
constructor() {
|
|
@@ -1721,6 +1869,7 @@ class VflowComponent {
|
|
|
1721
1869
|
this.edgesChangeService = inject(EdgeChangesService);
|
|
1722
1870
|
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1723
1871
|
this.flowSettingsService = inject(FlowSettingsService);
|
|
1872
|
+
this.componentEventBusService = inject(ComponentEventBusService);
|
|
1724
1873
|
this.injector = inject(Injector);
|
|
1725
1874
|
/**
|
|
1726
1875
|
* Minimum zoom value
|
|
@@ -1731,12 +1880,20 @@ class VflowComponent {
|
|
|
1731
1880
|
*/
|
|
1732
1881
|
this.maxZoom = 3;
|
|
1733
1882
|
/**
|
|
1734
|
-
* Background
|
|
1883
|
+
* Background for flow
|
|
1735
1884
|
*/
|
|
1736
|
-
this.background = '#
|
|
1885
|
+
this.background = '#fff';
|
|
1737
1886
|
this.nodeModels = computed(() => this.nodeRenderingService.nodes());
|
|
1738
1887
|
this.edgeModels = computed(() => this.flowEntitiesService.validEdges());
|
|
1739
1888
|
// #endregion
|
|
1889
|
+
// #region OUTPUTS
|
|
1890
|
+
/**
|
|
1891
|
+
* Event that accumulates all custom node events
|
|
1892
|
+
*
|
|
1893
|
+
* @experimental
|
|
1894
|
+
*/
|
|
1895
|
+
this.onComponentNodeEvent = this.componentEventBusService.event$; // TODO: research how to remove as any
|
|
1896
|
+
// #endregion
|
|
1740
1897
|
// #region SIGNAL_API
|
|
1741
1898
|
/**
|
|
1742
1899
|
* Signal for reading viewport change
|
|
@@ -1873,7 +2030,7 @@ class VflowComponent {
|
|
|
1873
2030
|
return edge;
|
|
1874
2031
|
}
|
|
1875
2032
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
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: [
|
|
2033
|
+
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" }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, providers: [
|
|
1877
2034
|
DraggableService,
|
|
1878
2035
|
ViewportService,
|
|
1879
2036
|
FlowStatusService,
|
|
@@ -1882,8 +2039,9 @@ class VflowComponent {
|
|
|
1882
2039
|
EdgeChangesService,
|
|
1883
2040
|
NodeRenderingService,
|
|
1884
2041
|
SelectionService,
|
|
1885
|
-
FlowSettingsService
|
|
1886
|
-
|
|
2042
|
+
FlowSettingsService,
|
|
2043
|
+
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 }); }
|
|
1887
2045
|
}
|
|
1888
2046
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, decorators: [{
|
|
1889
2047
|
type: Component,
|
|
@@ -1896,11 +2054,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1896
2054
|
EdgeChangesService,
|
|
1897
2055
|
NodeRenderingService,
|
|
1898
2056
|
SelectionService,
|
|
1899
|
-
FlowSettingsService
|
|
2057
|
+
FlowSettingsService,
|
|
2058
|
+
ComponentEventBusService
|
|
1900
2059
|
], hostDirectives: [
|
|
1901
2060
|
connectionControllerHostDirective,
|
|
1902
2061
|
changesControllerHostDirective
|
|
1903
|
-
], template: "<svg:svg\n rootSvgRef\n rootSvgContext\n rootPointer\n class=\"root-svg\"\n #flow\n [
|
|
2062
|
+
], 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"] }]
|
|
1904
2063
|
}], propDecorators: { view: [{
|
|
1905
2064
|
type: Input
|
|
1906
2065
|
}], minZoom: [{
|
|
@@ -1921,6 +2080,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1921
2080
|
args: [{ required: true }]
|
|
1922
2081
|
}], edges: [{
|
|
1923
2082
|
type: Input
|
|
2083
|
+
}], onComponentNodeEvent: [{
|
|
2084
|
+
type: Output
|
|
1924
2085
|
}], nodeHtmlDirective: [{
|
|
1925
2086
|
type: ContentChild,
|
|
1926
2087
|
args: [NodeHtmlTemplateDirective]
|
|
@@ -2019,7 +2180,8 @@ const components = [
|
|
|
2019
2180
|
EdgeLabelComponent,
|
|
2020
2181
|
ConnectionComponent,
|
|
2021
2182
|
HandleComponent,
|
|
2022
|
-
DefsComponent
|
|
2183
|
+
DefsComponent,
|
|
2184
|
+
BackgroundComponent
|
|
2023
2185
|
];
|
|
2024
2186
|
const directives = [
|
|
2025
2187
|
SpacePointContextDirective,
|
|
@@ -2046,7 +2208,8 @@ class VflowModule {
|
|
|
2046
2208
|
EdgeLabelComponent,
|
|
2047
2209
|
ConnectionComponent,
|
|
2048
2210
|
HandleComponent,
|
|
2049
|
-
DefsComponent,
|
|
2211
|
+
DefsComponent,
|
|
2212
|
+
BackgroundComponent, SpacePointContextDirective,
|
|
2050
2213
|
MapContextDirective,
|
|
2051
2214
|
RootSvgReferenceDirective,
|
|
2052
2215
|
RootSvgContextDirective,
|
|
@@ -2086,5 +2249,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
2086
2249
|
* Generated bundle index. Do not edit.
|
|
2087
2250
|
*/
|
|
2088
2251
|
|
|
2089
|
-
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, SelectableDirective, VflowComponent, VflowModule };
|
|
2252
|
+
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, CustomNodeComponent, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, SelectableDirective, VflowComponent, VflowModule };
|
|
2090
2253
|
//# sourceMappingURL=ngx-vflow.mjs.map
|