UNPKG

code-craft-studio

Version:

A comprehensive QR code and barcode scanning/generation library for React. Works with or without Capacitor. Supports 22+ QR data types and 14+ barcode formats (EAN, UPC, Code 128, etc.), with customizable designs, analytics, and React components. Provider

147 lines 8 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useState, useEffect, useCallback, useRef } from 'react'; import { QRCodeStudio } from '../../index'; import { validateQRData, QRValidationError } from '../../core/validators/qr-validators'; // import './QRGenerator.css'; // CSS should be imported by the consuming app export const QRGenerator = ({ type, data, design = {}, size = 300, format = 'png', onGenerate, className = '', style, showDownload = true, showShare = true, errorCorrectionLevel = 'M', version, maskPattern, margin, scale, width, toSJISFunc, }) => { const [qrCode, setQrCode] = useState(null); const [isGenerating, setIsGenerating] = useState(false); const [error, setError] = useState(null); const [selectedFormat, setSelectedFormat] = useState(format); const canvasRef = useRef(null); const containerRef = useRef(null); // Generate QR code when props change useEffect(() => { generateQRCode(); }, [type, data, design, size]); const generateQRCode = useCallback(async () => { try { // Validate data validateQRData(type, data); setIsGenerating(true); setError(null); const result = await QRCodeStudio.generate({ type, data, design, size, errorCorrectionLevel, version, maskPattern, margin, scale, width, toSJISFunc, }); setQrCode(result); onGenerate === null || onGenerate === void 0 ? void 0 : onGenerate(result); // Apply custom design if needed if (design.logo || design.frame) { applyCustomDesign(result); } } catch (err) { if (err instanceof QRValidationError) { setError(`Validation Error: ${err.message}`); } else { setError(err instanceof Error ? err.message : 'Failed to generate QR code'); } } finally { setIsGenerating(false); } }, [type, data, design, size, onGenerate]); const applyCustomDesign = async (qrResult) => { if (!canvasRef.current || !qrResult.dataUrl) return; const canvas = canvasRef.current; const ctx = canvas.getContext('2d'); if (!ctx) return; canvas.width = size; canvas.height = size; // Draw QR code const img = new Image(); img.onload = () => { ctx.drawImage(img, 0, 0, size, size); // Apply logo if provided if (design.logo) { const logoImg = new Image(); logoImg.crossOrigin = 'anonymous'; logoImg.onload = () => { var _a; const logoSize = design.logo.size || size * 0.2; const logoMargin = design.logo.margin || 10; const x = (size - logoSize) / 2; const y = (size - logoSize) / 2; // Draw white background for logo ctx.fillStyle = ((_a = design.colors) === null || _a === void 0 ? void 0 : _a.light) || '#FFFFFF'; ctx.fillRect(x - logoMargin, y - logoMargin, logoSize + logoMargin * 2, logoSize + logoMargin * 2); // Draw logo if (design.logo.borderRadius) { ctx.save(); ctx.beginPath(); ctx.roundRect(x, y, logoSize, logoSize, design.logo.borderRadius); ctx.clip(); ctx.drawImage(logoImg, x, y, logoSize, logoSize); ctx.restore(); } else { ctx.drawImage(logoImg, x, y, logoSize, logoSize); } }; logoImg.src = design.logo.src; } }; img.src = qrResult.dataUrl; }; const handleDownload = async () => { if (!qrCode) return; try { await QRCodeStudio.saveQRCode({ qrCode, fileName: `qrcode_${type}_${Date.now()}`, format: selectedFormat, }); } catch (_a) { setError('Failed to download QR code'); } }; const handleShare = async () => { if (!qrCode || !qrCode.dataUrl) return; if (navigator.share) { try { const blob = await (await fetch(qrCode.dataUrl)).blob(); const file = new File([blob], `qrcode.${selectedFormat}`, { type: `image/${selectedFormat}` }); await navigator.share({ title: 'QR Code', text: `QR Code for ${type}`, files: [file], }); } catch (err) { if (err.name !== 'AbortError') { setError('Failed to share QR code'); } } } else { // Fallback: Copy to clipboard try { await navigator.clipboard.writeText(qrCode.shortUrl || qrCode.landingPageUrl || qrCode.dataUrl); alert('Link copied to clipboard!'); } catch (_a) { setError('Sharing not supported on this device'); } } }; const exportFormats = ['png', 'jpg', 'svg', 'pdf', 'json', 'webp', 'gif', 'eps', 'wmf']; return (_jsxs("div", { ref: containerRef, className: `qr-generator-container ${className}`, style: style, children: [error && (_jsxs("div", { className: "qr-generator-error", children: [_jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), _jsx("p", { children: error }), _jsx("button", { onClick: generateQRCode, children: "Retry" })] })), isGenerating && (_jsxs("div", { className: "qr-generator-loading", children: [_jsx("div", { className: "loading-spinner" }), _jsx("p", { children: "Generating QR Code..." })] })), !isGenerating && qrCode && !error && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "qr-code-preview", children: [qrCode.svg ? (_jsx("div", { className: "qr-code-svg", dangerouslySetInnerHTML: { __html: qrCode.svg }, style: { width: size, height: size } })) : qrCode.dataUrl ? (_jsx("img", { src: qrCode.dataUrl, alt: "QR Code", className: "qr-code-image", style: { width: size, height: size } })) : null, _jsx("canvas", { ref: canvasRef, style: { display: 'none' } })] }), _jsxs("div", { className: "qr-generator-actions", children: [showDownload && (_jsxs("div", { className: "download-section", children: [_jsx("select", { value: selectedFormat, onChange: (e) => setSelectedFormat(e.target.value), className: "format-select", children: exportFormats.map(fmt => (_jsx("option", { value: fmt, children: fmt.toUpperCase() }, fmt))) }), _jsxs("button", { onClick: handleDownload, className: "download-button", children: [_jsx("span", { className: "button-icon", children: "\u2B07\uFE0F" }), "Download"] })] })), showShare && (_jsxs("button", { onClick: handleShare, className: "share-button", children: [_jsx("span", { className: "button-icon", children: "\uD83D\uDD17" }), "Share"] }))] }), qrCode.shortUrl && (_jsxs("div", { className: "qr-code-url", children: [_jsx("label", { children: "Short URL:" }), _jsx("input", { type: "text", value: qrCode.shortUrl, readOnly: true, onClick: (e) => e.target.select() })] })), qrCode.landingPageUrl && (_jsxs("div", { className: "qr-code-url", children: [_jsx("label", { children: "Landing Page:" }), _jsx("input", { type: "text", value: qrCode.landingPageUrl, readOnly: true, onClick: (e) => e.target.select() })] }))] }))] })); }; export default QRGenerator; //# sourceMappingURL=QRGenerator.js.map