"use client"; import * as React from "react"; import { cn } from "../../lib/utils"; // Ensure this utility is present or replace with className logic import { motion, AnimatePresence, HTMLMotionProps } from "framer-motion"; // Import HTMLMotionProps interface HoverCardContextType { open: boolean; setOpen: React.Dispatch>; } const HoverCardContext = React.createContext(undefined); interface HoverCardProps { children: React.ReactNode; defaultOpen?: boolean; open?: boolean; onOpenChange?: (open: boolean) => void; openDelay?: number; closeDelay?: number; } const HoverCard: React.FC = ({ children, defaultOpen = false, open: controlledOpen, onOpenChange, openDelay = 700, closeDelay = 300, }) => { const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen); const isControlled = controlledOpen !== undefined; const open = isControlled ? controlledOpen : uncontrolledOpen; const setOpen = React.useCallback( (value: boolean | ((prev: boolean) => boolean)) => { if (!isControlled) { setUncontrolledOpen(value); } if (onOpenChange) { const newValue = typeof value === "function" ? value(open) : value; onOpenChange(newValue); } }, [isControlled, onOpenChange, open] ); const openTimerRef = React.useRef | null>(null); const closeTimerRef = React.useRef | null>(null); const handleOpen = React.useCallback(() => { if (closeTimerRef.current) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; } if (!open) { openTimerRef.current = setTimeout(() => { setOpen(true); }, openDelay); } }, [open, openDelay, setOpen]); const handleClose = React.useCallback(() => { if (openTimerRef.current) { clearTimeout(openTimerRef.current); openTimerRef.current = null; } if (open) { closeTimerRef.current = setTimeout(() => { setOpen(false); }, closeDelay); } }, [open, closeDelay, setOpen]); // Clear timers on unmount React.useEffect(() => { return () => { if (openTimerRef.current) clearTimeout(openTimerRef.current); if (closeTimerRef.current) clearTimeout(closeTimerRef.current); }; }, []); return (
{children}
); }; interface HoverCardTriggerProps { children: React.ReactNode; asChild?: boolean; } const HoverCardTrigger: React.FC = ({ children, asChild = false }) => { // If asChild is true, we just render the child directly. // The onMouseEnter/Leave/Focus/Blur listeners are on the parent HoverCard div. if (asChild) { return <>{children}; } // If not asChild, we wrap the children in a div to ensure the HoverCard has a DOM element to attach listeners to. // This div also needs to be part of the hover/focus interaction, so it's placed inside the HoverCard's event listeners. // The outer div in HoverCard handles the events, so this div simply renders the content. return
{children}
; // Add tabIndex for keyboard accessibility }; // --- // **CHANGE MADE HERE:** // Changed `React.HTMLAttributes` to `HTMLMotionProps<"div">` // --- interface HoverCardContentProps extends HTMLMotionProps<"div"> { align?: "center" | "start" | "end"; sideOffset?: number; } const HoverCardContent = React.forwardRef( ({ className, align = "center", sideOffset = 4, ...props }, ref) => { const context = React.useContext(HoverCardContext); if (!context) { throw new Error("HoverCardContent must be used within a HoverCard"); } const { open } = context; return ( {open && ( // Conditionally render the motion.div based on `open` state )} ); } ); HoverCardContent.displayName = "HoverCardContent"; // Exports export { HoverCard, HoverCardTrigger, HoverCardContent };