UNPKG

pagamio-frontend-commons-lib

Version:

Pagamio library for Frontend reusable components like the form engine and table container

83 lines (82 loc) 5.4 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useCallback, useEffect, useState } from 'react'; import { Input } from '../../../../components'; const CARD_PATTERNS = { visa: '4', mastercard: { twoDigitPrefixes: ['51', '52', '53', '54', '55'], fourDigitPrefixStart: '2', fourDigitSecondMin: 2, fourDigitSecondMax: 7, fourDigitThirdMin: 2, fourDigitThirdMax: 9, }, }; // SVG icons for card types const CardIcons = { visa: (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", width: "24px", height: "24px", children: [_jsx("path", { fill: "#1565C0", d: "M45,35c0,2.209-1.791,4-4,4H7c-2.209,0-4-1.791-4-4V13c0-2.209,1.791-4,4-4h34c2.209,0,4,1.791,4,4V35z" }), _jsx("path", { fill: "#FFF", d: "M15.186 19l-2.626 7.832c0 0-.667-3.313-.733-3.729-1.495-3.411-3.701-3.221-3.701-3.221L10.726 30v-.002h3.161L18.258 19H15.186zM17.689 30L20.56 30 22.296 19 19.389 19zM38.008 19h-3.021l-4.71 11h2.852l.588-1.571h3.596L37.619 30h2.613L38.008 19zM34.513 26.328l1.563-4.157.818 4.157H34.513zM26.369 22.206c0-.606.498-1.057 1.926-1.057.928 0 1.991.674 1.991.674l.466-2.309c0 0-1.358-.515-2.691-.515-3.019 0-4.576 1.444-4.576 3.272 0 3.306 3.979 2.853 3.979 4.551 0 .291-.231.964-1.888.964-1.662 0-2.759-.609-2.759-.609l-.495 2.216c0 0 1.063.606 3.117.606 2.059 0 4.915-1.54 4.915-3.752C30.354 23.586 26.369 23.394 26.369 22.206z" }), _jsx("path", { fill: "#FFC107", d: "M12.212,24.945l-0.966-4.748c0,0-0.437-1.029-1.573-1.029c-1.136,0-4.44,0-4.44,0S10.894,20.84,12.212,24.945z" })] })), mastercard: (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", width: "35px", height: "35px", children: [_jsx("path", { fill: "#ff9800", d: "M32 10A14 14 0 1 0 32 38A14 14 0 1 0 32 10Z" }), _jsx("path", { fill: "#d50000", d: "M16 10A14 14 0 1 0 16 38A14 14 0 1 0 16 10Z" }), _jsx("path", { fill: "#ff3d00", d: "M18,24c0,4.755,2.376,8.95,6,11.48c3.624-2.53,6-6.725,6-11.48s-2.376-8.95-6-11.48 C20.376,15.05,18,19.245,18,24z" })] })), }; const CreditCardInput = forwardRef(({ field, error, onChange, value, ...props }, ref) => { const [cardType, setCardType] = useState(null); const [formattedValue, setFormattedValue] = useState(''); // Format card number with spaces const formatCardNumber = useCallback((input) => { const numbers = input.replace(/\D/g, ''); const groups = numbers.match(/.{1,4}/g) || []; return groups.join(' '); }, []); // Detect card type const detectCardType = useCallback((input) => { const numbers = input.replace(/\D/g, ''); // Check Visa (starts with 4) if (numbers.startsWith(CARD_PATTERNS.visa)) return 'visa'; // Check Mastercard if ( // Check 51-55 prefixes CARD_PATTERNS.mastercard.twoDigitPrefixes.some((prefix) => numbers.startsWith(prefix)) || // Check 222x-279x prefixes (numbers.length >= 4 && numbers.startsWith(CARD_PATTERNS.mastercard.fourDigitPrefixStart) && Number(numbers[1]) >= CARD_PATTERNS.mastercard.fourDigitSecondMin && Number(numbers[1]) <= CARD_PATTERNS.mastercard.fourDigitSecondMax && Number(numbers[2]) >= CARD_PATTERNS.mastercard.fourDigitThirdMin && Number(numbers[2]) <= CARD_PATTERNS.mastercard.fourDigitThirdMax)) { return 'mastercard'; } return null; }, []); // Handle input change const handleChange = useCallback((e) => { const input = e.target.value; const numbers = input.replace(/\D/g, ''); if (numbers.length > 16) return; const formatted = formatCardNumber(numbers); const type = detectCardType(numbers); setFormattedValue(formatted); setCardType(type); // Call parent onChange with raw numeric value if (onChange) { const event = { ...e, target: { ...e.target, value: numbers, }, }; onChange(event); } }, [formatCardNumber, detectCardType, onChange]); // Initialize formatted value when value prop changes useEffect(() => { if (value) { setFormattedValue(formatCardNumber(value.toString())); setCardType(detectCardType(value.toString())); } }, [value, formatCardNumber, detectCardType]); return (_jsxs("div", { className: "relative", children: [_jsx("label", { htmlFor: field.name, className: "block text-sm font-medium text-gray-700", children: field.label }), _jsxs("div", { className: "relative", children: [_jsx(Input, { ...props, id: field.name, ref: ref, type: "creditCard", value: formattedValue, onChange: handleChange, disabled: field.disabled, placeholder: field.placeholder ?? '4242 4242 4242 4242', className: `mt-1 block w-full p-2 border ${error ? 'border-red-500' : 'border-gray-300'} rounded-md shadow-sm disabled:text-gray-400 disabled:bg-gray-50 pr-12` }), _jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2", children: cardType && CardIcons[cardType] })] }), error && _jsx("p", { className: "mt-2 text-sm text-red-500", children: error.message })] })); }); CreditCardInput.displayName = 'CreditCardInput'; export default CreditCardInput;