{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "qr-code",
  "title": "Qr Code",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/qr-code/QrCode.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore -- qrcode ships no types unless @types/qrcode (a devDependency) is installed; @ts-ignore stays valid either way\nimport QRCodeLib from 'qrcode'\nimport { Loader2, RotateCcw, Check, ScanLine } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport type QRCodeType = 'canvas' | 'svg'\nexport type QRCodeStatus = 'active' | 'expired' | 'loading' | 'scanned'\nexport type QRCodeErrorLevel = 'L' | 'M' | 'Q' | 'H'\n\nexport interface QrCodeProps {\n  value: string\n  type?: QRCodeType\n  size?: number\n  color?: string\n  bgColor?: string\n  icon?: string\n  iconSize?: number | { width: number; height: number }\n  errorLevel?: QRCodeErrorLevel\n  bordered?: boolean\n  status?: QRCodeStatus\n  marginSize?: number\n  className?: string\n  /** Fired when the \"Refresh\" action of the expired overlay is clicked. */\n  onRefresh?: () => void\n  /** Overrides the default download button (parity with the Vue `extra` slot). */\n  extra?: React.ReactNode\n}\n\nconst QrCode = React.forwardRef<HTMLDivElement, QrCodeProps>(\n  (\n    {\n      value,\n      type = 'canvas',\n      size = 160,\n      color = '#000000',\n      bgColor = '#ffffff',\n      icon,\n      iconSize,\n      errorLevel = 'M',\n      bordered = true,\n      status = 'active',\n      marginSize = 0,\n      className,\n      onRefresh,\n      extra,\n    },\n    ref,\n  ) => {\n    const [qrDataUrl, setQrDataUrl] = React.useState('')\n    const [qrSvg, setQrSvg] = React.useState('')\n\n    const iconDimensions =\n      typeof iconSize === 'number'\n        ? { width: iconSize, height: iconSize }\n        : iconSize ?? { width: 40, height: 40 }\n\n    React.useEffect(() => {\n      let cancelled = false\n      async function generateQR() {\n        if (!value || status === 'loading') return\n        try {\n          const options = {\n            width: size,\n            margin: marginSize,\n            color: { dark: color, light: bgColor },\n            errorCorrectionLevel: errorLevel,\n          }\n          if (type === 'svg') {\n            const svg = await QRCodeLib.toString(value, { type: 'svg', ...options })\n            if (!cancelled) setQrSvg(svg)\n          } else {\n            const url = await QRCodeLib.toDataURL(value, options)\n            if (!cancelled) setQrDataUrl(url)\n          }\n        } catch (e) {\n          console.error('QR Code generation failed:', e)\n        }\n      }\n      generateQR()\n      return () => {\n        cancelled = true\n      }\n    }, [value, type, size, color, bgColor, errorLevel, marginSize, status])\n\n    function downloadQR() {\n      const link = document.createElement('a')\n      link.download = `qrcode-${value.slice(0, 20)}.png`\n      link.href = qrDataUrl\n      link.click()\n    }\n\n    const statusOverlay = (() => {\n      switch (status) {\n        case 'expired':\n          return { Icon: RotateCcw, text: 'Expired', action: onRefresh ?? null }\n        case 'scanned':\n          return { Icon: Check, text: 'Scanned', action: null }\n        case 'loading':\n          return { Icon: Loader2, text: 'Loading...', action: null }\n        default:\n          return null\n      }\n    })()\n\n    return (\n      <div\n        ref={ref}\n        data-uipkge=\"\"\n        data-slot=\"qr-code\"\n        className={cn(\n          'inline-flex flex-col items-center gap-2',\n          bordered && 'bg-background rounded-lg border p-4',\n          className,\n        )}\n      >\n        <div\n          className=\"relative inline-flex items-center justify-center overflow-hidden\"\n          style={{ width: `${size}px`, height: `${size}px` }}\n        >\n          {/* QR Code */}\n          {type === 'svg' && qrSvg ? (\n            <div className=\"size-full\" dangerouslySetInnerHTML={{ __html: qrSvg }} />\n          ) : qrDataUrl ? (\n            <img src={qrDataUrl} alt={`QR Code for ${value}`} className=\"size-full\" />\n          ) : null}\n\n          {/* Icon overlay */}\n          {icon && status === 'active' && (\n            <div className=\"absolute inset-0 flex items-center justify-center\">\n              <div\n                className=\"overflow-hidden rounded-md bg-white shadow-sm\"\n                style={{ width: `${iconDimensions.width}px`, height: `${iconDimensions.height}px` }}\n              >\n                <img src={icon} alt=\"\" className=\"size-full object-cover\" />\n              </div>\n            </div>\n          )}\n\n          {/* Status overlay */}\n          {statusOverlay && (\n            <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 bg-white/90 backdrop-blur-sm\">\n              <statusOverlay.Icon className={cn('size-8', status === 'loading' && 'animate-spin')} />\n              <span className=\"text-foreground text-sm font-medium\">{statusOverlay.text}</span>\n              {statusOverlay.action && (\n                <button\n                  type=\"button\"\n                  className=\"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-ring inline-flex items-center gap-1 rounded-md px-3 py-1 text-xs font-medium focus-visible:ring-2 focus-visible:outline-none\"\n                  onClick={statusOverlay.action}\n                >\n                  <ScanLine className=\"size-3\" />\n                  Refresh\n                </button>\n              )}\n            </div>\n          )}\n        </div>\n\n        {/* Download button (overridable via the `extra` prop) */}\n        {extra !== undefined\n          ? extra\n          : type === 'canvas' &&\n            status === 'active' &&\n            qrDataUrl && (\n              <button\n                type=\"button\"\n                className=\"text-muted-foreground hover:text-foreground focus-visible:ring-ring text-xs underline-offset-2 hover:underline focus-visible:ring-2 focus-visible:outline-none\"\n                onClick={downloadQR}\n              >\n                Download\n              </button>\n            )}\n      </div>\n    )\n  },\n)\nQrCode.displayName = 'QrCode'\n\nexport { QrCode }\n",
      "type": "registry:ui",
      "target": "~/components/ui/qr-code/QrCode.tsx"
    },
    {
      "path": "packages/registry-react/components/qr-code/index.ts",
      "content": "export { QrCode, type QrCodeProps, type QRCodeType, type QRCodeStatus, type QRCodeErrorLevel } from './QrCode'\n",
      "type": "registry:ui",
      "target": "~/components/ui/qr-code/index.ts"
    }
  ],
  "dependencies": [
    "qrcode"
  ],
  "devDependencies": [
    "@types/qrcode"
  ],
  "registryDependencies": [],
  "description": "Static QR code renderer — pass `value` and a size, get an SVG. Useful for sign-in links, share URLs, and Wi-Fi credentials. No dependencies on a heavy QR library.",
  "categories": [
    "data-display"
  ]
}