{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hover-card",
  "dependencies": [
    "motion",
    "radix-ui"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/watermelon-ui/hover-card.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { HoverCard as HoverCardPrime } from 'radix-ui';\nimport {\n  AnimatePresence,\n  motion,\n  useMotionValue,\n  useSpring,\n  type MotionValue,\n  type HTMLMotionProps,\n  type SpringOptions,\n} from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype HoverCardProps = HoverCardPrimitiveProps;\n\nfunction HoverCard(props: HoverCardProps) {\n  return <HoverCardPrimitive {...props} />;\n}\n\ntype HoverCardTriggerProps = HoverCardTriggerPrimitiveProps;\n\nfunction HoverCardTrigger(props: HoverCardTriggerProps) {\n  return <HoverCardTriggerPrimitive {...props} />;\n}\n\ntype HoverCardContentProps = HoverCardContentPrimitiveProps;\n\nfunction HoverCardContent({\n  className,\n  align = 'center',\n  sideOffset = 4,\n  ...props\n}: HoverCardContentProps) {\n  return (\n    <HoverCardPortalPrimitive>\n      <HoverCardContentPrimitive\n        align={align}\n        sideOffset={sideOffset}\n        className={cn(\n          'bg-popover text-popover-foreground z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',\n          className,\n        )}\n        {...props}\n      />\n    </HoverCardPortalPrimitive>\n  );\n}\n\nexport {\n  HoverCard,\n  HoverCardTrigger,\n  HoverCardContent,\n  type HoverCardProps,\n  type HoverCardTriggerProps,\n  type HoverCardContentProps,\n};\n\n\ntype HoverCardContextType = {\n  isOpen: boolean;\n  setIsOpen: (isOpen: boolean) => void;\n  x: MotionValue<number>;\n  y: MotionValue<number>;\n  followCursor?: boolean | 'x' | 'y';\n  followCursorSpringOptions?: SpringOptions;\n};\n\nconst [HoverCardProvider, useHoverCard] =\n  getStrictContext<HoverCardContextType>('HoverCardContext');\n\ntype HoverCardPrimitiveProps = React.ComponentProps<typeof HoverCardPrime.Root> & {\n  followCursor?: boolean | 'x' | 'y';\n  followCursorSpringOptions?: SpringOptions;\n};\n\nfunction HoverCardPrimitive({\n  followCursor = false,\n  followCursorSpringOptions = { stiffness: 200, damping: 17 },\n  ...props\n}: HoverCardPrimitiveProps) {\n  const [isOpen, setIsOpen] = useControlledState({\n    value: props?.open,\n    defaultValue: props?.defaultOpen,\n    onChange: props?.onOpenChange,\n  });\n  const x = useMotionValue(0);\n  const y = useMotionValue(0);\n\n  return (\n    <HoverCardProvider\n      value={{\n        isOpen,\n        setIsOpen,\n        x,\n        y,\n        followCursor,\n        followCursorSpringOptions,\n      }}\n    >\n      <HoverCardPrime.Root\n        data-slot=\"hover-card\"\n        {...props}\n        onOpenChange={setIsOpen}\n      />\n    </HoverCardProvider>\n  );\n}\n\ntype HoverCardTriggerPrimitiveProps = React.ComponentProps<\n  typeof HoverCardPrime.Trigger\n>;\n\nfunction HoverCardTriggerPrimitive({ onMouseMove, ...props }: HoverCardTriggerPrimitiveProps) {\n  const { x, y, followCursor } = useHoverCard();\n\n  const handleMouseMove = (event: React.MouseEvent<HTMLAnchorElement>) => {\n    onMouseMove?.(event);\n\n    const target = event.currentTarget.getBoundingClientRect();\n\n    if (followCursor === 'x' || followCursor === true) {\n      const eventOffsetX = event.clientX - target.left;\n      const offsetXFromCenter = (eventOffsetX - target.width / 2) / 2;\n      x.set(offsetXFromCenter);\n    }\n\n    if (followCursor === 'y' || followCursor === true) {\n      const eventOffsetY = event.clientY - target.top;\n      const offsetYFromCenter = (eventOffsetY - target.height / 2) / 2;\n      y.set(offsetYFromCenter);\n    }\n  };\n\n  return (\n    <HoverCardPrime.Trigger\n      data-slot=\"hover-card-trigger\"\n      onMouseMove={handleMouseMove}\n      {...props}\n    />\n  );\n}\n\ntype HoverCardPortalPrimitiveProps = Omit<\n  React.ComponentProps<typeof HoverCardPrime.Portal>,\n  'forceMount'\n>;\n\nfunction HoverCardPortalPrimitive(props: HoverCardPortalPrimitiveProps) {\n  const { isOpen } = useHoverCard();\n\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <HoverCardPrime.Portal\n          forceMount\n          data-slot=\"hover-card-portal\"\n          {...props}\n        />\n      )}\n    </AnimatePresence>\n  );\n}\n\ntype HoverCardContentPrimitiveProps = React.ComponentProps<\n  typeof HoverCardPrime.Content\n> &\n  HTMLMotionProps<'div'>;\n\nfunction HoverCardContentPrimitive({\n  align,\n  alignOffset,\n  side,\n  sideOffset,\n  avoidCollisions,\n  collisionBoundary,\n  collisionPadding,\n  arrowPadding,\n  sticky,\n  hideWhenDetached,\n  style,\n  transition = { type: 'spring', stiffness: 300, damping: 25 },\n  ...props\n}: HoverCardContentPrimitiveProps) {\n  const { x, y, followCursor, followCursorSpringOptions } = useHoverCard();\n  const translateX = useSpring(x, followCursorSpringOptions);\n  const translateY = useSpring(y, followCursorSpringOptions);\n\n  return (\n    <HoverCardPrime.Content\n      asChild\n      forceMount\n      align={align}\n      alignOffset={alignOffset}\n      side={side}\n      sideOffset={sideOffset}\n      avoidCollisions={avoidCollisions}\n      collisionBoundary={collisionBoundary}\n      collisionPadding={collisionPadding}\n      arrowPadding={arrowPadding}\n      sticky={sticky}\n      hideWhenDetached={hideWhenDetached}\n    >\n      <motion.div\n        key=\"hover-card-content\"\n        data-slot=\"hover-card-content\"\n        initial={{ opacity: 0, scale: 0.5 }}\n        animate={{ opacity: 1, scale: 1 }}\n        exit={{ opacity: 0, scale: 0.5 }}\n        transition={transition}\n        style={{\n          x:\n            followCursor === 'x' || followCursor === true\n              ? translateX\n              : undefined,\n          y:\n            followCursor === 'y' || followCursor === true\n              ? translateY\n              : undefined,\n          ...style,\n        }}\n        {...props}\n      />\n    </HoverCardPrime.Content>\n  );\n}\n\n\n\n\nfunction getStrictContext<T>(\n  name?: string,\n): readonly [\n  ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => React.JSX.Element,\n  () => T,\n] {\n  const Context = React.createContext<T | undefined>(undefined);\n\n  const Provider = ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => <Context.Provider value={value}>{children}</Context.Provider>;\n\n  const useSafeContext = () => {\n    const ctx = React.useContext(Context);\n    if (ctx === undefined) {\n      throw new Error(`useContext must be used within ${name ?? 'a Provider'}`);\n    }\n    return ctx;\n  };\n\n  return [Provider, useSafeContext] as const;\n}\n\nexport { getStrictContext };\n\n\ninterface CommonControlledStateProps<T> {\n  value?: T;\n  defaultValue?: T;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useControlledState<T, Rest extends any[] = []>(\n  props: CommonControlledStateProps<T> & {\n    onChange?: (value: T, ...args: Rest) => void;\n  },\n): readonly [T, (next: T, ...args: Rest) => void] {\n  const { value, defaultValue, onChange } = props;\n\n  const [state, setInternalState] = React.useState<T>(\n    value !== undefined ? value : (defaultValue as T),\n  );\n\n  React.useEffect(() => {\n    if (value !== undefined) setInternalState(value);\n  }, [value]);\n\n  const setState = React.useCallback(\n    (next: T, ...args: Rest) => {\n      setInternalState(next);\n      onChange?.(next, ...args);\n    },\n    [onChange],\n  );\n\n  return [state, setState] as const;\n}\n",
      "type": "registry:ui",
      "target": "components/ui/hover-card.tsx"
    }
  ],
  "type": "registry:ui"
}
