UNPKG

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

96 lines 7.36 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useRef, useState } from 'react'; import { QRCodeStudio } from '../index'; export const BarcodeScanner = ({ onScan, onError, formats, showTorchButton = true, showFormatSelector = false, multiple = false, scanOptions = {}, className = '', style = {}, showOverlay = true, overlayComponent, showProductInfo = true, }) => { const [isScanning, setIsScanning] = useState(false); const [torchEnabled, setTorchEnabled] = useState(false); const [torchAvailable, setTorchAvailable] = useState(false); const [selectedFormats, setSelectedFormats] = useState(formats || []); const [lastScan, setLastScan] = useState(null); const scannerRef = useRef(null); useEffect(() => { let scanListener; let errorListener; let torchListener; const initScanner = async () => { try { // Check permissions const permissions = await QRCodeStudio.checkPermissions(); if (permissions.camera !== 'granted') { const requestResult = await QRCodeStudio.requestPermissions(); if (requestResult.camera !== 'granted') { onError === null || onError === void 0 ? void 0 : onError({ code: 'PERMISSION_DENIED', message: 'Camera permission denied', }); return; } } // Check torch availability const torch = await QRCodeStudio.isTorchAvailable(); setTorchAvailable(torch.available); // Setup listeners scanListener = await QRCodeStudio.addListener('scanResult', (result) => { setLastScan(result); onScan(result); }); errorListener = await QRCodeStudio.addListener('scanError', (error) => { onError === null || onError === void 0 ? void 0 : onError(error); }); torchListener = await QRCodeStudio.addListener('torchStateChanged', (state) => { setTorchEnabled(state.isEnabled); }); // Start scanning await QRCodeStudio.startScan(Object.assign(Object.assign({}, scanOptions), { formats: selectedFormats.length > 0 ? selectedFormats : undefined, multiple, showTorchButton: false })); setIsScanning(true); } catch (error) { onError === null || onError === void 0 ? void 0 : onError({ code: 'INIT_ERROR', message: error instanceof Error ? error.message : 'Failed to initialize scanner', }); } }; initScanner(); return () => { if (isScanning) { QRCodeStudio.stopScan(); } scanListener === null || scanListener === void 0 ? void 0 : scanListener.remove(); errorListener === null || errorListener === void 0 ? void 0 : errorListener.remove(); torchListener === null || torchListener === void 0 ? void 0 : torchListener.remove(); }; }, [selectedFormats, multiple]); const handleTorchToggle = async () => { try { if (torchEnabled) { await QRCodeStudio.disableTorch(); } else { await QRCodeStudio.enableTorch(); } } catch (error) { console.error('Failed to toggle torch:', error); } }; const handleFormatChange = (format, checked) => { setSelectedFormats(prev => { if (checked) { return [...prev, format]; } else { return prev.filter(f => f !== format); } }); }; const formatGroups = { '2D Codes': ['QR_CODE', 'DATA_MATRIX', 'AZTEC', 'PDF_417', 'MAXICODE'], 'Product Codes': ['EAN_13', 'EAN_8', 'UPC_A', 'UPC_E'], 'Industrial Codes': ['CODE_128', 'CODE_39', 'CODE_93', 'CODABAR', 'ITF', 'ITF_14'], 'Specialty': ['MSI', 'MSI_PLESSEY', 'PHARMACODE', 'RSS_14', 'RSS_EXPANDED'], }; return (_jsxs("div", { ref: scannerRef, className: `barcode-scanner ${className}`, style: Object.assign({ position: 'relative', width: '100%', height: '100%' }, style), children: [showOverlay && !overlayComponent && (_jsxs("div", { className: "barcode-scanner-overlay", children: [_jsxs("div", { className: "scanning-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" })] }), _jsxs("div", { className: "scanner-controls", children: [showTorchButton && torchAvailable && (_jsx("button", { className: `torch-button ${torchEnabled ? 'enabled' : ''}`, onClick: handleTorchToggle, "aria-label": torchEnabled ? 'Turn off flashlight' : 'Turn on flashlight', children: _jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: torchEnabled ? (_jsx("path", { d: "M6,14L7,14.05L13,14.05L14,14L14,7L13,6.95L7,6.95L6,7L6,14M8,2L16,2L16,7L20,7L20,12L16,12L16,22L8,22L8,12L4,12L4,7L8,7L8,2M10,4L10,10L14,10L14,4L10,4Z" })) : (_jsx("path", { d: "M6,14L7,14.05L13,14.05L14,14L14,7L13,6.95L7,6.95L6,7L6,14M8,2L16,2L16,7L20,7L20,12L16,12L16,22L8,22L8,12L4,12L4,7L8,7L8,2Z" })) }) })), showFormatSelector && (_jsxs("div", { className: "format-selector", children: [_jsx("button", { className: "format-selector-toggle", children: _jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M3,4H7V8H3V4M9,5V7H21V5H9M3,10H7V14H3V10M9,11V13H21V11H9M3,16H7V20H3V16M9,17V19H21V17H9" }) }) }), _jsx("div", { className: "format-dropdown", children: Object.entries(formatGroups).map(([group, groupFormats]) => (_jsxs("div", { className: "format-group", children: [_jsx("div", { className: "format-group-label", children: group }), groupFormats.map(format => (_jsxs("label", { className: "format-option", children: [_jsx("input", { type: "checkbox", checked: selectedFormats.includes(format), onChange: (e) => handleFormatChange(format, e.target.checked) }), _jsx("span", { children: format.replace(/_/g, ' ') })] }, format)))] }, group))) })] }))] }), lastScan && showProductInfo && lastScan.productInfo && (_jsx("div", { className: "product-info-overlay", children: _jsxs("div", { className: "product-info", children: [_jsx("h3", { children: lastScan.productInfo.name }), lastScan.productInfo.brand && _jsx("p", { className: "brand", children: lastScan.productInfo.brand }), lastScan.productInfo.price && (_jsxs("p", { className: "price", children: [lastScan.productInfo.price.currency, " ", lastScan.productInfo.price.value] })), _jsx("p", { className: "barcode", children: lastScan.content }), _jsx("p", { className: "format", children: lastScan.format.replace(/_/g, ' ') })] }) })), _jsx("div", { className: "scanner-instructions", children: multiple ? 'Scan multiple barcodes' : 'Position barcode within frame' })] })), overlayComponent] })); }; export default BarcodeScanner; //# sourceMappingURL=BarcodeScanner.js.map