fix(site): stabilize media and notification runtime

This commit is contained in:
dcconstructions
2026-06-27 13:22:33 +03:00
parent 12493711d1
commit c506f242d8
6 changed files with 200 additions and 4 deletions
+1
View File
@@ -3,3 +3,4 @@
.project-video-detail .project-video-detail-copy{position:relative;z-index:2}.project-video-detail .project-video-detail-copy-bottom{margin-top:2.5rem}.project-video-detail .project-video-detail-copy-bottom .main-h{margin-bottom:0}@media screen and (max-width:767px){.project-video-detail .project-video-detail-hgroup{flex-flow:row;gap:1.25rem}.project-video-detail .project-video-detail-hgroup.flip{flex-flow:row-reverse}.project-video-detail .project-video-detail-hgroup .main-h.h1{font-size:2.35rem}.project-video-detail .project-video-detail-hgroup .h-txt{max-width:22ch}.project-video-detail .project-video-detail-copy-bottom{margin-top:2rem}}@media screen and (max-width:479px){.project-video-detail .project-video-detail-copy{width:86%}.project-video-detail .project-video-detail-hgroup{gap:1rem}.project-video-detail .project-video-detail-hgroup .main-h.h1{font-size:2rem}.project-video-detail .project-video-detail-hgroup .h-txt{max-width:17ch;font-size:.86rem;line-height:1.28em}}
.project-composition .project-composition-copy{position:relative;z-index:2}.project-composition .project-composition-copy-bottom{margin-top:2.5rem}.project-composition .project-composition-copy-bottom .main-h{margin-bottom:0}@media screen and (max-width:767px){.project-composition .project-composition-hgroup{flex-flow:row;gap:1.25rem}.project-composition .project-composition-hgroup.flip{flex-flow:row-reverse}.project-composition .project-composition-hgroup .main-h.h2{font-size:2.35rem}.project-composition .project-composition-hgroup .h-txt{max-width:22ch}.project-composition .project-composition-copy-bottom{margin-top:2rem}}@media screen and (max-width:479px){.project-composition .project-composition-copy{width:86%}.project-composition .project-composition-hgroup{gap:1rem}.project-composition .project-composition-hgroup .main-h.h2{font-size:2rem}.project-composition .project-composition-hgroup .h-txt{max-width:17ch;font-size:.86rem;line-height:1.28em}}
.pricing-table-section .pricing-table-shell{padding-top:12svh;padding-bottom:12svh}@media screen and (max-width:767px){.pricing-table-section .pricing-table-shell{padding-top:8svh;padding-bottom:8svh}}
[data-module=notification-w][data-notification-stack-ready]{height:auto;max-height:calc(100svh - 3.2rem);overflow:visible;scrollbar-width:none;overscroll-behavior:contain}[data-module=notification-w][data-notification-stack-ready]::-webkit-scrollbar{display:none}[data-module=notification-w][data-notification-stack-ready]:not(:hover):not([data-notification-expanded=true]){height:var(--notification-collapsed-height,6.6rem);max-height:var(--notification-collapsed-height,6.6rem)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true]){overflow-x:visible;overflow-y:auto;padding-bottom:.2rem}[data-module=notification-w][data-notification-stack-ready]>[data-module=notification]{position:relative;z-index:var(--notification-z,1);transform:translateY(var(--notification-stack-y,0));transition:transform .3s cubic-bezier(.22,1,.36,1)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true])>[data-module=notification]{transform:translateY(0)}
+1
View File
@@ -3,3 +3,4 @@
.project-video-detail .project-video-detail-copy{position:relative;z-index:2}.project-video-detail .project-video-detail-copy-bottom{margin-top:2.5rem}.project-video-detail .project-video-detail-copy-bottom .main-h{margin-bottom:0}@media screen and (max-width:767px){.project-video-detail .project-video-detail-hgroup{flex-flow:row;gap:1.25rem}.project-video-detail .project-video-detail-hgroup.flip{flex-flow:row-reverse}.project-video-detail .project-video-detail-hgroup .main-h.h1{font-size:2.35rem}.project-video-detail .project-video-detail-hgroup .h-txt{max-width:22ch}.project-video-detail .project-video-detail-copy-bottom{margin-top:2rem}}@media screen and (max-width:479px){.project-video-detail .project-video-detail-copy{width:86%}.project-video-detail .project-video-detail-hgroup{gap:1rem}.project-video-detail .project-video-detail-hgroup .main-h.h1{font-size:2rem}.project-video-detail .project-video-detail-hgroup .h-txt{max-width:17ch;font-size:.86rem;line-height:1.28em}}
.project-composition .project-composition-copy{position:relative;z-index:2}.project-composition .project-composition-copy-bottom{margin-top:2.5rem}.project-composition .project-composition-copy-bottom .main-h{margin-bottom:0}@media screen and (max-width:767px){.project-composition .project-composition-hgroup{flex-flow:row;gap:1.25rem}.project-composition .project-composition-hgroup.flip{flex-flow:row-reverse}.project-composition .project-composition-hgroup .main-h.h2{font-size:2.35rem}.project-composition .project-composition-hgroup .h-txt{max-width:22ch}.project-composition .project-composition-copy-bottom{margin-top:2rem}}@media screen and (max-width:479px){.project-composition .project-composition-copy{width:86%}.project-composition .project-composition-hgroup{gap:1rem}.project-composition .project-composition-hgroup .main-h.h2{font-size:2rem}.project-composition .project-composition-hgroup .h-txt{max-width:17ch;font-size:.86rem;line-height:1.28em}}
.pricing-table-section .pricing-table-shell{padding-top:12svh;padding-bottom:12svh}@media screen and (max-width:767px){.pricing-table-section .pricing-table-shell{padding-top:8svh;padding-bottom:8svh}}
[data-module=notification-w][data-notification-stack-ready]{height:auto;max-height:calc(100svh - 3.2rem);overflow:visible;scrollbar-width:none;overscroll-behavior:contain}[data-module=notification-w][data-notification-stack-ready]::-webkit-scrollbar{display:none}[data-module=notification-w][data-notification-stack-ready]:not(:hover):not([data-notification-expanded=true]){height:var(--notification-collapsed-height,6.6rem);max-height:var(--notification-collapsed-height,6.6rem)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true]){overflow-x:visible;overflow-y:auto;padding-bottom:.2rem}[data-module=notification-w][data-notification-stack-ready]>[data-module=notification]{position:relative;z-index:var(--notification-z,1);transform:translateY(var(--notification-stack-y,0));transition:transform .3s cubic-bezier(.22,1,.36,1)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true])>[data-module=notification]{transform:translateY(0)}
+125 -1
View File
@@ -12,7 +12,9 @@
const MEDIA_HANDLE_BOUND_FLAG = "__nodedcMediaHandleBound";
const DOCK_LINK_BOUND_FLAG = "__nodedcDockLinkBound";
const ORDERED_SLIDER_BOUND_FLAG = "__nodedcOrderedSliderBound";
const LAZY_MEDIA_VIDEO_BOUND_FLAG = "__nodedcLazyMediaVideoBound";
const SCROLL_HEIGHT_SYNC_FLAG = "__nodedcScrollHeightSyncBound";
const NOTIFICATION_STACK_BOUND_FLAG = "__nodedcNotificationStackBound";
const SCROLL_HEIGHT_SYNC_WARMUP_MS = 14000;
const SCROLL_HEIGHT_SYNC_INTERVAL_MS = 90;
const IMAGE_EXTENSIONS = new Set(["avif", "gif", "jpeg", "jpg", "png", "svg", "webp"]);
@@ -384,6 +386,75 @@
document.querySelectorAll('[data-module="dock"] a[data-app]').forEach(bindDockLink);
}
function refreshNotificationStack(wrapper) {
const notifications = Array.from(wrapper.querySelectorAll(':scope > [data-module="notification"]'));
const firstOffset = notifications[0]?.offsetTop || 0;
const collapsedHeight = (notifications[0]?.offsetHeight || 0) + Math.min(Math.max(notifications.length - 1, 0), 3) * 5;
wrapper.dataset.notificationStackReady = "true";
wrapper.style.setProperty("--notification-count", String(notifications.length));
wrapper.style.setProperty("--notification-collapsed-height", `${collapsedHeight}px`);
notifications.forEach((notification, index) => {
const naturalOffset = notification.offsetTop - firstOffset;
const deckOffset = Math.min(index, 3) * 5;
notification.style.setProperty("--notification-stack-y", `${deckOffset - naturalOffset}px`);
notification.style.setProperty("--notification-z", String(index + 1));
});
}
function scheduleNotificationStackRefresh(wrapper) {
if (wrapper.__nodedcNotificationStackFrame) return;
wrapper.__nodedcNotificationStackFrame = window.requestAnimationFrame(() => {
wrapper.__nodedcNotificationStackFrame = 0;
refreshNotificationStack(wrapper);
});
}
function bindNotificationStack(wrapper) {
if (!wrapper || wrapper[NOTIFICATION_STACK_BOUND_FLAG]) return;
wrapper[NOTIFICATION_STACK_BOUND_FLAG] = true;
scheduleNotificationStackRefresh(wrapper);
const mutationObserver =
typeof MutationObserver === "function"
? new MutationObserver(() => scheduleNotificationStackRefresh(wrapper))
: null;
mutationObserver?.observe(wrapper, { childList: true });
wrapper.addEventListener("pointerdown", (event) => {
if (event.target?.closest?.("[data-close]")) return;
wrapper.dataset.notificationExpanded = "true";
});
wrapper.addEventListener("mouseleave", () => {
delete wrapper.dataset.notificationExpanded;
wrapper.scrollTop = 0;
scheduleNotificationStackRefresh(wrapper);
});
document.addEventListener(
"pointerdown",
(event) => {
if (wrapper.contains(event.target)) return;
delete wrapper.dataset.notificationExpanded;
wrapper.scrollTop = 0;
},
{ capture: true },
);
window.addEventListener("resize", () => scheduleNotificationStackRefresh(wrapper));
window.setTimeout(() => scheduleNotificationStackRefresh(wrapper), 120);
}
function bindNotificationStacks() {
document.querySelectorAll('[data-module="notification-w"]').forEach(bindNotificationStack);
}
function mediaExtension(src) {
const cleanSrc = String(src || "").split(/[?#]/)[0];
const match = /\.([a-z0-9]+)$/i.exec(cleanSrc);
@@ -407,7 +478,7 @@
const video = document.createElement("video");
video.className = "video-el";
video.dataset.module = "video-handle";
video.dataset.lazyVideo = "";
video.src = src;
video.muted = true;
video.loop = true;
@@ -458,8 +529,53 @@
document.querySelectorAll("[data-adaptive-video] video").forEach(bindAdaptiveVideo);
}
function playLazyVideo(video) {
video.preload = "auto";
const playPromise = video.play();
if (playPromise && typeof playPromise.catch === "function") {
playPromise.catch(() => {});
}
}
function bindLazyMediaVideo(video) {
if (!video || video[LAZY_MEDIA_VIDEO_BOUND_FLAG]) return;
video[LAZY_MEDIA_VIDEO_BOUND_FLAG] = true;
video.muted = true;
video.loop = true;
video.playsInline = true;
video.preload = "none";
video.removeAttribute("autoplay");
if (typeof IntersectionObserver !== "function") {
playLazyVideo(video);
return;
}
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
playLazyVideo(video);
} else {
video.pause();
}
});
},
{ rootMargin: "80px 0px", threshold: 0.01 },
);
observer.observe(video);
}
function bindLazyMediaVideos() {
document.querySelectorAll("video[data-lazy-video]").forEach(bindLazyMediaVideo);
}
bindScrollHeightSync();
hydrateMediaHandles();
bindNotificationStacks();
if (document.readyState === "loading") {
document.addEventListener(
@@ -470,7 +586,9 @@
bindInteractiveScroll();
bindOrderedSliders();
bindDockLinks();
bindNotificationStacks();
bindAdaptiveVideos();
bindLazyMediaVideos();
scheduleScrollHeightSync(true);
},
{ once: true },
@@ -481,7 +599,9 @@
bindInteractiveScroll();
bindOrderedSliders();
bindDockLinks();
bindNotificationStacks();
bindAdaptiveVideos();
bindLazyMediaVideos();
scheduleScrollHeightSync(true);
}
@@ -491,14 +611,18 @@
bindInteractiveScroll();
bindOrderedSliders();
bindDockLinks();
bindNotificationStacks();
bindAdaptiveVideos();
bindLazyMediaVideos();
scheduleScrollHeightSync(true);
window.setTimeout(() => {
hydrateMediaHandles();
bindInteractiveScroll();
bindOrderedSliders();
bindDockLinks();
bindNotificationStacks();
bindAdaptiveVideos();
bindLazyMediaVideos();
scheduleScrollHeightSync(true);
}, 500);
});