@re-flex/ui
Version:
Re-Flex ui library
55 lines (54 loc) • 2.07 kB
JavaScript
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;