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
6 changes: 6 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ yarn add react-native-otp-entry
textInputProps={{
accessibilityLabel: "One-Time Password",
}}
textProps={{
accessibilityRole: "text",
accessibilityLabel: "OTP digit",
allowFontScaling: false,
}}
theme={{
containerStyle: styles.container,
pinCodeContainerStyle: styles.pinCodeContainer,
Expand All @@ -97,6 +102,7 @@ The `react-native-otp-entry` component accepts the following props:
| `numberOfDigits` | number | The number of digits to be displayed in the OTP entry. |
| `theme` | Theme | Custom styles for each element. (See below) |
| `textInputProps` | TextInputProps | Extra props passed to underlying hidden TextInput (see: <https://reactnative.dev/docs/textinput>) |
| `textProps` | TextProps | Props passed to the Text component that renders each digit (see: <https://reactnative.dev/docs/text>) |
| `autoFocus` | boolean | _Default: true_. Sets autofocus. |
| `focusColor` | ColorValue | The color of the input field border and stick when it is focused. |
| `placeholder` | string | Placeholder value to the input. |
Expand Down
4 changes: 4 additions & 0 deletions src/OtpInput/OtpInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const OtpInput = forwardRef<OtpInputRef, OtpInputProps>((props, ref) => {
secureTextEntry = false,
theme = {},
textInputProps,
textProps,
type = "numeric",
} = props;
const {
Expand Down Expand Up @@ -91,10 +92,13 @@ export const OtpInput = forwardRef<OtpInputRef, OtpInputProps>((props, ref) => {
/>
) : (
<Text
{...textProps}
testID={textProps?.testID ? `${textProps.testID}-${index}` : undefined}
style={[
styles.codeText,
pinCodeTextStyle,
isPlaceholderCell ? placeholderStyle : {},
textProps?.style,
]}
>
{char && secureTextEntry ? "•" : char}
Expand Down
3 changes: 2 additions & 1 deletion src/OtpInput/OtpInput.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColorValue, TextInputProps, TextStyle, ViewStyle } from "react-native";
import { ColorValue, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";

export interface OtpInputProps {
numberOfDigits?: number;
Expand All @@ -15,6 +15,7 @@ export interface OtpInputProps {
theme?: Theme;
disabled?: boolean;
textInputProps?: TextInputProps;
textProps?: TextProps;
type?: "alpha" | "numeric" | "alphanumeric";
placeholder?: string;
}
Expand Down
53 changes: 51 additions & 2 deletions src/OtpInput/__tests__/OtpInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,56 @@ describe("OtpInput", () => {
expect(inputs[0]).toHaveStyle({ borderBottomColor: "red" });
});

test("should pass textProps to Text component", () => {
renderOtpInput({
numberOfDigits: 3,
textProps: {
testID: "custom-text-id",
numberOfLines: 1,
accessibilityLabel: "OTP digit",
allowFontScaling: false,
},
});

const input = screen.getByTestId("otp-input-hidden");
fireEvent.changeText(input, "123");

["1", "2", "3"].forEach((digit, index) => {
const digitElement = screen.getByTestId(`custom-text-id-${index}`);
expect(digitElement).toBeTruthy();
expect(digitElement.props.numberOfLines).toBe(1);
expect(digitElement.props.accessibilityLabel).toBe("OTP digit");
expect(digitElement.props.allowFontScaling).toBe(false);
expect(digitElement).toHaveTextContent(digit);
});
});

test("should correctly merge textProps with theme styles", () => {
renderOtpInput({
numberOfDigits: 2,
textProps: {
testID: "custom-styled-text",
style: { fontWeight: "bold" },
},
theme: {
pinCodeTextStyle: { fontSize: 20, color: "blue" },
},
});

const input = screen.getByTestId("otp-input-hidden");
fireEvent.changeText(input, "12");
const textElement = screen.getByTestId("custom-styled-text-0");
// Check that our custom style from textProps.style is applied
const styles = textElement.props.style;
const customStyleApplied = styles.some((style: any) => style.fontWeight === "bold");
expect(customStyleApplied).toBe(true);
// Check that theme styles are also applied
const themeStyleApplied = styles.some(
(style: any) => style.fontSize === 20 && style.color === "blue"
);
expect(themeStyleApplied).toBe(true);
});

test('autoComplete should be set "sms-otp" on Android', () => {
Platform.OS = "android";
renderOtpInput();
Expand Down Expand Up @@ -361,7 +411,7 @@ describe("OtpInput", () => {
const input = screen.getByTestId("otp-input-hidden");
const otherInput = screen.getByTestId("other-input");
fireEvent.press(input);
// Blur the input
fireEvent.changeText(input, "");
fireEvent.press(otherInput);

const inputs = screen.getAllByTestId("otp-input");
Expand All @@ -379,7 +429,6 @@ describe("OtpInput", () => {
const otherInput = screen.getByTestId("other-input");
fireEvent.press(input);
fireEvent.changeText(input, "123456");
// Blur the input
fireEvent.press(otherInput);

const placeholder = screen.queryByText("000000");
Expand Down
5 changes: 5 additions & 0 deletions src/OtpInput/__tests__/__snapshots__/OtpInput.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ exports[`OtpInput UI should render correctly 1`] = `
},
undefined,
{},
undefined,
]
}
/>
Expand Down Expand Up @@ -201,6 +202,7 @@ exports[`OtpInput UI should render correctly 1`] = `
},
undefined,
{},
undefined,
]
}
/>
Expand Down Expand Up @@ -259,6 +261,7 @@ exports[`OtpInput UI should render correctly 1`] = `
},
undefined,
{},
undefined,
]
}
/>
Expand Down Expand Up @@ -317,6 +320,7 @@ exports[`OtpInput UI should render correctly 1`] = `
},
undefined,
{},
undefined,
]
}
/>
Expand Down Expand Up @@ -375,6 +379,7 @@ exports[`OtpInput UI should render correctly 1`] = `
},
undefined,
{},
undefined,
]
}
/>
Expand Down
8 changes: 7 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
declare module "OTPInput" {
import { ColorValue, TextInputProps, TextStyle, ViewStyle } from "react-native";
import { ColorValue, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";

export interface OtpEntryProps {
/**
Expand Down Expand Up @@ -74,6 +74,12 @@ declare module "OTPInput" {
*/
textInputProps?: TextInputProps;

/**
* Additional props to be passed to the `Text` component that renders each digit.
* Allows customizing text behavior beyond styling (which is handled by pinCodeTextStyle in theme).
*/
textProps?: TextProps;

/**
* The type of characters allowed in the OTP entry.
*/
Expand Down