nuxt-anchorscroll
Version:
Scroll with anchor support for Nuxt
72 lines (71 loc) • 3.05 kB
JavaScript
import { computed, toValue } from "vue";
import { useNuxtApp } from "nuxt/app";
export const useAnchorScroll = (options = {}) => {
const toAnchorSurfaces = computed(() => {
const unwrappedOptions = toValue(options);
return unwrappedOptions?.surfaces ?? unwrappedOptions?.toAnchor?.surfaces ?? toValue(useNuxtApp().$anchorScroll?.defaults.surfaces) ?? [];
});
const toAnchorScrollOptions = computed(() => {
const unwrappedOptions = toValue(options);
return unwrappedOptions?.scrollOptions ?? unwrappedOptions?.toAnchor?.scrollOptions ?? toValue(useNuxtApp().$anchorScroll?.defaults?.toAnchor);
});
const toTopSurfaces = computed(() => {
const unwrappedOptions = toValue(options);
return unwrappedOptions?.surfaces ?? unwrappedOptions?.toTop?.surfaces ?? toValue(useNuxtApp().$anchorScroll?.defaults.surfaces) ?? [];
});
const toTopScrollOptions = computed(() => {
const unwrappedOptions = toValue(options);
return unwrappedOptions?.scrollOptions ?? unwrappedOptions?.toTop?.scrollOptions ?? toValue(useNuxtApp().$anchorScroll?.defaults?.toTop);
});
return {
scrollToAnchor(target) {
const maybeElement = toValue(target);
let anchorElement = null;
if (typeof maybeElement === "string") {
anchorElement = document.getElementById(maybeElement.replace(/^#/, ""));
} else if (maybeElement instanceof HTMLElement) {
anchorElement = maybeElement;
} else {
const elementId = toValue(maybeElement.id);
const elementSelector = toValue(maybeElement.sr);
if (elementId) {
anchorElement = document.getElementById(elementId.replace(/^#/, ""));
} else if (elementSelector) {
try {
anchorElement = document.querySelector(elementSelector);
} catch (error) {
console.error("[useAnchorScroll]: While select element from document, next error occurred:", error);
}
} else {
console.error(
"[useAnchorScroll]: Wrong object provided to scrollToAnchor composable:",
"either 'id' and 'sr' (selector) are not provided in object",
maybeElement
);
}
}
if (!anchorElement)
return false;
const { top, left } = anchorElement.getBoundingClientRect();
const { behavior, offsetLeft, offsetTop } = toValue(toAnchorScrollOptions) ?? {};
const scrollToAnchorOptions = {
behavior,
...offsetLeft !== void 0 && { left: left + offsetLeft },
...offsetTop !== void 0 && { top: top + offsetTop }
};
for (const surface of toValue(toAnchorSurfaces))
surface.scrollBy(scrollToAnchorOptions);
return true;
},
scrollToTop() {
const { behavior, offsetLeft, offsetTop } = toValue(toTopScrollOptions) ?? {};
const scrollToTopOptions = {
behavior,
left: offsetLeft,
top: offsetTop
};
for (const surface of toValue(toTopSurfaces))
surface.scrollTo(scrollToTopOptions);
}
};
};