30 lines
894 B
TypeScript
30 lines
894 B
TypeScript
import { useMemo } from 'react';
|
|
import { encodeQr } from '@/lib/qr';
|
|
import styles from './QrCode.module.css';
|
|
|
|
const QUIET = 4; // 码周围的静区(模块数),规范要求 ≥ 4
|
|
|
|
export function QrCode({ text, label }: { text: string; label: string }) {
|
|
const grid = useMemo(() => {
|
|
try {
|
|
return encodeQr(text);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}, [text]);
|
|
|
|
if (!grid) return <p className={styles.fail}>内容太长,无法生成二维码。</p>;
|
|
|
|
const n = grid.length + QUIET * 2;
|
|
const path = grid
|
|
.flatMap((row, y) => row.map((dark, x) => (dark ? `M${x + QUIET} ${y + QUIET}h1v1h-1z` : '')))
|
|
.join('');
|
|
|
|
return (
|
|
<svg className={styles.qr} viewBox={`0 0 ${n} ${n}`} role="img" aria-label={label} shapeRendering="crispEdges">
|
|
<rect width={n} height={n} className={styles.bg} />
|
|
<path d={path} className={styles.fg} />
|
|
</svg>
|
|
);
|
|
}
|