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
277 lines • 10.2 kB
JavaScript
import { QRType } from '../types';
/**
* Validates if a string is a valid URL
*/
export function isValidUrl(url) {
try {
const urlObj = new URL(url);
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
}
catch (_a) {
return false;
}
}
/**
* Validates if a string is a valid email address
*/
export function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
/**
* Validates if a string is a valid phone number
*/
export function isValidPhoneNumber(phone) {
// Basic validation for international phone numbers
const phoneRegex = /^\+[1-9]\d{1,14}$/;
return phoneRegex.test(phone);
}
/**
* Validates if a string is a valid hex color
*/
export function isValidHexColor(color) {
const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
return hexRegex.test(color);
}
/**
* Validates if a number is a valid QR code size
*/
export function isValidQRSize(size) {
return size >= 50 && size <= 1000;
}
/**
* Validates QR data based on type
*/
export function validateQRData(type, data) {
const dataAny = data;
switch (type) {
case QRType.TEXT:
return Boolean(dataAny.text && dataAny.text.length > 0);
case QRType.WEBSITE:
return Boolean(dataAny.url && isValidUrl(dataAny.url));
case QRType.EMAIL:
return Boolean(dataAny.to && isValidEmail(dataAny.to));
case QRType.PHONE:
return Boolean(dataAny.phoneNumber && isValidPhoneNumber(dataAny.phoneNumber));
case QRType.SMS:
return Boolean(dataAny.phoneNumber && isValidPhoneNumber(dataAny.phoneNumber));
case QRType.WHATSAPP:
return Boolean(dataAny.phoneNumber && isValidPhoneNumber(dataAny.phoneNumber));
case QRType.WIFI:
return Boolean(dataAny.ssid && dataAny.ssid.length > 0);
case QRType.VCARD:
return Boolean((dataAny.firstName || dataAny.lastName) &&
(dataAny.phone || dataAny.email));
case QRType.LOCATION:
return Boolean(typeof dataAny.latitude === 'number' &&
typeof dataAny.longitude === 'number' &&
dataAny.latitude >= -90 && dataAny.latitude <= 90 &&
dataAny.longitude >= -180 && dataAny.longitude <= 180);
case QRType.EVENT:
return Boolean(dataAny.title &&
dataAny.startDate &&
isValidDate(dataAny.startDate));
case QRType.SOCIAL_MEDIA:
return Boolean(dataAny.facebook || dataAny.instagram || dataAny.twitter ||
dataAny.linkedin || dataAny.youtube || dataAny.tiktok);
case QRType.PDF:
case QRType.VIDEO:
case QRType.MP3:
return Boolean(dataAny.url && isValidUrl(dataAny.url));
case QRType.FACEBOOK:
case QRType.INSTAGRAM:
return Boolean((dataAny.pageUrl && isValidUrl(dataAny.pageUrl)) ||
(dataAny.profileUrl && isValidUrl(dataAny.profileUrl)));
case QRType.IMAGES:
return Boolean(dataAny.images &&
Array.isArray(dataAny.images) &&
dataAny.images.length > 0);
case QRType.MENU:
return Boolean(dataAny.restaurantName &&
dataAny.categories &&
Array.isArray(dataAny.categories) &&
dataAny.categories.length > 0);
case QRType.BUSINESS:
return Boolean(dataAny.name && dataAny.name.length > 0);
case QRType.APPS:
return Boolean(dataAny.appStoreUrl || dataAny.playStoreUrl);
case QRType.LINKS_LIST:
return Boolean(dataAny.links &&
Array.isArray(dataAny.links) &&
dataAny.links.length > 0);
case QRType.COUPON:
return Boolean(dataAny.code && dataAny.code.length > 0);
default:
return false;
}
}
/**
* Helper function to validate date strings
*/
function isValidDate(dateStr) {
const date = new Date(dateStr);
return !isNaN(date.getTime());
}
/**
* Validates EAN-13 barcode (13 digits with checksum)
*/
export function isValidEAN13(code) {
if (!/^\d{13}$/.test(code))
return false;
const digits = code.split('').map(Number);
const checksum = digits.pop();
const sum = digits.reduce((acc, digit, index) => {
return acc + digit * (index % 2 === 0 ? 1 : 3);
}, 0);
const calculatedChecksum = (10 - (sum % 10)) % 10;
return calculatedChecksum === checksum;
}
/**
* Validates EAN-8 barcode (8 digits with checksum)
*/
export function isValidEAN8(code) {
if (!/^\d{8}$/.test(code))
return false;
const digits = code.split('').map(Number);
const checksum = digits.pop();
const sum = digits.reduce((acc, digit, index) => {
return acc + digit * (index % 2 === 0 ? 3 : 1);
}, 0);
const calculatedChecksum = (10 - (sum % 10)) % 10;
return calculatedChecksum === checksum;
}
/**
* Validates UPC-A barcode (12 digits with checksum)
*/
export function isValidUPCA(code) {
if (!/^\d{12}$/.test(code))
return false;
const digits = code.split('').map(Number);
const checksum = digits.pop();
const sum = digits.reduce((acc, digit, index) => {
return acc + digit * (index % 2 === 0 ? 3 : 1);
}, 0);
const calculatedChecksum = (10 - (sum % 10)) % 10;
return calculatedChecksum === checksum;
}
/**
* Validates UPC-E barcode (8 digits, converts to UPC-A internally)
*/
export function isValidUPCE(code) {
return /^\d{8}$/.test(code);
}
/**
* Validates Code 128 barcode (alphanumeric with ASCII 0-127)
*/
export function isValidCode128(code) {
// Code 128 can encode all ASCII characters from 0 to 127
if (code.length === 0 || code.length > 80)
return false;
for (let i = 0; i < code.length; i++) {
if (code.charCodeAt(i) > 127)
return false;
}
return true;
}
/**
* Validates Code 39 barcode (uppercase letters, digits, and special characters)
*/
export function isValidCode39(code) {
// Code 39 allows uppercase letters, digits, space, and - . $ / + %
const code39Regex = /^[A-Z0-9\s\-\.\$\/\+\%]+$/;
return code.length > 0 && code.length <= 48 && code39Regex.test(code);
}
/**
* Validates Code 93 barcode (similar to Code 39 but more compact)
*/
export function isValidCode93(code) {
// Code 93 allows uppercase letters, digits, space, and special characters
const code93Regex = /^[A-Z0-9\s\-\.\$\/\+\%]+$/;
return code.length > 0 && code.length <= 48 && code93Regex.test(code);
}
/**
* Validates ITF (Interleaved 2 of 5) barcode (even number of digits)
*/
export function isValidITF(code) {
return /^\d+$/.test(code) && code.length % 2 === 0 && code.length >= 2;
}
/**
* Validates Codabar barcode (digits and special start/stop characters)
*/
export function isValidCodabar(code) {
// Codabar allows digits 0-9 and special characters - $ : / . +
// Must start and end with A, B, C, or D
const codabarRegex = /^[ABCD][0-9\-\$\:\/\.\+]+[ABCD]$/;
return code.length >= 3 && codabarRegex.test(code);
}
/**
* Validates barcode data based on format
*/
export function validateBarcodeData(format, data) {
switch (format) {
case 'EAN_13':
return isValidEAN13(data);
case 'EAN_8':
return isValidEAN8(data);
case 'UPC_A':
return isValidUPCA(data);
case 'UPC_E':
return isValidUPCE(data);
case 'CODE_128':
return isValidCode128(data);
case 'CODE_39':
return isValidCode39(data);
case 'CODE_93':
return isValidCode93(data);
case 'ITF':
case 'ITF_14':
return isValidITF(data);
case 'CODABAR':
return isValidCodabar(data);
case 'QR_CODE':
case 'DATA_MATRIX':
case 'AZTEC':
case 'PDF_417':
// 2D barcodes can contain any data
return data.length > 0;
default:
return false;
}
}
/**
* Gets barcode format constraints
*/
export function getBarcodeConstraints(format) {
switch (format) {
case 'EAN_13':
return { fixedLength: 13, pattern: '^\\d{13}$', description: 'Exactly 13 digits' };
case 'EAN_8':
return { fixedLength: 8, pattern: '^\\d{8}$', description: 'Exactly 8 digits' };
case 'UPC_A':
return { fixedLength: 12, pattern: '^\\d{12}$', description: 'Exactly 12 digits' };
case 'UPC_E':
return { fixedLength: 8, pattern: '^\\d{8}$', description: 'Exactly 8 digits' };
case 'CODE_128':
return { minLength: 1, maxLength: 80, description: 'ASCII characters (1-80 chars)' };
case 'CODE_39':
return { minLength: 1, maxLength: 48, pattern: '^[A-Z0-9\\s\\-\\.\\$\\/\\+\\%]+$', description: 'Uppercase letters, digits, and - . $ / + % space' };
case 'CODE_93':
return { minLength: 1, maxLength: 48, pattern: '^[A-Z0-9\\s\\-\\.\\$\\/\\+\\%]+$', description: 'Uppercase letters, digits, and special characters' };
case 'ITF':
case 'ITF_14':
return { minLength: 2, pattern: '^\\d+$', description: 'Even number of digits' };
case 'CODABAR':
return { minLength: 3, pattern: '^[ABCD][0-9\\-\\$\\:\\/\\.\\+]+[ABCD]$', description: 'Start/end with A-D, digits and - $ : / . + in between' };
case 'QR_CODE':
return { minLength: 1, maxLength: 4296, description: 'Any text up to 4296 characters' };
case 'DATA_MATRIX':
return { minLength: 1, maxLength: 2335, description: 'Any text up to 2335 characters' };
case 'AZTEC':
return { minLength: 1, maxLength: 3832, description: 'Any text up to 3832 characters' };
case 'PDF_417':
return { minLength: 1, maxLength: 1850, description: 'Any text up to 1850 characters' };
default:
return { minLength: 1, description: 'Any text' };
}
}
//# sourceMappingURL=validators.js.map