{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "copy-confirm",
  "type": "registry:component",
  "title": "Copy Confirm",
  "description": "Interactive micro-interaction component for copy confirm.",
  "dependencies": [
    "framer-motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/watermelon/copy-confirm.tsx",
      "type": "registry:component",
      "content": "import {\n  Boxes,\n  CheckIcon,\n  CopyIcon,\n  Settings2,\n} from 'lucide-react';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { type ReactNode, useState } from 'react';\n\ninterface SkillCardProps {\n  title?: string;\n  icon?: ReactNode;\n  valueToCopy?: string;\n\n  copiedText?: string;\n  copyText?: string;\n\n  showSettings?: boolean;\n  loading?: boolean;\n\n  onSettingsClick?: () => void;\n}\n\nexport default function CopyConfirm({\n  title = 'Clay Skill',\n  icon = <Boxes size={16} />,\n  valueToCopy = 'Clay Skill',\n\n  copiedText = 'Copied',\n  copyText = 'Copy',\n\n  showSettings = true,\n  loading = false,\n\n  onSettingsClick = () => {},\n}: SkillCardProps) {\n  const [copied, setCopied] = useState(false);\n\n  async function handleCopy() {\n    await navigator.clipboard.writeText(valueToCopy);\n\n    setCopied(true);\n\n    setTimeout(() => {\n      setCopied(false);\n    }, 1800);\n  }\n\n  return (\n    <div className=\"flex h-screen w-full items-center justify-center\">\n      <div className=\"flex items-center gap-2\">\n        <div className=\"flex gap-0.5 rounded-full\">\n          <div className=\"border-border/20 flex items-center gap-1.5 rounded-l-full border bg-zinc-100 p-3\">\n            <div className=\"text-zinc-500\">{icon}</div>\n\n            <span className=\"text-sm font-semibold text-zinc-800\">\n              {title}\n            </span>\n          </div>\n\n          {showSettings && (\n            <button\n              onClick={onSettingsClick}\n              className=\"flex items-center justify-center rounded-r-full bg-zinc-100 px-3 transition\"\n            >\n              <Settings2 size={20} className=\"text-zinc-700\" />\n            </button>\n          )}\n        </div>\n\n        <motion.button\n          whileHover={{ scale: 1.02 }}\n          whileTap={{ scale: 0.97 }}\n          disabled={loading}\n          animate={{\n            backgroundColor: copied ? '#15803d' : '#000000', // green-500 : black\n          }}\n          onClick={handleCopy}\n          className=\"relative flex  items-center justify-center gap-2 overflow-hidden rounded-full bg-[#0C3415] py-2 px-4 text-white\"\n        >\n          <AnimatePresence mode=\"popLayout\" initial={false}>\n            <motion.div\n              key={copied ? 'check' : 'copy'}\n              initial={{ opacity: 0, scale: 0.25, filter: 'blur(4px)' }}\n              animate={{ opacity: 1, scale: 1, filter: 'blur(0px)' }}\n              exit={{ opacity: 0, scale: 0.25, filter: 'blur(4px)' }}\n              transition={{\n                type: 'spring',\n                duration: 0.3,\n                bounce: 0,\n              }}\n                          className='text-sm'\n            >\n              {copied ? (\n                <CheckIcon className=\"stoke-2 size-4\" />\n              ) : (\n                <CopyIcon className=\"stroke-2 size-4\" />\n              )}\n            </motion.div>\n          </AnimatePresence>\n          <AnimatedText from={copyText} to={copiedText} isCopied={copied} />\n        </motion.button>\n      </div>\n    </div>\n  );\n}\n\nconst AnimatedText = ({\n  from,\n  to,\n  isCopied,\n}: {\n  from: string;\n  to: string;\n  isCopied: boolean;\n}) => {\n  const activeText = isCopied ? to : from;\n\n  return (\n    <div className=\"flex text-lg tracking-tight will-change-transform\">\n      <AnimatePresence mode=\"popLayout\" initial={false}>\n        {activeText.split('').map((char, index) => {\n          const displayChar = char === ' ' ? '\\u00A0' : char;\n\n          return (\n            <motion.span\n              key={char + index}\n              layout\n              initial={{ opacity: 0, y: 5, scale: 0.7 }}\n              animate={{\n                opacity: 1,\n                y: 0,\n                scale: 1,\n                transition: {\n                  type: 'spring',\n                  stiffness: 200,\n                  damping: 20,\n                  delay: 0.03 * index,\n                },\n              }}\n              exit={{ opacity: 0, y: -5, scale: 0.7 }}\n            >\n              {displayChar}\n            </motion.span>\n          );\n        })}\n      </AnimatePresence>\n    </div>\n  );\n};\n"
    }
  ]
}
