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
JavaScript
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