{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "qr-code",
  "title": "QR Code",
  "description": "A beautiful QR code component with dot styling, gradient support, and extensive color customization.",
  "dependencies": [
    "qrcode"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/spark-ui/qr-code.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport QRCodeLib from \"qrcode\";\nimport * as React from \"react\";\n\ntype GradientPreset =\n  | \"default\"\n  | \"ocean\"\n  | \"sunset\"\n  | \"forest\"\n  | \"berry\"\n  | \"twilight\"\n  | \"aurora\"\n  | \"fire\"\n  | \"neon\"\n  | \"rose\"\n  | \"mint\";\n\nexport type { GradientPreset };\n\ninterface QRCodeProps extends React.SVGProps<SVGSVGElement> {\n  /** The URL or data to encode in the QR code */\n  value: string;\n  /** Overall size of the QR code */\n  size?: number;\n  /** Foreground color (ignored if gradient is set) */\n  fgColor?: string;\n  /** Background color */\n  bgColor?: string;\n  /** Error correction level */\n  errorCorrectionLevel?: \"L\" | \"M\" | \"Q\" | \"H\";\n  /** Gradient preset to apply */\n  gradient?: GradientPreset;\n  /** Custom className for the SVG */\n  className?: string;\n}\n\nconst gradients: Record<GradientPreset, [string, string]> = {\n  default: [\"var(--foreground)\", \"var(--foreground)\"],\n  ocean: [\"#06b6d4\", \"#3b82f6\"],\n  sunset: [\"#f97316\", \"#ec4899\"],\n  forest: [\"#22c55e\", \"#06b6d4\"],\n  berry: [\"#8b5cf6\", \"#ec4899\"],\n  twilight: [\"#6366f1\", \"#06b6d4\"],\n  aurora: [\"#10b981\", \"#8b5cf6\"],\n  fire: [\"#ef4444\", \"#f59e0b\"],\n  neon: [\"#06b6d4\", \"#8b5cf6\"],\n  rose: [\"#f43f5e\", \"#ec4899\"],\n  mint: [\"#10b981\", \"#06b6d4\"],\n};\n\nfunction isInFinderPattern(row: number, col: number, size: number): boolean {\n  return (\n    (row < 7 && col < 7) ||\n    (row < 7 && col >= size - 7) ||\n    (row >= size - 7 && col < 7)\n  );\n}\n\nexport function QRCode({\n  value,\n  size = 160,\n  fgColor = \"var(--foreground)\",\n  bgColor = \"var(--background)\",\n  errorCorrectionLevel = \"M\",\n  gradient = \"default\",\n  className,\n  ...props\n}: QRCodeProps) {\n  const qrData = React.useMemo(() => {\n    try {\n      return QRCodeLib.create(value, { errorCorrectionLevel });\n    } catch {\n      return null;\n    }\n  }, [value, errorCorrectionLevel]);\n\n  if (!qrData) {\n    return null;\n  }\n\n  const moduleCount = qrData.modules.size;\n  const moduleSize = size / moduleCount;\n  const radius = moduleSize * 0.45;\n  const gradientId = `qr-grad-${gradient}-${size}`;\n  const [gradStart, gradEnd] = gradients[gradient];\n  const useGradient = gradient !== \"default\";\n  const effectiveColor = useGradient ? `url(#${gradientId})` : (gradient === \"default\" ? fgColor : gradStart);\n\n  const finderPositions: [number, number][] = [\n    [0, 0],\n    [0, moduleCount - 7],\n    [moduleCount - 7, 0],\n  ];\n\n  const finderOuterSize = 7 * moduleSize;\n  const finderMiddleSize = 3 * moduleSize;\n\n  const dots: { cx: number; cy: number }[] = [];\n\n  for (let row = 0; row < moduleCount; row++) {\n    for (let col = 0; col < moduleCount; col++) {\n      if (\n        qrData.modules.get(row, col) &&\n        !isInFinderPattern(row, col, moduleCount)\n      ) {\n        dots.push({\n          cx: (col + 0.5) * moduleSize,\n          cy: (row + 0.5) * moduleSize,\n        });\n      }\n    }\n  }\n\n  return (\n    <svg\n      width={size}\n      height={size}\n      viewBox={`0 0 ${size} ${size}`}\n      className={cn(className)}\n      {...props}\n    >\n      <defs>\n        {useGradient && (\n          <linearGradient\n            id={gradientId}\n            x1=\"0%\"\n            y1=\"0%\"\n            x2=\"100%\"\n            y2=\"100%\"\n          >\n            <stop offset=\"0%\" stopColor={gradStart} />\n            <stop offset=\"100%\" stopColor={gradEnd} />\n          </linearGradient>\n        )}\n      </defs>\n\n      <rect width={size} height={size} fill={bgColor} rx={moduleSize * 1.5} />\n\n      {finderPositions.map(([r, c], idx) => {\n        const cx = c * moduleSize + finderOuterSize / 2;\n        const cy = r * moduleSize + finderOuterSize / 2;\n        const outerSize = finderOuterSize;\n        const whiteSize = finderOuterSize - moduleSize * 1.5;\n        const innerSize = finderMiddleSize;\n\n        return (\n          <g key={`finder-${idx}`}>\n            <rect\n              x={cx - outerSize / 2}\n              y={cy - outerSize / 2}\n              width={outerSize}\n              height={outerSize}\n              rx={outerSize * 0.3}\n              ry={outerSize * 0.3}\n              fill={effectiveColor}\n            />\n            <rect\n              x={cx - whiteSize / 2}\n              y={cy - whiteSize / 2}\n              width={whiteSize}\n              height={whiteSize}\n              rx={whiteSize * 0.3}\n              ry={whiteSize * 0.3}\n              fill={bgColor}\n            />\n            <rect\n              x={cx - innerSize / 2}\n              y={cy - innerSize / 2}\n              width={innerSize}\n              height={innerSize}\n              rx={innerSize * 0.3}\n              ry={innerSize * 0.3}\n              fill={effectiveColor}\n            />\n          </g>\n        );\n      })}\n\n      {dots.map(({ cx, cy }, i) => (\n        <circle key={i} cx={cx} cy={cy} r={radius} fill={effectiveColor} />\n      ))}\n    </svg>\n  );\n}\n\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}