import * as React from "react"; import { cn } from "../../lib/utils"; type PopoverContextValue = { open: boolean; setOpen: (open: boolean) => void; }; const PopoverContext = React.createContext(null); function usePopover() { const ctx = React.useContext(PopoverContext); if (!ctx) throw new Error("Popover components must be used within "); return ctx; } function Popover({ children, open: openProp, onOpenChange, }: { children: React.ReactNode; open?: boolean; onOpenChange?: (open: boolean) => void; }) { const [internalOpen, setInternalOpen] = React.useState(false); const open = openProp ?? internalOpen; const setOpen = onOpenChange ?? setInternalOpen; const value = React.useMemo(() => ({ open, setOpen }), [open, setOpen]); return (
{children}
); } function PopoverTrigger({ children, asChild, }: { children: React.ReactNode; asChild?: boolean; }) { const { setOpen } = usePopover(); const child = React.Children.only(children) as React.ReactElement; return React.cloneElement(child, { onFocus: (e: React.FocusEvent) => { (child.props as any).onFocus?.(e); setOpen(true); }, onBlur: (e: React.FocusEvent) => { (child.props as any).onBlur?.(e); setTimeout(() => setOpen(false), 150); }, } as any); } function PopoverContent({ children, className, align = "start", side = "bottom", ...props }: React.ComponentProps<"div"> & { align?: "start" | "center" | "end"; side?: "top" | "bottom"; }) { const { open } = usePopover(); if (!open) return null; return (
{children}
); } export { Popover, PopoverContent, PopoverTrigger };