23 lines · 977 B
import { useMemo } from "react";
import { encode } from "uqr";

type Props = { value: string; label: string; className?: string };

/** Dark modules on a white quiet zone so phone cameras can scan it on the dark theme. */
export function QrCode({ value, label, className }: Props) {
  const src = useMemo(() => {
    const qr = encode(value, { ecc: "M", border: 4 });
    const size = qr.data.length;
    const segments: string[] = [];
    qr.data.forEach((row, y) => {
      row.forEach((dark, x) => {
        if (dark) segments.push(`M${x} ${y}h1v1h-1z`);
      });
    });
    const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" shape-rendering="crispEdges"><rect width="${size}" height="${size}" fill="#fff"/><path d="${segments.join("")}" fill="#000"/></svg>`;
    return `data:image/svg+xml,${encodeURIComponent(svg)}`;
  }, [value]);

  return <img src={src} alt={label} className={className} style={{ imageRendering: "pixelated" }} />;
}