import clsx from 'clsx'; import { Position } from '@/utils/sel'; import { useEffect, useRef, useState } from 'react'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { useKeyDownActions } from '@/hooks/useKeyDownActions'; const Popup = ({ width, height, minHeight, maxHeight, position, trianglePosition, children, className = '', triangleClassName = '', additionalStyle = {}, isOpen = true, onDismiss, }: { isOpen?: boolean; width: number; height?: number; minHeight?: number; maxHeight?: number; position?: Position; trianglePosition?: Position; children: React.ReactNode; className?: string; triangleClassName?: string; additionalStyle?: React.CSSProperties; onDismiss?: () => void; }) => { const containerRef = useRef(null); const [adjustedPosition, setAdjustedPosition] = useState(position); const [childrenHeight, setChildrenHeight] = useState(height || minHeight || 0); useKeyDownActions({ onCancel: onDismiss, elementRef: containerRef, enabled: isOpen }); const popupPadding = useResponsiveSize(10); let availableHeight = window.innerHeight - 2 * popupPadding; if (trianglePosition?.dir === 'up') { availableHeight = trianglePosition.point.y - popupPadding; } else if (trianglePosition?.dir === 'down') { availableHeight = window.innerHeight - trianglePosition.point.y - popupPadding; } maxHeight = Math.min(maxHeight || availableHeight, availableHeight); if (minHeight) { minHeight = Math.min(minHeight, availableHeight); } useEffect(() => { if (!containerRef.current) return; const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { const newHeight = entry.contentRect.height; if (newHeight !== childrenHeight) { setChildrenHeight(newHeight); return; } } }); resizeObserver.observe(containerRef.current); return () => { resizeObserver.disconnect(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (!containerRef.current) return; if (!position || !trianglePosition || position.dir !== 'up') { setAdjustedPosition(position); return; } const containerHeight = childrenHeight || containerRef.current.offsetHeight; const newPosition = { ...position, point: { ...position.point, y: trianglePosition.point.y - containerHeight, }, }; setAdjustedPosition(newPosition); }, [position, trianglePosition, childrenHeight]); return (
); }; export default Popup;