{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"pull-hover","type":"registry:ui","title":"Pull Hover","description":"Pulls its children toward the cursor when it gets close.","dependencies":[],"registryDependencies":[],"files":[{"path":"registry/ui/pull-hover.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { useEffect, useRef, type ReactNode } from \"react\";\n\nexport interface PullHoverProps {\n  children: ReactNode;\n  /** Extra px around the element where the pull starts. */\n  padding?: number;\n  /** Higher is weaker: offset = distance / strength. */\n  strength?: number;\n  className?: string;\n}\n\nexport function PullHover({ children, padding = 80, strength = 3, className }: PullHoverProps) {\n  const outer = useRef<HTMLDivElement>(null);\n  const inner = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const onMove = (e: PointerEvent) => {\n      if (!outer.current || !inner.current) return;\n      // Measure the untransformed wrapper so the pull does not feed back on itself.\n      const r = outer.current.getBoundingClientRect();\n      const dx = e.clientX - (r.left + r.width / 2);\n      const dy = e.clientY - (r.top + r.height / 2);\n      const active = Math.abs(dx) < r.width / 2 + padding && Math.abs(dy) < r.height / 2 + padding;\n      inner.current.style.transition = `transform ${active ? 0.2 : 0.5}s ease-out`;\n      inner.current.style.transform = active ? `translate3d(${dx / strength}px, ${dy / strength}px, 0)` : \"\";\n    };\n    window.addEventListener(\"pointermove\", onMove, { passive: true });\n    return () => window.removeEventListener(\"pointermove\", onMove);\n  }, [padding, strength]);\n\n  return (\n    <div ref={outer} className={className} style={{ display: \"inline-block\" }}>\n      <div ref={inner} style={{ willChange: \"transform\" }}>\n        {children}\n      </div>\n    </div>\n  );\n}\n"}]}