Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Basis Theory React Native SDK

[![Version](https://img.shields.io/npm/v/@basis-theory/react-native-elements.svg)](https://www.npmjs.org/package/@basis-theory/react-native-elements)
[![Downloads](https://img.shields.io/npm/dm/@basis-theory/react-native-elements.svg)](https://www.npmjs.org/package/@basis-theory/react-native-elements)
[![Verify](https://github.com/Basis-Theory/react-native-elements/actions/workflows/release.yml/badge.svg)](https://github.com/Basis-Theory/react-native-elements/actions/workflows/release.yml)
> [!CAUTION]
> This SDK has been deprecated.
>
> Our new SDK can be found at https://github.com/Basis-Theory/react-native-elements
>
> See our documentation site for more information. [https://developers.basistheory.com/docs/sdks/mobile/react-native](https://developers.basistheory.com/docs/sdks/mobile/react-native/)

[![Version](https://img.shields.io/npm/v/@basis-theory/basis-theory-react-native.svg)](https://www.npmjs.org/package/@basis-theory/basis-theory-react-native)
[![Downloads](https://img.shields.io/npm/dm/@basis-theory/basis-theory-react-native.svg)](https://www.npmjs.org/package/@basis-theory/basis-theory-react-native)
[![Verify](https://github.com/Basis-Theory/basis-theory-react-native/actions/workflows/release.yml/badge.svg)](https://github.com/Basis-Theory/basis-theory-react-native/actions/workflows/release.yml)

The [Basis Theory](https://basistheory.com/) React Native SDK
10 changes: 8 additions & 2 deletions demo/Collect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const Collect = () => {

const { bt, error } = useBasisTheory('<API_KEY>');

const [cvcLength, setCvcLength] = useState<number>();

useEffect(() => {
if (error) {
console.log(error);
Expand All @@ -56,6 +58,10 @@ export const Collect = () => {
const updateElementsEvents =
(eventSource: 'cardExpirationDate' | 'cardNumber' | 'cvc') =>
(event: ElementEvent) => {
if (event.cvcLength) {
setCvcLength(event.cvcLength);
}

setElementsEvents({
...elementsEvents,
[eventSource]: event,
Expand Down Expand Up @@ -177,10 +183,10 @@ export const Collect = () => {
/>
<CardVerificationCodeElement
btRef={cardVerificationCodeRef}
cvcLength={3}
cvcLength={cvcLength}
keyboardType="numeric"
onChange={updateElementsEvents('cvc')}
placeholder="CVC"
placeholder={'Security code'}
placeholderTextColor="#99a0bf"
style={styles.elements}
/>
Expand Down
37 changes: 37 additions & 0 deletions src/BaseElementTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,43 @@ type ElementEvent = {
* Array of objects that indicates if an element is invalid or incomplete.
*/
errors?: FieldError[];

/**
* Card brand identifier
* Only present for card number elements
*/
brand?:
| string
| 'american-express'
| 'diners-club'
| 'discover'
| 'ebt'
| 'elo'
| 'hiper'
| 'hipercard'
| 'jcb'
| 'maestro'
| 'mastercard'
| 'mir'
| 'private-label'
| 'proprietary'
| 'unionpay'
| 'visa';
/**
* Last 4 digits of the card number
* Only present for card number elements
*/
cardLast4?: string;
/**
* Required length of the CVC for the detected card brand
* Only present for card number elements
*/
cvcLength?: number;
/**
* Bank Identification Number (first 6-8 digits of card number)
* Only present for card number elements
*/
cardBin?: string;
};

type EventConsumer = (event: ElementEvent) => void;
Expand Down
2 changes: 1 addition & 1 deletion src/components/CardVerificationCodeElement.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const useCardVerificationCodeElement = ({
setElementValue,
element: {
id,
validatorOptions: { mask },
validatorOptions: { mask, cvcLength: [cvcLength] },
type,
},
onBlur,
Expand Down
19 changes: 14 additions & 5 deletions src/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cvv, expirationDate, number } from 'card-validator';
import { flip, isEmpty, partial, split } from 'ramda';
import { isEmpty, partial, split } from 'ramda';
import type { Mask, ValidationResult } from '../BaseElementTypes';
import { ElementType } from '../BaseElementTypes';
import {
Expand All @@ -16,7 +16,8 @@ type ValidatorResult = {

type ValidatorFunction = (value: string) => ValidatorResult;

const _cardCvvValidator = partial(flip(cvv), [[3, 4]]);
const _cardCvvValidator = (length = [3, 4], value: string) =>
cvv(value, length);

interface CardNumberValidatorOptions {
skipLuhnValidation?: boolean;
Expand All @@ -26,8 +27,13 @@ interface TextValidatorOptions {
mask?: Mask;
}

interface CvcValidatorOptions {
cvcLength?: number[];
}

export type ValidatorOptions = CardNumberValidatorOptions &
TextValidatorOptions;
TextValidatorOptions &
CvcValidatorOptions;

const _cardNumberValidator = (
options: CardNumberValidatorOptions = {},
Expand Down Expand Up @@ -148,8 +154,11 @@ const cardExpirationDateValidator = (
expirationDate: string
): ValidationResult => runValidator(expirationDate, _expirationDateValidator);

const cardVerificationCodeValidator = (cvc: string): ValidationResult =>
runValidator(cvc, _cardCvvValidator);
const cardVerificationCodeValidator = (
cvc: string,
validatorOptions?: ValidatorOptions
): ValidationResult =>
runValidator(cvc, partial(_cardCvvValidator, [validatorOptions?.cvcLength]));

const textMaskValidator = (
value: string,
Expand Down