{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "floating-tooltip",
  "title": "Floating Tooltip",
  "description": "A floating tooltip component.",
  "dependencies": [
    "class-variance-authority",
    "motion"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/components/unlumen/floating-tooltip/index.tsx",
      "content": "\"use client\";\n\nimport { createContext, useContext, useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n  AnimatePresence,\n  motion,\n  useMotionValue,\n  useSpring,\n  useVelocity,\n  useTransform,\n} from \"motion/react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst floatingTooltipVariants = cva(\"ml-4 mt-4 font-medium\", {\n  variants: {\n    variant: {\n      default: \"bg-primary text-background dark:bg-white\",\n      outline: \"border border-border bg-background text-foreground shadow-none\",\n    },\n    size: {\n      md: \"rounded-md px-3.5 py-2.5 text-sm\",\n      lg: \"rounded-lg px-5 py-4 text-base\",\n    },\n  },\n  defaultVariants: {\n    variant: \"default\",\n    size: \"md\",\n  },\n});\n\ninterface TooltipContextType {\n  setContent: (\n    content: string,\n    description?: string,\n    contentClassName?: string,\n    descriptionClassName?: string,\n  ) => void;\n  setIsActive: (active: boolean) => void;\n}\n\nconst TooltipContext = createContext<TooltipContextType | null>(null);\n\nexport function FloatingTooltipProvider({\n  children,\n  className,\n  variant,\n  size,\n}: {\n  children: React.ReactNode;\n  className?: string;\n} & VariantProps<typeof floatingTooltipVariants>) {\n  const x = useMotionValue(0);\n  const y = useMotionValue(0);\n\n  const springConfig = { damping: 45, stiffness: 750 };\n  const smoothX = useSpring(x, springConfig);\n  const smoothY = useSpring(y, springConfig);\n\n  const velocityX = useVelocity(smoothX);\n  const velocityY = useVelocity(smoothY);\n\n  const scaleX = useTransform(velocityX, [-1000, 0, 1000], [0.9, 1, 1.15]);\n  const scaleY = useTransform(velocityY, [-1000, 0, 1000], [1.15, 1, 0.9]);\n\n  const skewX = useTransform(velocityX, [-1000, 0, 1000], [-3, 0, 3]);\n  const skewY = useTransform(velocityY, [-1000, 0, 1000], [-3, 0, 3]);\n\n  const [isActive, setIsActive] = useState(false);\n  const [content, setContent] = useState(\"\");\n  const [description, setDescription] = useState(\"\");\n  const [contentClassName, setContentClassName] = useState(\"\");\n  const [descriptionClassName, setDescriptionClassName] = useState(\"\");\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n\n    const getZoom = () => {\n      const htmlElement = document.documentElement;\n      const computedZoom = window.getComputedStyle(htmlElement).zoom;\n      return computedZoom ? parseFloat(computedZoom) : 1;\n    };\n\n    const handleMouseMove = (e: MouseEvent) => {\n      const zoom = getZoom();\n      x.set(e.clientX / zoom);\n      y.set(e.clientY / zoom);\n    };\n\n    window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\n\n    return () => {\n      window.removeEventListener(\"mousemove\", handleMouseMove);\n    };\n  }, [x, y]);\n\n  const handleSetContent = (\n    newContent: string,\n    newDescription?: string,\n    newContentClassName?: string,\n    newDescriptionClassName?: string,\n  ) => {\n    setContent(newContent);\n    setDescription(newDescription || \"\");\n    setContentClassName(newContentClassName || \"\");\n    setDescriptionClassName(newDescriptionClassName || \"\");\n  };\n\n  return (\n    <TooltipContext.Provider\n      value={{ setContent: handleSetContent, setIsActive }}\n    >\n      {children}\n      {typeof document !== \"undefined\" &&\n        createPortal(\n          <AnimatePresence>\n            {isActive && content && (\n              <motion.div\n                className=\"pointer-events-none fixed z-50\"\n                style={{\n                  top: smoothY,\n                  left: smoothX,\n                }}\n                initial={{\n                  opacity: 0,\n                  scale: 0.8,\n                }}\n                animate={{\n                  opacity: 1,\n                  scale: 1,\n                }}\n                exit={{\n                  opacity: 0,\n                  scale: 0.8,\n                }}\n                transition={{\n                  duration: 0.15,\n                  ease: \"easeOut\",\n                }}\n              >\n                <motion.div\n                  layout\n                  className={cn(\n                    floatingTooltipVariants({ variant, size }),\n                    className,\n                  )}\n                  style={{\n                    scaleX,\n                    scaleY,\n                    skewX,\n                    skewY,\n                  }}\n                  transition={{\n                    layout: {\n                      type: \"spring\",\n                      damping: 25,\n                      stiffness: 400,\n                    },\n                  }}\n                >\n                  <motion.div\n                    key={content}\n                    initial={{ opacity: 0 }}\n                    animate={{ opacity: 1 }}\n                    transition={{ duration: 0.15 }}\n                    className=\"flex flex-col gap-1\"\n                  >\n                    <span\n                      className={cn(\n                        \"whitespace-nowrap font-semibold\",\n                        contentClassName,\n                      )}\n                    >\n                      {content}\n                    </span>\n                    {description && (\n                      <span\n                        className={cn(\n                          \"max-w-[28ch] whitespace-normal text-sm leading-snug font-normal opacity-70\",\n                          descriptionClassName,\n                        )}\n                      >\n                        {description}\n                      </span>\n                    )}\n                  </motion.div>\n                </motion.div>\n              </motion.div>\n            )}\n          </AnimatePresence>,\n          document.body,\n        )}\n    </TooltipContext.Provider>\n  );\n}\n\nexport function FloatingTooltipTrigger({\n  children,\n  content,\n  description,\n  contentClassName,\n  descriptionClassName,\n}: {\n  children: React.ReactNode;\n  content: string;\n  description?: string;\n  contentClassName?: string;\n  descriptionClassName?: string;\n}) {\n  const context = useContext(TooltipContext);\n\n  if (!context) {\n    throw new Error(\n      \"FloatingTooltipTrigger must be used within FloatingTooltipProvider\",\n    );\n  }\n\n  const { setContent, setIsActive } = context;\n\n  const handleMouseEnter = () => {\n    setContent(content, description, contentClassName, descriptionClassName);\n    setIsActive(true);\n  };\n\n  const handleMouseLeave = () => {\n    setIsActive(false);\n  };\n\n  return (\n    <div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n      {children}\n    </div>\n  );\n}\n\nexport const FloatingTooltip = {\n  Provider: FloatingTooltipProvider,\n  Trigger: FloatingTooltipTrigger,\n};\n",
      "type": "registry:ui",
      "target": "components/unlumen-ui/floating-tooltip.tsx"
    }
  ],
  "type": "registry:ui"
}