import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
// Pointer-aware hover that ignores touch — without this, Stylable's JS-toggled
// `:hovered` sticks on tap (mobile fires `mouseenter` but no `mouseleave`).
// Mouse listeners are kept for unidriver test fakes; duplicate pointer/mouse
// pairs from real browsers are deduped via WeakMap.
const POINTER_TO_MOUSE_DEDUPE_MS = 50;
const recentPointerEvents = new WeakMap();
const isHoverCapablePointer = (pointerType) => pointerType === 'mouse' || pointerType === 'pen';
const markPointerHandled = (target) => {
    if (target) {
        recentPointerEvents.set(target, Date.now());
    }
};
const recentlyHandledByPointer = (target) => {
    if (!target)
        return false;
    const at = recentPointerEvents.get(target);
    return at !== undefined && Date.now() - at < POINTER_TO_MOUSE_DEDUPE_MS;
};
export const useHover = ({ isDisabled, onHoverStart, onHoverEnd, } = {}) => {
    const [hovered, setHovered] = useState(false);
    const isHoveredRef = useRef(false);
    const onHoverStartRef = useRef(onHoverStart);
    const onHoverEndRef = useRef(onHoverEnd);
    useEffect(() => {
        onHoverStartRef.current = onHoverStart;
        onHoverEndRef.current = onHoverEnd;
    });
    const triggerHoverStart = useCallback((event) => {
        if (isHoveredRef.current)
            return;
        isHoveredRef.current = true;
        setHovered(true);
        onHoverStartRef.current?.(event);
    }, []);
    const triggerHoverEnd = useCallback((event) => {
        if (!isHoveredRef.current)
            return;
        isHoveredRef.current = false;
        setHovered(false);
        onHoverEndRef.current?.(event);
    }, []);
    useEffect(() => {
        if (isDisabled && isHoveredRef.current) {
            isHoveredRef.current = false;
            setHovered(false);
        }
    }, [isDisabled]);
    const hoverProps = useMemo(() => ({
        onPointerEnter: (event) => {
            markPointerHandled(event.currentTarget);
            if (isDisabled || !isHoverCapablePointer(event.pointerType)) {
                return;
            }
            triggerHoverStart(event);
        },
        onPointerLeave: (event) => {
            markPointerHandled(event.currentTarget);
            if (!isHoverCapablePointer(event.pointerType)) {
                return;
            }
            triggerHoverEnd(event);
        },
        onMouseEnter: (event) => {
            if (recentlyHandledByPointer(event.currentTarget))
                return;
            if (isDisabled)
                return;
            triggerHoverStart(event);
        },
        onMouseLeave: (event) => {
            if (recentlyHandledByPointer(event.currentTarget))
                return;
            triggerHoverEnd(event);
        },
    }), [isDisabled, triggerHoverStart, triggerHoverEnd]);
    return { hovered, hoverProps };
};
// Stateless variant for components that already manage hover state externally
// (e.g. per-item indices in DropdownLayout, RadarChart, FacesRatingBar).
export const createHoverHandlers = ({ isDisabled, onHoverStart, onHoverEnd, } = {}) => ({
    onPointerEnter: (event) => {
        markPointerHandled(event.currentTarget);
        if (isDisabled || !isHoverCapablePointer(event.pointerType)) {
            return;
        }
        onHoverStart?.(event);
    },
    onPointerLeave: (event) => {
        markPointerHandled(event.currentTarget);
        if (!isHoverCapablePointer(event.pointerType)) {
            return;
        }
        onHoverEnd?.(event);
    },
    onMouseEnter: (event) => {
        if (recentlyHandledByPointer(event.currentTarget))
            return;
        if (isDisabled)
            return;
        onHoverStart?.(event);
    },
    onMouseLeave: (event) => {
        if (recentlyHandledByPointer(event.currentTarget))
            return;
        onHoverEnd?.(event);
    },
});
//# sourceMappingURL=useHover.js.map