Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
+135
View File
@@ -0,0 +1,135 @@
/**
* Мягкая поэтапная анимация zootech-страниц: navbar → main → блоки.
* html.wesp-page-enter-pending ставится inline в <head> до первого paint.
*/
(function () {
const MAX_ITEMS = 8;
let held = false;
let revealed = false;
function prefersReducedMotion() {
return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches ?? false;
}
function isGridListPage() {
const body = document.body;
if (!body) return false;
return (
body.classList.contains("components-page") ||
body.classList.contains("feed-dispensers-page") ||
body.classList.contains("reports-page")
);
}
function markEnterItems() {
const html = document.documentElement;
if (isGridListPage()) {
html.classList.add("wesp-page-enter-grid-page");
return;
}
html.classList.remove("wesp-page-enter-grid-page");
const root = document.querySelector(".wesp-page-main");
if (!root) return;
let items = Array.from(root.querySelectorAll("[data-wesp-enter]"));
if (!items.length) {
items = Array.from(root.children).filter((el) => el.nodeType === 1);
}
items.slice(0, MAX_ITEMS).forEach((el, i) => {
el.classList.add("wesp-page-enter-item");
el.style.setProperty("--wesp-enter-i", String(i));
});
document.querySelectorAll("[data-wesp-enter].app-footer, footer[data-wesp-enter]").forEach((el, i) => {
if (el.classList.contains("wesp-page-enter-item")) return;
el.classList.add("wesp-page-enter-item");
el.style.setProperty("--wesp-enter-i", String(items.length + i));
});
}
function finalizeReveal() {
if (revealed) return;
revealed = true;
const html = document.documentElement;
html.classList.remove("wesp-page-enter-pending");
html.classList.add("wesp-page-enter-ready");
let settled = false;
let fallbackTimer = 0;
const settleDone = () => {
if (settled || !html.classList.contains("wesp-page-enter-ready")) return;
settled = true;
if (fallbackTimer) window.clearTimeout(fallbackTimer);
requestAnimationFrame(() => {
html.classList.remove("wesp-page-enter-ready");
html.classList.add("wesp-page-enter-done");
requestAnimationFrame(() => {
globalThis.WespNavLogoShimmer?.init?.();
});
});
};
const items = document.querySelectorAll(".wesp-page-enter-item");
let pending = items.length;
if (pending === 0) {
settleDone();
return;
}
const onAnimEnd = (event) => {
if (event.animationName !== "wesp-enter-fade") return;
pending -= 1;
if (pending <= 0) settleDone();
};
items.forEach((el) => {
el.addEventListener("animationend", onAnimEnd, { once: true });
});
const fallbackMs =
80 + (MAX_ITEMS - 1) * 55 + 350 + 80;
fallbackTimer = window.setTimeout(settleDone, fallbackMs);
}
function revealPageMain() {
if (revealed || held) return;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (!held && !revealed) finalizeReveal();
});
});
}
function holdPageMain() {
held = true;
}
function releaseAndReveal() {
held = false;
if (!revealed) revealPageMain();
}
function init() {
markEnterItems();
if (prefersReducedMotion()) {
finalizeReveal();
document.documentElement.classList.add("wesp-page-enter-done");
return;
}
if (!held) {
revealPageMain();
}
}
window.WespPageEnter = {
init,
hold: holdPageMain,
reveal: releaseAndReveal,
};
})();