{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slant-morph-button",
  "type": "registry:ui",
  "title": "Slant Morph Button",
  "description": "A slanted label and arrow tile whose diagonal seam smoothly flips its lean like a hinge on hover with GSAP MorphSVG, while the colors trade places and a fresh arrow slides through.",
  "dependencies": [
    "gsap",
    "@gsap/react"
  ],
  "registryDependencies": [],
  "cssVars": {
    "theme": {}
  },
  "files": [
    {
      "path": "components/tweenui/slant-morph-button.tsx",
      "type": "registry:component",
      "target": "components/tweenui/slant-morph-button.tsx",
      "content": "'use client';\n\nimport { useRef, type ComponentPropsWithRef } from 'react';\nimport { useGSAP } from '@gsap/react';\nimport gsap from 'gsap';\nimport { MorphSVGPlugin } from 'gsap/MorphSVGPlugin';\nimport { cn } from '@/lib/utils';\n\ngsap.registerPlugin(useGSAP, MorphSVGPlugin);\n\nconst SEAM_REST =\n  'M0 0H5.63C13.438 0 19.166 7.337 17.272 14.91L11.182 39.269A11.527 11.527 0 0 1 0 48V0Z';\nconst SEAM_FLIPPED =\n  'M0 48H5.63C13.438 48 19.166 40.663 17.272 33.09L11.182 8.731A11.527 11.527 0 0 0 0 0V48Z';\nconst TILE_REST =\n  'M6.728 9.09A12 12 0 0 1 18.369 0H39C45.627 0 51 5.373 51 12V36C51 42.627 45.627 48 39 48H12.37C4.561 48 -1.167 40.663 0.727 33.09L6.728 9.09Z';\nconst TILE_FLIPPED =\n  'M6.728 38.91A12 12 0 0 0 18.369 48H39C45.627 48 51 42.627 51 36V12C51 5.373 45.627 0 39 0H12.37C4.561 0 -1.167 7.337 0.727 14.91L6.728 38.91Z';\nconst ARROW = 'M7.703 5.8H.398V4.6h7.305l-3.36-3.36.855-.84 4.8 4.8-4.8 4.8-.855-.84 3.36-3.36Z';\n\nconst canMorph = () =>\n  typeof window !== 'undefined' &&\n  !window.matchMedia('(prefers-reduced-motion: reduce)').matches &&\n  window.matchMedia('(hover: hover) and (pointer: fine)').matches;\n\nconst swap = 'transition-[fill] duration-600 ease-(--settle) motion-reduce:transition-none';\n\nconst slide =\n  'size-2.5 flex-none -translate-x-full transition-transform duration-600 ease-(--settle) group-hover:translate-x-0 group-focus-visible:translate-x-0 motion-reduce:transition-none';\n\nexport interface SlantMorphButtonProps extends ComponentPropsWithRef<'button'> {\n  children: string;\n}\n\nconst SlantMorphButton = ({\n  children,\n  className,\n  type = 'button',\n  disabled,\n  ref,\n  ...props\n}: SlantMorphButtonProps) => {\n  const btnRef = useRef<HTMLButtonElement>(null);\n  const seamRef = useRef<SVGPathElement>(null);\n  const tileRef = useRef<SVGPathElement>(null);\n\n  const setRef = (node: HTMLButtonElement | null) => {\n    btnRef.current = node;\n    if (typeof ref === 'function') ref(node);\n    else if (ref) ref.current = node;\n  };\n\n  useGSAP(\n    () => {\n      const btn = btnRef.current;\n      const seam = seamRef.current;\n      const tile = tileRef.current;\n      if (!btn || !seam || !tile || disabled || !canMorph()) return;\n\n      const hinge = gsap\n        .timeline({ paused: true, defaults: { duration: 0.6, ease: 'power3.inOut' } })\n        .to(seam, { morphSVG: { shape: SEAM_FLIPPED, shapeIndex: 'auto' } }, 0)\n        .to(tile, { morphSVG: { shape: TILE_FLIPPED, shapeIndex: 'auto' } }, 0);\n\n      const open = () => hinge.play();\n      const close = () => hinge.reverse();\n      const onFocus = () => {\n        if (btn.matches(':focus-visible')) open();\n      };\n      const onBlur = () => {\n        if (!btn.matches(':hover')) close();\n      };\n\n      btn.addEventListener('pointerenter', open);\n      btn.addEventListener('pointerleave', close);\n      btn.addEventListener('focus', onFocus);\n      btn.addEventListener('blur', onBlur);\n\n      return () => {\n        hinge.kill();\n        btn.removeEventListener('pointerenter', open);\n        btn.removeEventListener('pointerleave', close);\n        btn.removeEventListener('focus', onFocus);\n        btn.removeEventListener('blur', onBlur);\n      };\n    },\n    { scope: btnRef, dependencies: [disabled], revertOnUpdate: true }\n  );\n\n  return (\n    <button\n      ref={setRef}\n      type={type}\n      disabled={disabled}\n      className={cn(\n        'group relative inline-flex h-12 cursor-pointer items-stretch font-mono text-sm whitespace-nowrap uppercase select-none [--settle:cubic-bezier(0.25,1,0.5,1)] focus-visible:outline-none disabled:pointer-events-none disabled:opacity-60',\n        className\n      )}\n      {...props}\n    >\n      <span className=\"relative mr-4 flex items-center rounded-l-xl bg-[#045f64] py-2 pr-2 pl-5 text-[#c6f56f] transition-colors duration-600 ease-(--settle) group-hover:bg-[#c6f56f] group-hover:text-[#045f64] group-focus-visible:bg-[#c6f56f] group-focus-visible:text-[#045f64] motion-reduce:transition-none\">\n        {children}\n        <svg\n          viewBox=\"0 0 18 48\"\n          aria-hidden=\"true\"\n          className=\"absolute top-0 -right-4 h-full w-[18px] overflow-visible\"\n        >\n          <path\n            ref={seamRef}\n            d={SEAM_REST}\n            className={cn(\n              swap,\n              'fill-[#045f64] group-hover:fill-[#c6f56f] group-focus-visible:fill-[#c6f56f]'\n            )}\n          />\n        </svg>\n      </span>\n      <span aria-hidden=\"true\" className=\"relative grid w-[51px] place-items-center\">\n        <svg viewBox=\"0 0 51 48\" className=\"absolute inset-0 size-full overflow-visible\">\n          <path\n            ref={tileRef}\n            d={TILE_REST}\n            className={cn(\n              swap,\n              'fill-[#c6f56f] group-hover:fill-[#045f64] group-focus-visible:fill-[#045f64]'\n            )}\n          />\n        </svg>\n        <span className=\"relative ml-px flex w-2.5 overflow-hidden\">\n          <svg viewBox=\"0 0 10 10\" className={cn(slide, 'fill-[#c6f56f]')}>\n            <path d={ARROW} />\n          </svg>\n          <svg viewBox=\"0 0 10 10\" className={cn(slide, 'fill-[#045f64]')}>\n            <path d={ARROW} />\n          </svg>\n        </span>\n      </span>\n    </button>\n  );\n};\n\nexport default SlantMorphButton;\n"
    }
  ],
  "docs": "Docs, props and examples: https://tween-ui.vercel.app/component/slant-morph-button\nGSAP plugins (MorphSVGPlugin) are registered inside the component, so there is nothing to set up."
}