import React from 'react'; import ReactDOM from 'react-dom'; type DropdownMenuProps = { name: string; options: { label: string; value: string }[]; onSelect: (value: string) => void; defaultValue?: string; icon?: string; isOpen: boolean; onOpenChange: (isOpen: boolean) => void; anchorRef: React.RefObject; position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'; offset?: { x: number; y: number }; className?: string; }; export default function DropdownMenu({ name, options, onSelect, defaultValue = 'none', icon, isOpen: controlledIsOpen, onOpenChange, anchorRef, className = '', position = 'bottom-right', offset = { x: 0, y: 8 }, }: DropdownMenuProps) { const dropdownRef = React.useRef(null); const [internalIsOpen, setInternalIsOpen] = React.useState(false); const [selectedOption, setSelectedOption] = React.useState( options.find((option) => option.value === defaultValue) || options[0], ); const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen; const setIsOpen = onOpenChange || setInternalIsOpen; const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) && !anchorRef?.current?.contains(event.target as Node) ) { setIsOpen(false); } }; const handleClickOption = (optionId: number) => { setIsOpen(false); setSelectedOption(options[optionId]); onSelect(options[optionId].value); }; React.useEffect(() => { if (isOpen) { document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); } }, [isOpen]); if (!isOpen) return null; const getMenuPosition = (): React.CSSProperties => { if (!anchorRef?.current) return {}; const rect = anchorRef.current.getBoundingClientRect(); const top = rect.bottom + offset.y; const left = rect.right + offset.x; return { position: 'fixed', top: `${top}px`, left: `${left}px`, zIndex: 9999, }; }; // Use a portal to render the dropdown outside the table flow return ReactDOM.createPortal(
e.stopPropagation()} >
{options.map((option, idx) => ( ))}
, document.body, ); }