@foblex/flow 18.6.0 → 18.6.1
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/fesm2022/foblex-flow.mjs +56 -5
- package/fesm2022/foblex-flow.mjs.map +1 -1
- package/index.d.ts +30 -15
- package/package.json +1 -1
package/fesm2022/foblex-flow.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, Injectable, ElementRef, Injector, input, effect, untracked, Directive, signal, numberAttribute, model, booleanAttribute, ChangeDetectionStrategy, Component, viewChild, Input, computed, contentChildren, contentChild, NgZone, Renderer2,
|
|
2
|
+
import { InjectionToken, inject, Injectable, ElementRef, DestroyRef, Injector, input, effect, untracked, Directive, signal, numberAttribute, model, booleanAttribute, ChangeDetectionStrategy, Component, viewChild, Input, computed, contentChildren, contentChild, NgZone, Renderer2, output, ViewContainerRef, TemplateRef, runInInjectionContext, EventEmitter, Output, afterNextRender, NgModule } from '@angular/core';
|
|
3
3
|
import { TransformModelExtensions, PointExtensions, RectExtensions, GetIntersections, RoundedRect, Point, LineExtensions, SizeExtensions, setRectToElement, adjustRectToMinSize, setRectToViewBox } from '@foblex/2d';
|
|
4
4
|
import { __decorate } from 'tslib';
|
|
5
5
|
import { FExecutionRegister, FMediator } from '@foblex/mediator';
|
|
@@ -1320,6 +1320,40 @@ class FConnectionContentBase {
|
|
|
1320
1320
|
* Used internally for positioning calculations.
|
|
1321
1321
|
*/
|
|
1322
1322
|
hostElement = inject((ElementRef)).nativeElement;
|
|
1323
|
+
// ResizeObserver-backed size cache. Avoids `getBoundingClientRect`
|
|
1324
|
+
// inside the placement loop, where one DOM read per label per redraw
|
|
1325
|
+
// forced a synchronous layout flush and dominated drag-time at a few
|
|
1326
|
+
// hundred labelled connections (issue #304). The observer also keeps
|
|
1327
|
+
// the cache correct when the label content actually resizes.
|
|
1328
|
+
//
|
|
1329
|
+
// The initial size is populated by the observer's first asynchronous
|
|
1330
|
+
// delivery — calling `getBoundingClientRect()` from the constructor
|
|
1331
|
+
// re-introduces the thrashing during Angular CD when many labels
|
|
1332
|
+
// mount in the same tick. Until the first delivery, the size stays
|
|
1333
|
+
// at zero; the only visible effect is that the edge-guard does not
|
|
1334
|
+
// push labels away from path endpoints on the very first frame.
|
|
1335
|
+
// Labels at `position` ≠ 0 / 1 are unaffected.
|
|
1336
|
+
_cachedSize = { width: 0, height: 0 };
|
|
1337
|
+
_observer = null;
|
|
1338
|
+
constructor() {
|
|
1339
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
this._observer = new ResizeObserver((entries) => {
|
|
1343
|
+
for (const entry of entries) {
|
|
1344
|
+
const rect = entry.contentRect;
|
|
1345
|
+
this._cachedSize = { width: rect.width, height: rect.height };
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
this._observer.observe(this.hostElement);
|
|
1349
|
+
inject(DestroyRef).onDestroy(() => {
|
|
1350
|
+
this._observer?.disconnect();
|
|
1351
|
+
this._observer = null;
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
measureSize() {
|
|
1355
|
+
return this._cachedSize;
|
|
1356
|
+
}
|
|
1323
1357
|
}
|
|
1324
1358
|
|
|
1325
1359
|
/**
|
|
@@ -1555,7 +1589,7 @@ class PolylineContentPlace {
|
|
|
1555
1589
|
const x = point.x + normal.x * lateral;
|
|
1556
1590
|
const y = point.y + normal.y * lateral;
|
|
1557
1591
|
// Edge guard
|
|
1558
|
-
const projectedSize = this._sizeAlongDirection(content
|
|
1592
|
+
const projectedSize = this._sizeAlongDirection(content, tangent);
|
|
1559
1593
|
const halfExtent = projectedSize * 0.5;
|
|
1560
1594
|
const distanceFromStart = progress * sampler.totalLength;
|
|
1561
1595
|
const distanceFromEnd = sampler.totalLength - distanceFromStart;
|
|
@@ -1577,9 +1611,14 @@ class PolylineContentPlace {
|
|
|
1577
1611
|
}
|
|
1578
1612
|
return { x, y };
|
|
1579
1613
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1614
|
+
// Reads the size via `content.measureSize()` — a ResizeObserver-backed
|
|
1615
|
+
// cache. This loop runs interleaved with `style.transform` writes for
|
|
1616
|
+
// every label, so a `getBoundingClientRect()` here would force a
|
|
1617
|
+
// synchronous layout flush per label and stall drag at a few hundred
|
|
1618
|
+
// labelled connections (issue #304).
|
|
1619
|
+
_sizeAlongDirection(content, dir) {
|
|
1620
|
+
const size = content.measureSize();
|
|
1621
|
+
return Math.abs(dir.x) * size.width + Math.abs(dir.y) * size.height;
|
|
1583
1622
|
}
|
|
1584
1623
|
_normalize180(angleDeg) {
|
|
1585
1624
|
let a = (angleDeg + 180) % 360;
|
|
@@ -13415,10 +13454,22 @@ class FReflowOrchestrator {
|
|
|
13415
13454
|
}
|
|
13416
13455
|
return result;
|
|
13417
13456
|
}
|
|
13457
|
+
// We only emit a shift plan for nodes whose model signal matches
|
|
13458
|
+
// `_position`. A mismatch means the node is mid-flight — either its
|
|
13459
|
+
// `positionChanges()` effect has not yet mirrored the latest signal
|
|
13460
|
+
// into `_position`, or an internal write (fit-to-children) advanced
|
|
13461
|
+
// `_position` ahead of the model. Planning against a half-applied
|
|
13462
|
+
// state poisons every candidate read from DOM and propagates one
|
|
13463
|
+
// measured rect onto many siblings (issue #305). Skipping the rect
|
|
13464
|
+
// makes the orchestrator wait until the next coherent tick.
|
|
13418
13465
|
_safeGetRect(node) {
|
|
13419
13466
|
if (!node.hostElement) {
|
|
13420
13467
|
return null;
|
|
13421
13468
|
}
|
|
13469
|
+
const modelPos = node.position();
|
|
13470
|
+
if (modelPos.x !== node._position.x || modelPos.y !== node._position.y) {
|
|
13471
|
+
return null;
|
|
13472
|
+
}
|
|
13422
13473
|
try {
|
|
13423
13474
|
return this._mediator.execute(new GetNormalizedElementRectRequest(node.hostElement));
|
|
13424
13475
|
}
|