UNPKG

@re-flex/ui

Version:
55 lines (54 loc) 2.07 kB
import { autoPlacement, getScrollParents, shift, useFloating, } from "@floating-ui/react-dom"; import { useCallback } from "react"; import useIsomorphicEffect from "./useIsomorphicEffect"; const usePopper = ({ placement, modifiers, anchor, onClickAway, open, }) => { const { x, y, reference, floating, strategy, update, refs } = useFloating({ placement: placement, middleware: [shift(), autoPlacement(), ...modifiers], strategy: "fixed", }); useIsomorphicEffect(() => { if (!!anchor) { reference(anchor); } }, [anchor]); useIsomorphicEffect(() => { if (!refs.reference.current || !refs.floating.current) { return; } const parents = [ ...getScrollParents(refs.reference.current), ...getScrollParents(refs.floating.current), ]; parents.forEach((parent) => { parent.addEventListener("scroll", update); parent.addEventListener("resize", update); }); return () => { parents.forEach((parent) => { parent.removeEventListener("scroll", update); parent.removeEventListener("resize", update); }); }; }, [refs.reference, refs.floating, update]); const handleEvents = useCallback((event) => { const anchor = refs.floating.current; if (!anchor) return; if (open === true && !anchor?.contains(event.target)) { onClickAway(event); } }, [refs.floating, open]); useIsomorphicEffect(() => { if (open) { document.addEventListener("mousedown", handleEvents); document.addEventListener("touchmove", handleEvents); return () => { document.removeEventListener("mousedown", handleEvents); document.removeEventListener("touchmove", handleEvents); }; } }, [refs.floating, open]); return { x, y, reference, floating, strategy, update, refs }; }; export default usePopper;