@mantine/hooks
Version: 
A collection of 50+ hooks for state and UI management
95 lines (91 loc) • 2.4 kB
JavaScript
'use client';
;
var React = require('react');
var randomId = require('../utils/random-id/random-id.cjs');
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.randomId(),
      getNode: () => heading.id ? document.getElementById(heading.id) : heading
    });
  }
  return result;
}
function getActiveElement(rects, offset = 0) {
  if (rects.length === 0) {
    return -1;
  }
  const closest = 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 }
  );
  return closest.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] = React.useState(-1);
  const [initialized, setInitialized] = React.useState(false);
  const [data, setData] = React.useState([]);
  const headingsRef = React.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
      )
    );
  };
  React.useEffect(() => {
    initialize();
    const _scrollHost = scrollHost || window;
    _scrollHost.addEventListener("scroll", handleScroll);
    return () => _scrollHost.removeEventListener("scroll", handleScroll);
  }, [scrollHost]);
  return {
    reinitialize: initialize,
    active,
    initialized,
    data
  };
}
exports.useScrollSpy = useScrollSpy;
//# sourceMappingURL=use-scroll-spy.cjs.map