qrcode-studio
Version:
A comprehensive Capacitor plugin for QR code and barcode scanning/generation. Supports 22+ QR data types and 14+ barcode formats (EAN, UPC, Code 128, etc.), with customizable designs, analytics, and React components. Works seamlessly across web, iOS, and
114 lines • 5.89 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useRef, useState, useCallback } from 'react';
import { QRCodeStudio } from '../../index';
// 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);
// Check permissions on mount
useEffect(() => {
checkPermissions();
}, []);
// Handle scan results
useEffect(() => {
if (!isScanning)
return;
const handleScanResult = (result) => {
onScan(result);
};
const handleScanError = (error) => {
setError(error.message);
onError === null || onError === void 0 ? void 0 : onError(error);
};
const resultListener = QRCodeStudio.addListener('scanResult', handleScanResult);
const errorListener = QRCodeStudio.addListener('scanError', handleScanError);
return () => {
resultListener.then(l => l.remove());
errorListener.then(l => l.remove());
};
}, [isScanning, onScan, onError]);
const checkPermissions = async () => {
try {
const result = await QRCodeStudio.checkPermissions();
setPermissionStatus(result.camera);
}
catch (_a) {
setError('Failed to check camera permissions');
}
};
const requestPermissions = async () => {
try {
const result = await QRCodeStudio.requestPermissions();
setPermissionStatus(result.camera);
if (result.camera === 'granted') {
startScanning();
}
}
catch (_a) {
setError('Failed to request camera permissions');
}
};
const startScanning = useCallback(async () => {
if (scanningRef.current)
return;
try {
scanningRef.current = true;
setError(null);
await QRCodeStudio.startScan(options);
setIsScanning(true);
}
catch (err) {
scanningRef.current = false;
setError(err instanceof Error ? err.message : 'Failed to start scanner');
onError === null || onError === void 0 ? void 0 : onError({
code: 'START_SCAN_ERROR',
message: err instanceof Error ? err.message : 'Failed to start scanner',
});
}
}, [options, onError]);
const stopScanning = useCallback(async () => {
if (!scanningRef.current)
return;
try {
await QRCodeStudio.stopScan();
setIsScanning(false);
scanningRef.current = false;
}
catch (err) {
setError(err instanceof Error ? err.message : 'Failed to stop scanner');
}
}, []);
// Cleanup on unmount
useEffect(() => {
return () => {
if (scanningRef.current) {
QRCodeStudio.stopScan().catch(console.error);
}
};
}, []);
const renderPermissionRequest = () => (_jsxs("div", { className: "qr-scanner-permission", children: [_jsx("div", { className: "permission-icon", children: "\uD83D\uDCF7" }), _jsx("h3", { children: "Camera Permission Required" }), _jsx("p", { children: "This app needs camera access to scan QR codes" }), _jsx("button", { className: "permission-button", onClick: requestPermissions, children: "Grant Permission" })] }));
const renderError = () => (_jsxs("div", { className: "qr-scanner-error", children: [_jsx("div", { className: "error-icon", children: "\u26A0\uFE0F" }), _jsx("h3", { children: "Scanner Error" }), _jsx("p", { children: error }), _jsx("button", { className: "retry-button", onClick: () => {
setError(null);
if (permissionStatus === 'granted') {
startScanning();
}
else {
requestPermissions();
}
}, children: "Retry" })] }));
const renderScanner = () => (_jsxs(_Fragment, { children: [_jsx("div", { className: "qr-scanner-video" }), showOverlay && (overlayComponent || (_jsxs("div", { className: "qr-scanner-overlay", children: [_jsxs("div", { className: "scan-region", children: [_jsx("div", { className: "corner top-left" }), _jsx("div", { className: "corner top-right" }), _jsx("div", { className: "corner bottom-left" }), _jsx("div", { className: "corner bottom-right" })] }), _jsx("div", { className: "scan-line" }), _jsx("p", { className: "scan-hint", children: "Position QR code within the frame" })] }))), _jsx("button", { className: "stop-scan-button", onClick: stopScanning, children: "Stop Scanning" })] }));
const renderControls = () => (_jsx("div", { className: "qr-scanner-controls", children: _jsx("button", { className: "start-scan-button", onClick: () => {
if (permissionStatus === 'granted') {
startScanning();
}
else {
requestPermissions();
}
}, children: "Start Scanner" }) }));
return (_jsxs("div", { ref: containerRef, className: `qr-scanner-container ${className}`, style: style, children: [error && renderError(), !error && permissionStatus === 'denied' && renderPermissionRequest(), !error && permissionStatus === 'granted' && !isScanning && renderControls(), !error && isScanning && renderScanner()] }));
};
export default QRScanner;
//# sourceMappingURL=QRScanner.js.map