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
94 lines • 6.93 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useRef, useState, useCallback } from 'react';
import { useCodeCraftStudio } from '../../hooks';
// import './QRScanner.css'; // CSS should be imported by the consuming app
export const QRScanner = ({ onScan, onError, options, className = '', style, showOverlay = true, overlayComponent, }) => {
const [isScanning, setIsScanning] = useState(false);
const [permissionStatus, setPermissionStatus] = useState('prompt');
const [error, setError] = useState(null);
const containerRef = useRef(null);
const scanningRef = useRef(false);
const { isReady, scanQRCode, checkPermissions: checkPlatformPermissions, requestPermissions: requestPlatformPermissions } = useCodeCraftStudio({
onError: (err) => {
setError(err.message);
onError === null || onError === void 0 ? void 0 : onError({ message: err.message, code: 'PLATFORM_ERROR' });
}
});
// Check permissions on mount
useEffect(() => {
if (isReady) {
checkPermissions();
}
}, [isReady]);
const checkPermissions = async () => {
try {
const result = await checkPlatformPermissions();
setPermissionStatus(result.camera || 'prompt');
}
catch (_a) {
setError('Failed to check camera permissions');
}
};
const requestPermissions = async () => {
try {
const result = await requestPlatformPermissions();
setPermissionStatus(result.camera || 'prompt');
if (result.camera === 'granted') {
startScanning();
}
}
catch (_a) {
setError('Failed to request camera permissions');
}
};
const startScanning = useCallback(async () => {
if (scanningRef.current || !isReady)
return;
try {
scanningRef.current = true;
setError(null);
setIsScanning(true);
const result = await scanQRCode(options);
// Successfully scanned
setIsScanning(false);
scanningRef.current = false;
onScan(result);
}
catch (err) {
scanningRef.current = false;
setIsScanning(false);
setError(err instanceof Error ? err.message : 'Failed to scan');
onError === null || onError === void 0 ? void 0 : onError({
code: 'SCAN_ERROR',
message: err instanceof Error ? err.message : 'Failed to scan',
});
}
}, [isReady, options, onError, onScan, scanQRCode]);
const stopScanning = useCallback(() => {
setIsScanning(false);
scanningRef.current = false;
}, []);
const handleContainerClick = () => {
if (permissionStatus === 'prompt' || permissionStatus === 'denied') {
requestPermissions();
}
else if (permissionStatus === 'granted' && !isScanning) {
startScanning();
}
};
// Render permission prompt
if (!isReady) {
return (_jsx("div", { className: `qr-scanner-container ${className}`, style: style, ref: containerRef, children: _jsxs("div", { className: "qr-scanner-loading", children: [_jsx("div", { className: "spinner" }), _jsx("p", { children: "Initializing scanner..." })] }) }));
}
if (permissionStatus === 'denied') {
return (_jsx("div", { className: `qr-scanner-container ${className}`, style: style, ref: containerRef, children: _jsxs("div", { className: "qr-scanner-permission-denied", children: [_jsx("svg", { className: "icon", viewBox: "0 0 24 24", width: "48", height: "48", children: _jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }), _jsx("h3", { children: "Camera Permission Denied" }), _jsx("p", { children: "Please enable camera permissions in your browser settings to use the QR scanner." })] }) }));
}
if (error) {
return (_jsx("div", { className: `qr-scanner-container ${className}`, style: style, ref: containerRef, children: _jsxs("div", { className: "qr-scanner-error", children: [_jsx("svg", { className: "icon", viewBox: "0 0 24 24", width: "48", height: "48", children: _jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) }), _jsx("h3", { children: "Scanner Error" }), _jsx("p", { children: error }), _jsx("button", { onClick: () => setError(null), className: "qr-scanner-button", children: "Try Again" })] }) }));
}
return (_jsxs("div", { className: `qr-scanner-container ${className}`, style: style, ref: containerRef, onClick: handleContainerClick, children: [permissionStatus === 'prompt' && !isScanning && (_jsxs("div", { className: "qr-scanner-prompt", children: [_jsx("svg", { className: "icon", viewBox: "0 0 24 24", width: "48", height: "48", children: _jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }), _jsx("h3", { children: "Enable Camera Access" }), _jsx("p", { children: "Click to enable camera access for QR code scanning" }), _jsx("button", { className: "qr-scanner-button qr-scanner-button-primary", children: "Enable Camera" })] })), permissionStatus === 'granted' && !isScanning && (_jsxs("div", { className: "qr-scanner-ready", children: [_jsx("svg", { className: "icon", viewBox: "0 0 24 24", width: "48", height: "48", children: _jsx("path", { d: "M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" }) }), _jsx("h3", { children: "Ready to Scan" }), _jsx("p", { children: "Click to start scanning QR codes" }), _jsx("button", { className: "qr-scanner-button qr-scanner-button-primary", children: "Start Scanning" })] })), isScanning && (_jsxs(_Fragment, { children: [showOverlay && !overlayComponent && (_jsxs("div", { className: "qr-scanner-overlay", children: [_jsxs("div", { className: "qr-scanner-frame", children: [_jsx("div", { className: "corner corner-tl" }), _jsx("div", { className: "corner corner-tr" }), _jsx("div", { className: "corner corner-bl" }), _jsx("div", { className: "corner corner-br" })] }), _jsx("p", { className: "qr-scanner-hint", children: "Align QR code within the frame" }), _jsx("button", { className: "qr-scanner-button qr-scanner-cancel-button", onClick: (e) => {
e.stopPropagation();
stopScanning();
}, children: "Cancel" })] })), overlayComponent] }))] }));
};
//# sourceMappingURL=QRScanner.js.map