Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.3 kB · 93 lines
TSX
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394import * as React from "react";import { cn } from "../../lib/utils";
type PopoverContextValue = { open: boolean; setOpen: (open: boolean) => void;};
const PopoverContext = React.createContext<PopoverContextValue | null>(null);
function usePopover() { const ctx = React.useContext(PopoverContext); if (!ctx) throw new Error("Popover components must be used within <Popover>"); 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 ( <PopoverContext.Provider value={value}> <div className="relative inline-flex">{children}</div> </PopoverContext.Provider> );}
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 ( <div className={cn( "absolute z-50 min-w-48 overflow-hidden rounded-md border border-(--color-border) bg-(--color-bg-elevated) shadow-md", side === "bottom" && "top-full mt-1", side === "top" && "bottom-full mb-1", align === "start" && "left-0", align === "center" && "left-1/2 -translate-x-1/2", align === "end" && "right-0", className, )} {...props} > {children} </div> );}
export { Popover, PopoverContent, PopoverTrigger };