import { prefersReducedMotion } from "../shared/media.js"; export function initMiniProjectsExpand(masonry) { if (!masonry) return; const controllers = Array.isArray(masonry) ? masonry : [masonry]; controllers.forEach(initMiniProjectsExpandForList); } function initMiniProjectsExpandForList(masonry) { if (!masonry?.list) return; const scope = masonry.list.closest("section, main") ?? masonry.list.parentElement; const btn = scope?.querySelector("[data-mp-toggle]"); const extras = masonry.extraItems; if (!btn || extras.length === 0) return; const labelExpand = "Показать все"; const labelCollapse = "Свернуть"; const reducedMotion = prefersReducedMotion(); let locked = false; const wait = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms)); function animateOpen(el, delayMs) { const card = el.querySelector(".mp-card"); if (!card) return Promise.resolve(); if (reducedMotion) { el.setAttribute("aria-hidden", "false"); card.style.opacity = "1"; card.style.transform = "translateY(0)"; card.style.pointerEvents = ""; return Promise.resolve(); } const duration = 280; el.setAttribute("aria-hidden", "false"); card.style.opacity = "0"; card.style.transform = "translateY(12px)"; card.style.pointerEvents = ""; card.style.willChange = "opacity, transform"; return new Promise((resolve) => { window.setTimeout(() => { card.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`; card.style.opacity = "1"; card.style.transform = "translateY(0)"; }, delayMs); window.setTimeout(() => { card.style.transition = ""; card.style.opacity = ""; card.style.transform = ""; card.style.willChange = ""; resolve(); }, delayMs + duration + 30); }); } function animateClose(el, delayMs) { const card = el.querySelector(".mp-card"); if (!card) return Promise.resolve(); if (reducedMotion) { el.setAttribute("aria-hidden", "true"); card.style.opacity = "0"; card.style.transform = "translateY(12px)"; card.style.pointerEvents = "none"; return Promise.resolve(); } const duration = 240; card.style.opacity = "1"; card.style.transform = "translateY(0)"; card.style.willChange = "opacity, transform"; return new Promise((resolve) => { window.setTimeout(() => { card.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`; card.style.opacity = "0"; card.style.transform = "translateY(12px)"; }, delayMs); window.setTimeout(() => { card.style.transition = ""; card.style.opacity = ""; card.style.transform = ""; card.style.willChange = ""; el.setAttribute("aria-hidden", "true"); card.style.opacity = "0"; card.style.transform = "translateY(12px)"; card.style.pointerEvents = "none"; resolve(); }, delayMs + duration + 30); }); } function setExpandedUi(expanded) { btn.setAttribute("aria-expanded", expanded ? "true" : "false"); btn.textContent = expanded ? labelCollapse : labelExpand; } btn.addEventListener("click", async () => { if (locked) return; locked = true; btn.disabled = true; const next = btn.getAttribute("aria-expanded") !== "true"; setExpandedUi(next); if (next) { masonry.setExpanded(true); const jobs = []; extras.forEach((el, i) => jobs.push(animateOpen(el, i * 45))); await Promise.all(jobs); } else { const reversed = Array.from(extras).reverse(); const jobs = []; reversed.forEach((el, i) => jobs.push(animateClose(el, i * 35))); await Promise.all(jobs); masonry.setExpanded(false); await wait(10); } masonry.relayout(); btn.disabled = false; locked = false; }); extras.forEach((el) => { const card = el.querySelector(".mp-card"); el.setAttribute("aria-hidden", "true"); if (!card) return; card.style.opacity = "0"; card.style.transform = "translateY(12px)"; card.style.pointerEvents = "none"; }); masonry.setExpanded(false); masonry.relayout(); }