@@ -39,316 +39,15 @@ yarn add input-otp-native
3939pnpm add input-otp-native
4040```
4141
42- ## Full Documentation
43-
44- [ Homepage] ( https://input-otp-native.better-app.dev )
45- [ Getting Started] ( https://input-otp-native.better-app.dev/getting-started )
46- [ Examples] ( https://input-otp-native.better-app.dev/examples )
47-
48- ## Examples
49-
50- We create a few examples that you can copy paste and use in your project.
51-
52- 💳 [ Stripe OTP Input with Nativewind] ( ./example/src/examples/stripe-nativewind.tsx )
53-
54- ``` tsx
55- import { View , Text } from ' react-native' ;
56- import { OTPInput , type SlotProps } from ' input-otp-native' ;
57- import type { OTPInputRef } from ' input-otp-native' ;
58- import { useRef } from ' react' ;
59- import { Alert } from ' react-native' ;
60-
61- import Animated , {
62- useAnimatedStyle ,
63- withRepeat ,
64- withTiming ,
65- withSequence ,
66- useSharedValue ,
67- } from ' react-native-reanimated' ;
68- import { useEffect } from ' react' ;
69- import { cn } from ' ./utils' ;
70-
71- export default function StripeOTPInput() {
72- const ref = useRef <OTPInputRef >(null );
73- const onComplete = (code : string ) => {
74- Alert .alert (' Completed with code:' , code );
75- ref .current ?.clear ();
76- };
77-
78- return (
79- <OTPInput
80- ref = { ref }
81- onComplete = { onComplete }
82- maxLength = { 6 }
83- render = { ({ slots }) => (
84- <View className = " flex-1 flex-row items-center justify-center my-4" >
85- <View className = " flex-row" >
86- { slots .slice (0 , 3 ).map ((slot , idx ) => (
87- <Slot key = { idx } { ... slot } index = { idx } />
88- ))}
89- </View >
90- <FakeDash />
91- <View className = " flex-row" >
92- { slots .slice (3 ).map ((slot , idx ) => (
93- <Slot key = { idx } { ... slot } index = { idx } />
94- ))}
95- </View >
96- </View >
97- )}
98- />
99- );
100- }
101-
102- function Slot({
103- char ,
104- isActive ,
105- hasFakeCaret ,
106- index ,
107- }: SlotProps & { index: number }) {
108- const isFirst = index === 0 ;
109- const isLast = index === 2 ;
110- return (
111- <View
112- className = { cn (
113- ` w-12 h-16 items-center justify-center bg-gray-50 ` ,
114- ' border border-gray-200' ,
115- {
116- ' rounded-r-lg' : isLast ,
117- ' rounded-l-lg' : isFirst ,
118- ' bg-white border-black' : isActive ,
119- }
120- )}
121- >
122- { char !== null && (
123- <Text className = " text-2xl font-medium text-gray-900" >{ char } </Text >
124- )}
125- { hasFakeCaret && <FakeCaret />}
126- </View >
127- );
128- }
129-
130- function FakeDash() {
131- return (
132- <View className = " w-8 items-center justify-center" >
133- <View className = " w-2 h-0.5 bg-gray-200 rounded-sm" />
134- </View >
135- );
136- }
137-
138- function FakeCaret() {
139- const opacity = useSharedValue (1 );
140-
141- useEffect (() => {
142- opacity .value = withRepeat (
143- withSequence (
144- withTiming (0 , { duration: 500 }),
145- withTiming (1 , { duration: 500 })
146- ),
147- - 1 ,
148- true
149- );
150- }, [opacity ]);
151-
152- const animatedStyle = useAnimatedStyle (() => ({
153- opacity: opacity .value ,
154- }));
155-
156- const baseStyle = {
157- width: 2 ,
158- height: 32 ,
159- backgroundColor: ' black' ,
160- borderRadius: 1 ,
161- };
162-
163- return (
164- <View className = " absolute w-full h-full items-center justify-center" >
165- <Animated.View style = { [baseStyle , animatedStyle ]} />
166- </View >
167- );
168- }
169- ```
170-
171- 💳 [ Stripe OTP Input] ( ./example/src/examples/stripe.tsx )
172-
173- ``` tsx
174- import { View , Text , StyleSheet , type ViewStyle , Alert } from ' react-native' ;
175- import { OTPInput , type SlotProps } from ' input-otp-native' ;
176- import type { OTPInputRef } from ' input-otp-native' ;
177- import { useRef } from ' react' ;
178-
179- import Animated , {
180- useAnimatedStyle ,
181- withRepeat ,
182- withTiming ,
183- withSequence ,
184- useSharedValue ,
185- } from ' react-native-reanimated' ;
186- import { useEffect } from ' react' ;
187-
188- export default function StripeOTPInput() {
189- const ref = useRef <OTPInputRef >(null );
190- const onComplete = (code : string ) => {
191- Alert .alert (' Completed with code:' , code );
192- ref .current ?.clear ();
193- };
194-
195- return (
196- <OTPInput
197- ref = { ref }
198- onComplete = { onComplete }
199- maxLength = { 6 }
200- render = { ({ slots }) => (
201- <View style = { styles .mainContainer } >
202- <View style = { styles .slotsContainer } >
203- { slots .slice (0 , 3 ).map ((slot , idx ) => (
204- <Slot key = { idx } { ... slot } index = { idx } />
205- ))}
206- </View >
207- <FakeDash />
208- <View style = { styles .slotsContainer } >
209- { slots .slice (3 ).map ((slot , idx ) => (
210- <Slot key = { idx } { ... slot } index = { idx } />
211- ))}
212- </View >
213- </View >
214- )}
215- />
216- );
217- }
218-
219- function Slot({
220- char ,
221- isActive ,
222- hasFakeCaret ,
223- index ,
224- }: SlotProps & { index: number }) {
225- const isFirst = index === 0 ;
226- const isLast = index === 2 ;
227-
228- return (
229- <View
230- style = { [
231- styles .slot ,
232- isFirst && styles .slotFirst ,
233- isLast && styles .slotLast ,
234- isActive && styles .activeSlot ,
235- ]}
236- >
237- { char !== null && <Text style = { styles .char } >{ char } </Text >}
238- { hasFakeCaret && <FakeCaret />}
239- </View >
240- );
241- }
242-
243- function FakeDash() {
244- return (
245- <View style = { styles .fakeDashContainer } >
246- <View style = { styles .fakeDash } />
247- </View >
248- );
249- }
250-
251- function FakeCaret({ style }: { style? : ViewStyle }) {
252- const opacity = useSharedValue (1 );
253-
254- useEffect (() => {
255- opacity .value = withRepeat (
256- withSequence (
257- withTiming (0 , { duration: 500 }),
258- withTiming (1 , { duration: 500 })
259- ),
260- - 1 ,
261- true
262- );
263- }, [opacity ]);
264-
265- const animatedStyle = useAnimatedStyle (() => ({
266- opacity: opacity .value ,
267- }));
268-
269- return (
270- <View style = { styles .fakeCaretContainer } >
271- <Animated.View style = { [styles .fakeCaret , style , animatedStyle ]} />
272- </View >
273- );
274- }
275-
276- const styles = StyleSheet .create ({
277- mainContainer: {
278- flex: 1 ,
279- flexDirection: ' row' ,
280- alignItems: ' center' ,
281- justifyContent: ' center' ,
282- marginVertical: 16 ,
283- },
284- slotsContainer: {
285- flexDirection: ' row' ,
286- },
287- slot: {
288- width: 42 ,
289- height: 52 ,
290- alignItems: ' center' ,
291- justifyContent: ' center' ,
292- backgroundColor: ' #F9FAFB' ,
293- borderWidth: 1 ,
294- borderColor: ' #E5E7EB' ,
295- },
296- slotFirst: {
297- borderTopLeftRadius: 8 ,
298- borderBottomLeftRadius: 8 ,
299- },
300- slotLast: {
301- borderTopRightRadius: 8 ,
302- borderBottomRightRadius: 8 ,
303- },
304- activeSlot: {
305- backgroundColor: ' #FFF' ,
306- borderColor: ' #000' ,
307- },
308- char: {
309- fontSize: 22 ,
310- fontWeight: ' 500' ,
311- color: ' #111827' ,
312- },
313- fakeDashContainer: {
314- width: 32 ,
315- alignItems: ' center' ,
316- justifyContent: ' center' ,
317- },
318- fakeDash: {
319- width: 8 ,
320- height: 2 ,
321- backgroundColor: ' #E5E7EB' ,
322- borderRadius: 1 ,
323- },
324- /* Caret */
325- fakeCaretContainer: {
326- position: ' absolute' ,
327- width: ' 100%' ,
328- height: ' 100%' ,
329- alignItems: ' center' ,
330- justifyContent: ' center' ,
331- },
332- fakeCaret: {
333- width: 2 ,
334- height: 32 ,
335- backgroundColor: ' #000' ,
336- borderRadius: 1 ,
337- },
338- });
339- ```
340-
341- 🍏 [ Apple OTP Input with Nativewind] ( ./example/src/examples/apple-nativewind.tsx )
342-
343- 🍎 [ Apple OTP Input] ( ./example/src/examples/apple.tsx )
344-
345- 🔄 [ Revolt OTP Input] ( ./example/src/examples/revolt.tsx )
346-
347- 🔄 [ Revolt OTP Input with Nativewind] ( ./example/src/examples/revolt-nativewind.tsx )
348-
349- 〰️ [ Dashed OTP Input] ( ./example/src/examples/dashed.tsx )
350-
351- 〰️ [ Dashed OTP Input with Nativewind] ( ./example/src/examples/dashed-nativewind.tsx )
42+ ## Documentation
43+
44+ - [ Homepage] ( https://input-otp-native.better-app.dev )
45+ - [ Getting Started] ( https://input-otp-native.better-app.dev/getting-started )
46+ - [ Examples] ( https://input-otp-native.better-app.dev/examples )
47+ - [ Apple] ( https://input-otp-native.better-app.dev/examples/apple )
48+ - [ Stripe] ( https://input-otp-native.better-app.dev/examples/stripe )
49+ - [ Revolt] ( https://input-otp-native.better-app.dev/examples/revolt )
50+ - [ Dashed] ( https://input-otp-native.better-app.dev/examples/dashed )
35251
35352## API Reference
35453
0 commit comments