since3-website/modules/shared/lib/intro.ts
2026-09-25 00:45:33 +02:00

25 lines
1.2 KiB
TypeScript

// Shared contract between the inline intro script, the preloader and
// everything that waits for the intro to finish (smooth scroll, hero shader).
export const INTRO_CLASS = "is-intro"
export const INTRO_END_EVENT = "since3:intro-end"
export const INTRO_STORAGE_KEY = "since3:intro-seen"
// Runs synchronously before the first paint. Plays the intro once per session
// and never for people who prefer reduced motion. The timeout is a failsafe in
// case the JavaScript bundle never arrives.
export const introScript = `(function(){try{var d=document.documentElement;if(!sessionStorage.getItem("${INTRO_STORAGE_KEY}")&&!matchMedia("(prefers-reduced-motion: reduce)").matches){d.classList.add("${INTRO_CLASS}");setTimeout(function(){d.classList.remove("${INTRO_CLASS}")},8000)}}catch(e){}})()`
export function isIntroRunning() {
return document.documentElement.classList.contains(INTRO_CLASS)
}
/** Calls `callback` once the intro is over (immediately if there is none). */
export function onIntroEnd(callback: () => void) {
if (!isIntroRunning()) {
callback()
return () => {}
}
window.addEventListener(INTRO_END_EVENT, callback, { once: true })
return () => window.removeEventListener(INTRO_END_EVENT, callback)
}