{
  "name": "magnetic",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "ui/magnetic.tsx",
      "content": "\"use client\";\n\nimport {\n  motion,\n  type SpringOptions,\n  useMotionValue,\n  useSpring,\n} from \"motion/react\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nconst SPRING_CONFIG = { stiffness: 26.7, damping: 4.1, mass: 0.2 };\n\nexport type MagneticProps = {\n  children: React.ReactNode;\n  intensity?: number;\n  range?: number;\n  actionArea?: \"self\" | \"parent\" | \"global\";\n  springOptions?: SpringOptions;\n};\n\nexport function Magnetic({\n  children,\n  intensity = 0.6,\n  range = 100,\n  actionArea = \"self\",\n  springOptions = SPRING_CONFIG,\n}: MagneticProps) {\n  const [isHovered, setIsHovered] = useState(false);\n  const ref = useRef<HTMLDivElement>(null);\n\n  const x = useMotionValue(0);\n  const y = useMotionValue(0);\n\n  const springX = useSpring(x, springOptions);\n  const springY = useSpring(y, springOptions);\n\n  useEffect(() => {\n    const calculateDistance = (e: MouseEvent) => {\n      if (ref.current) {\n        const rect = ref.current.getBoundingClientRect();\n        const centerX = rect.left + rect.width / 2;\n        const centerY = rect.top + rect.height / 2;\n        const distanceX = e.clientX - centerX;\n        const distanceY = e.clientY - centerY;\n\n        const absoluteDistance = Math.sqrt(distanceX ** 2 + distanceY ** 2);\n\n        if (isHovered && absoluteDistance <= range) {\n          const scale = 1 - absoluteDistance / range;\n          x.set(distanceX * intensity * scale);\n          y.set(distanceY * intensity * scale);\n        } else {\n          x.set(0);\n          y.set(0);\n        }\n      }\n    };\n\n    document.addEventListener(\"mousemove\", calculateDistance);\n\n    return () => {\n      document.removeEventListener(\"mousemove\", calculateDistance);\n    };\n  }, [isHovered, intensity, range, x.set, y.set, y, x]);\n\n  useEffect(() => {\n    if (actionArea === \"parent\" && ref.current?.parentElement) {\n      const parent = ref.current.parentElement;\n\n      const handleParentEnter = () => setIsHovered(true);\n      const handleParentLeave = () => setIsHovered(false);\n\n      parent.addEventListener(\"mouseenter\", handleParentEnter);\n      parent.addEventListener(\"mouseleave\", handleParentLeave);\n\n      return () => {\n        parent.removeEventListener(\"mouseenter\", handleParentEnter);\n        parent.removeEventListener(\"mouseleave\", handleParentLeave);\n      };\n    } else if (actionArea === \"global\") {\n      setIsHovered(true);\n    }\n  }, [actionArea]);\n\n  const handleMouseEnter = () => {\n    if (actionArea === \"self\") {\n      setIsHovered(true);\n    }\n  };\n\n  const handleMouseLeave = () => {\n    if (actionArea === \"self\") {\n      setIsHovered(false);\n      x.set(0);\n      y.set(0);\n    }\n  };\n\n  return (\n    <motion.div\n      ref={ref}\n      onMouseEnter={actionArea === \"self\" ? handleMouseEnter : undefined}\n      onMouseLeave={actionArea === \"self\" ? handleMouseLeave : undefined}\n      style={{\n        x: springX,\n        y: springY,\n      }}\n    >\n      {children}\n    </motion.div>\n  );\n}\n",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}