@basis-theory/react-elements
v3.0.0
Published
React components for Basis Theory Elements v3
Readme
@basis-theory/react-elements
React components for collecting sensitive data with Basis Theory Elements v3. Secure, PCI-compliant iframes wrapped as React components with hooks, refs, and typed event handlers.
Installation
npm install @basis-theory/react-elements@beta@basis-theory/web-elements is a dependency and will be installed automatically.
React 16.8+, 17, 18, and 19 are supported.
Quick Start
import { useState, useRef } from 'react';
import {
BasisTheoryProvider,
CardNumberElement,
ExpiryElement,
CVVElement,
useBasisTheory,
} from '@basis-theory/react-elements';
function PaymentForm() {
const { bt, error } = useBasisTheory();
const cardNumberRef = useRef(null);
const expiryRef = useRef(null);
const cvvRef = useRef(null);
const [cardNumberValid, setCardNumberValid] = useState(false);
const [expiryValid, setExpiryValid] = useState(false);
const [cvvValid, setCvvValid] = useState(false);
const allValid = cardNumberValid && expiryValid && cvvValid;
if (error) return <div>Failed to load payment form.</div>;
const handleSubmit = async (e) => {
e.preventDefault();
const token = await bt.tokens.create({
type: 'card',
data: {
number: cardNumberRef.current,
expiration_month: expiryRef.current,
expiration_year: expiryRef.current,
cvc: cvvRef.current,
},
});
// Send token.id to your backend
console.log('Token created:', token.id);
};
return (
<form onSubmit={handleSubmit}>
<CardNumberElement
ref={cardNumberRef}
placeholder="4242 4242 4242 4242"
onChange={(event) => setCardNumberValid(event.detail.isValid)}
/>
<ExpiryElement
ref={expiryRef}
placeholder="MM/YY"
onChange={(event) => setExpiryValid(event.detail.isValid)}
/>
<CVVElement
ref={cvvRef}
placeholder="123"
onChange={(event) => setCvvValid(event.detail.isValid)}
/>
<button type="submit" disabled={!allValid}>Pay</button>
</form>
);
}
export default function App() {
return (
<BasisTheoryProvider apiKey="pk_test_...">
<PaymentForm />
</BasisTheoryProvider>
);
}Components
BasisTheoryProvider
Initializes the SDK and provides it to child components via React Context. All element components and the useBasisTheory hook must be descendants of this provider.
<BasisTheoryProvider
apiKey="pk_test_..."
options={{
debug: true,
themeMode: 'auto',
theme: { /* ThemeTokens */ },
}}
errorFallback={<div>Something went wrong.</div>}
>
{children}
</BasisTheoryProvider>| Prop | Type | Required | Description |
|------|------|----------|-------------|
| apiKey | string | Yes | Public API key (starts with pk_) |
| options | SDKOptions | No | SDK configuration (debug, theme, etc.) |
| children | ReactNode | Yes | Child components |
| errorFallback | ReactNode | No | Fallback UI if initialization fails |
CardNumberElement
Secure card number input with Luhn validation and brand detection.
<CardNumberElement
ref={cardNumberRef}
placeholder="4242 4242 4242 4242"
ariaLabel="Card number"
disabled={false}
readOnly={false}
onChange={(event) => console.log(event.detail.isValid)}
onReady={(event) => console.log('Ready')}
onFocus={(event) => console.log('Focused')}
onBlur={(event) => console.log('Blurred')}
onError={(event) => console.error(event.detail.code)}
className="my-card-input"
containerStyle={{ border: '1px solid #ccc' }}
/>ExpiryElement
Secure expiry date input (MM/YY format).
<ExpiryElement
ref={expiryRef}
placeholder="MM/YY"
onChange={(event) => console.log(event.detail.isValid)}
/>CVVElement
Secure CVV/CVC input. Automatically adjusts expected length when a CardNumberElement is present on the same page (3 digits for Visa/Mastercard, 4 for Amex).
<CVVElement
ref={cvvRef}
placeholder="123"
onChange={(event) => console.log(event.detail.isValid)}
/>TextElement
General-purpose secure text input for any sensitive value (SSN, account numbers, etc.).
<TextElement
ref={textRef}
placeholder="###-##-####"
mask={[/\d/, /\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]}
transform={[/-/g, '']}
validation={/^\d{9}$/}
password={false}
inputMode="numeric"
required={true}
maxLength={11}
onChange={(event) => console.log(event.detail.isValid)}
/>CardElement
Unified card element that combines card number, expiry, and CVV into a single component.
<CardElement
ref={cardRef}
placeholder={{
cardNumber: '4242 4242 4242 4242',
expiryDate: 'MM/YY',
cvc: '123',
}}
layout="auto"
stackAt={400}
iconPosition="right"
onChange={(event) => console.log(event.detail.isValid)}
/>Shared Element Props
All element components accept:
| Prop | Type | Description |
|------|------|-------------|
| placeholder | string | Placeholder text |
| disabled | boolean | Disable the input |
| readOnly | boolean | Make the input read-only |
| ariaLabel | string | ARIA label for accessibility |
| onReady | (event) => void | Fired when the element is interactive |
| onChange | (event) => void | Fired when the value changes |
| onFocus | (event) => void | Fired when the element gains focus |
| onBlur | (event) => void | Fired when the element loses focus |
| onError | (event) => void | Fired on infrastructure or API errors |
| className | string | CSS class for the container div |
| containerStyle | CSSProperties | Inline styles for the container div |
Hooks
useBasisTheory
Access the SDK instance from any component under BasisTheoryProvider.
import { useBasisTheory } from '@basis-theory/react-elements';
function MyComponent() {
const { bt, error } = useBasisTheory();
if (error) return <div>SDK failed to initialize.</div>;
if (!bt) return <div>Loading...</div>;
const handleTokenize = async () => {
const token = await bt.tokens.create({
type: 'card',
data: { number: cardNumberRef.current },
});
};
}Returns { bt: BasisTheorySDK | null, error: Error | null }.
Ref Methods
All element refs expose these methods and properties:
| Method / Property | Type | Description |
|-------------------|------|-------------|
| mount | (selector) => Promise<void> | Mount the element (handled automatically) |
| unmount | () => void | Remove the element |
| update | (options) => Promise<void> | Update element options |
| focus | () => void | Focus the input |
| blur | () => void | Blur the input |
| clear | () => void | Clear the input value |
| on | (event, listener) => () => void | Subscribe to an event |
| complete | boolean | Input is valid and non-empty |
| empty | boolean | Input is empty |
| valid | boolean | Input passes validation |
| id | string | Unique element ID |
| type | string | Element type |
| mounted | boolean | Whether the element is mounted |
CardNumberElementRef adds: cardBrand, last4, bin.
CardElementRef adds: cardBrand, last4, bin, errors, number, expiryDate, cvc.
TypeScript
All components are fully typed. Import ref types for useRef:
import { useRef } from 'react';
import type {
CardNumberElementRef,
CVVElementRef,
ExpiryElementRef,
TextElementRef,
CardElementRef,
} from '@basis-theory/react-elements';
const cardNumberRef = useRef<CardNumberElementRef | null>(null);
const cvvRef = useRef<CVVElementRef | null>(null);
const expiryRef = useRef<ExpiryElementRef | null>(null);Event handler types are also available:
import type {
ChangeEventDetail,
CardNumberChangeEventDetail,
CardElementChangeEventDetail,
ReadyEventDetail,
ErrorEventDetail,
FocusEventDetail,
} from '@basis-theory/react-elements';Documentation
Full documentation: https://developers.basistheory.com/docs/sdks/web/web-elements/
License
Apache-2.0
