{
    "name": "spring-button",
    "title": "Spring Button",
    "description": "A button that shrinks on press and springs back with bounce.",
    "type": "registry:ui",
    "dependencies": ["gsap", "@gsap/react"],
    "files": [
        {
            "path": "components/gsap/spring-button.tsx",
            "type": "registry:ui",
            "target": "~/components/gsap/spring-button.tsx",
            "content": "\"use client\";\n\nimport { ComponentProps, useRef } from \"react\";\n\nimport { useGSAP } from \"@gsap/react\";\nimport gsap from \"gsap\";\n\ntype SpringButtonProps = {\n    scale?: number;\n    shaking?: boolean;\n} & ComponentProps<\"button\">;\n\nexport const SpringButton = ({ scale = 0.85, shaking = true, ...props }: SpringButtonProps) => {\n    const buttonRef = useRef<HTMLButtonElement | null>(null);\n    const pressed = useRef(false);\n\n    useGSAP(\n        () => {\n            const element = buttonRef.current;\n            if (!element) return;\n            let pressTimeline = gsap.timeline();\n            let shakingTimeline = gsap.timeline({ repeat: -1 });\n\n            const press = () => {\n                pressed.current = true;\n                pressTimeline.pause(0);\n                pressTimeline.kill();\n                pressTimeline = gsap.timeline();\n                shakingTimeline = gsap.timeline({ repeat: -1 });\n\n                pressTimeline.to(element, {\n                    scale: scale,\n                    duration: 1,\n                    ease: \"power4.out\",\n                });\n\n                if (shaking) {\n                    pressTimeline.add(shakingTimeline);\n                    shakingTimeline\n                        .to(element, { x: -1, y: 1, duration: 0.08 })\n                        .to(element, { x: 1, y: -1, duration: 0.08 })\n                        .to(element, { x: -0.5, y: -0.5, duration: 0.08 })\n                        .to(element, { x: 0.5, y: 0.5, duration: 0.08 })\n                        .to(element, { x: 0, y: 0, duration: 0.08 });\n                }\n            };\n\n            const release = () => {\n                pressed.current = false;\n                if (shakingTimeline) {\n                    shakingTimeline.pause(0);\n                    shakingTimeline.kill();\n                }\n                gsap.to(element, {\n                    scale: 1,\n                    duration: 0.5,\n                    ease: \"elastic.out(1.4, 0.2)\",\n                    onComplete: () => {\n                        if (!pressed.current && pressTimeline) {\n                            pressTimeline.pause(0);\n                            pressTimeline.kill();\n                        }\n                    },\n                });\n            };\n\n            element.addEventListener(\"mousedown\", press);\n            element.addEventListener(\"touchstart\", press);\n            element.addEventListener(\"mouseup\", release);\n            element.addEventListener(\"mouseleave\", release);\n            element.addEventListener(\"touchend\", release);\n\n            return () => {\n                element.removeEventListener(\"mousedown\", press);\n                element.removeEventListener(\"touchstart\", press);\n                element.removeEventListener(\"mouseup\", release);\n                element.removeEventListener(\"mouseleave\", release);\n                element.removeEventListener(\"touchend\", release);\n            };\n        },\n        { scope: buttonRef },\n    );\n\n    return <button {...props} ref={buttonRef} />;\n};\n"
        }
    ]
}
