import * as PopoverPrimitive from "@radix-ui/react-popover"; import * as React from "react"; import { JSX } from "react"; import { usePortalContainer } from "../../hooks/PortalContainerProvider"; import { cn } from "../libs/utils"; export interface PopoverContextValue { open: boolean; setOpen: React.Dispatch>; hover: boolean; click: boolean; } export const PopoverContext = React.createContext(null); interface PopoverProps { _open?: boolean; onOpenChange?: (open: boolean) => void; hover?: boolean; click?: boolean; modal?: boolean; children?: React.ReactNode; } const Popover = ({ hover = false, click = false, modal, children, _open, onOpenChange }: PopoverProps): JSX.Element => { const [open, setOpen] = React.useState(_open || false); const handleOpenChange = (open: boolean) => { setOpen(open); if (onOpenChange) { onOpenChange(open); } }; return ( {children} ); }; function handleHover(hover: boolean = false, setOpen: React.Dispatch> = () => { }, type: "enter" | "leave") { if (hover) { setOpen(type === "enter"); } } const PopoverTrigger = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ children, ...props }, ref) => { const context = React.useContext(PopoverContext); if (!context) { throw new Error("PopoverTrigger must be used within a Popover"); } const { setOpen, hover, click } = context; return ( handleHover(hover, setOpen, "enter")} onMouseLeave={() => handleHover(hover, setOpen, "leave")} onClick={() => { if (click) setOpen((prev) => !prev); }} {...props} > {children} ); }); PopoverTrigger.displayName = PopoverPrimitive.Trigger.displayName; const PopoverAnchor = PopoverPrimitive.Anchor; const PopoverContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, align = "center", side = "bottom", ...props }, ref) => { const context = React.useContext(PopoverContext); if (!context) { throw new Error("PopoverContent must be used within a Popover"); } const { setOpen, hover } = context; const container = usePortalContainer(); return ( handleHover(hover, setOpen, "enter")} onMouseLeave={() => handleHover(hover, setOpen, "leave")} // onClick={() => {setOpen(false)}} className={cn( "z-50 w-72 rounded-md border-popover bg-popover text-popover-foreground ring-1 ring-gray-200 dark:ring-slate-700 shadow-md focus:outline-none animate-in", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className )} {...props} /> ); }); PopoverContent.displayName = PopoverPrimitive.Content.displayName; const PopoverClose = PopoverPrimitive.Close; PopoverClose.displayName = PopoverPrimitive.Close.displayName; export function usePopoverContext() { const ctx = React.useContext(PopoverContext); if (!ctx) throw new Error('usePopoverContext must be used within a Popover'); return { ...ctx, close: () => ctx.setOpen(false) }; } export { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger };