import { useEffect } from 'react';
import { css } from 'styled-components';
import { isInstance } from '../utils';
function* getTextNodes(rootNode) {
    const walker = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT);
    let node = walker.nextNode();
    while (node !== null) {
        if (isInstance(node, Text))
            yield node;
        node = walker.nextNode();
    }
}
export const HIGHLIGHT_NAME = 'search-highlight';
export const createHighlightStyles = (theme) => css `
  ::highlight(${HIGHLIGHT_NAME}) {
    color: ${theme.base.colors.black};
    background-color: ${theme.components.mark['background-color']};
    font-weight: ${theme.components.mark['font-weight']};
  }
`;
// Single shared Highlight instance — each hook call adds/removes its own ranges.
const sharedHighlight = new Highlight();
/**
 * @example useHighlight(ref, /search/gi);
 * @param ref - A ref to the DOM element whose text nodes should be searched.
 * @param pattern - A RegExp to match against text content. Ranges for each match are highlighted.
 */
const useHighlight = (ref, pattern) => {
    const source = pattern?.source;
    const flags = pattern?.flags;
    useEffect(() => {
        if (!source || !ref.current || !CSS.highlights)
            return;
        CSS.highlights.set(HIGHLIGHT_NAME, sharedHighlight);
        const ranges = [];
        const effectiveFlags = flags ?? '';
        const globalPattern = new RegExp(source, effectiveFlags.includes('g') ? effectiveFlags : `${effectiveFlags}g`);
        for (const textNode of getTextNodes(ref.current)) {
            for (const match of (textNode.textContent ?? '').matchAll(globalPattern)) {
                const range = new Range();
                range.setStart(textNode, match.index);
                range.setEnd(textNode, match.index + match[0].length);
                ranges.push(range);
                sharedHighlight.add(range);
            }
        }
        return () => {
            for (const range of ranges) {
                sharedHighlight.delete(range);
            }
        };
    }, [source, flags]);
};
export default useHighlight;
//# sourceMappingURL=useHighlight.js.map