72 lines
2.3 KiB
JavaScript
72 lines
2.3 KiB
JavaScript
import { START_LOCATION } from "vue-router";
|
|
import { useNuxtApp } from "#app/nuxt";
|
|
import { isChangingPage } from "#app/components/utils";
|
|
import { useRouter } from "#app/composables/router";
|
|
export default {
|
|
scrollBehavior(to, from, savedPosition) {
|
|
const nuxtApp = useNuxtApp();
|
|
const router = useRouter();
|
|
const hashScrollBehaviour = router.options?.scrollBehaviorType ?? "auto";
|
|
if (to.path.replace(/\/$/, "") === from.path.replace(/\/$/, "")) {
|
|
if (from.hash && !to.hash) {
|
|
return { left: 0, top: 0 };
|
|
}
|
|
if (to.hash) {
|
|
return { el: to.hash, top: _getHashElementScrollMarginTop(to.hash), behavior: hashScrollBehaviour };
|
|
}
|
|
return false;
|
|
}
|
|
const routeAllowsScrollToTop = typeof to.meta.scrollToTop === "function" ? to.meta.scrollToTop(to, from) : to.meta.scrollToTop;
|
|
if (routeAllowsScrollToTop === false) {
|
|
return false;
|
|
}
|
|
if (from === START_LOCATION) {
|
|
return _calculatePosition(to, from, savedPosition, hashScrollBehaviour);
|
|
}
|
|
return new Promise((resolve) => {
|
|
const doScroll = () => {
|
|
requestAnimationFrame(() => {
|
|
if (router.currentRoute.value.fullPath !== to.fullPath) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
resolve(_calculatePosition(to, from, savedPosition, hashScrollBehaviour));
|
|
});
|
|
};
|
|
nuxtApp.hooks.hookOnce("page:loading:end", () => {
|
|
const transitionPromise = nuxtApp["~transitionPromise"];
|
|
if (transitionPromise) {
|
|
transitionPromise.then(doScroll);
|
|
} else {
|
|
doScroll();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
};
|
|
function _getHashElementScrollMarginTop(selector) {
|
|
try {
|
|
const elem = document.querySelector(selector);
|
|
if (elem) {
|
|
return (Number.parseFloat(getComputedStyle(elem).scrollMarginTop) || 0) + (Number.parseFloat(getComputedStyle(document.documentElement).scrollPaddingTop) || 0);
|
|
}
|
|
} catch {
|
|
}
|
|
return 0;
|
|
}
|
|
function _calculatePosition(to, from, savedPosition, defaultHashScrollBehaviour) {
|
|
if (savedPosition) {
|
|
return savedPosition;
|
|
}
|
|
if (to.hash) {
|
|
return {
|
|
el: to.hash,
|
|
top: _getHashElementScrollMarginTop(to.hash),
|
|
behavior: isChangingPage(to, from) ? defaultHashScrollBehaviour : "instant"
|
|
};
|
|
}
|
|
return {
|
|
left: 0,
|
|
top: 0
|
|
};
|
|
}
|