'use client'; import * as React from 'react'; import { HoverCard as HoverCardPrimitive } from 'radix-ui'; import { AnimatePresence, motion, type HTMLMotionProps, type Transition, } from 'motion/react'; import { cn } from '@workspace/ui/lib/utils'; type HoverCardContextType = { isOpen: boolean; }; const HoverCardContext = React.createContext( undefined, ); const useHoverCard = (): HoverCardContextType => { const context = React.useContext(HoverCardContext); if (!context) { throw new Error('useHoverCard must be used within a HoverCard'); } return context; }; type Side = 'top' | 'bottom' | 'left' | 'right'; const getInitialPosition = (side: Side) => { switch (side) { case 'top': return { y: 15 }; case 'bottom': return { y: -15 }; case 'left': return { x: 15 }; case 'right': return { x: -15 }; } }; type HoverCardProps = React.ComponentProps; function HoverCard({ children, ...props }: HoverCardProps) { const [isOpen, setIsOpen] = React.useState( props?.open ?? props?.defaultOpen ?? false, ); React.useEffect(() => { if (props?.open !== undefined) setIsOpen(props.open); }, [props?.open]); const handleOpenChange = React.useCallback( (open: boolean) => { setIsOpen(open); props.onOpenChange?.(open); }, [props], ); return ( {children} ); } type HoverCardTriggerProps = React.ComponentProps< typeof HoverCardPrimitive.Trigger >; function HoverCardTrigger(props: HoverCardTriggerProps) { return ( ); } type HoverCardContentProps = React.ComponentProps< typeof HoverCardPrimitive.Content > & HTMLMotionProps<'div'> & { transition?: Transition; }; function HoverCardContent({ className, align = 'center', side = 'bottom', sideOffset = 4, transition = { type: 'spring', stiffness: 300, damping: 25 }, children, ...props }: HoverCardContentProps) { const { isOpen } = useHoverCard(); const initialPosition = getInitialPosition(side); return ( {isOpen && ( {children} )} ); } export { HoverCard, HoverCardTrigger, HoverCardContent, useHoverCard, type HoverCardContextType, type HoverCardProps, type HoverCardTriggerProps, type HoverCardContentProps, };