@vectoriox/iox-builder 1.4.35 → 1.4.36
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.
|
@@ -348,6 +348,8 @@ class DragEngineService {
|
|
|
348
348
|
this._flipEls = new Set();
|
|
349
349
|
// ── Viewport scale ────────────────────────────────────────
|
|
350
350
|
this._scale = 1;
|
|
351
|
+
// ── Dropzone rect cache — snapshotted at drag start and on scroll ─────────
|
|
352
|
+
this._dropzoneRectCache = new Map();
|
|
351
353
|
// ── Root-escape ───────────────────────────────────────────
|
|
352
354
|
this.ROOT_ESCAPE_PX = 14;
|
|
353
355
|
this._rootEscapeActiveFor = null;
|
|
@@ -403,6 +405,14 @@ class DragEngineService {
|
|
|
403
405
|
}
|
|
404
406
|
/** Called by BuilderComponent whenever the viewport scale changes. */
|
|
405
407
|
setScale(scale) { this._scale = scale; }
|
|
408
|
+
_snapshotRects() {
|
|
409
|
+
this._dropzoneRectCache.clear();
|
|
410
|
+
for (const id of this.ids) {
|
|
411
|
+
const el = this._getEl(id);
|
|
412
|
+
if (el)
|
|
413
|
+
this._dropzoneRectCache.set(id, el.getBoundingClientRect());
|
|
414
|
+
}
|
|
415
|
+
}
|
|
406
416
|
// ─────────────────────────────────────────────────────────
|
|
407
417
|
// Element lookup — elMap first, DOM id fallback
|
|
408
418
|
// ─────────────────────────────────────────────────────────
|
|
@@ -558,6 +568,7 @@ class DragEngineService {
|
|
|
558
568
|
this._createExternalChip(this._payload, event.client.x, event.client.y);
|
|
559
569
|
el.classList.add('iox-drag-source');
|
|
560
570
|
}
|
|
571
|
+
this._snapshotRects();
|
|
561
572
|
}
|
|
562
573
|
_onDragMove(event) {
|
|
563
574
|
this._lastPointerX = event.client.x;
|
|
@@ -652,7 +663,7 @@ class DragEngineService {
|
|
|
652
663
|
// whose DOM element lives inside the dragged source wrapper.
|
|
653
664
|
if (this._sourceEl?.contains(el))
|
|
654
665
|
continue;
|
|
655
|
-
const rect = el.getBoundingClientRect();
|
|
666
|
+
const rect = this._dropzoneRectCache.get(id) ?? el.getBoundingClientRect();
|
|
656
667
|
if (px >= rect.left && px <= rect.right && py >= rect.top && py <= rect.bottom) {
|
|
657
668
|
const area = rect.width * rect.height;
|
|
658
669
|
if (area < bestArea) {
|
|
@@ -674,7 +685,7 @@ class DragEngineService {
|
|
|
674
685
|
if (this._rootEscapeActiveFor) {
|
|
675
686
|
const escEl = this._getEl(this._rootEscapeActiveFor);
|
|
676
687
|
if (escEl) {
|
|
677
|
-
const r = escEl.getBoundingClientRect();
|
|
688
|
+
const r = this._dropzoneRectCache.get(this._rootEscapeActiveFor) ?? escEl.getBoundingClientRect();
|
|
678
689
|
const inside = px >= r.left && px <= r.right && py >= r.top && py <= r.bottom;
|
|
679
690
|
if (inside) {
|
|
680
691
|
bestId = 'canvas-preview';
|
|
@@ -691,7 +702,7 @@ class DragEngineService {
|
|
|
691
702
|
bestId && bestId !== 'canvas-preview' && this._isRootContainer(bestId)) {
|
|
692
703
|
const el = this._getEl(bestId);
|
|
693
704
|
if (el) {
|
|
694
|
-
const rect = el.getBoundingClientRect();
|
|
705
|
+
const rect = this._dropzoneRectCache.get(bestId) ?? el.getBoundingClientRect();
|
|
695
706
|
const nearEdge = py <= rect.top + this.ROOT_ESCAPE_PX ||
|
|
696
707
|
py >= rect.bottom - this.ROOT_ESCAPE_PX;
|
|
697
708
|
// Only escape if we were already targeting this section or
|
|
@@ -731,6 +742,7 @@ class DragEngineService {
|
|
|
731
742
|
refreshDragOverlays() {
|
|
732
743
|
if (!this._isDragging)
|
|
733
744
|
return;
|
|
745
|
+
this._snapshotRects();
|
|
734
746
|
this._moveTargetOverlay(this._deepTargetId);
|
|
735
747
|
}
|
|
736
748
|
_moveTargetOverlay(targetId) {
|
|
@@ -2613,6 +2625,11 @@ class OverlayComponent {
|
|
|
2613
2625
|
this.moreMenuStyle = {};
|
|
2614
2626
|
this.subs = [];
|
|
2615
2627
|
this.boundUpdate = () => this.updateAll();
|
|
2628
|
+
this._scrollRaf = 0;
|
|
2629
|
+
this.boundScrollUpdate = () => {
|
|
2630
|
+
cancelAnimationFrame(this._scrollRaf);
|
|
2631
|
+
this._scrollRaf = requestAnimationFrame(() => this.updateAll());
|
|
2632
|
+
};
|
|
2616
2633
|
this.activeScrollContainer = null;
|
|
2617
2634
|
}
|
|
2618
2635
|
ngOnInit() {
|
|
@@ -2647,9 +2664,9 @@ class OverlayComponent {
|
|
|
2647
2664
|
// its wrapper element after each raf tick — listen to that to reposition
|
|
2648
2665
|
// overlay boxes as the canvas scrolls.
|
|
2649
2666
|
this.subs.push(this.overlayService.scrollContainer$.subscribe(el => {
|
|
2650
|
-
this.activeScrollContainer?.removeEventListener('scroll', this.
|
|
2667
|
+
this.activeScrollContainer?.removeEventListener('scroll', this.boundScrollUpdate);
|
|
2651
2668
|
this.activeScrollContainer = el;
|
|
2652
|
-
el.addEventListener('scroll', this.
|
|
2669
|
+
el.addEventListener('scroll', this.boundScrollUpdate, { passive: true });
|
|
2653
2670
|
}));
|
|
2654
2671
|
// Open the more menu when a canvas element is right-clicked.
|
|
2655
2672
|
this.subs.push(this.overlayService.contextMenu$.subscribe(({ x, y }) => {
|
|
@@ -2663,8 +2680,9 @@ class OverlayComponent {
|
|
|
2663
2680
|
this.resizeObserver?.disconnect();
|
|
2664
2681
|
this.containerResizeObserver?.disconnect();
|
|
2665
2682
|
this.mutationObserver?.disconnect();
|
|
2683
|
+
cancelAnimationFrame(this._scrollRaf);
|
|
2666
2684
|
window.removeEventListener('resize', this.boundUpdate);
|
|
2667
|
-
this.activeScrollContainer?.removeEventListener('scroll', this.
|
|
2685
|
+
this.activeScrollContainer?.removeEventListener('scroll', this.boundScrollUpdate);
|
|
2668
2686
|
this.activeScrollContainer = null;
|
|
2669
2687
|
}
|
|
2670
2688
|
// ── Toolbar actions ──────────────────────────────────────
|