'use client'; import styles from '@components/HoverComponentTrigger.module.css'; import * as React from 'react'; import * as Position from '@common/position'; import OutsideElementEvent from '@components/detectors/OutsideElementEvent'; import Popover from '@components/Popover'; import Tooltip from '@components/Tooltip'; import { createPortal } from 'react-dom'; interface HoverComponentTriggerProps { children: React.ReactElement>; text: string; component: 'popover' | 'tooltip'; } function HoverComponentTrigger({ children, text, component }: HoverComponentTriggerProps) { const [open, setOpen] = React.useState(false); const [placement, setPlacement] = React.useState('bottom'); const [position, setPosition] = React.useState<{ top: number; left: number }>({ top: 0, left: 0 }); const triggerRef = React.useRef(null); const popoverRef = React.useRef(null); const onMouseEnter = () => setOpen(true); const onClick = () => setOpen(true); const onHandleFocus = () => setOpen(true); const onOutsideEvent = () => setOpen(false); React.useEffect(() => { if (!open || !triggerRef.current || !popoverRef.current) return; const updatePosition = () => { const { placement, position } = Position.calculate(triggerRef.current!, popoverRef.current!); setPlacement(placement); setPosition(position); }; updatePosition(); const handleResizeOrScroll = () => updatePosition(); const mutationObserver = new MutationObserver(() => updatePosition()); mutationObserver.observe(document.body, { attributes: true, childList: true, subtree: true }); window.addEventListener('resize', handleResizeOrScroll); window.addEventListener('scroll', handleResizeOrScroll, true); return () => { window.removeEventListener('resize', handleResizeOrScroll); window.removeEventListener('scroll', handleResizeOrScroll, true); mutationObserver.disconnect(); }; }, [open]); const renderComponent = () => { if (component === 'popover') { return ( {text} ); } else if (component === 'tooltip') { return ( {text} ); } return null; }; const popoverElement = open ? createPortal({renderComponent()}, document.body) : null; return (
{React.cloneElement(children, { tabIndex: 0, } as any)} {popoverElement}
); } export default HoverComponentTrigger;