@vectoriox/iox-builder 1.4.74 → 1.4.75
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.
|
@@ -1448,58 +1448,51 @@ class InteractionEngineService {
|
|
|
1448
1448
|
this.runActions(node, ix.actions);
|
|
1449
1449
|
};
|
|
1450
1450
|
const canvasRoot = this.overlayService.getIntersectionRoot();
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
// Use getBoundingClientRect against the canvas clipping container instead.
|
|
1454
|
-
const isInCanvasViewport = () => {
|
|
1455
|
-
const rootRect = canvasRoot.getBoundingClientRect();
|
|
1456
|
-
const elRect = element.getBoundingClientRect();
|
|
1457
|
-
const overlapH = Math.min(elRect.bottom, rootRect.bottom) - Math.max(elRect.top, rootRect.top);
|
|
1458
|
-
const elH = elRect.bottom - elRect.top;
|
|
1459
|
-
return elH > 0 && overlapH / elH >= 0.1;
|
|
1460
|
-
};
|
|
1461
|
-
let fired = false;
|
|
1462
|
-
const checkAndFire = () => {
|
|
1463
|
-
if (fired)
|
|
1464
|
-
return;
|
|
1465
|
-
if (isInCanvasViewport()) {
|
|
1466
|
-
fired = true;
|
|
1467
|
-
fire();
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
// Initial checks: a single RAF fires before deeply-nested Angular components
|
|
1471
|
-
// have settled their layout. Schedule retries so above-fold elements are
|
|
1472
|
-
// detected even when render takes a few frames.
|
|
1473
|
-
const rafId = requestAnimationFrame(checkAndFire);
|
|
1474
|
-
const t1 = window.setTimeout(checkAndFire, 100);
|
|
1475
|
-
const t2 = window.setTimeout(checkAndFire, 400);
|
|
1476
|
-
// Lenis changes scrollTop on .preview-scroll → native scroll event fires.
|
|
1477
|
-
// Builder also dispatches a synthetic scroll on .preview-lenis-content.
|
|
1478
|
-
// Listen on both so we catch all scroll notifications.
|
|
1479
|
-
const lenisEl = this.overlayService.getScrollContainer();
|
|
1480
|
-
canvasRoot.addEventListener('scroll', checkAndFire, { passive: true });
|
|
1481
|
-
if (lenisEl)
|
|
1482
|
-
lenisEl.addEventListener('scroll', checkAndFire, { passive: true });
|
|
1483
|
-
return () => {
|
|
1484
|
-
fired = true; // stop any pending checks
|
|
1485
|
-
cancelAnimationFrame(rafId);
|
|
1486
|
-
clearTimeout(t1);
|
|
1487
|
-
clearTimeout(t2);
|
|
1488
|
-
canvasRoot.removeEventListener('scroll', checkAndFire);
|
|
1489
|
-
if (lenisEl)
|
|
1490
|
-
lenisEl.removeEventListener('scroll', checkAndFire);
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
// Production mode: standard IntersectionObserver against browser viewport.
|
|
1451
|
+
// IntersectionObserver (browser viewport, no root) fires immediately for elements
|
|
1452
|
+
// already visible in the canvas frame. Works for initial above-fold detection.
|
|
1494
1453
|
const observer = new IntersectionObserver((entries) => {
|
|
1495
1454
|
for (const entry of entries) {
|
|
1496
1455
|
if (entry.isIntersecting) {
|
|
1456
|
+
observer.disconnect();
|
|
1497
1457
|
fire();
|
|
1498
1458
|
}
|
|
1499
1459
|
}
|
|
1500
1460
|
}, { threshold: 0.1 });
|
|
1501
1461
|
observer.observe(element);
|
|
1502
|
-
|
|
1462
|
+
if (!canvasRoot) {
|
|
1463
|
+
// Production mode: IntersectionObserver alone is sufficient.
|
|
1464
|
+
return () => observer.disconnect();
|
|
1465
|
+
}
|
|
1466
|
+
// Builder mode: Lenis scrolls .preview-scroll via scrollTop on an overflow:hidden
|
|
1467
|
+
// element. Browsers may not re-trigger IntersectionObserver when scrollTop changes
|
|
1468
|
+
// on a non-scroll-container. Add a manual BoundingClientRect check on every Lenis
|
|
1469
|
+
// scroll frame (dispatched as a native 'scroll' event on .preview-lenis-content).
|
|
1470
|
+
const isInCanvasViewport = () => {
|
|
1471
|
+
const rootRect = canvasRoot.getBoundingClientRect();
|
|
1472
|
+
const elRect = element.getBoundingClientRect();
|
|
1473
|
+
const overlapH = Math.min(elRect.bottom, rootRect.bottom) - Math.max(elRect.top, rootRect.top);
|
|
1474
|
+
const elH = elRect.bottom - elRect.top;
|
|
1475
|
+
return elH > 0 && overlapH / elH >= 0.1;
|
|
1476
|
+
};
|
|
1477
|
+
let scrollFired = false;
|
|
1478
|
+
const onLenisScroll = () => {
|
|
1479
|
+
if (scrollFired)
|
|
1480
|
+
return;
|
|
1481
|
+
if (isInCanvasViewport()) {
|
|
1482
|
+
scrollFired = true;
|
|
1483
|
+
observer.disconnect();
|
|
1484
|
+
fire();
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
const lenisEl = this.overlayService.getScrollContainer();
|
|
1488
|
+
if (lenisEl)
|
|
1489
|
+
lenisEl.addEventListener('scroll', onLenisScroll, { passive: true });
|
|
1490
|
+
return () => {
|
|
1491
|
+
scrollFired = true;
|
|
1492
|
+
observer.disconnect();
|
|
1493
|
+
if (lenisEl)
|
|
1494
|
+
lenisEl.removeEventListener('scroll', onLenisScroll);
|
|
1495
|
+
};
|
|
1503
1496
|
}
|
|
1504
1497
|
isBuilderMode() {
|
|
1505
1498
|
return document.body.classList.contains('builder-active');
|
|
@@ -1660,11 +1653,7 @@ class InteractionEngineService {
|
|
|
1660
1653
|
// Mark as hidden so the builder overlay and drag engine can ignore this element
|
|
1661
1654
|
// and all of its children regardless of which entrance animation type is used.
|
|
1662
1655
|
element.setAttribute('data-iox-hidden', '');
|
|
1663
|
-
|
|
1664
|
-
// pointer-events:none so wheel events still reach Lenis and canvas scroll works.
|
|
1665
|
-
if (!this.isBuilderMode()) {
|
|
1666
|
-
element.style.setProperty('pointer-events', 'none');
|
|
1667
|
-
}
|
|
1656
|
+
element.style.setProperty('pointer-events', 'none');
|
|
1668
1657
|
this.preStatedElements.add(element);
|
|
1669
1658
|
}
|
|
1670
1659
|
clearInlineAnimationStyles(element) {
|
|
@@ -2774,9 +2763,13 @@ class RenderDirective {
|
|
|
2774
2763
|
nativeEl.addEventListener('mouseenter', (event) => {
|
|
2775
2764
|
if (event._fromClick)
|
|
2776
2765
|
return;
|
|
2766
|
+
if (nativeEl.hasAttribute('data-iox-hidden'))
|
|
2767
|
+
return;
|
|
2777
2768
|
this.onMouseEnter.emit({ element: nativeEl, node });
|
|
2778
2769
|
});
|
|
2779
2770
|
nativeEl.addEventListener('mouseleave', (event) => {
|
|
2771
|
+
if (nativeEl.hasAttribute('data-iox-hidden'))
|
|
2772
|
+
return;
|
|
2780
2773
|
// When leaving a child component, check if the mouse moved to a
|
|
2781
2774
|
// parent component (e.g. card → section). If so, emit mouseenter
|
|
2782
2775
|
// for that parent instead of clearing hover entirely.
|
|
@@ -2792,12 +2785,15 @@ class RenderDirective {
|
|
|
2792
2785
|
});
|
|
2793
2786
|
nativeEl.addEventListener('click', (event) => {
|
|
2794
2787
|
event.stopPropagation();
|
|
2788
|
+
if (nativeEl.hasAttribute('data-iox-hidden'))
|
|
2789
|
+
return;
|
|
2795
2790
|
this.onClick.emit({ element: nativeEl, node, componentRef });
|
|
2796
2791
|
});
|
|
2797
2792
|
nativeEl.addEventListener('contextmenu', (event) => {
|
|
2798
2793
|
event.preventDefault();
|
|
2799
2794
|
event.stopPropagation();
|
|
2800
|
-
|
|
2795
|
+
if (nativeEl.hasAttribute('data-iox-hidden'))
|
|
2796
|
+
return;
|
|
2801
2797
|
this.onClick.emit({ element: nativeEl, node, componentRef });
|
|
2802
2798
|
this.overlayService.triggerContextMenu(event.clientX, event.clientY);
|
|
2803
2799
|
});
|