ngx-vflow 1.8.0 → 1.8.2

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.
@@ -0,0 +1,243 @@
1
+ import { ChangeDetectorRef, DestroyRef, Directive, inject, Input, IterableDiffers, TemplateRef, ViewContainerRef, isDevMode, } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { Subject, animationFrames, bufferCount, concatMap, delayWhen, finalize, from, of, take, takeUntil, tap, } from 'rxjs';
4
+ import * as i0 from "@angular/core";
5
+ /** Enum with lazy render directive state */
6
+ var LazyForState;
7
+ (function (LazyForState) {
8
+ /** Directive is in idle state */
9
+ LazyForState["idle"] = "idle";
10
+ /** Directive is rendering */
11
+ LazyForState["rendering"] = "rendering";
12
+ })(LazyForState || (LazyForState = {}));
13
+ /**
14
+ * Context for an element in lazyFor
15
+ */
16
+ class LazyForContextModel {
17
+ /** Whether the element is first */
18
+ get first() {
19
+ return this.index === 0;
20
+ }
21
+ /** Whether the element is last */
22
+ get last() {
23
+ return this.index === this.count - 1;
24
+ }
25
+ /** Whether the element is even */
26
+ get even() {
27
+ return this.index % 2 === 0;
28
+ }
29
+ /** Whether the element is odd */
30
+ get odd() {
31
+ return !this.even;
32
+ }
33
+ constructor($implicit, lazyFor, index, count) {
34
+ this.$implicit = $implicit;
35
+ this.lazyFor = lazyFor;
36
+ this.index = index;
37
+ this.count = count;
38
+ }
39
+ }
40
+ export class LazyForDirective {
41
+ /**
42
+ * Asserts the correct type of the context for the template that `lazyFor` will render.
43
+ *
44
+ * The presence of this method is a signal to the Ivy template type-check compiler that the
45
+ * `lazyFor` structural directive renders its template with a specific context type.
46
+ */
47
+ static ngTemplateContextGuard(dir, ctx) {
48
+ return true;
49
+ }
50
+ //#region INPUTS
51
+ /** Setter for the array to be rendered by the directive */
52
+ set lazyForOf(lazyFor) {
53
+ this._lazyFor = lazyFor;
54
+ this._lazyForDirty = true;
55
+ }
56
+ /**
57
+ * Input - setter for TrackBy function
58
+ * @description is required
59
+ */
60
+ set lazyForTrackBy(fn) {
61
+ if (isDevMode() && fn !== null && typeof fn !== 'function') {
62
+ console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
63
+ `See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
64
+ }
65
+ this._trackByFn = fn;
66
+ }
67
+ /**
68
+ * Setter for the number of items that will be rendered per frame
69
+ * @param value number of items that will be rendered per frame
70
+ */
71
+ set lazyForItemsPerFrame(value) {
72
+ if (value <= 0) {
73
+ if (isDevMode()) {
74
+ console.warn('Items per frame parameter cannot be lower than 0! Input value was ignored');
75
+ }
76
+ return;
77
+ }
78
+ this._itemsPerFrame = value;
79
+ }
80
+ /** Setter for array item template */
81
+ set lazyForTemplate(value) {
82
+ if (value) {
83
+ this._template = value;
84
+ }
85
+ }
86
+ /** Getter for TrackBy function */
87
+ get lazyForTrackBy() {
88
+ return this._trackByFn;
89
+ }
90
+ //#endregion
91
+ constructor() {
92
+ this._template = inject(TemplateRef);
93
+ this._viewContainer = inject(ViewContainerRef);
94
+ this._differs = inject(IterableDiffers);
95
+ this._cdr = inject(ChangeDetectorRef);
96
+ this._destroyRef$ = inject(DestroyRef);
97
+ //#region PROPERTIES
98
+ /** Array for rendering */
99
+ this._lazyFor = null;
100
+ /** lazyFor initialization flag */
101
+ this._lazyForDirty = true;
102
+ /** Differ for tracking changes in input array */
103
+ this._differ = null;
104
+ /** Number of items to be rendered per frame */
105
+ this._itemsPerFrame = 5;
106
+ /** Directive state */
107
+ this._lazyForState = LazyForState.idle;
108
+ //#endregion
109
+ //#region RXJS
110
+ /** Private subject for stopping dynamic render process */
111
+ this._rerenderUnsub$ = new Subject();
112
+ this._destroyRef$.onDestroy(() => this._viewContainer.clear());
113
+ }
114
+ /** ngDoCheck hook */
115
+ ngDoCheck() {
116
+ if (this._lazyForDirty) {
117
+ this._lazyForDirty = false;
118
+ const value = this._lazyFor;
119
+ if (!this._differ && value) {
120
+ this._differ = this._differs.find(value).create(this.lazyForTrackBy);
121
+ }
122
+ }
123
+ if (this._differ) {
124
+ let changes = this._differ.diff(this._lazyFor);
125
+ if (changes) {
126
+ if (this._lazyForState === LazyForState.rendering) {
127
+ /**
128
+ * If the array changed during an active render process
129
+ * Need to clear container of all views
130
+ * And restart rendering from the beginning.
131
+ */
132
+ this._rerenderUnsub$.next();
133
+ changes = this._differ.diff([]);
134
+ changes = this._differ.diff(this._lazyFor);
135
+ this._viewContainer.clear();
136
+ if (changes) {
137
+ this.applyChanges(changes);
138
+ }
139
+ }
140
+ else {
141
+ this.applyChanges(changes);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ /**
147
+ * Apply changes detected by differ
148
+ * @param changes changes
149
+ */
150
+ applyChanges(changes) {
151
+ const itemDataListToRender = [];
152
+ changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
153
+ const itemToPush = {
154
+ item: { ...item },
155
+ adjustedPreviousIndex,
156
+ currentIndex,
157
+ };
158
+ itemDataListToRender.push(itemToPush);
159
+ });
160
+ this.performLazyRender(itemDataListToRender, changes);
161
+ }
162
+ /**
163
+ * Perform lazy rendering
164
+ * @param itemDataListToRender list of items to render
165
+ * @param changes changes
166
+ */
167
+ performLazyRender(itemDataListToRender, changes) {
168
+ this.updateLazyForState(LazyForState.rendering);
169
+ this._rerenderUnsub$.next();
170
+ from(itemDataListToRender)
171
+ .pipe(bufferCount(this._itemsPerFrame), concatMap((itemList) => of(itemList).pipe(delayWhen(() => animationFrames()))), tap((itemList) => {
172
+ for (let i = 0; i < itemList.length; i++) {
173
+ const data = itemList[i];
174
+ if (data.item.previousIndex === null) {
175
+ this._viewContainer.createEmbeddedView(this._template, new LazyForContextModel(data.item.item, this._lazyFor, -1, -1), data.currentIndex === null ? undefined : data.currentIndex);
176
+ }
177
+ else if (data.currentIndex === null) {
178
+ this._viewContainer.remove(data.adjustedPreviousIndex === null ? undefined : data.adjustedPreviousIndex);
179
+ }
180
+ else if (data.adjustedPreviousIndex !== null) {
181
+ const view = this._viewContainer.get(data.adjustedPreviousIndex);
182
+ this._viewContainer.move(view, data.currentIndex);
183
+ this.applyViewChange(view, data.item);
184
+ }
185
+ }
186
+ this.updateViewContext();
187
+ this._cdr.markForCheck();
188
+ }),
189
+ /** Using take we automatically unsubscribe from the stream when rendering is complete */
190
+ take(Math.ceil(itemDataListToRender.length / this._itemsPerFrame)), takeUntil(this._rerenderUnsub$), takeUntilDestroyed(this._destroyRef$), finalize(() => {
191
+ changes.forEachIdentityChange((record) => {
192
+ const viewRef = (this._viewContainer.get(record.currentIndex));
193
+ this.applyViewChange(viewRef, record);
194
+ });
195
+ this.updateLazyForState(LazyForState.idle);
196
+ }))
197
+ .subscribe();
198
+ }
199
+ /** Update context (without implicit$) for elements inside view */
200
+ updateViewContext() {
201
+ for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
202
+ const viewRef = (this._viewContainer.get(i));
203
+ const context = viewRef.context;
204
+ context.index = i;
205
+ context.count = ilen;
206
+ context.lazyFor = this._lazyFor;
207
+ }
208
+ }
209
+ /**
210
+ * Apply implicit$ context
211
+ * @param view view
212
+ * @param record data
213
+ */
214
+ applyViewChange(view, record) {
215
+ view.context.$implicit = record.item;
216
+ }
217
+ /**
218
+ * Update directive state
219
+ * @param stateToSet state to set
220
+ */
221
+ updateLazyForState(stateToSet) {
222
+ this._lazyForState = stateToSet;
223
+ }
224
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
225
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: LazyForDirective, isStandalone: true, selector: "[lazyFor][lazyForOf]", inputs: { lazyForOf: "lazyForOf", lazyForTrackBy: "lazyForTrackBy", lazyForItemsPerFrame: "lazyForItemsPerFrame", lazyForTemplate: "lazyForTemplate" }, ngImport: i0 }); }
226
+ }
227
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, decorators: [{
228
+ type: Directive,
229
+ args: [{
230
+ selector: '[lazyFor][lazyForOf]',
231
+ standalone: true,
232
+ }]
233
+ }], ctorParameters: () => [], propDecorators: { lazyForOf: [{
234
+ type: Input
235
+ }], lazyForTrackBy: [{
236
+ type: Input,
237
+ args: [{ required: true }]
238
+ }], lazyForItemsPerFrame: [{
239
+ type: Input
240
+ }], lazyForTemplate: [{
241
+ type: Input
242
+ }] } });
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF6eS1mb3IuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXZmbG93LWxpYi9zcmMvbGliL3ZmbG93L2RpcmVjdGl2ZXMvbGF6eS1mb3IuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsVUFBVSxFQUNWLFNBQVMsRUFHVCxNQUFNLEVBQ04sS0FBSyxFQUlMLGVBQWUsRUFFZixXQUFXLEVBRVgsZ0JBQWdCLEVBRWhCLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBQ0wsT0FBTyxFQUNQLGVBQWUsRUFDZixXQUFXLEVBQ1gsU0FBUyxFQUNULFNBQVMsRUFDVCxRQUFRLEVBQ1IsSUFBSSxFQUNKLEVBQUUsRUFDRixJQUFJLEVBQ0osU0FBUyxFQUNULEdBQUcsR0FDSixNQUFNLE1BQU0sQ0FBQzs7QUFFZCw0Q0FBNEM7QUFDNUMsSUFBSyxZQUtKO0FBTEQsV0FBSyxZQUFZO0lBQ2YsaUNBQWlDO0lBQ2pDLDZCQUFhLENBQUE7SUFDYiw2QkFBNkI7SUFDN0IsdUNBQXVCLENBQUE7QUFDekIsQ0FBQyxFQUxJLFlBQVksS0FBWixZQUFZLFFBS2hCO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLG1CQUFtQjtJQUN2QixtQ0FBbUM7SUFDbkMsSUFBVyxLQUFLO1FBQ2QsT0FBTyxJQUFJLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsa0NBQWtDO0lBQ2xDLElBQVcsSUFBSTtRQUNiLE9BQU8sSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsa0NBQWtDO0lBQ2xDLElBQVcsSUFBSTtRQUNiLE9BQU8sSUFBSSxDQUFDLEtBQUssR0FB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Q0FBQztJQUVEOzs7O09BSUc7SUFDSyxlQUFlLENBQUMsSUFBNkMsRUFBRSxNQUErQjtRQUNwRyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxrQkFBa0IsQ0FBQyxVQUF3QjtRQUNqRCxJQUFJLENBQUMsYUFBYSxHQUFHLFVBQVUsQ0FBQztJQUNsQyxDQUFDOytHQXZPVSxnQkFBZ0I7bUdBQWhCLGdCQUFnQjs7NEZBQWhCLGdCQUFnQjtrQkFKNUIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsc0JBQXNCO29CQUNoQyxVQUFVLEVBQUUsSUFBSTtpQkFDakI7d0RBd0JZLFNBQVM7c0JBRG5CLEtBQUs7Z0JBV0ssY0FBYztzQkFEeEIsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBZ0JkLG9CQUFvQjtzQkFEOUIsS0FBSztnQkFlSyxlQUFlO3NCQUR6QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIERlc3Ryb3lSZWYsXG4gIERpcmVjdGl2ZSxcbiAgRG9DaGVjayxcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBpbmplY3QsXG4gIElucHV0LFxuICBJdGVyYWJsZUNoYW5nZVJlY29yZCxcbiAgSXRlcmFibGVDaGFuZ2VzLFxuICBJdGVyYWJsZURpZmZlcixcbiAgSXRlcmFibGVEaWZmZXJzLFxuICBOZ0l0ZXJhYmxlLFxuICBUZW1wbGF0ZVJlZixcbiAgVHJhY2tCeUZ1bmN0aW9uLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBWaWV3UmVmLFxuICBpc0Rldk1vZGUsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHtcbiAgU3ViamVjdCxcbiAgYW5pbWF0aW9uRnJhbWVzLFxuICBidWZmZXJDb3VudCxcbiAgY29uY2F0TWFwLFxuICBkZWxheVdoZW4sXG4gIGZpbmFsaXplLFxuICBmcm9tLFxuICBvZixcbiAgdGFrZSxcbiAgdGFrZVVudGlsLFxuICB0YXAsXG59IGZyb20gJ3J4anMnO1xuXG4vKiogRW51bSB3aXRoIGxhenkgcmVuZGVyIGRpcmVjdGl2ZSBzdGF0ZSAqL1xuZW51bSBMYXp5Rm9yU3RhdGUge1xuICAvKiogRGlyZWN0aXZlIGlzIGluIGlkbGUgc3RhdGUgKi9cbiAgaWRsZSA9ICdpZGxlJyxcbiAgLyoqIERpcmVjdGl2ZSBpcyByZW5kZXJpbmcgKi9cbiAgcmVuZGVyaW5nID0gJ3JlbmRlcmluZycsXG59XG5cbi8qKlxuICogQ29udGV4dCBmb3IgYW4gZWxlbWVudCBpbiBsYXp5Rm9yXG4gKi9cbmNsYXNzIExhenlGb3JDb250ZXh0TW9kZWw8VCwgVSBleHRlbmRzIE5nSXRlcmFibGU8VD4gPSBOZ0l0ZXJhYmxlPFQ+PiB7XG4gIC8qKiBXaGV0aGVyIHRoZSBlbGVtZW50IGlzIGZpcnN0ICovXG4gIHB1YmxpYyBnZXQgZmlyc3QoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZXggPT09IDA7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgZWxlbWVudCBpcyBsYXN0ICovXG4gIHB1YmxpYyBnZXQgbGFzdCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbmRleCA9PT0gdGhpcy5jb3VudCAtIDE7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgZWxlbWVudCBpcyBldmVuICovXG4gIHB1YmxpYyBnZXQgZXZlbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbmRleCAlIDIgPT09IDA7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgZWxlbWVudCBpcyBvZGQgKi9cbiAgcHVibGljIGdldCBvZGQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmV2ZW47XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgJGltcGxpY2l0OiBULFxuICAgIHB1YmxpYyBsYXp5Rm9yOiBVLFxuICAgIHB1YmxpYyBpbmRleDogbnVtYmVyLFxuICAgIHB1YmxpYyBjb3VudDogbnVtYmVyLFxuICApIHt9XG59XG5cbnR5cGUgTGF6eUZvckl0ZW08VD4gPSB7XG4gIGl0ZW06IEl0ZXJhYmxlQ2hhbmdlUmVjb3JkPFQ+O1xuICBhZGp1c3RlZFByZXZpb3VzSW5kZXg6IG51bWJlciB8IG51bGw7XG4gIGN1cnJlbnRJbmRleDogbnVtYmVyIHwgbnVsbDtcbn07XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tsYXp5Rm9yXVtsYXp5Rm9yT2ZdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgTGF6eUZvckRpcmVjdGl2ZTxULCBVIGV4dGVuZHMgTmdJdGVyYWJsZTxUPiA9IE5nSXRlcmFibGU8VD4+IGltcGxlbWVudHMgRG9DaGVjayB7XG4gIHByaXZhdGUgX3RlbXBsYXRlID0gaW5qZWN0PFRlbXBsYXRlUmVmPExhenlGb3JDb250ZXh0TW9kZWw8VCwgVT4+PihUZW1wbGF0ZVJlZik7XG4gIHByaXZhdGUgX3ZpZXdDb250YWluZXIgPSBpbmplY3QoVmlld0NvbnRhaW5lclJlZik7XG4gIHByaXZhdGUgX2RpZmZlcnMgPSBpbmplY3QoSXRlcmFibGVEaWZmZXJzKTtcbiAgcHJpdmF0ZSBfY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcbiAgcHJpdmF0ZSBfZGVzdHJveVJlZiQgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgLyoqXG4gICAqIEFzc2VydHMgdGhlIGNvcnJlY3QgdHlwZSBvZiB0aGUgY29udGV4dCBmb3IgdGhlIHRlbXBsYXRlIHRoYXQgYGxhenlGb3JgIHdpbGwgcmVuZGVyLlxuICAgKlxuICAgKiBUaGUgcHJlc2VuY2Ugb2YgdGhpcyBtZXRob2QgaXMgYSBzaWduYWwgdG8gdGhlIEl2eSB0ZW1wbGF0ZSB0eXBlLWNoZWNrIGNvbXBpbGVyIHRoYXQgdGhlXG4gICAqIGBsYXp5Rm9yYCBzdHJ1Y3R1cmFsIGRpcmVjdGl2ZSByZW5kZXJzIGl0cyB0ZW1wbGF0ZSB3aXRoIGEgc3BlY2lmaWMgY29udGV4dCB0eXBlLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBuZ1RlbXBsYXRlQ29udGV4dEd1YXJkPFQsIFUgZXh0ZW5kcyBOZ0l0ZXJhYmxlPFQ+PihcbiAgICBkaXI6IExhenlGb3JEaXJlY3RpdmU8VCwgVT4sXG4gICAgY3R4OiBhbnksXG4gICk6IGN0eCBpcyBMYXp5Rm9yQ29udGV4dE1vZGVsPFQsIFU+IHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vI3JlZ2lvbiBJTlBVVFNcbiAgLyoqIFNldHRlciBmb3IgdGhlIGFycmF5IHRvIGJlIHJlbmRlcmVkIGJ5IHRoZSBkaXJlY3RpdmUgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBsYXp5Rm9yT2YobGF6eUZvcjogKFUgJiBOZ0l0ZXJhYmxlPFQ+KSB8IHVuZGVmaW5lZCB8IG51bGwpIHtcbiAgICB0aGlzLl9sYXp5Rm9yID0gbGF6eUZvcjtcbiAgICB0aGlzLl9sYXp5Rm9yRGlydHkgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIElucHV0IC0gc2V0dGVyIGZvciBUcmFja0J5IGZ1bmN0aW9uXG4gICAqIEBkZXNjcmlwdGlvbiBpcyByZXF1aXJlZFxuICAgKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSlcbiAgcHVibGljIHNldCBsYXp5Rm9yVHJhY2tCeShmbjogVHJhY2tCeUZ1bmN0aW9uPFQ+KSB7XG4gICAgaWYgKGlzRGV2TW9kZSgpICYmIGZuICE9PSBudWxsICYmIHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgdHJhY2tCeSBtdXN0IGJlIGEgZnVuY3Rpb24sIGJ1dCByZWNlaXZlZCAke0pTT04uc3RyaW5naWZ5KGZuKX0uIGAgK1xuICAgICAgICAgIGBTZWUgaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9jb21tb24vTmdGb3JPZiNjaGFuZ2UtcHJvcGFnYXRpb24gZm9yIG1vcmUgaW5mb3JtYXRpb24uYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHRoaXMuX3RyYWNrQnlGbiA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHRlciBmb3IgdGhlIG51bWJlciBvZiBpdGVtcyB0aGF0IHdpbGwgYmUgcmVuZGVyZWQgcGVyIGZyYW1lXG4gICAqIEBwYXJhbSB2YWx1ZSBudW1iZXIgb2YgaXRlbXMgdGhhdCB3aWxsIGJlIHJlbmRlcmVkIHBlciBmcmFtZVxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBsYXp5Rm9ySXRlbXNQZXJGcmFtZSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgaWYgKHZhbHVlIDw9IDApIHtcbiAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0l0ZW1zIHBlciBmcmFtZSBwYXJhbWV0ZXIgY2Fubm90IGJlIGxvd2VyIHRoYW4gMCEgSW5wdXQgdmFsdWUgd2FzIGlnbm9yZWQnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2l0ZW1zUGVyRnJhbWUgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKiBTZXR0ZXIgZm9yIGFycmF5IGl0ZW0gdGVtcGxhdGUgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBsYXp5Rm9yVGVtcGxhdGUodmFsdWU6IFRlbXBsYXRlUmVmPExhenlGb3JDb250ZXh0TW9kZWw8VCwgVT4+KSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXR0ZXIgZm9yIFRyYWNrQnkgZnVuY3Rpb24gKi9cbiAgcHVibGljIGdldCBsYXp5Rm9yVHJhY2tCeSgpOiBUcmFja0J5RnVuY3Rpb248VD4ge1xuICAgIHJldHVybiB0aGlzLl90cmFja0J5Rm47XG4gIH1cblxuICAvLyNyZWdpb24gUFJPUEVSVElFU1xuICAvKiogQXJyYXkgZm9yIHJlbmRlcmluZyAqL1xuICBwcml2YXRlIF9sYXp5Rm9yOiBVIHwgdW5kZWZpbmVkIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBsYXp5Rm9yIGluaXRpYWxpemF0aW9uIGZsYWcgKi9cbiAgcHJpdmF0ZSBfbGF6eUZvckRpcnR5OiBib29sZWFuID0gdHJ1ZTtcbiAgLyoqIERpZmZlciBmb3IgdHJhY2tpbmcgY2hhbmdlcyBpbiBpbnB1dCBhcnJheSAqL1xuICBwcml2YXRlIF9kaWZmZXI6IEl0ZXJhYmxlRGlmZmVyPFQ+IHwgbnVsbCA9IG51bGw7XG4gIC8qKiB0cmFja0J5IGZ1bmN0aW9uICovXG4gIHByaXZhdGUgX3RyYWNrQnlGbiE6IFRyYWNrQnlGdW5jdGlvbjxUPjtcbiAgLyoqIE51bWJlciBvZiBpdGVtcyB0byBiZSByZW5kZXJlZCBwZXIgZnJhbWUgKi9cbiAgcHJpdmF0ZSBfaXRlbXNQZXJGcmFtZTogbnVtYmVyID0gNTtcbiAgLyoqIERpcmVjdGl2ZSBzdGF0ZSAqL1xuICBwcml2YXRlIF9sYXp5Rm9yU3RhdGU6IExhenlGb3JTdGF0ZSA9IExhenlGb3JTdGF0ZS5pZGxlO1xuICAvLyNlbmRyZWdpb25cblxuICAvLyNyZWdpb24gUlhKU1xuICAvKiogUHJpdmF0ZSBzdWJqZWN0IGZvciBzdG9wcGluZyBkeW5hbWljIHJlbmRlciBwcm9jZXNzICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX3JlcmVuZGVyVW5zdWIkOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgLy8jZW5kcmVnaW9uXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5fZGVzdHJveVJlZiQub25EZXN0cm95KCgpID0+IHRoaXMuX3ZpZXdDb250YWluZXIuY2xlYXIoKSk7XG4gIH1cblxuICAvKiogbmdEb0NoZWNrIGhvb2sgKi9cbiAgcHVibGljIG5nRG9DaGVjaygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fbGF6eUZvckRpcnR5KSB7XG4gICAgICB0aGlzLl9sYXp5Rm9yRGlydHkgPSBmYWxzZTtcbiAgICAgIGNvbnN0IHZhbHVlOiBVIHwgdW5kZWZpbmVkIHwgbnVsbCA9IHRoaXMuX2xhenlGb3I7XG4gICAgICBpZiAoIXRoaXMuX2RpZmZlciAmJiB2YWx1ZSkge1xuICAgICAgICB0aGlzLl9kaWZmZXIgPSB0aGlzLl9kaWZmZXJzLmZpbmQodmFsdWUpLmNyZWF0ZSh0aGlzLmxhenlGb3JUcmFja0J5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZGlmZmVyKSB7XG4gICAgICBsZXQgY2hhbmdlczogSXRlcmFibGVDaGFuZ2VzPFQ+IHwgbnVsbCA9IHRoaXMuX2RpZmZlci5kaWZmKHRoaXMuX2xhenlGb3IpO1xuICAgICAgaWYgKGNoYW5nZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuX2xhenlGb3JTdGF0ZSA9PT0gTGF6eUZvclN0YXRlLnJlbmRlcmluZykge1xuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIElmIHRoZSBhcnJheSBjaGFuZ2VkIGR1cmluZyBhbiBhY3RpdmUgcmVuZGVyIHByb2Nlc3NcbiAgICAgICAgICAgKiBOZWVkIHRvIGNsZWFyIGNvbnRhaW5lciBvZiBhbGwgdmlld3NcbiAgICAgICAgICAgKiBBbmQgcmVzdGFydCByZW5kZXJpbmcgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAgICAgICAqL1xuICAgICAgICAgIHRoaXMuX3JlcmVuZGVyVW5zdWIkLm5leHQoKTtcbiAgICAgICAgICBjaGFuZ2VzID0gdGhpcy5fZGlmZmVyLmRpZmYoW10pO1xuICAgICAgICAgIGNoYW5nZXMgPSB0aGlzLl9kaWZmZXIuZGlmZih0aGlzLl9sYXp5Rm9yKTtcbiAgICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyLmNsZWFyKCk7XG4gICAgICAgICAgaWYgKGNoYW5nZXMpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlDaGFuZ2VzKGNoYW5nZXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmFwcGx5Q2hhbmdlcyhjaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBjaGFuZ2VzIGRldGVjdGVkIGJ5IGRpZmZlclxuICAgKiBAcGFyYW0gY2hhbmdlcyBjaGFuZ2VzXG4gICAqL1xuICBwcml2YXRlIGFwcGx5Q2hhbmdlcyhjaGFuZ2VzOiBJdGVyYWJsZUNoYW5nZXM8VD4pOiB2b2lkIHtcbiAgICBjb25zdCBpdGVtRGF0YUxpc3RUb1JlbmRlcjogQXJyYXk8TGF6eUZvckl0ZW08VD4+ID0gW107XG4gICAgY2hhbmdlcy5mb3JFYWNoT3BlcmF0aW9uKFxuICAgICAgKGl0ZW06IEl0ZXJhYmxlQ2hhbmdlUmVjb3JkPFQ+LCBhZGp1c3RlZFByZXZpb3VzSW5kZXg6IG51bWJlciB8IG51bGwsIGN1cnJlbnRJbmRleDogbnVtYmVyIHwgbnVsbCkgPT4ge1xuICAgICAgICBjb25zdCBpdGVtVG9QdXNoOiBMYXp5Rm9ySXRlbTxUPiA9IHtcbiAgICAgICAgICBpdGVtOiB7IC4uLml0ZW0gfSxcbiAgICAgICAgICBhZGp1c3RlZFByZXZpb3VzSW5kZXgsXG4gICAgICAgICAgY3VycmVudEluZGV4LFxuICAgICAgICB9O1xuICAgICAgICBpdGVtRGF0YUxpc3RUb1JlbmRlci5wdXNoKGl0ZW1Ub1B1c2gpO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgdGhpcy5wZXJmb3JtTGF6eVJlbmRlcihpdGVtRGF0YUxpc3RUb1JlbmRlciwgY2hhbmdlcyk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBsYXp5IHJlbmRlcmluZ1xuICAgKiBAcGFyYW0gaXRlbURhdGFMaXN0VG9SZW5kZXIgbGlzdCBvZiBpdGVtcyB0byByZW5kZXJcbiAgICogQHBhcmFtIGNoYW5nZXMgY2hhbmdlc1xuICAgKi9cbiAgcHJpdmF0ZSBwZXJmb3JtTGF6eVJlbmRlcihpdGVtRGF0YUxpc3RUb1JlbmRlcjogQXJyYXk8TGF6eUZvckl0ZW08VD4+LCBjaGFuZ2VzOiBJdGVyYWJsZUNoYW5nZXM8VD4pOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZUxhenlGb3JTdGF0ZShMYXp5Rm9yU3RhdGUucmVuZGVyaW5nKTtcbiAgICB0aGlzLl9yZXJlbmRlclVuc3ViJC5uZXh0KCk7XG5cbiAgICBmcm9tKGl0ZW1EYXRhTGlzdFRvUmVuZGVyKVxuICAgICAgLnBpcGUoXG4gICAgICAgIGJ1ZmZlckNvdW50KHRoaXMuX2l0ZW1zUGVyRnJhbWUpLFxuICAgICAgICBjb25jYXRNYXAoKGl0ZW1MaXN0KSA9PiBvZihpdGVtTGlzdCkucGlwZShkZWxheVdoZW4oKCkgPT4gYW5pbWF0aW9uRnJhbWVzKCkpKSksXG4gICAgICAgIHRhcCgoaXRlbUxpc3Q6IEFycmF5PExhenlGb3JJdGVtPFQ+PikgPT4ge1xuICAgICAgICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCBpdGVtTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgZGF0YTogTGF6eUZvckl0ZW08VD4gPSBpdGVtTGlzdFtpXTtcblxuICAgICAgICAgICAgaWYgKGRhdGEuaXRlbS5wcmV2aW91c0luZGV4ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3ZpZXdDb250YWluZXIuY3JlYXRlRW1iZWRkZWRWaWV3KFxuICAgICAgICAgICAgICAgIHRoaXMuX3RlbXBsYXRlLFxuICAgICAgICAgICAgICAgIG5ldyBMYXp5Rm9yQ29udGV4dE1vZGVsPFQsIFU+KGRhdGEuaXRlbS5pdGVtLCB0aGlzLl9sYXp5Rm9yISwgLTEsIC0xKSxcbiAgICAgICAgICAgICAgICBkYXRhLmN1cnJlbnRJbmRleCA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IGRhdGEuY3VycmVudEluZGV4LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhLmN1cnJlbnRJbmRleCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyLnJlbW92ZShkYXRhLmFkanVzdGVkUHJldmlvdXNJbmRleCA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IGRhdGEuYWRqdXN0ZWRQcmV2aW91c0luZGV4KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YS5hZGp1c3RlZFByZXZpb3VzSW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgY29uc3QgdmlldzogVmlld1JlZiB8IG51bGwgPSB0aGlzLl92aWV3Q29udGFpbmVyLmdldChkYXRhLmFkanVzdGVkUHJldmlvdXNJbmRleCkhO1xuICAgICAgICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyLm1vdmUodmlldywgZGF0YS5jdXJyZW50SW5kZXgpO1xuICAgICAgICAgICAgICB0aGlzLmFwcGx5Vmlld0NoYW5nZSh2aWV3IGFzIEVtYmVkZGVkVmlld1JlZjxMYXp5Rm9yQ29udGV4dE1vZGVsPFQsIFU+PiwgZGF0YS5pdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnVwZGF0ZVZpZXdDb250ZXh0KCk7XG5cbiAgICAgICAgICB0aGlzLl9jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIH0pLFxuICAgICAgICAvKiogVXNpbmcgdGFrZSB3ZSBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIGZyb20gdGhlIHN0cmVhbSB3aGVuIHJlbmRlcmluZyBpcyBjb21wbGV0ZSAqL1xuICAgICAgICB0YWtlKE1hdGguY2VpbChpdGVtRGF0YUxpc3RUb1JlbmRlci5sZW5ndGggLyB0aGlzLl9pdGVtc1BlckZyYW1lKSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9yZXJlbmRlclVuc3ViJCksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmJCksXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgICBjaGFuZ2VzLmZvckVhY2hJZGVudGl0eUNoYW5nZSgocmVjb3JkOiBhbnkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZpZXdSZWY6IEVtYmVkZGVkVmlld1JlZjxMYXp5Rm9yQ29udGV4dE1vZGVsPFQsIFU+PiA9IDxFbWJlZGRlZFZpZXdSZWY8TGF6eUZvckNvbnRleHRNb2RlbDxULCBVPj4+KFxuICAgICAgICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyLmdldChyZWNvcmQuY3VycmVudEluZGV4KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlWaWV3Q2hhbmdlKHZpZXdSZWYsIHJlY29yZCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy51cGRhdGVMYXp5Rm9yU3RhdGUoTGF6eUZvclN0YXRlLmlkbGUpO1xuICAgICAgICB9KSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8qKiBVcGRhdGUgY29udGV4dCAod2l0aG91dCBpbXBsaWNpdCQpIGZvciBlbGVtZW50cyBpbnNpZGUgdmlldyAqL1xuICBwcml2YXRlIHVwZGF0ZVZpZXdDb250ZXh0KCk6IHZvaWQge1xuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDAsIGlsZW46IG51bWJlciA9IHRoaXMuX3ZpZXdDb250YWluZXIubGVuZ3RoOyBpIDwgaWxlbjsgaSsrKSB7XG4gICAgICBjb25zdCB2aWV3UmVmOiBFbWJlZGRlZFZpZXdSZWY8TGF6eUZvckNvbnRleHRNb2RlbDxULCBVPj4gPSA8RW1iZWRkZWRWaWV3UmVmPExhenlGb3JDb250ZXh0TW9kZWw8VCwgVT4+PihcbiAgICAgICAgdGhpcy5fdmlld0NvbnRhaW5lci5nZXQoaSlcbiAgICAgICk7XG4gICAgICBjb25zdCBjb250ZXh0OiBMYXp5Rm9yQ29udGV4dE1vZGVsPFQsIFU+ID0gdmlld1JlZi5jb250ZXh0O1xuICAgICAgY29udGV4dC5pbmRleCA9IGk7XG4gICAgICBjb250ZXh0LmNvdW50ID0gaWxlbjtcbiAgICAgIGNvbnRleHQubGF6eUZvciA9IHRoaXMuX2xhenlGb3IhO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBpbXBsaWNpdCQgY29udGV4dFxuICAgKiBAcGFyYW0gdmlldyB2aWV3XG4gICAqIEBwYXJhbSByZWNvcmQgZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseVZpZXdDaGFuZ2UodmlldzogRW1iZWRkZWRWaWV3UmVmPExhenlGb3JDb250ZXh0TW9kZWw8VD4+LCByZWNvcmQ6IEl0ZXJhYmxlQ2hhbmdlUmVjb3JkPFQ+KTogdm9pZCB7XG4gICAgdmlldy5jb250ZXh0LiRpbXBsaWNpdCA9IHJlY29yZC5pdGVtO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBkaXJlY3RpdmUgc3RhdGVcbiAgICogQHBhcmFtIHN0YXRlVG9TZXQgc3RhdGUgdG8gc2V0XG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUxhenlGb3JTdGF0ZShzdGF0ZVRvU2V0OiBMYXp5Rm9yU3RhdGUpOiB2b2lkIHtcbiAgICB0aGlzLl9sYXp5Rm9yU3RhdGUgPSBzdGF0ZVRvU2V0O1xuICB9XG59XG4iXX0=
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, output, HostListener, Injector, runInInjectionContext, contentChild, Input, forwardRef } from '@angular/core';
2
+ import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, output, HostListener, Injector, runInInjectionContext, isDevMode, ViewContainerRef, IterableDiffers, ChangeDetectorRef, Input, contentChild, forwardRef } from '@angular/core';
3
3
  import { select } from 'd3-selection';
4
4
  import { zoomIdentity, zoom } from 'd3-zoom';
5
- import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith, of } from 'rxjs';
5
+ import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith, from, bufferCount, concatMap, of, delayWhen, animationFrames, take, takeUntil, finalize } from 'rxjs';
6
6
  import { toObservable, takeUntilDestroyed, outputFromObservable, toSignal } from '@angular/core/rxjs-interop';
7
7
  import { drag } from 'd3-drag';
8
8
  import { __decorate } from 'tslib';
@@ -2269,14 +2269,14 @@ class EdgeComponent {
2269
2269
  this.connectionController?.startReconnection(handle, this.model());
2270
2270
  }
2271
2271
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2272
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerStartUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2272
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2273
2273
  }
2274
2274
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, decorators: [{
2275
2275
  type: Component,
2276
2276
  args: [{ standalone: true, selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2277
2277
  class: 'selectable',
2278
2278
  '[style.visibility]': 'isReconnecting() ? "hidden" : "visible"',
2279
- }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerStartUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2279
+ }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2280
2280
  }] });
2281
2281
 
2282
2282
  class HandleService {
@@ -3232,6 +3232,245 @@ function getSpacePoints(point, groups) {
3232
3232
  return result;
3233
3233
  }
3234
3234
 
3235
+ /** Enum with lazy render directive state */
3236
+ var LazyForState;
3237
+ (function (LazyForState) {
3238
+ /** Directive is in idle state */
3239
+ LazyForState["idle"] = "idle";
3240
+ /** Directive is rendering */
3241
+ LazyForState["rendering"] = "rendering";
3242
+ })(LazyForState || (LazyForState = {}));
3243
+ /**
3244
+ * Context for an element in lazyFor
3245
+ */
3246
+ class LazyForContextModel {
3247
+ /** Whether the element is first */
3248
+ get first() {
3249
+ return this.index === 0;
3250
+ }
3251
+ /** Whether the element is last */
3252
+ get last() {
3253
+ return this.index === this.count - 1;
3254
+ }
3255
+ /** Whether the element is even */
3256
+ get even() {
3257
+ return this.index % 2 === 0;
3258
+ }
3259
+ /** Whether the element is odd */
3260
+ get odd() {
3261
+ return !this.even;
3262
+ }
3263
+ constructor($implicit, lazyFor, index, count) {
3264
+ this.$implicit = $implicit;
3265
+ this.lazyFor = lazyFor;
3266
+ this.index = index;
3267
+ this.count = count;
3268
+ }
3269
+ }
3270
+ class LazyForDirective {
3271
+ /**
3272
+ * Asserts the correct type of the context for the template that `lazyFor` will render.
3273
+ *
3274
+ * The presence of this method is a signal to the Ivy template type-check compiler that the
3275
+ * `lazyFor` structural directive renders its template with a specific context type.
3276
+ */
3277
+ static ngTemplateContextGuard(dir, ctx) {
3278
+ return true;
3279
+ }
3280
+ //#region INPUTS
3281
+ /** Setter for the array to be rendered by the directive */
3282
+ set lazyForOf(lazyFor) {
3283
+ this._lazyFor = lazyFor;
3284
+ this._lazyForDirty = true;
3285
+ }
3286
+ /**
3287
+ * Input - setter for TrackBy function
3288
+ * @description is required
3289
+ */
3290
+ set lazyForTrackBy(fn) {
3291
+ if (isDevMode() && fn !== null && typeof fn !== 'function') {
3292
+ console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
3293
+ `See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
3294
+ }
3295
+ this._trackByFn = fn;
3296
+ }
3297
+ /**
3298
+ * Setter for the number of items that will be rendered per frame
3299
+ * @param value number of items that will be rendered per frame
3300
+ */
3301
+ set lazyForItemsPerFrame(value) {
3302
+ if (value <= 0) {
3303
+ if (isDevMode()) {
3304
+ console.warn('Items per frame parameter cannot be lower than 0! Input value was ignored');
3305
+ }
3306
+ return;
3307
+ }
3308
+ this._itemsPerFrame = value;
3309
+ }
3310
+ /** Setter for array item template */
3311
+ set lazyForTemplate(value) {
3312
+ if (value) {
3313
+ this._template = value;
3314
+ }
3315
+ }
3316
+ /** Getter for TrackBy function */
3317
+ get lazyForTrackBy() {
3318
+ return this._trackByFn;
3319
+ }
3320
+ //#endregion
3321
+ constructor() {
3322
+ this._template = inject(TemplateRef);
3323
+ this._viewContainer = inject(ViewContainerRef);
3324
+ this._differs = inject(IterableDiffers);
3325
+ this._cdr = inject(ChangeDetectorRef);
3326
+ this._destroyRef$ = inject(DestroyRef);
3327
+ //#region PROPERTIES
3328
+ /** Array for rendering */
3329
+ this._lazyFor = null;
3330
+ /** lazyFor initialization flag */
3331
+ this._lazyForDirty = true;
3332
+ /** Differ for tracking changes in input array */
3333
+ this._differ = null;
3334
+ /** Number of items to be rendered per frame */
3335
+ this._itemsPerFrame = 5;
3336
+ /** Directive state */
3337
+ this._lazyForState = LazyForState.idle;
3338
+ //#endregion
3339
+ //#region RXJS
3340
+ /** Private subject for stopping dynamic render process */
3341
+ this._rerenderUnsub$ = new Subject();
3342
+ this._destroyRef$.onDestroy(() => this._viewContainer.clear());
3343
+ }
3344
+ /** ngDoCheck hook */
3345
+ ngDoCheck() {
3346
+ if (this._lazyForDirty) {
3347
+ this._lazyForDirty = false;
3348
+ const value = this._lazyFor;
3349
+ if (!this._differ && value) {
3350
+ this._differ = this._differs.find(value).create(this.lazyForTrackBy);
3351
+ }
3352
+ }
3353
+ if (this._differ) {
3354
+ let changes = this._differ.diff(this._lazyFor);
3355
+ if (changes) {
3356
+ if (this._lazyForState === LazyForState.rendering) {
3357
+ /**
3358
+ * If the array changed during an active render process
3359
+ * Need to clear container of all views
3360
+ * And restart rendering from the beginning.
3361
+ */
3362
+ this._rerenderUnsub$.next();
3363
+ changes = this._differ.diff([]);
3364
+ changes = this._differ.diff(this._lazyFor);
3365
+ this._viewContainer.clear();
3366
+ if (changes) {
3367
+ this.applyChanges(changes);
3368
+ }
3369
+ }
3370
+ else {
3371
+ this.applyChanges(changes);
3372
+ }
3373
+ }
3374
+ }
3375
+ }
3376
+ /**
3377
+ * Apply changes detected by differ
3378
+ * @param changes changes
3379
+ */
3380
+ applyChanges(changes) {
3381
+ const itemDataListToRender = [];
3382
+ changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
3383
+ const itemToPush = {
3384
+ item: { ...item },
3385
+ adjustedPreviousIndex,
3386
+ currentIndex,
3387
+ };
3388
+ itemDataListToRender.push(itemToPush);
3389
+ });
3390
+ this.performLazyRender(itemDataListToRender, changes);
3391
+ }
3392
+ /**
3393
+ * Perform lazy rendering
3394
+ * @param itemDataListToRender list of items to render
3395
+ * @param changes changes
3396
+ */
3397
+ performLazyRender(itemDataListToRender, changes) {
3398
+ this.updateLazyForState(LazyForState.rendering);
3399
+ this._rerenderUnsub$.next();
3400
+ from(itemDataListToRender)
3401
+ .pipe(bufferCount(this._itemsPerFrame), concatMap((itemList) => of(itemList).pipe(delayWhen(() => animationFrames()))), tap((itemList) => {
3402
+ for (let i = 0; i < itemList.length; i++) {
3403
+ const data = itemList[i];
3404
+ if (data.item.previousIndex === null) {
3405
+ this._viewContainer.createEmbeddedView(this._template, new LazyForContextModel(data.item.item, this._lazyFor, -1, -1), data.currentIndex === null ? undefined : data.currentIndex);
3406
+ }
3407
+ else if (data.currentIndex === null) {
3408
+ this._viewContainer.remove(data.adjustedPreviousIndex === null ? undefined : data.adjustedPreviousIndex);
3409
+ }
3410
+ else if (data.adjustedPreviousIndex !== null) {
3411
+ const view = this._viewContainer.get(data.adjustedPreviousIndex);
3412
+ this._viewContainer.move(view, data.currentIndex);
3413
+ this.applyViewChange(view, data.item);
3414
+ }
3415
+ }
3416
+ this.updateViewContext();
3417
+ this._cdr.markForCheck();
3418
+ }),
3419
+ /** Using take we automatically unsubscribe from the stream when rendering is complete */
3420
+ take(Math.ceil(itemDataListToRender.length / this._itemsPerFrame)), takeUntil(this._rerenderUnsub$), takeUntilDestroyed(this._destroyRef$), finalize(() => {
3421
+ changes.forEachIdentityChange((record) => {
3422
+ const viewRef = (this._viewContainer.get(record.currentIndex));
3423
+ this.applyViewChange(viewRef, record);
3424
+ });
3425
+ this.updateLazyForState(LazyForState.idle);
3426
+ }))
3427
+ .subscribe();
3428
+ }
3429
+ /** Update context (without implicit$) for elements inside view */
3430
+ updateViewContext() {
3431
+ for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
3432
+ const viewRef = (this._viewContainer.get(i));
3433
+ const context = viewRef.context;
3434
+ context.index = i;
3435
+ context.count = ilen;
3436
+ context.lazyFor = this._lazyFor;
3437
+ }
3438
+ }
3439
+ /**
3440
+ * Apply implicit$ context
3441
+ * @param view view
3442
+ * @param record data
3443
+ */
3444
+ applyViewChange(view, record) {
3445
+ view.context.$implicit = record.item;
3446
+ }
3447
+ /**
3448
+ * Update directive state
3449
+ * @param stateToSet state to set
3450
+ */
3451
+ updateLazyForState(stateToSet) {
3452
+ this._lazyForState = stateToSet;
3453
+ }
3454
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3455
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: LazyForDirective, isStandalone: true, selector: "[lazyFor][lazyForOf]", inputs: { lazyForOf: "lazyForOf", lazyForTrackBy: "lazyForTrackBy", lazyForItemsPerFrame: "lazyForItemsPerFrame", lazyForTemplate: "lazyForTemplate" }, ngImport: i0 }); }
3456
+ }
3457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LazyForDirective, decorators: [{
3458
+ type: Directive,
3459
+ args: [{
3460
+ selector: '[lazyFor][lazyForOf]',
3461
+ standalone: true,
3462
+ }]
3463
+ }], ctorParameters: () => [], propDecorators: { lazyForOf: [{
3464
+ type: Input
3465
+ }], lazyForTrackBy: [{
3466
+ type: Input,
3467
+ args: [{ required: true }]
3468
+ }], lazyForItemsPerFrame: [{
3469
+ type: Input
3470
+ }], lazyForTemplate: [{
3471
+ type: Input
3472
+ }] } });
3473
+
3235
3474
  const changesControllerHostDirective = {
3236
3475
  directive: ChangesControllerDirective,
3237
3476
  outputs: [
@@ -3546,7 +3785,7 @@ class VflowComponent {
3546
3785
  ComponentEventBusService,
3547
3786
  KeyboardService,
3548
3787
  OverlaysService,
3549
- ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3788
+ ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n <svg:g\n *lazyFor=\"let model of groups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nonGroups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: LazyForDirective, selector: "[lazyFor][lazyForOf]", inputs: ["lazyForOf", "lazyForTrackBy", "lazyForItemsPerFrame", "lazyForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3550
3789
  }
3551
3790
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, decorators: [{
3552
3791
  type: Component,
@@ -3577,7 +3816,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3577
3816
  NodeComponent,
3578
3817
  EdgeComponent,
3579
3818
  NgTemplateOutlet,
3580
- ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
3819
+ LazyForDirective,
3820
+ ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (optimization().detachedGroupsLayer) {\n <!-- Groups -->\n <svg:g\n *lazyFor=\"let model of groups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nonGroups(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n\n @if (!optimization().detachedGroupsLayer) {\n <!-- Edges -->\n <svg:g\n *lazyFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n\n <!-- Nodes -->\n <svg:g\n *lazyFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
3581
3821
  }], propDecorators: { view: [{
3582
3822
  type: Input
3583
3823
  }], minZoom: [{