const KIOSK_SKELETON_MIN_MS = 300; const KIOSK_SKELETON_EXIT_MS = 160; const GRID_CARD_INNER = `
`; const GROUP_ITEM_INNER = `
`; export function buildGridSkeletonCards(rowCount = 4) { return Array.from({ length: rowCount }, () => `` ).join(""); } export function buildDispenserGridSkeletonHtml(rowCount = 4) { return buildGridSkeletonCards(rowCount); } export function buildPeriodRecipeGridSkeletonHtml(rowCount = 4) { return buildGridSkeletonCards(rowCount); } export function buildUnloadingGroupsSkeletonHtml(rowCount = 3) { const items = Array.from({ length: rowCount }, () => `
${GROUP_ITEM_INNER}
` ).join(""); return `
${items}
`; } export function buildDuplicatePanelSkeletonHtml() { return `
`; } export function buildRecipeIngredientsSkeletonHtml(rowCount = 6) { const rows = Array.from({ length: rowCount }, () => `
` ).join(""); return `
${rows}
`; } function prefersReducedMotion() { return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches; } function isGridSkeletonHost(container) { if (!container) return false; return ( container.getAttribute("aria-busy") === "true" && container.querySelector(":scope > .kiosk-skeleton-card") != null ); } function findSkeletonRoot(container) { if (!container) return null; if (isGridSkeletonHost(container)) return container; return container.querySelector( ":scope > .kiosk-skeleton-groups, :scope > .kiosk-skeleton-table, :scope > .kiosk-skeleton-panel" ); } export function mountKioskSkeleton(container, html, label) { if (!container) return performance.now(); container.innerHTML = html; container.classList.remove("kiosk-skeleton-host--exit"); if (container.querySelector(":scope > .kiosk-skeleton-card")) { container.setAttribute("aria-busy", "true"); if (label) container.setAttribute("aria-label", label); } return performance.now(); } export async function awaitKioskSkeletonMin(startedAt, minMs = KIOSK_SKELETON_MIN_MS) { const elapsed = performance.now() - startedAt; const rest = minMs - elapsed; if (rest > 0) { await new Promise((resolve) => setTimeout(resolve, rest)); } } async function fadeOutSkeleton(skel) { if (!skel || prefersReducedMotion()) return; const exitClass = isGridSkeletonHost(skel) ? "kiosk-skeleton-host--exit" : skel.classList.contains("kiosk-skeleton-groups") ? "kiosk-skeleton-groups--exit" : skel.classList.contains("kiosk-skeleton-table") ? "kiosk-skeleton-table--exit" : "kiosk-skeleton-panel--exit"; skel.classList.add(exitClass); await new Promise((resolve) => { let settled = false; const finish = () => { if (settled) return; settled = true; skel.removeEventListener("transitionend", onEnd); resolve(); }; const onEnd = (event) => { if (event.target === skel && event.propertyName === "opacity") finish(); }; skel.addEventListener("transitionend", onEnd); globalThis.setTimeout(finish, KIOSK_SKELETON_EXIT_MS + 40); }); } function clearSkeletonHostAttrs(container) { if (!container) return; container.classList.remove("kiosk-skeleton-host--exit"); container.removeAttribute("aria-busy"); container.removeAttribute("aria-label"); } export async function replaceKioskContent(container, html, options = {}) { if (!container) return; const { minMs = KIOSK_SKELETON_MIN_MS, startedAt = performance.now() } = options; const skel = findSkeletonRoot(container); if (skel) { await awaitKioskSkeletonMin(startedAt, minMs); await fadeOutSkeleton(skel); } else { await awaitKioskSkeletonMin(startedAt, minMs); } container.innerHTML = html; clearSkeletonHostAttrs(container); } export function clearStaleKioskSkeleton(container) { if (!container) return; if (findSkeletonRoot(container)) { container.innerHTML = ""; clearSkeletonHostAttrs(container); } } export function mountDuplicatePanelSkeleton(recipeInfoEl, weightSectionEl) { const html = buildDuplicatePanelSkeletonHtml(); const startedAt = performance.now(); if (recipeInfoEl) { recipeInfoEl.style.display = "block"; recipeInfoEl.innerHTML = html; } if (weightSectionEl) { weightSectionEl.classList.add("kiosk-skeleton-host"); const host = weightSectionEl.querySelector(".weight-content"); if (host) { host.dataset.kioskSkeletonBackup = host.innerHTML; host.innerHTML = ``; } } return startedAt; } export function clearDuplicatePanelSkeleton(recipeInfoEl, weightSectionEl) { if (recipeInfoEl) { const skel = recipeInfoEl.querySelector(".kiosk-skeleton-panel"); if (skel) { recipeInfoEl.style.display = "none"; recipeInfoEl.innerHTML = `

Рецепт:

Компонент 0 из 0

`; } } if (weightSectionEl) { weightSectionEl.classList.remove("kiosk-skeleton-host"); const host = weightSectionEl.querySelector(".weight-content"); if (host?.dataset.kioskSkeletonBackup) { host.innerHTML = host.dataset.kioskSkeletonBackup; delete host.dataset.kioskSkeletonBackup; } } } const api = { buildGridSkeletonCards, buildDispenserGridSkeletonHtml, buildPeriodRecipeGridSkeletonHtml, buildUnloadingGroupsSkeletonHtml, buildDuplicatePanelSkeletonHtml, buildRecipeIngredientsSkeletonHtml, mountKioskSkeleton, replaceKioskContent, awaitKioskSkeletonMin, clearStaleKioskSkeleton, mountDuplicatePanelSkeleton, clearDuplicatePanelSkeleton, }; if (typeof globalThis !== "undefined") { globalThis.WespKioskSkeleton = api; }