diff --git a/README.md b/README.md index 90a0a74c..d021c05c 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,12 @@ yarn example web |--------------------|-------------------------------------------|---------------------------------------------------------------| | `autoFocus` | `boolean` | Optional. Specifies if the input should auto-focus. | | `style` | `ViewStyle` | Optional. Custom style for the component's container. | -| `inputStyle` | `TextStyle` | Optional. Custom style for the input fields. | +| `numberInputStyle` | `TextStyle` | Optional. Custom style for the card number input field. | +| `expiryInputStyle` | `TextStyle` | Optional. Custom style for the expiry input field. | +| `cvcInputStyle` | `TextStyle` | Optional. Custom style for the CVC input field. | +| `numberInputRef` | `Ref` | Optional. Reference object for the card number input field. | +| `expiryInputRef` | `Ref` | Optional. Reference object for the expiry input field. | +| `cvcInputRef` | `Ref` | Optional. Reference object for the CVC input field. | | `placeholderColor` | `string` | Optional. Color for the placeholder text. | | `placeholders` | `{ number: string; expiry: string; cvc: string; }` | Optional. Custom placeholders for the input fields. | | `onChange` | `(formData: CreditCardFormData) => void` | Required. Callback function called when form data changes. | @@ -108,7 +113,12 @@ yarn example web | `autoFocus` | `boolean` | Optional. Specifies if the input should auto-focus. | | `style` | `ViewStyle` | Optional. Custom style for the component's container. | | `labelStyle` | `TextStyle` | Optional. Custom style for the labels. | -| `inputStyle` | `TextStyle` | Optional. Custom style for the input fields. | +| `numberInputStyle` | `TextStyle` | Optional. Custom style for the card number input field. | +| `expiryInputStyle` | `TextStyle` | Optional. Custom style for the expiry input field. | +| `cvcInputStyle` | `TextStyle` | Optional. Custom style for the CVC input field. | +| `numberInputRef` | `Ref` | Optional. Reference object for the card number input field. | +| `expiryInputRef` | `Ref` | Optional. Reference object for the expiry input field. | +| `cvcInputRef` | `Ref` | Optional. Reference object for the CVC input field. | | `placeholderColor` | `string` | Optional. Color for the placeholder text. | | `labels` | `{ number: string; expiry: string; cvc: string; }` | Optional. Custom labels for the input fields. | | `placeholders` | `{ number: string; expiry: string; cvc: string; }` | Optional. Custom placeholders for the input fields. | diff --git a/src/CreditCardInput.tsx b/src/CreditCardInput.tsx index cbbc6b48..e53fce89 100644 --- a/src/CreditCardInput.tsx +++ b/src/CreditCardInput.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, type RefObject } from 'react'; import { StyleSheet, Text, @@ -17,7 +17,12 @@ interface Props { autoFocus?: boolean; style?: ViewStyle; labelStyle?: TextStyle; - inputStyle?: TextStyle; + numberInputStyle?: TextStyle; + expiryInputStyle?: TextStyle; + cvcInputStyle?: TextStyle; + numberInputRef?: RefObject; + expiryInputRef?: RefObject; + cvcInputRef?: RefObject; placeholderColor?: string; labels?: { number: string; @@ -76,7 +81,12 @@ const CreditCardInput = (props: Props) => { autoFocus, style, labelStyle, - inputStyle, + numberInputStyle, + expiryInputStyle, + cvcInputStyle, + numberInputRef, + expiryInputRef, + cvcInputRef, placeholderColor = 'darkgray', labels = { number: 'CARD NUMBER', @@ -98,7 +108,11 @@ const CreditCardInput = (props: Props) => { const numberInput = useRef(null); useEffect(() => { - if (autoFocus) numberInput.current?.focus(); + if (autoFocus) { + (numberInputRef) + ? numberInputRef.current?.focus() + : numberInput.current?.focus(); + } }, [autoFocus]); return ( @@ -109,9 +123,9 @@ const CreditCardInput = (props: Props) => { {labels.number} { {labels.expiry} { {labels.cvc} ; + expiryInputRef?: RefObject; + cvcInputRef?: RefObject; placeholderColor?: string; placeholders?: { number: string; @@ -86,7 +98,12 @@ const LiteCreditCardInput = (props: Props) => { const { autoFocus = false, style, - inputStyle, + numberInputStyle, + expiryInputStyle, + cvcInputStyle, + numberInputRef, + expiryInputRef, + cvcInputRef, placeholderColor = 'darkgray', placeholders = { number: '1234 5678 1234 5678', @@ -100,13 +117,15 @@ const LiteCreditCardInput = (props: Props) => { const _onChange = (formData: CreditCardFormData): void => { // Focus next field when number/expiry field become valid - if (status.number !== 'valid' && formData.status.number === 'valid') { - toggleFormState(); - expiryInput.current?.focus(); + if (status.number !== 'valid' && formData.status.number === 'valid' && + (formData.status.expiry === "incomplete" || formData.status.expiry === "invalid")) { + toggleFormState(); + (expiryInputRef) ? expiryInputRef.current?.focus() : expiryInput.current?.focus(); } - if (status.expiry !== 'valid' && formData.status.expiry === 'valid') { - cvcInput.current?.focus(); + if (status.expiry !== 'valid' && formData.status.expiry === 'valid' && + (formData.status.cvc === "incomplete" || formData.status.cvc === "invalid")) { + (cvcInputRef) ? cvcInputRef.current?.focus() : cvcInput.current?.focus(); } onChange(formData); @@ -126,7 +145,11 @@ const LiteCreditCardInput = (props: Props) => { const cvcInput = useRef(null); useEffect(() => { - if (autoFocus) numberInput.current?.focus(); + if (autoFocus) { + (numberInputRef) + ? numberInputRef.current?.focus() + : numberInput.current?.focus(); + } }, [autoFocus]); const cardIcon = useMemo(() => { @@ -142,9 +165,9 @@ const LiteCreditCardInput = (props: Props) => { { - [ + { opacity: pressed ? 0.8 : 1} + ]} onPress={toggleFormState} > - + - [ + s.last4, + { opacity: pressed ? 0.8 : 1} + ]} onPress={toggleFormState} - style={s.last4} > { readOnly /> - + {