{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "show-qr",
  "type": "registry:component",
  "title": "Show QR",
  "description": "A widget to show QR code.",
  "dependencies": [
    "lucide-react",
    "motion",
    "qrcode.react",
    "react-icons",
    "react-use-measure"
  ],
  "files": [
    {
      "path": "components/watermelon/show-qr.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport { X, Link } from 'lucide-react';\nimport { IoQrCodeOutline } from 'react-icons/io5';\nimport {\n  AnimatePresence,\n  motion,\n  MotionConfig,\n  type Transition,\n} from 'motion/react';\nimport { useEffect, useState } from 'react';\nimport { QRCodeSVG } from 'qrcode.react';\nimport useMeasure from 'react-use-measure';\n\ninterface ShowQrProps {\n  value: string;\n  buttonLabel?: string;\n  onCopy?: () => void;\n}\n\nexport const ShowQr = ({\n  value,\n  buttonLabel = 'Show QR Code',\n  onCopy,\n}: ShowQrProps) => {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const [isCopied, setIsCopied] = useState(false);\n\n  const [ref, bounds] = useMeasure();\n\n  useEffect(() => {\n    if (isCopied) {\n      const t = setTimeout(() => setIsCopied(false), 2000);\n      return () => clearTimeout(t);\n    }\n  }, [isCopied]);\n\n  const springConfig: Transition = {\n    type: 'spring',\n    bounce: 0.25,\n    visualDuration: 0.35,\n  };\n\n  const collapsedTransition: Transition = {\n    type: 'spring',\n    bounce: 0.15,\n    visualDuration: 0.35,\n  };\n\n  return (\n    <div className=\"flex w-full items-center justify-center overflow-hidden\">\n      <MotionConfig\n        transition={isExpanded ? springConfig : collapsedTransition}\n      >\n        <motion.div\n          initial={{\n            width: 180,\n          }}\n          animate={{\n            width: isExpanded ? 250 : 180,\n            height: isExpanded ? bounds.height : 48,\n          }}\n          className=\"overflow-hidden rounded-[32px] bg-[#F4F4F9] dark:bg-[#1C1C1E]\"\n        >\n          <div ref={ref} className=\"\">\n            <AnimatePresence mode=\"popLayout\" initial={false}>\n              {!isExpanded ? (\n                <motion.div\n                  key=\"collapsed\"\n                  className=\"flex cursor-pointer items-center justify-center gap-1 px-4 py-3 font-medium text-neutral-900 dark:text-white\"\n                  onClick={() => setIsExpanded(true)}\n                  initial={{ opacity: 0, filter: 'blur(4px)' }}\n                  animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}\n                  exit={{ opacity: 0, filter: 'blur(4px)' }}\n                >\n                  <IoQrCodeOutline className=\"size-6\" />\n                  <span>{buttonLabel}</span>\n                </motion.div>\n              ) : (\n                <motion.div\n                  key=\"expanded\"\n                  className=\"flex flex-col items-center gap-2 p-4 text-neutral-900 dark:text-white\"\n                  initial={{ opacity: 0 }}\n                  animate={{ opacity: 1 }}\n                  exit={{\n                    opacity: 0,\n                    transition: {\n                      duration: 0.2,\n                      ease: 'easeOut',\n                    },\n                  }}\n                >\n                  <motion.div\n                    className=\"flex h-[220px] w-[220px] items-center justify-center rounded-3xl border border-gray-200 bg-white p-4 dark:border-white/10 dark:bg-[#0B0B0E]\"\n                    initial={{ opacity: 0, y: 60, scale: 1.2 }}\n                    animate={{ opacity: 1, y: 0, scale: 1 }}\n                  >\n                    <QRCodeSVG\n                      value={value}\n                      size={200}\n                      level=\"H\"\n                      fgColor=\"currentColor\"\n                      bgColor=\"transparent\"\n                      className=\"h-full w-full text-black dark:text-white\"\n                    />\n                  </motion.div>\n\n                  <div className=\"flex w-full items-center gap-2\">\n                    <motion.div\n                      className=\"flex flex-1 cursor-pointer items-center justify-center gap-1 rounded-full border border-gray-200 bg-white p-2 text-lg font-medium dark:border-white/10 dark:bg-neutral-950\"\n                      onClick={() => {\n                        navigator.clipboard.writeText(value);\n                        setIsCopied(true);\n                        onCopy?.();\n                      }}\n                      layout\n                    >\n                      <motion.div layout>\n                        <Link />\n                      </motion.div>\n                      <AnimatedText\n                        from=\"Copy\"\n                        to=\"Copied\"\n                        isCopied={isCopied}\n                      />\n                      <motion.span layout>Link</motion.span>\n                    </motion.div>\n\n                    <div\n                      className=\"flex cursor-pointer items-center justify-center rounded-full border border-gray-200 bg-white p-2 dark:border-white/10 dark:bg-neutral-950\"\n                      onClick={() => {\n                        setIsExpanded(false);\n                        setIsCopied(false);\n                      }}\n                    >\n                      <X />\n                    </div>\n                  </div>\n                </motion.div>\n              )}\n            </AnimatePresence>\n          </div>\n        </motion.div>\n      </MotionConfig>\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"
    }
  ]
}
