Skip to main content

Element Types

v3 provides four element types. Each renders as a sandboxed iframe and exposes the same core interface.

TypecreateElement keyDescription
Card Number'cardNumber'PAN input with Luhn validation and brand detection
Expiry'expiry'MM/YY expiration date input
CVV'cvv'Card verification code input
Text'text'General-purpose single-line text input

Shared Options

All elements accept these options in createElement and element.update():

OptionTypeDefaultDescription
placeholderstringPlaceholder text shown when the input is empty
ariaLabelstringElement-specificARIA label for screen readers
disabledbooleanfalseDisables the input
readOnlybooleanfalseMakes the input read-only

Shared Methods

Every element exposes the same interface:

MethodSignatureDescription
mount(selector: string | HTMLElement) => Promise<void>Attaches the iframe to the DOM; resolves when the element is interactive
unmount() => voidRemoves the iframe from the DOM and clears cached values
update(options: Partial<ElementOptions>) => Promise<void>Updates options on a mounted element
focus() => voidFocuses the input
blur() => voidBlurs the input
clear() => voidClears the current value
on(event, listener) => () => voidSubscribes to an event; returns an unsubscribe function

Properties:

PropertyTypeDescription
idstringUnique element identifier (read-only)
typeElementTypeElement type string (read-only)
mountedbooleanWhether the element is currently mounted (read-only)

Events:

EventFires when…
readyThe iframe has loaded and the element is interactive
changeThe user types or the value changes
focusThe input gains focus
blurThe input loses focus
errorAn infrastructure or API error occurs

See Events for full payload shapes.


cardNumber

Collects the card PAN. Validates format and Luhn checksum, and detects the card brand as the user types.

const cardNumberEl = bt.createElement('cardNumber', {
placeholder: '4242 4242 4242 4242',
ariaLabel: 'Card number',
});

await cardNumberEl.mount('#card-number-container');

change event

The cardNumber element emits additional fields on its change event beyond the shared ChangeEventDetail:

FieldTypeDescription
cardBrandstringDetected brand (e.g. 'visa', 'mastercard', 'amex')
last4string | nullLast 4 digits — safe to display
binstring | nullBIN (first 6–8 digits)
cvvLengthsnumber[] | nullExpected CVV length(s) for detected brand
potentialBrandsstring[]All brands that could match at the current input length
matchStrengthnumberBrand detection confidence (0–1)
cardNumberEl.on('change', (event) => {
const { isValid, cardBrand, last4, bin } = event.detail;
console.log(`${cardBrand} ...${last4}`, isValid);
});

Co-brand detection

Some card numbers match more than one brand (for example, a card that could be Mastercard or Maestro). The SDK detects this automatically and exposes potentialBrands on the change event. When potentialBrands.length > 1, you can prompt the user to pick their preferred brand:

cardNumberEl.on('change', (event) => {
const { cardBrand, potentialBrands, matchStrength } = event.detail;

if (potentialBrands && potentialBrands.length > 1) {
// Show brand picker UI with potentialBrands options
showBrandPicker(potentialBrands);
} else {
hideBrandPicker();
// cardBrand is the detected brand (e.g. 'mastercard')
}
});

matchStrength (0–1) indicates how confident the detection is — useful for deciding when to show or hide UI. A value approaching 1 means only one brand matches.

React ref

CardNumberElementRef extends the base ref with convenience state:

PropertyTypeDescription
completebooleanInput is valid and complete
emptybooleanInput is empty
validbooleanInput passes validation
cardBrandstringDetected card brand
last4stringLast 4 digits
binstringBIN

expiry

Collects the card expiration date in MM/YY format. Validates that the date is not in the past.

const expiryEl = bt.createElement('expiry', {
placeholder: 'MM/YY',
});

await expiryEl.mount('#expiry-container');

The expiry element accepts only the shared options. When used in tokenization, pass the same element reference for both expiration_month and expiration_year — Basis Theory resolves them server-side:

bt.tokens.create({
type: 'card',
data: {
number: cardNumberEl,
expiration_month: expiryEl,
expiration_year: expiryEl,
cvc: cvvEl,
},
});

cvv

Collects the card verification code (CVV/CVC). When a cardNumber element is present on the same page, the SDK automatically updates the CVV element's expected length to match the detected card brand (3 digits for Visa/Mastercard, 4 for Amex).

const cvvEl = bt.createElement('cvv', {
placeholder: '•••',
showToggle: true, // renders a show/hide button inside the field
});

await cvvEl.mount('#cvv-container');

CVV-specific options

OptionTypeDefaultDescription
showTogglebooleanfalseRenders a show/hide toggle inside the field. Web elements only. Set at creation — cannot be changed via update().

text

General-purpose single-line text input. Use it to collect any non-card sensitive value (SSN, account number, routing number, etc.) without it touching your servers.

const ssnEl = bt.createElement('text', {
placeholder: '•••-••-••••',
mask: [/\d/, /\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/],
transform: [/-/g, ''], // strip dashes before tokenization
validation: /^\d{9}$/, // must be exactly 9 digits after transform
});

await ssnEl.mount('#ssn-container');

Text-specific options

OptionTypeMutable via update()Description
validationRegExpNoPattern the value must match to be considered valid
requiredbooleanYesWhether the field is required
maxLengthnumberYesMaximum character length
passwordbooleanYesRenders as a password field (type="password")
inputModestringYesMobile keyboard hint ('numeric', 'tel', 'email', etc.)
mask(RegExp | string)[]NoCharacter-by-character input mask. Each position is a RegExp that the typed character must match, or a literal string character inserted automatically
transform[RegExp, string]NoApplied to the value before tokenization: value.replace(pattern, replacement). Does not affect what the user sees
validation, mask, and transform define the data contract for the element and are immutable after creation. To change them, unmount and recreate the element.

Mask example

// Phone: (555) 123-4567
const phoneEl = bt.createElement('text', {
placeholder: '(555) 123-4567',
mask: [
'(', /\d/, /\d/, /\d/, ')',
' ', /\d/, /\d/, /\d/,
'-', /\d/, /\d/, /\d/, /\d/,
],
transform: [/\D/g, ''], // strip non-digits → "5551234567" is tokenized
});

For visual customization across all elements (colors, typography, spacing, border radius), see Theming.