UNPKG

nuxt

Version:

Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.

83 lines (82 loc) 3.22 kB
import { defineNuxtPlugin } from "../nuxt.js"; import { useRouter } from "../composables/router.js"; import { isChangingPage } from "../components/utils.js"; import { appViewTransition } from "#build/nuxt.config.mjs"; //#region src/app/plugins/view-transitions.client.ts const plugin = /* @__PURE__ */ defineNuxtPlugin((nuxtApp) => { if (!document.startViewTransition) return; let transition; let hasUAVisualTransition = false; let finishTransition; let abortTransition; const resetTransitionState = () => { transition = void 0; hasUAVisualTransition = false; abortTransition = void 0; finishTransition = void 0; }; window.addEventListener("popstate", (event) => { hasUAVisualTransition = event.hasUAVisualTransition; if (hasUAVisualTransition) transition?.skipTransition(); }); const router = useRouter(); const normalizeViewTransitionOptions = (value) => { if (typeof value === "boolean" || value === "always") return { enabled: value }; if (value && typeof value === "object") return value; return {}; }; router.beforeResolve(async (to, from) => { if (to.matched.length === 0) return; const toViewTransitionOptions = normalizeViewTransitionOptions(to.meta.viewTransition); const fromViewTransitionOptions = normalizeViewTransitionOptions(from.meta.viewTransition); const viewTransitionMode = toViewTransitionOptions.enabled ?? appViewTransition.enabled; const prefersNoTransition = window.matchMedia("(prefers-reduced-motion: reduce)").matches && viewTransitionMode !== "always"; if (viewTransitionMode === false || prefersNoTransition || hasUAVisualTransition || !isChangingPage(to, from)) return; const resolveViewTransitionTypes = (types) => { return types ? typeof types === "function" ? types(to, from) : types : void 0; }; const viewTransitionBaseTypes = resolveViewTransitionTypes(toViewTransitionOptions.types) ?? resolveViewTransitionTypes(appViewTransition.types) ?? []; const viewTransitionFromTypes = resolveViewTransitionTypes(fromViewTransitionOptions.fromTypes) ?? []; const viewTransitionToTypes = resolveViewTransitionTypes(toViewTransitionOptions.toTypes) ?? []; const allTypes = [ ...viewTransitionBaseTypes, ...viewTransitionFromTypes, ...viewTransitionToTypes ]; const promise = new Promise((resolve, reject) => { finishTransition = resolve; abortTransition = reject; }); let changeRoute; const ready = new Promise((resolve) => changeRoute = resolve); const update = () => { changeRoute(); return promise; }; transition = allTypes.length > 0 ? document.startViewTransition({ update, types: allTypes }) : document.startViewTransition(update); transition.finished.catch(() => {}).finally(resetTransitionState); await nuxtApp.callHook("page:view-transition:start", transition); return ready; }); router.onError(() => { abortTransition?.(); resetTransitionState(); }); nuxtApp.hook("app:error", () => { abortTransition?.(); resetTransitionState(); }); nuxtApp.hook("vue:error", () => { abortTransition?.(); resetTransitionState(); }); nuxtApp.hook("page:finish", () => { finishTransition?.(); resetTransitionState(); }); }); //#endregion export { plugin as default };