UNPKG

nuxt-anchorscroll

Version:
95 lines (94 loc) 3.1 kB
import { toValue } from "vue"; import { defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from "nuxt/app"; const generalAnchorScroll = ({ hash }) => { const scrollVariants = { toTop: { scrollOptions: toValue(useNuxtApp().$anchorScroll?.defaults.toTop) || {} } }; if (hash !== "") { try { const target = document.querySelector(hash); if (!target) { console.error(`[AnchorScroll]: unable to find element with selector '${hash}'`); return scrollVariants; } scrollVariants.toAnchor = { target, scrollOptions: toValue(useNuxtApp().$anchorScroll?.defaults.toAnchor) ?? {} }; } catch (error) { console.error(`[AnchorScroll]: unable to get element for selector '${hash}':`, error); } } return scrollVariants; }; const anchorScrollExecutor = (hook) => { const nuxtApp = useNuxtApp(); const currentRoute = nuxtApp.$router.currentRoute; const disableAnchorScroll = currentRoute.value.meta.disableAnchorScroll ?? {}; const { toAnchor: disableToAnchor = false, toTop: disableToTop = false } = disableAnchorScroll === true ? { toAnchor: true, toTop: true } : disableAnchorScroll; if (disableToAnchor && disableToTop) return; const allMatched = [...nuxtApp?.$anchorScroll?.matched ?? [], generalAnchorScroll]; for (const matched of allMatched) { const maybeAnchorScrollAlternatives = matched(currentRoute.value, hook); if (maybeAnchorScrollAlternatives === false) return; const { toAnchor, toTop } = maybeAnchorScrollAlternatives ?? {}; if (!disableToAnchor && toAnchor) { const { target, scrollOptions: { behavior, offsetLeft, offsetTop }, surfaces = toValue(nuxtApp.$anchorScroll?.defaults.surfaces) ?? [] } = toAnchor; const { top, left } = target.getBoundingClientRect(); const scrollToAnchorOptions = { behavior, ...offsetLeft !== void 0 && { left: left + offsetLeft }, ...offsetTop !== void 0 && { top: top + offsetTop } }; for (const surface of surfaces) surface.scrollBy(scrollToAnchorOptions); return; } if (!disableToTop && toTop) { const { scrollOptions: { behavior, offsetLeft, offsetTop }, surfaces = toValue(nuxtApp.$anchorScroll?.defaults.surfaces) ?? [] } = toTop; const scrollToTopOptions = { behavior, left: offsetLeft, top: offsetTop }; for (const surface of surfaces) surface.scrollTo(scrollToTopOptions); } } }; export default defineNuxtPlugin((nuxtApp) => { const { hooks = [] } = useRuntimeConfig().public.anchorScroll ?? {}; useNuxtApp().$anchorScroll = { matched: [], general: generalAnchorScroll, defaults: { toAnchor: { behavior: "smooth", offsetTop: 0 }, toTop: { behavior: "instant", offsetTop: 0 }, surfaces: () => [document.documentElement, document.body] } }; for (const hook of hooks) nuxtApp.hook(hook, () => anchorScrollExecutor(hook)); });