{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "magnetic-button",
  "title": "Magnetic Button",
  "description": "Leans toward the cursor and springs back on leave.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/velora/magnetic-button.tsx",
      "content": "\"use client\";\n\nimport { useRef } from \"react\";\nimport { motion, useMotionValue, useReducedMotion, useSpring } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\n// style and the drag/animation handlers are owned by motion.button, whose\n// signatures differ from the DOM ones.\ninterface MagneticButtonProps\n  extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"style\" | \"onAnimationStart\" | \"onDrag\" | \"onDragStart\" | \"onDragEnd\"> {\n  children: React.ReactNode;\n  className?: string;\n  /** How far the button is allowed to travel toward the cursor, in px */\n  strength?: number;\n}\n\n/**\n * Button that leans toward the cursor while it is nearby and springs back\n * when the pointer leaves.\n */\nexport function MagneticButton({\n  children,\n  className,\n  strength = 14,\n  type = \"button\",\n  onMouseMove,\n  onMouseLeave,\n  onBlur,\n  ...props\n}: MagneticButtonProps) {\n  const ref = useRef<HTMLButtonElement>(null);\n  const reducedMotion = useReducedMotion();\n\n  const x = useMotionValue(0);\n  const y = useMotionValue(0);\n  const springX = useSpring(x, { stiffness: 260, damping: 16, mass: 0.4 });\n  const springY = useSpring(y, { stiffness: 260, damping: 16, mass: 0.4 });\n\n  const handleMouseMove = (event: React.MouseEvent<HTMLButtonElement>) => {\n    onMouseMove?.(event);\n    if (reducedMotion) return;\n    const rect = ref.current?.getBoundingClientRect();\n    if (!rect) return;\n    // Offset from centre, normalised to -1..1, then scaled by `strength`.\n    x.set(((event.clientX - rect.left) / rect.width - 0.5) * 2 * strength);\n    y.set(((event.clientY - rect.top) / rect.height - 0.5) * 2 * strength);\n  };\n\n  const reset = () => {\n    x.set(0);\n    y.set(0);\n  };\n\n  return (\n    <motion.button\n      {...props}\n      ref={ref}\n      type={type}\n      data-slot=\"magnetic-button\"\n      onMouseMove={handleMouseMove}\n      onMouseLeave={(event) => {\n        reset();\n        onMouseLeave?.(event);\n      }}\n      onBlur={(event) => {\n        reset();\n        onBlur?.(event);\n      }}\n      style={{ x: springX, y: springY }}\n      className={cn(\n        \"inline-flex h-11 cursor-pointer items-center justify-center rounded-xl bg-primary px-6 text-sm font-medium text-primary-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50\",\n        className\n      )}\n    >\n      {children}\n    </motion.button>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/velora/magnetic-button.tsx"
    }
  ],
  "type": "registry:ui"
}