"use client"; import { useState, useRef, useEffect, ReactNode } from "react"; import { Button } from "@/app/_components/GlobalComponents/UIElements/Button"; import { DotsThreeVerticalIcon } from "@phosphor-icons/react"; const DROPDOWN_HEIGHT = 200; interface DropdownMenuItem { label: string; icon?: ReactNode; onClick: () => void; disabled?: boolean; variant?: "default" | "destructive"; } interface DropdownMenuProps { items: DropdownMenuItem[]; triggerLabel?: string; triggerIcon?: ReactNode; triggerClassName?: string; onOpenChange?: (isOpen: boolean) => void; } export const DropdownMenu = ({ items, triggerLabel, triggerIcon = , triggerClassName = "btn-outline h-8 px-3", onOpenChange, }: DropdownMenuProps) => { const [isOpen, setIsOpen] = useState(false); const [positionAbove, setPositionAbove] = useState(false); const dropdownRef = useRef(null); const triggerRef = useRef(null); const handleOpenChange = (open: boolean) => { if (open && triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect(); const viewportHeight = window.innerHeight; const spaceBelow = viewportHeight - rect.bottom; const spaceAbove = rect.top; setPositionAbove(spaceBelow < DROPDOWN_HEIGHT && spaceAbove > spaceBelow); } setIsOpen(open); onOpenChange?.(open); }; useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { handleOpenChange(false); } }; const handleEscape = (event: KeyboardEvent) => { if (event.key === "Escape") { handleOpenChange(false); } }; if (isOpen) { document.addEventListener("mousedown", handleClickOutside); document.addEventListener("keydown", handleEscape); } return () => { document.removeEventListener("mousedown", handleClickOutside); document.removeEventListener("keydown", handleEscape); }; }, [isOpen]); const handleItemClick = (item: DropdownMenuItem) => { if (!item.disabled) { item.onClick(); handleOpenChange(false); } }; return (
{isOpen && (
{items.map((item, index) => ( ))}
)}
); };