Skip to content

Commit 5dd94f0

Browse files
authored
feat: expose underlying text props (#96)
* feat: expose underlying text props * chore: update index.d.ts with textProps
1 parent 824bb68 commit 5dd94f0

File tree

6 files changed

+75
-4
lines changed

6 files changed

+75
-4
lines changed

README.MD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ yarn add react-native-otp-entry
7575
textInputProps={{
7676
accessibilityLabel: "One-Time Password",
7777
}}
78+
textProps={{
79+
accessibilityRole: "text",
80+
accessibilityLabel: "OTP digit",
81+
allowFontScaling: false,
82+
}}
7883
theme={{
7984
containerStyle: styles.container,
8085
pinCodeContainerStyle: styles.pinCodeContainer,
@@ -97,6 +102,7 @@ The `react-native-otp-entry` component accepts the following props:
97102
| `numberOfDigits` | number | The number of digits to be displayed in the OTP entry. |
98103
| `theme` | Theme | Custom styles for each element. (See below) |
99104
| `textInputProps` | TextInputProps | Extra props passed to underlying hidden TextInput (see: <https://reactnative.dev/docs/textinput>) |
105+
| `textProps` | TextProps | Props passed to the Text component that renders each digit (see: <https://reactnative.dev/docs/text>) |
100106
| `autoFocus` | boolean | _Default: true_. Sets autofocus. |
101107
| `focusColor` | ColorValue | The color of the input field border and stick when it is focused. |
102108
| `placeholder` | string | Placeholder value to the input. |

src/OtpInput/OtpInput.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const OtpInput = forwardRef<OtpInputRef, OtpInputProps>((props, ref) => {
2222
secureTextEntry = false,
2323
theme = {},
2424
textInputProps,
25+
textProps,
2526
type = "numeric",
2627
} = props;
2728
const {
@@ -91,10 +92,13 @@ export const OtpInput = forwardRef<OtpInputRef, OtpInputProps>((props, ref) => {
9192
/>
9293
) : (
9394
<Text
95+
{...textProps}
96+
testID={textProps?.testID ? `${textProps.testID}-${index}` : undefined}
9497
style={[
9598
styles.codeText,
9699
pinCodeTextStyle,
97100
isPlaceholderCell ? placeholderStyle : {},
101+
textProps?.style,
98102
]}
99103
>
100104
{char && secureTextEntry ? "•" : char}

src/OtpInput/OtpInput.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ColorValue, TextInputProps, TextStyle, ViewStyle } from "react-native";
1+
import { ColorValue, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";
22

33
export interface OtpInputProps {
44
numberOfDigits?: number;
@@ -15,6 +15,7 @@ export interface OtpInputProps {
1515
theme?: Theme;
1616
disabled?: boolean;
1717
textInputProps?: TextInputProps;
18+
textProps?: TextProps;
1819
type?: "alpha" | "numeric" | "alphanumeric";
1920
placeholder?: string;
2021
}

src/OtpInput/__tests__/OtpInput.test.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,56 @@ describe("OtpInput", () => {
164164
expect(inputs[0]).toHaveStyle({ borderBottomColor: "red" });
165165
});
166166

167+
test("should pass textProps to Text component", () => {
168+
renderOtpInput({
169+
numberOfDigits: 3,
170+
textProps: {
171+
testID: "custom-text-id",
172+
numberOfLines: 1,
173+
accessibilityLabel: "OTP digit",
174+
allowFontScaling: false,
175+
},
176+
});
177+
178+
const input = screen.getByTestId("otp-input-hidden");
179+
fireEvent.changeText(input, "123");
180+
181+
["1", "2", "3"].forEach((digit, index) => {
182+
const digitElement = screen.getByTestId(`custom-text-id-${index}`);
183+
expect(digitElement).toBeTruthy();
184+
expect(digitElement.props.numberOfLines).toBe(1);
185+
expect(digitElement.props.accessibilityLabel).toBe("OTP digit");
186+
expect(digitElement.props.allowFontScaling).toBe(false);
187+
expect(digitElement).toHaveTextContent(digit);
188+
});
189+
});
190+
191+
test("should correctly merge textProps with theme styles", () => {
192+
renderOtpInput({
193+
numberOfDigits: 2,
194+
textProps: {
195+
testID: "custom-styled-text",
196+
style: { fontWeight: "bold" },
197+
},
198+
theme: {
199+
pinCodeTextStyle: { fontSize: 20, color: "blue" },
200+
},
201+
});
202+
203+
const input = screen.getByTestId("otp-input-hidden");
204+
fireEvent.changeText(input, "12");
205+
const textElement = screen.getByTestId("custom-styled-text-0");
206+
// Check that our custom style from textProps.style is applied
207+
const styles = textElement.props.style;
208+
const customStyleApplied = styles.some((style: any) => style.fontWeight === "bold");
209+
expect(customStyleApplied).toBe(true);
210+
// Check that theme styles are also applied
211+
const themeStyleApplied = styles.some(
212+
(style: any) => style.fontSize === 20 && style.color === "blue"
213+
);
214+
expect(themeStyleApplied).toBe(true);
215+
});
216+
167217
test('autoComplete should be set "sms-otp" on Android', () => {
168218
Platform.OS = "android";
169219
renderOtpInput();
@@ -361,7 +411,7 @@ describe("OtpInput", () => {
361411
const input = screen.getByTestId("otp-input-hidden");
362412
const otherInput = screen.getByTestId("other-input");
363413
fireEvent.press(input);
364-
// Blur the input
414+
fireEvent.changeText(input, "");
365415
fireEvent.press(otherInput);
366416

367417
const inputs = screen.getAllByTestId("otp-input");
@@ -379,7 +429,6 @@ describe("OtpInput", () => {
379429
const otherInput = screen.getByTestId("other-input");
380430
fireEvent.press(input);
381431
fireEvent.changeText(input, "123456");
382-
// Blur the input
383432
fireEvent.press(otherInput);
384433

385434
const placeholder = screen.queryByText("000000");

src/OtpInput/__tests__/__snapshots__/OtpInput.test.tsx.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ exports[`OtpInput UI should render correctly 1`] = `
143143
},
144144
undefined,
145145
{},
146+
undefined,
146147
]
147148
}
148149
/>
@@ -201,6 +202,7 @@ exports[`OtpInput UI should render correctly 1`] = `
201202
},
202203
undefined,
203204
{},
205+
undefined,
204206
]
205207
}
206208
/>
@@ -259,6 +261,7 @@ exports[`OtpInput UI should render correctly 1`] = `
259261
},
260262
undefined,
261263
{},
264+
undefined,
262265
]
263266
}
264267
/>
@@ -317,6 +320,7 @@ exports[`OtpInput UI should render correctly 1`] = `
317320
},
318321
undefined,
319322
{},
323+
undefined,
320324
]
321325
}
322326
/>
@@ -375,6 +379,7 @@ exports[`OtpInput UI should render correctly 1`] = `
375379
},
376380
undefined,
377381
{},
382+
undefined,
378383
]
379384
}
380385
/>

src/index.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare module "OTPInput" {
2-
import { ColorValue, TextInputProps, TextStyle, ViewStyle } from "react-native";
2+
import { ColorValue, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";
33

44
export interface OtpEntryProps {
55
/**
@@ -74,6 +74,12 @@ declare module "OTPInput" {
7474
*/
7575
textInputProps?: TextInputProps;
7676

77+
/**
78+
* Additional props to be passed to the `Text` component that renders each digit.
79+
* Allows customizing text behavior beyond styling (which is handled by pinCodeTextStyle in theme).
80+
*/
81+
textProps?: TextProps;
82+
7783
/**
7884
* The type of characters allowed in the OTP entry.
7985
*/

0 commit comments

Comments
 (0)