import qrcode from 'qrcode-generator'; export interface QrShape { /** Width/height in modules (no quiet zone; renderers add margin). */ size: number; /** SVG path in module units: draw it in a `0 0 size size` viewBox. */ path: string; } /** Dark/light grid for `text`. Medium error correction survives a scratched or dim screen. */ export function qrMatrix(text: string): boolean[][] { const qr = qrcode(0, 'M'); // 0 = smallest version that fits qr.addData(text); qr.make(); const n = qr.getModuleCount(); return Array.from({ length: n }, (_, row) => Array.from({ length: n }, (_, col) => qr.isDark(row, col))); } /** One SVG path for the whole code, merging horizontal runs so it stays small to render. */ export function qrShape(text: string): QrShape { const matrix = qrMatrix(text); let path = ''; matrix.forEach((cells, y) => { let x = 0; while (x < cells.length) { if (!cells[x]) { x++; continue; } const start = x; while (x < cells.length && cells[x]) x++; path += `M${start} ${y}h${x - start}v1h${start - x}z`; } }); return { size: matrix.length, path }; }