UNPKG

wix-style-react

Version:
78 lines 3.06 kB
import { useEffect, useState, useCallback, useRef, Children } from 'react'; export const usePopoverState = ({ scrollAreaRef, disabled, isMenuOpen, ...rest }) => { const children = Children.toArray(rest.children); const popoverContentRef = useRef(null); const [moveBy, setMoveBy] = useState({ y: 0 }); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [isMouseOver, setIsMouseOver] = useState(false); useEffect(() => { const onSidebarScroll = () => !isPopoverOpen && setMoveBy({ y: 0 }); const scrollArea = scrollAreaRef && scrollAreaRef.current; if (scrollArea) { scrollArea && scrollArea.addEventListener('scroll', onSidebarScroll); window.addEventListener('scroll', onSidebarScroll); } return () => { scrollArea && scrollArea.removeEventListener('scroll', onSidebarScroll); window.removeEventListener('scroll', onSidebarScroll); }; // TODO: fix ESLint error // eslint-disable-next-line react-hooks/exhaustive-deps }, [scrollAreaRef]); const calculateMoveBy = useCallback(() => { const rect = popoverContentRef && popoverContentRef.current && popoverContentRef.current.getBoundingClientRect(); if (!rect) return 0; const margin = 12; const popoverPaddings = 2 * 12; const screenHeight = window.innerHeight; const { top } = rect; const height = rect.height + popoverPaddings; const isPopoverOffsetToTop = top <= margin; const popoverTopValue = -(top - popoverPaddings - margin); const isPopoverOffsetToBottom = top + height > screenHeight; const popoverBottomValue = screenHeight - top - height - margin; if (isPopoverOffsetToTop) { return popoverTopValue; } if (isPopoverOffsetToBottom) { return popoverBottomValue; } return 0; }, [popoverContentRef]); useEffect(() => { let timeout; if (isPopoverOpen) { timeout = setTimeout(() => { setMoveBy({ y: moveBy.y || calculateMoveBy() }); }, 200); } return () => { clearTimeout(timeout); }; }, [isPopoverOpen, calculateMoveBy, moveBy.y]); useEffect(() => { if (!isMouseOver) { return; } setIsPopoverOpen(!isMenuOpen); }, [isMenuOpen, isMouseOver]); const onOpen = useCallback(() => { if (disabled || !children || !children.length) return; if (!isMenuOpen) { setIsPopoverOpen(true); } setIsMouseOver(true); // TODO: fix ESLint error // eslint-disable-next-line react-hooks/exhaustive-deps }, [disabled, isMenuOpen]); const onClose = () => { setIsPopoverOpen(false); setIsMouseOver(false); }; return { moveBy, popoverContentRef, isPopoverOpen, onOpen, onClose }; }; //# sourceMappingURL=usePopoverState.js.map