feat: add QR code generator tool
Add a sixth tool with live SVG preview, customizable foreground/background colors, error correction level, margin control, and export as PNG (256–2048px) or SVG. URL params enable shareable state. All processing runs client-side via the qrcode package. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
85
lib/qrcode/urlSharing.ts
Normal file
85
lib/qrcode/urlSharing.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
'use client';
|
||||
|
||||
import type { ErrorCorrectionLevel } from '@/types/qrcode';
|
||||
|
||||
export interface QRShareableState {
|
||||
text?: string;
|
||||
errorCorrection?: ErrorCorrectionLevel;
|
||||
foregroundColor?: string;
|
||||
backgroundColor?: string;
|
||||
margin?: number;
|
||||
}
|
||||
|
||||
const DEFAULTS = {
|
||||
errorCorrection: 'M' as ErrorCorrectionLevel,
|
||||
foregroundColor: '#000000',
|
||||
backgroundColor: '#ffffff',
|
||||
margin: 4,
|
||||
};
|
||||
|
||||
export function decodeQRFromUrl(): QRShareableState | null {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const text = params.get('text');
|
||||
const ec = params.get('ec') as ErrorCorrectionLevel | null;
|
||||
const fg = params.get('fg');
|
||||
const bg = params.get('bg');
|
||||
const margin = params.get('margin');
|
||||
|
||||
if (!text && !ec && !fg && !bg && !margin) return null;
|
||||
|
||||
return {
|
||||
text: text || undefined,
|
||||
errorCorrection: ec || undefined,
|
||||
foregroundColor: fg ? `#${fg}` : undefined,
|
||||
backgroundColor: bg ? `#${bg}` : undefined,
|
||||
margin: margin ? parseInt(margin, 10) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function updateQRUrl(
|
||||
text: string,
|
||||
errorCorrection: ErrorCorrectionLevel,
|
||||
foregroundColor: string,
|
||||
backgroundColor: string,
|
||||
margin: number,
|
||||
): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (text) params.set('text', text);
|
||||
if (errorCorrection !== DEFAULTS.errorCorrection) params.set('ec', errorCorrection);
|
||||
if (foregroundColor !== DEFAULTS.foregroundColor) params.set('fg', foregroundColor.replace('#', ''));
|
||||
if (backgroundColor !== DEFAULTS.backgroundColor) params.set('bg', backgroundColor.replace('#', ''));
|
||||
if (margin !== DEFAULTS.margin) params.set('margin', String(margin));
|
||||
|
||||
const query = params.toString();
|
||||
const newUrl = query
|
||||
? `${window.location.pathname}?${query}`
|
||||
: window.location.pathname;
|
||||
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
}
|
||||
|
||||
export function getQRShareableUrl(
|
||||
text: string,
|
||||
errorCorrection: ErrorCorrectionLevel,
|
||||
foregroundColor: string,
|
||||
backgroundColor: string,
|
||||
margin: number,
|
||||
): string {
|
||||
if (typeof window === 'undefined') return '';
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (text) params.set('text', text);
|
||||
if (errorCorrection !== DEFAULTS.errorCorrection) params.set('ec', errorCorrection);
|
||||
if (foregroundColor !== DEFAULTS.foregroundColor) params.set('fg', foregroundColor.replace('#', ''));
|
||||
if (backgroundColor !== DEFAULTS.backgroundColor) params.set('bg', backgroundColor.replace('#', ''));
|
||||
if (margin !== DEFAULTS.margin) params.set('margin', String(margin));
|
||||
|
||||
const query = params.toString();
|
||||
return `${window.location.origin}${window.location.pathname}${query ? `?${query}` : ''}`;
|
||||
}
|
||||
Reference in New Issue
Block a user