feat(runtime): support viewport-ahead reveals
This commit is contained in:
+30
-12
@@ -881,8 +881,14 @@
|
||||
everyTimers.delete(el);
|
||||
}
|
||||
|
||||
function revealedRootMargin(el) {
|
||||
const ahead = Number(el.getAttribute("data-hemx-revealed-ahead") || "0");
|
||||
const viewports = Number.isFinite(ahead) && ahead >= 0 ? ahead : 0;
|
||||
return `0px 0px ${viewports * window.innerHeight}px 0px`;
|
||||
}
|
||||
|
||||
function bindRevealed(root) {
|
||||
let observer = revealObservers.get(root);
|
||||
let observers = revealObservers.get(root);
|
||||
forEachElement(root, (el) => {
|
||||
if (!el.hasAttribute("data-hemx-revealed") || revealed.has(el)) return;
|
||||
if (typeof IntersectionObserver === "undefined") {
|
||||
@@ -890,6 +896,12 @@
|
||||
schedule(el, "revealed");
|
||||
return;
|
||||
}
|
||||
if (!observers) {
|
||||
observers = new Map();
|
||||
revealObservers.set(root, observers);
|
||||
}
|
||||
const rootMargin = revealedRootMargin(el);
|
||||
let observer = observers.get(rootMargin);
|
||||
if (!observer) {
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
@@ -898,8 +910,8 @@
|
||||
observer.unobserve(entry.target);
|
||||
schedule(entry.target, "revealed");
|
||||
});
|
||||
});
|
||||
revealObservers.set(root, observer);
|
||||
}, { rootMargin });
|
||||
observers.set(rootMargin, observer);
|
||||
}
|
||||
observer.observe(el);
|
||||
});
|
||||
@@ -1123,25 +1135,30 @@
|
||||
const source = sseSources.get(root);
|
||||
if (source) source.close();
|
||||
sseSources.delete(root);
|
||||
const observer = revealObservers.get(root);
|
||||
if (observer) observer.disconnect();
|
||||
const observers = revealObservers.get(root);
|
||||
if (observers) observers.forEach((observer) => observer.disconnect());
|
||||
revealObservers.delete(root);
|
||||
stopDescendantPolling(root);
|
||||
}
|
||||
|
||||
function restoreRevealed(event) {
|
||||
if (!event.persisted) return;
|
||||
function rebindRevealed(resetDispatched) {
|
||||
roots().forEach((root) => {
|
||||
const observer = revealObservers.get(root);
|
||||
if (observer) observer.disconnect();
|
||||
const observers = revealObservers.get(root);
|
||||
if (observers) observers.forEach((observer) => observer.disconnect());
|
||||
revealObservers.delete(root);
|
||||
forEachElement(root, (el) => {
|
||||
if (attrEquals(el, "data-hemx-on", "revealed") || el.hasAttribute("data-hemx-revealed")) revealed.delete(el);
|
||||
});
|
||||
if (resetDispatched) {
|
||||
forEachElement(root, (el) => {
|
||||
if (attrEquals(el, "data-hemx-on", "revealed") || el.hasAttribute("data-hemx-revealed")) revealed.delete(el);
|
||||
});
|
||||
}
|
||||
bindRevealed(root);
|
||||
});
|
||||
}
|
||||
|
||||
function restoreRevealed(event) {
|
||||
if (event.persisted) rebindRevealed(true);
|
||||
}
|
||||
|
||||
function start() {
|
||||
roots().forEach((root) => {
|
||||
root.setAttribute("data-hemx-request-timeout-ms", String(REQUEST_TIMEOUT_MS));
|
||||
@@ -1189,6 +1206,7 @@
|
||||
}
|
||||
|
||||
window.addEventListener("pageshow", restoreRevealed);
|
||||
window.addEventListener("resize", () => rebindRevealed(false));
|
||||
|
||||
addEventListener("popstate", (event) => {
|
||||
const root = roots()[0];
|
||||
|
||||
@@ -146,7 +146,10 @@ fn runtime_supports_tiny_delay_and_revealed_scheduling() {
|
||||
assert!(source.contains("const revealObservers = new WeakMap()"));
|
||||
assert!(source.contains("const revealed = new WeakSet()"));
|
||||
assert!(source.contains("data-hemx-revealed"));
|
||||
assert!(source.contains("data-hemx-revealed-ahead")); // req: convention/011 test
|
||||
assert!(source.contains("typeof IntersectionObserver === \"undefined\""));
|
||||
assert!(source.contains("rootMargin"));
|
||||
assert!(source.contains("addEventListener(\"resize\", () => rebindRevealed(false))"));
|
||||
assert!(source.contains("schedule(entry.target, \"revealed\")"));
|
||||
assert!(source.contains("window.addEventListener(\"pageshow\", restoreRevealed)"));
|
||||
assert!(source.contains("revealed.delete(el)")); // req: convention/014 test
|
||||
|
||||
Reference in New Issue
Block a user