Components/Credit Card Input
Credit Card Input
Grouped card entry with live brand detection (including Elo and Hipercard), Luhn validation, and PCI-minded defaults - the number auto-masks on blur and the CVC is never revealed.
brand: unknown · luhn: false · complete: false
Test numbers: 4242 4242 4242 4242 (Visa), 5555 5555 5555 4444 (Mastercard), 6062 8288 8866 6688 (Hipercard). Fill the number and click outside to see the auto-mask.
Installation
npx @ajax-ui/cli add credit-card-inputProps
value/defaultValue-{ number, expiry, cvc }as raw digits (expiry isMMYY). Setvalue+onValueChangefor controlled.onValueChange(value, meta)- meta carriesbrand,luhnValid, andcomplete.maskOnBlur(defaulttrue) - collapses the number to•••• 1234when focus leaves the field.- Helpers exported alongside:
detectCardBrand(digits)andluhnCheck(digits).
Brand detection
Visa, Mastercard, Amex, Diners, Discover, plus the Brazilian brands Elo and Hipercard. Brazilian BINs overlap Visa/Discover ranges, so they are matched first. Grouping adapts per brand (Amex 4-6-5, Diners 4-6-4) and so does CVC length (Amex 4). BIN tables are UI-grade hints - the payment processor always has the final say.
Security notes
- The CVC renders as
type="password"and is never displayed. - State is held in memory only - nothing is persisted by the component.
- This is a UI capture component: tokenize with your PSP (Stripe, Adyen, Pagar.me) before the number touches your servers.
- Native
autocomplete="cc-*"attributes keep browser autofill working.
Accessibility
- Three real
<input>s with individualaria-labels - screen readers announce each part. aria-invalidis set on the number once it is full-length but fails Luhn.inputMode="numeric"opens the digit pad on mobile.