payment QR: center Goblin mark (opt-in, level H)
This commit is contained in:
@@ -99,7 +99,7 @@ function PayQR({ value }: { value: string }) {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<div className="rounded-2xl bg-white p-3 shadow-sm">
|
||||
<QRCodeCanvas value={value} size={224} level="M" className="h-auto w-full max-w-56" />
|
||||
<QRCodeCanvas value={value} size={224} level="H" logo className="h-auto w-full max-w-56" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,11 +6,17 @@ interface QRCodeCanvasProps {
|
||||
size?: number;
|
||||
level?: 'L' | 'M' | 'Q' | 'H';
|
||||
className?: string;
|
||||
/** Overlay the Goblin mark in the center (payment QRs only). Forces level H. */
|
||||
logo?: boolean;
|
||||
}
|
||||
|
||||
export function QRCodeCanvas({ value, size = 256, level = 'M', className }: QRCodeCanvasProps) {
|
||||
export function QRCodeCanvas({ value, size = 256, level = 'M', className, logo = false }: QRCodeCanvasProps) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
// When the logo is shown, force the highest error-correction level so the
|
||||
// center overlay never breaks scanning.
|
||||
const effectiveLevel = logo ? 'H' : level;
|
||||
|
||||
useEffect(() => {
|
||||
if (!canvasRef.current) return;
|
||||
|
||||
@@ -22,7 +28,7 @@ export function QRCodeCanvas({ value, size = 256, level = 'M', className }: QRCo
|
||||
{
|
||||
width: size,
|
||||
margin: 1,
|
||||
errorCorrectionLevel: level,
|
||||
errorCorrectionLevel: effectiveLevel,
|
||||
},
|
||||
(error) => {
|
||||
if (error) console.error('QR Code generation error:', error);
|
||||
@@ -35,7 +41,36 @@ export function QRCodeCanvas({ value, size = 256, level = 'M', className }: QRCo
|
||||
// className (e.g. `h-auto w-full`) controls the rendered size responsively.
|
||||
canvas.style.removeProperty('width');
|
||||
canvas.style.removeProperty('height');
|
||||
}, [value, size, level]);
|
||||
}, [value, size, effectiveLevel]);
|
||||
|
||||
return <canvas ref={canvasRef} className={className} />;
|
||||
if (!logo) {
|
||||
return <canvas ref={canvasRef} className={className} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`relative inline-block ${className ?? ''}`}>
|
||||
<canvas ref={canvasRef} className="block h-auto w-full" />
|
||||
<div
|
||||
aria-hidden="true"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
margin: 'auto',
|
||||
width: '24%',
|
||||
height: '24%',
|
||||
padding: '4%',
|
||||
borderRadius: '18%',
|
||||
background: '#fff',
|
||||
boxSizing: 'border-box',
|
||||
}}
|
||||
>
|
||||
<svg viewBox="0 0 64 64" aria-hidden="true" style={{ width: '100%', height: '100%', display: 'block' }}>
|
||||
<path fill="#201d09" d="M20 22c0-3 3-5 6-4l6 3 6-3c3-1 6 1 6 4v10c0 8-6 14-12 14S20 40 20 32z" />
|
||||
<circle cx="26" cy="30" r="3" fill="#fff" />
|
||||
<circle cx="38" cy="30" r="3" fill="#fff" />
|
||||
<path fill="#fff" d="M28 40h8l-4 5z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user