{ "name": "attract-button", "type": "registry:component", "dependencies": [ "lucide-react", "motion" ], "registryDependencies": [ "button" ], "files": [ { "type": "registry:component", "content": "\"use client\";\n\n/**\n * @author: @dorianbaffier\n * @description: Attract Button\n * @version: 1.0.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { Magnet } from \"lucide-react\";\nimport { motion, useAnimation } from \"motion/react\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\ninterface AttractButtonProps\n extends React.ButtonHTMLAttributes {\n particleCount?: number;\n attractRadius?: number;\n}\n\ninterface Particle {\n id: number;\n x: number;\n y: number;\n}\n\nexport default function AttractButton({\n className,\n particleCount = 12,\n attractRadius = 50,\n ...props\n}: AttractButtonProps) {\n const [isAttracting, setIsAttracting] = useState(false);\n const [particles, setParticles] = useState([]);\n const particlesControl = useAnimation();\n\n useEffect(() => {\n const newParticles = Array.from({ length: particleCount }, (_, i) => ({\n id: i,\n x: Math.random() * 360 - 180,\n y: Math.random() * 360 - 180,\n }));\n setParticles(newParticles);\n }, [particleCount]);\n\n const handleInteractionStart = useCallback(async () => {\n setIsAttracting(true);\n await particlesControl.start({\n x: 0,\n y: 0,\n transition: {\n type: \"spring\",\n stiffness: 50,\n damping: 10,\n },\n });\n }, [particlesControl]);\n\n const handleInteractionEnd = useCallback(async () => {\n setIsAttracting(false);\n await particlesControl.start((i) => ({\n x: particles[i].x,\n y: particles[i].y,\n transition: {\n type: \"spring\",\n stiffness: 100,\n damping: 15,\n },\n }));\n }, [particlesControl, particles]);\n\n return (\n \n {particles.map((_, index) => (\n \n ))}\n \n \n {isAttracting ? \"Attracting\" : \"Hover me\"}\n \n \n );\n}\n", "path": "/components/kokonutui/attract-button.tsx", "target": "components/kokonutui/attract-button.tsx" } ] }