{
  "name": "tooltip-card",
  "type": "registry:ui",
  "files": [
    {
      "path": "components/ui/tooltip-card.tsx",
      "content": "\"use client\";\nimport React, { useState, useRef, useEffect } from \"react\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nexport const Tooltip = ({\n  content,\n  children,\n  containerClassName,\n}: {\n  content: string | React.ReactNode;\n  children: React.ReactNode;\n  containerClassName?: string;\n}) => {\n  const [isVisible, setIsVisible] = useState(false);\n  const [mouse, setMouse] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n  const [height, setHeight] = useState(0);\n  const [position, setPosition] = useState<{ x: number; y: number }>({\n    x: 0,\n    y: 0,\n  });\n  const contentRef = useRef<HTMLDivElement>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    if (isVisible && contentRef.current) {\n      setHeight(contentRef.current.scrollHeight);\n    }\n  }, [isVisible, content]);\n\n  const calculatePosition = (mouseX: number, mouseY: number) => {\n    if (!contentRef.current || !containerRef.current)\n      return { x: mouseX + 12, y: mouseY + 12 };\n\n    const tooltip = contentRef.current;\n    const container = containerRef.current;\n    const containerRect = container.getBoundingClientRect();\n    const viewportWidth = window.innerWidth;\n    const viewportHeight = window.innerHeight;\n\n    // Get tooltip dimensions\n    const tooltipWidth = 240; // min-w-[15rem] = 240px\n    const tooltipHeight = tooltip.scrollHeight;\n\n    // Calculate absolute position relative to viewport\n    const absoluteX = containerRect.left + mouseX;\n    const absoluteY = containerRect.top + mouseY;\n\n    let finalX = mouseX + 12;\n    let finalY = mouseY + 12;\n\n    // Check if tooltip goes beyond right edge\n    if (absoluteX + 12 + tooltipWidth > viewportWidth) {\n      finalX = mouseX - tooltipWidth - 12;\n    }\n\n    // Check if tooltip goes beyond left edge\n    if (absoluteX + finalX < 0) {\n      finalX = -containerRect.left + 12;\n    }\n\n    // Check if tooltip goes beyond bottom edge\n    if (absoluteY + 12 + tooltipHeight > viewportHeight) {\n      finalY = mouseY - tooltipHeight - 12;\n    }\n\n    // Check if tooltip goes beyond top edge\n    if (absoluteY + finalY < 0) {\n      finalY = -containerRect.top + 12;\n    }\n\n    return { x: finalX, y: finalY };\n  };\n\n  const updateMousePosition = (mouseX: number, mouseY: number) => {\n    setMouse({ x: mouseX, y: mouseY });\n    const newPosition = calculatePosition(mouseX, mouseY);\n    setPosition(newPosition);\n  };\n\n  const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) => {\n    setIsVisible(true);\n    const rect = e.currentTarget.getBoundingClientRect();\n    const mouseX = e.clientX - rect.left;\n    const mouseY = e.clientY - rect.top;\n    updateMousePosition(mouseX, mouseY);\n  };\n\n  const handleMouseLeave = () => {\n    setMouse({ x: 0, y: 0 });\n    setPosition({ x: 0, y: 0 });\n    setIsVisible(false);\n  };\n\n  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n    if (!isVisible) return;\n    const rect = e.currentTarget.getBoundingClientRect();\n    const mouseX = e.clientX - rect.left;\n    const mouseY = e.clientY - rect.top;\n    updateMousePosition(mouseX, mouseY);\n  };\n\n  const handleTouchStart = (e: React.TouchEvent<HTMLDivElement>) => {\n    const touch = e.touches[0];\n    const rect = e.currentTarget.getBoundingClientRect();\n    const mouseX = touch.clientX - rect.left;\n    const mouseY = touch.clientY - rect.top;\n    updateMousePosition(mouseX, mouseY);\n    setIsVisible(true);\n  };\n\n  const handleTouchEnd = () => {\n    // Delay hiding to allow for tap interaction\n    setTimeout(() => {\n      setIsVisible(false);\n      setMouse({ x: 0, y: 0 });\n      setPosition({ x: 0, y: 0 });\n    }, 2000);\n  };\n\n  const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n    // Toggle visibility on click for mobile devices\n    if (window.matchMedia(\"(hover: none)\").matches) {\n      e.preventDefault();\n      if (isVisible) {\n        setIsVisible(false);\n        setMouse({ x: 0, y: 0 });\n        setPosition({ x: 0, y: 0 });\n      } else {\n        const rect = e.currentTarget.getBoundingClientRect();\n        const mouseX = e.clientX - rect.left;\n        const mouseY = e.clientY - rect.top;\n        updateMousePosition(mouseX, mouseY);\n        setIsVisible(true);\n      }\n    }\n  };\n\n  // Update position when tooltip becomes visible or content changes\n  useEffect(() => {\n    if (isVisible && contentRef.current) {\n      const newPosition = calculatePosition(mouse.x, mouse.y);\n      setPosition(newPosition);\n    }\n  }, [isVisible, height, mouse.x, mouse.y]);\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\"relative inline-block\", containerClassName)}\n      onMouseEnter={handleMouseEnter}\n      onMouseLeave={handleMouseLeave}\n      onMouseMove={handleMouseMove}\n      onTouchStart={handleTouchStart}\n      onTouchEnd={handleTouchEnd}\n      onClick={handleClick}\n    >\n      {children}\n      <AnimatePresence>\n        {isVisible && (\n          <motion.div\n            key={String(isVisible)}\n            initial={{ height: 0, opacity: 1 }}\n            animate={{ height, opacity: 1 }}\n            exit={{ height: 0, opacity: 0 }}\n            transition={{\n              type: \"spring\",\n              stiffness: 200,\n              damping: 20,\n            }}\n            className=\"pointer-events-none absolute z-50 min-w-[15rem] overflow-hidden rounded-md border border-transparent bg-white shadow-sm ring-1 shadow-black/5 ring-black/5 dark:bg-neutral-900 dark:shadow-white/10 dark:ring-white/5\"\n            style={{\n              top: position.y,\n              left: position.x,\n            }}\n          >\n            <div\n              ref={contentRef}\n              className=\"p-2 text-sm text-neutral-600 md:p-4 dark:text-neutral-400\"\n            >\n              {content}\n            </div>\n          </motion.div>\n        )}\n      </AnimatePresence>\n    </div>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/ui/tooltip-card.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Tooltip Card"
}