{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"qr-code","type":"registry:ui","title":"qr-code","description":"QR Code is a component that generates a QR code from a string.","author":"Hayden Bleasel <hello@haydenbleasel.com>","dependencies":["culori","qrcode"],"devDependencies":["@types/culori","@types/qrcode"],"registryDependencies":[],"files":[{"type":"registry:ui","path":"index.tsx","content":"\"use client\";\n\nimport { formatHex, oklch } from \"culori\";\nimport QR from \"qrcode\";\nimport { type HTMLAttributes, useEffect, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type QRCodeProps = HTMLAttributes<HTMLDivElement> & {\n  data: string;\n  foreground?: string;\n  background?: string;\n  robustness?: \"L\" | \"M\" | \"Q\" | \"H\";\n};\n\nconst oklchRegex = /oklch\\(([0-9.]+)\\s+([0-9.]+)\\s+([0-9.]+)\\)/;\n\nconst getOklch = (color: string, fallback: [number, number, number]) => {\n  const oklchMatch = color.match(oklchRegex);\n\n  if (!oklchMatch) {\n    return { l: fallback[0], c: fallback[1], h: fallback[2] };\n  }\n\n  return {\n    l: Number.parseFloat(oklchMatch[1]),\n    c: Number.parseFloat(oklchMatch[2]),\n    h: Number.parseFloat(oklchMatch[3]),\n  };\n};\n\nexport const QRCode = ({\n  data,\n  foreground,\n  background,\n  robustness = \"M\",\n  className,\n  ...props\n}: QRCodeProps) => {\n  const [svg, setSVG] = useState<string | null>(null);\n\n  useEffect(() => {\n    const generateQR = async () => {\n      try {\n        const styles = getComputedStyle(document.documentElement);\n        const foregroundColor =\n          foreground ?? styles.getPropertyValue(\"--foreground\");\n        const backgroundColor =\n          background ?? styles.getPropertyValue(\"--background\");\n\n        const foregroundOklch = getOklch(\n          foregroundColor,\n          [0.21, 0.006, 285.885]\n        );\n        const backgroundOklch = getOklch(backgroundColor, [0.985, 0, 0]);\n\n        const newSvg = await QR.toString(data, {\n          type: \"svg\",\n          color: {\n            dark: formatHex(oklch({ mode: \"oklch\", ...foregroundOklch })),\n            light: formatHex(oklch({ mode: \"oklch\", ...backgroundOklch })),\n          },\n          width: 200,\n          errorCorrectionLevel: robustness,\n          margin: 0,\n        });\n\n        setSVG(newSvg);\n      } catch (err) {\n        console.error(err);\n      }\n    };\n\n    generateQR();\n  }, [data, foreground, background, robustness]);\n\n  if (!svg) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\"size-full\", \"[&_svg]:size-full\", className)}\n      // biome-ignore lint/security/noDangerouslySetInnerHtml: \"Required for SVG\"\n      dangerouslySetInnerHTML={{ __html: svg }}\n      {...props}\n    />\n  );\n};\n","target":"components/kibo-ui/qr-code/index.tsx"},{"type":"registry:ui","path":"server.tsx","content":"import QR from \"qrcode\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type QRCodeProps = HTMLAttributes<HTMLDivElement> & {\n  data: string;\n  foreground: string;\n  background: string;\n  robustness?: \"L\" | \"M\" | \"Q\" | \"H\";\n};\n\nexport const QRCode = async ({\n  data,\n  foreground,\n  background,\n  robustness = \"M\",\n  className,\n  ...props\n}: QRCodeProps) => {\n  const svg = await QR.toString(data, {\n    type: \"svg\",\n    color: {\n      dark: foreground,\n      light: background,\n    },\n    width: 200,\n    errorCorrectionLevel: robustness,\n  });\n\n  if (!svg) {\n    throw new Error(\"Failed to generate QR code\");\n  }\n\n  return (\n    <div\n      className={cn(\"size-full\", \"[&_svg]:size-full\", className)}\n      // biome-ignore lint/security/noDangerouslySetInnerHtml: \"Required for SVG\"\n      dangerouslySetInnerHTML={{ __html: svg }}\n      {...props}\n    />\n  );\n};\n","target":"components/kibo-ui/qr-code/server.tsx"}],"css":{}}