UNPKG

@ariakit/react-core

Version:

Ariakit React core

125 lines (122 loc) 3.71 kB
"use client"; import { useCompositeContext } from "./APTFW6PT.js"; import { createElement, createHook, forwardRef, memo } from "./VOQWLFSQ.js"; import { useBooleanEvent, useEvent, useIsMouseMoving, useMergeRefs } from "./5GGHRIN3.js"; import { __objRest, __spreadProps, __spreadValues } from "./3YLGPPWQ.js"; // src/composite/composite-hover.tsx import { contains } from "@ariakit/core/utils/dom"; import { hasFocus, hasFocusWithin } from "@ariakit/core/utils/focus"; import { hasOwnProperty, invariant, removeUndefinedValues } from "@ariakit/core/utils/misc"; import { useCallback } from "react"; var TagName = "div"; function getMouseDestination(event) { const relatedTarget = event.relatedTarget; if ((relatedTarget == null ? void 0 : relatedTarget.nodeType) === Node.ELEMENT_NODE) { return relatedTarget; } return null; } function hoveringInside(event) { const nextElement = getMouseDestination(event); if (!nextElement) return false; return contains(event.currentTarget, nextElement); } var symbol = Symbol("composite-hover"); function movingToAnotherItem(event) { let dest = getMouseDestination(event); if (!dest) return false; do { if (hasOwnProperty(dest, symbol) && dest[symbol]) return true; dest = dest.parentElement; } while (dest); return false; } var useCompositeHover = createHook( function useCompositeHover2(_a) { var _b = _a, { store, focusOnHover = true, blurOnHoverEnd = !!focusOnHover } = _b, props = __objRest(_b, [ "store", "focusOnHover", "blurOnHoverEnd" ]); const context = useCompositeContext(); store = store || context; invariant( store, process.env.NODE_ENV !== "production" && "CompositeHover must be wrapped in a Composite component." ); const isMouseMoving = useIsMouseMoving(); const onMouseMoveProp = props.onMouseMove; const focusOnHoverProp = useBooleanEvent(focusOnHover); const onMouseMove = useEvent((event) => { onMouseMoveProp == null ? void 0 : onMouseMoveProp(event); if (event.defaultPrevented) return; if (!isMouseMoving()) return; if (!focusOnHoverProp(event)) return; if (!hasFocusWithin(event.currentTarget)) { const baseElement = store == null ? void 0 : store.getState().baseElement; if (baseElement && !hasFocus(baseElement)) { baseElement.focus(); } } store == null ? void 0 : store.setActiveId(event.currentTarget.id); }); const onMouseLeaveProp = props.onMouseLeave; const blurOnHoverEndProp = useBooleanEvent(blurOnHoverEnd); const onMouseLeave = useEvent((event) => { var _a2; onMouseLeaveProp == null ? void 0 : onMouseLeaveProp(event); if (event.defaultPrevented) return; if (!isMouseMoving()) return; if (hoveringInside(event)) return; if (movingToAnotherItem(event)) return; if (!focusOnHoverProp(event)) return; if (!blurOnHoverEndProp(event)) return; store == null ? void 0 : store.setActiveId(null); (_a2 = store == null ? void 0 : store.getState().baseElement) == null ? void 0 : _a2.focus(); }); const ref = useCallback((element) => { if (!element) return; element[symbol] = true; }, []); props = __spreadProps(__spreadValues({}, props), { ref: useMergeRefs(ref, props.ref), onMouseMove, onMouseLeave }); return removeUndefinedValues(props); } ); var CompositeHover = memo( forwardRef(function CompositeHover2(props) { const htmlProps = useCompositeHover(props); return createElement(TagName, htmlProps); }) ); export { useCompositeHover, CompositeHover };