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

96 lines 7.28 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useRef, useState } from 'react'; import { getPlatform } from '../platforms'; export const BarcodeScanner = ({ onScan, onError, formats, showTorchButton = true, showFormatSelector = false, multiple = false, className = '', style = {}, showOverlay = true, overlayComponent, showProductInfo = true, }) => { const [isScanning, setIsScanning] = useState(false); const [torchEnabled, setTorchEnabled] = useState(false); const [torchAvailable] = useState(false); const [selectedFormats, setSelectedFormats] = useState(formats || []); const [lastScan, setLastScan] = useState(null); const scannerRef = useRef(null); const [, setPlatform] = useState(null); useEffect(() => { // Removed unused listeners since we're using polling approach const initScanner = async () => { const QRCodeStudio = await getPlatform(); setPlatform(QRCodeStudio); 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; } } // For web platform, we'll simulate continuous scanning const scanLoop = async () => { if (!isScanning) return; try { const result = await QRCodeStudio.scanBarcode({ formats: selectedFormats.length > 0 ? selectedFormats : undefined, }); setLastScan(result); onScan(result); if (!multiple) { setIsScanning(false); } else { // Continue scanning for multiple barcodes setTimeout(scanLoop, 1000); } } catch (error) { if (error instanceof Error && error.message !== 'Scan cancelled') { onError === null || onError === void 0 ? void 0 : onError({ code: 'SCAN_ERROR', message: error.message, }); } } }; setIsScanning(true); scanLoop(); } 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 () => { setIsScanning(false); }; }, [selectedFormats, multiple]); const handleTorchToggle = async () => { // Torch functionality is not available in the current platform adapter // This would need to be implemented in the native plugin setTorchEnabled(!torchEnabled); }; 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