32 lines · 908 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 { size, path } = useMemo(() => {
    const qr = encode(value, { ecc: "M", border: 4 });
    const segments: string[] = [];
    qr.data.forEach((row, y) => {
      row.forEach((dark, x) => {
        if (dark) segments.push(`M${x} ${y}h1v1h-1z`);
      });
    });
    return { size: qr.data.length, path: segments.join("") };
  }, [value]);

  return (
    <svg
      role="img"
      aria-label={label}
      viewBox={`0 0 ${size} ${size}`}
      shapeRendering="crispEdges"
      className={className}
    >
      <rect width={size} height={size} fill="#fff" />
      <path d={path} fill="#000" />
    </svg>
  );
}