UNPKG

bootstrap-vue-next

Version:

BootstrapVueNext is an early and lovely component library for Vue 3 & Nuxt 3 based on Bootstrap 5 and Typescript.

186 lines (185 loc) 6.34 kB
import { f as useIntersectionObserver, g as useMutationObserver } from "../../../index-Cv338r2J.mjs"; import { toRef, ref, watch, getCurrentInstance, nextTick, onMounted, computed, readonly } from "vue"; import { g as getElement } from "../../../getElement-WfnRgCbF.mjs"; import { s as syncRef } from "../../../index-C4SnlHVo.mjs"; const useScrollspy = (content, target, options = {}) => { const cont = toRef(content); const tar = toRef(target); const resolvedContent = ref(getElement(cont.value)); const resolvedTarget = ref(getElement(tar.value)); watch([cont, tar], () => { updateList(); }); const { contentQuery = ":scope > [id]", targetQuery = "[href]", manual = false, root, rootMargin = "0px 0px -25%", threshold = [0.1, 0.5, 1], watchChanges = true } = options; const current = ref(null); const list = ref([]); const nodeList = ref([]); const ctx = getCurrentInstance(); if (!ctx) { nextTick(() => { updateList(); }); } else { onMounted(() => { syncRef(cont, resolvedContent, { transform: { ltr: (v) => getElement(v) }, direction: "ltr", immediate: true }); syncRef(tar, resolvedTarget, { transform: { ltr: (v) => getElement(v) }, direction: "ltr", immediate: true }); updateList(); }); } const updateList = () => { nodeList.value = resolvedContent.value ? Array.from(resolvedContent.value.querySelectorAll(contentQuery)) : []; list.value = nodeList.value.map((el) => ({ id: el.id, el, visible: false, text: el.textContent })); }; let isScrollingDown = true; let previousScrollTop = 0; const scrollRoot = computed( () => resolvedContent.value && getComputedStyle(resolvedContent.value).overflowY === "visible" ? null : resolvedContent.value ); const iobs = useIntersectionObserver( nodeList, (entries) => { var _a, _b, _c, _d; const scrollTop = (_a = scrollRoot.value || (document == null ? void 0 : document.documentElement)) == null ? void 0 : _a.scrollTop; isScrollingDown = scrollTop > previousScrollTop; previousScrollTop = scrollTop; entries.forEach((entry) => { if (entry.isIntersecting) { list.value.forEach((node) => { if (node.el === entry.target) { node.visible = true; } }); return; } list.value.forEach((node) => { if (node.el === entry.target) { node.visible = false; } }); }); let newId = null; if (isScrollingDown) { newId = ((_b = [...list.value].reverse().find((node) => node.visible)) == null ? void 0 : _b.id) || null; } else { newId = ((_c = list.value.find((node) => node.visible)) == null ? void 0 : _c.id) || null; } if (newId !== null) { current.value = newId; } if (!current.value) { current.value = ((_d = list.value[0]) == null ? void 0 : _d.id) || null; } }, { root: root ? getElement(root) : scrollRoot, rootMargin, threshold } ); watch(current, (newId) => { var _a; if (manual) return; const nodes = (_a = resolvedTarget.value) == null ? void 0 : _a.querySelectorAll(targetQuery); if (nodes === void 0) return; let foundParent = false; let activeElement = null; nodes.forEach((node) => { var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k; const parentDropdown = node.closest(".dropdown"); if ((_a2 = node.getAttribute("href")) == null ? void 0 : _a2.includes(`#${newId}`)) { activeElement = node; node.classList.add("active"); if (parentDropdown) { (_b = parentDropdown == null ? void 0 : parentDropdown.querySelector(".dropdown-toggle")) == null ? void 0 : _b.classList.add("active"); foundParent = true; } let parentNav = (_c = node.closest(".nav")) == null ? void 0 : _c.previousSibling; while ((_d = parentNav == null ? void 0 : parentNav.classList) == null ? void 0 : _d.contains("nav-item")) { foundParent = true; (_e = parentNav.querySelector(".nav-link")) == null ? void 0 : _e.classList.add("active"); parentNav = (_f = parentNav.closest(".nav")) == null ? void 0 : _f.previousSibling; } } else { node.classList.remove("active"); if (parentDropdown && !foundParent) { (_g = parentDropdown == null ? void 0 : parentDropdown.querySelector(".dropdown-toggle")) == null ? void 0 : _g.classList.remove("active"); } if (!foundParent) { let parentNav = (_h = node.closest(".nav")) == null ? void 0 : _h.previousSibling; while ((_i = parentNav == null ? void 0 : parentNav.classList) == null ? void 0 : _i.contains("nav-item")) { foundParent = true; if (parentNav.querySelector(".nav-link") !== activeElement) { (_j = parentNav.querySelector(".nav-link")) == null ? void 0 : _j.classList.remove("active"); } parentNav = (_k = parentNav.closest(".nav")) == null ? void 0 : _k.previousSibling; } } } }); }); const mobs = !watchChanges ? { stop: () => { } } : useMutationObserver( resolvedContent, () => { updateList(); }, { childList: true } ); const scrollIntoView = (event, smooth = false) => { var _a, _b; event.preventDefault(); const href = (_b = (_a = event.target) == null ? void 0 : _a.getAttribute) == null ? void 0 : _b.call(_a, "href"); const el = href ? document == null ? void 0 : document.querySelector(href) : null; if (el && resolvedContent.value) { if (resolvedContent.value.scrollTo) { resolvedContent.value.scrollTo({ top: el.offsetTop, behavior: smooth ? "smooth" : "auto" }); } else { resolvedContent.value.scrollTop = el.offsetTop; } } }; const cleanup = () => { iobs.stop(); mobs.stop(); }; return { current: readonly(current), list, content: resolvedContent, target: resolvedTarget, scrollIntoView, updateList, cleanup }; }; export { useScrollspy }; //# sourceMappingURL=index.mjs.map