UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

68 lines (67 loc) 2.18 kB
"use client"; import { randomId } from "../utils/random-id/random-id.mjs"; import { useEffect, useRef, useState } from "react"; //#region packages/@mantine/hooks/src/use-scroll-spy/use-scroll-spy.ts function getHeadingsData(headings, getDepth, getValue) { const result = []; for (let i = 0; i < headings.length; i += 1) { const heading = headings[i]; result.push({ depth: getDepth(heading), value: getValue(heading), id: heading.id || randomId(), getNode: () => heading.id ? document.getElementById(heading.id) : heading }); } return result; } function getActiveElement(rects, offset = 0) { if (rects.length === 0) return -1; return rects.reduce((acc, item, index) => { if (Math.abs(acc.position - offset) < Math.abs(item.y - offset)) return acc; return { index, position: item.y }; }, { index: 0, position: rects[0].y }).index; } function getDefaultDepth(element) { return Number(element.tagName[1]); } function getDefaultValue(element) { return element.textContent || ""; } function useScrollSpy({ selector = "h1, h2, h3, h4, h5, h6", getDepth = getDefaultDepth, getValue = getDefaultValue, offset = 0, scrollHost } = {}) { const [active, setActive] = useState(-1); const [initialized, setInitialized] = useState(false); const [data, setData] = useState([]); const headingsRef = useRef([]); const handleScroll = () => { setActive(getActiveElement(headingsRef.current.map((d) => d.getNode().getBoundingClientRect()), offset)); }; const initialize = () => { const headings = getHeadingsData(Array.from(document.querySelectorAll(selector)), getDepth, getValue); headingsRef.current = headings; setInitialized(true); setData(headings); setActive(getActiveElement(headings.map((d) => d.getNode().getBoundingClientRect()), offset)); }; useEffect(() => { initialize(); const _scrollHost = scrollHost || window; _scrollHost.addEventListener("scroll", handleScroll); return () => _scrollHost.removeEventListener("scroll", handleScroll); }, [scrollHost]); return { reinitialize: initialize, active, initialized, data }; } //#endregion export { useScrollSpy }; //# sourceMappingURL=use-scroll-spy.mjs.map