import { useState, useRef, useEffect, createContext, useContext, ReactNode } from "react"; import { cn } from "../utils/cn.ts"; interface DropdownContextValue { isOpen: boolean; setIsOpen: (isOpen: boolean) => void; } const DropdownContext = createContext(null); function useDropdownContext() { const context = useContext(DropdownContext); if (!context) { throw new Error("Dropdown components must be used within a Dropdown"); } return context; } interface DropdownProps { children: ReactNode; } function DropdownRoot({ children }: DropdownProps) { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; if (isOpen) { document.addEventListener("mousedown", handleClickOutside); } return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [isOpen]); return (
{children}
); } interface DropdownTriggerProps { children: ReactNode; className?: string; } function DropdownTrigger({ children, className }: DropdownTriggerProps) { const { isOpen, setIsOpen } = useDropdownContext(); return (
setIsOpen(!isOpen)} className={className}> {children}
); } interface DropdownContentProps { children: ReactNode; align?: "left" | "right"; className?: string; } function DropdownContent({ children, align = "right", className }: DropdownContentProps) { const { isOpen, setIsOpen } = useDropdownContext(); if (!isOpen) return null; return (
setIsOpen(false)} > {children}
); } interface DropdownItemProps { onClick?: () => void; children: ReactNode; variant?: "default" | "danger"; className?: string; } function DropdownItem({ onClick, children, variant: _variant = "default", className }: DropdownItemProps) { const variantClasses = "text-zinc-300 hover:bg-zinc-800"; return ( ); } export const Dropdown = Object.assign(DropdownRoot, { Trigger: DropdownTrigger, Content: DropdownContent, Item: DropdownItem, });