"use client";
import { useCallback, useRef, useState } from "react";
import { useIntersectionObserver } from "../useIntersectionObserver.js";
import { parseCssLengthUnit } from "../utils/parseCssLengthUnit.js";
/**
 * @defaultValue `[0.0, 1.0]`
 * @since 6.0.0
 */ export const DEFAULT_ACTIVE_HEADING_THRESHOLD = [
    0.0,
    1.0
];
/**
 * ```tsx
 * const headerHeightVar = window
 *   .getComputedStyle(document.documentElement)
 *   .getPropertyValue("--rmd-layout-header-height");
 * const headerHeight = parseCssLengthUnit({
 *   value: headerHeightVar || "3.5rem",
 * });

 * return `-${headerHeight}px 0px 0px 0px`;
 * ```
 * @since 6.0.0
 */ export const DEFAULT_ACTIVE_HEADING_GET_ROOT_MARGIN = ()=>{
    const headerHeightVar = window.getComputedStyle(document.documentElement).getPropertyValue("--rmd-layout-header-height");
    const headerHeight = parseCssLengthUnit({
        value: headerHeightVar || "3.5rem"
    });
    return `-${headerHeight}px 0px 0px 0px`;
};
/**
 * @internal
 * @since 6.0.0
 */ function getHeadingElements(items) {
    const headings = [];
    items.forEach((item)=>{
        const heading = document.getElementById(item.id);
        if (heading) {
            headings.push(heading);
        }
        if (item.items) {
            headings.push(...getHeadingElements(item.items));
        }
    });
    return headings;
}
/**
 * @internal
 * @since 6.0.0
 */ function getLastHeadingId(items) {
    const last = items.at(-1);
    if (!last) {
        return "";
    }
    if (last.items) {
        return getLastHeadingId(last.items);
    }
    return last.id;
}
/**
 * @internal
 * @since 6.0.0
 */ const isScrolledNearPageBottom = (threshold)=>window.scrollY >= document.documentElement.scrollHeight * threshold;
/**
 * This is heavily inspired by:
 * @see https://github.com/mdn/yari/blob/231d6aab8f1c8efe159d268c261446c5b7ae12d9/client/src/document/hooks.ts#L171
 *
 * @see {@link https://react-md.dev/hooks/use-active-heading-id | useActiveHeadingId Demos}
 * @since 6.0.0
 */ export function useActiveHeadingId(options) {
    const { headings, threshold = DEFAULT_ACTIVE_HEADING_THRESHOLD, getRootMargin = DEFAULT_ACTIVE_HEADING_GET_ROOT_MARGIN, defaultActiveId = headings[0]?.id ?? "", scrollBottomThreshold = 0.8 } = options;
    const elements = useRef();
    const isFirstRender = useRef(true);
    const [activeHeadingId, setActiveHeadingId] = useState(defaultActiveId);
    useIntersectionObserver({
        threshold,
        getRootMargin,
        getTargets: useCallback(()=>{
            const headingElements = getHeadingElements(headings);
            const lookup = new Map();
            headingElements.forEach((heading)=>{
                lookup.set(heading.id, false);
            });
            elements.current = lookup;
            return headingElements;
        }, [
            headings
        ]),
        onUpdate: useCallback((entries)=>{
            const lookup = elements.current;
            if (!lookup) {
                return;
            }
            entries.forEach((entry)=>{
                lookup.set(entry.target.id, entry.isIntersecting);
            });
            // get the first visible/intersecting item and set it
            let foundId = [
                ...lookup.entries()
            ].find(([_id, isIntersecting])=>isIntersecting)?.[0];
            if (!foundId && isFirstRender.current && isScrolledNearPageBottom(scrollBottomThreshold)) {
                foundId = getLastHeadingId(headings);
            }
            isFirstRender.current = false;
            // if there isn't a found id, it might be a really large section where
            // another heading isn't visible, so maintain the previous one
            if (foundId) {
                setActiveHeadingId(foundId);
            }
        }, [
            headings,
            scrollBottomThreshold
        ])
    });
    return activeHeadingId;
}

//# sourceMappingURL=useActiveHeadingId.js.map