"use client"; import { useClickOutside } from "@/hooks/use-click-outside"; import { cn } from "@/lib/utils"; import { SetStateActionType } from "@/types/set-state-action-type"; import { createContext, type PropsWithChildren, useContext, useEffect, useRef, } from "react"; type DropdownContextType = { isOpen: boolean; handleOpen: () => void; handleClose: () => void; }; const DropdownContext = createContext(null); function useDropdownContext() { const context = useContext(DropdownContext); if (!context) { throw new Error("useDropdownContext must be used within a Dropdown"); } return context; } type DropdownProps = { children: React.ReactNode; isOpen: boolean; setIsOpen: SetStateActionType; }; export function Dropdown({ children, isOpen, setIsOpen }: DropdownProps) { const triggerRef = useRef(null); const handleKeyDown = (event: React.KeyboardEvent) => { if (event.key === "Escape") { handleClose(); } }; useEffect(() => { if (isOpen) { triggerRef.current = document.activeElement as HTMLElement; document.body.style.pointerEvents = "none"; } else { document.body.style.removeProperty("pointer-events"); setTimeout(() => { triggerRef.current?.focus(); }, 0); } }, [isOpen]); function handleClose() { setIsOpen(false); } function handleOpen() { setIsOpen(true); } return (
{children}
); } type DropdownContentProps = { align?: "start" | "end" | "center"; className?: string; children: React.ReactNode; }; export function DropdownContent({ children, align = "center", className, }: DropdownContentProps) { const { isOpen, handleClose } = useDropdownContext(); const contentRef = useClickOutside(() => { if (isOpen) handleClose(); }); if (!isOpen) return null; return (
{children}
); } type DropdownTriggerProps = React.HTMLAttributes & { children: React.ReactNode; }; export function DropdownTrigger({ children, className }: DropdownTriggerProps) { const { handleOpen, isOpen } = useDropdownContext(); return ( ); } export function DropdownClose({ children }: PropsWithChildren) { const { handleClose } = useDropdownContext(); return
{children}
; }