8000 feat: create a strip otp example · yjose/input-otp-native@996fa22 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
10000

Commit 996fa22

Browse files
committed
feat: create a strip otp example
1 parent 69c116d commit 996fa22

File tree

5 files changed

+177
-122
lines changed

5 files changed

+177
-122
lines changed

example/src/App.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { Text, View, StyleSheet } from 'react-native';
2-
import OTPInputExample from './otp-input-example';
2+
import StripeOTPInput from './stripe';
3+
import { Title } from './title';
34

45
export default function App() {
56
return (
67
<View style={styles.container}>
78
<Text>Hello World</Text>
8-
<OTPInputExample />
9+
<View style={styles.exampleContainer}>
10+
<Title>Stripe OTP Input</Title>
11+
<StripeOTPInput />
12+
</View>
913
</View>
1014
);
1115
}
@@ -16,4 +20,7 @@ const styles = StyleSheet.create({
1620
alignItems: 'center',
1721
justifyContent: 'center',
1822
},
23+
exampleContainer: {
24+
marginTop: 16,
25+
},
1926
});

example/src/fake-caret.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { View, StyleSheet } from 'react-native';
2+
import Animated, {
3+
useAnimatedStyle,
4+
withRepeat,
5+
withTiming,
6+
withSequence,
7+
useSharedValue,
8+
} from 'react-native-reanimated';
9+
import { useEffect } from 'react';
10+
11+
export function FakeCaret() {
12+
const opacity = useSharedValue(1);
13+
14+
useEffect(() => {
15+
opacity.value = withRepeat(
16+
withSequence(
17+
withTiming(0, { duration: 500 }),
18+
withTiming(1, { duration: 500 })
19+
),
20+
-1,
21+
true
22+
);
23+
}, [opacity]);
24+
25+
const animatedStyle = useAnimatedStyle(() => ({
26+
opacity: opacity.value,
27+
}));
28+
29+
return (
30+
<View style={styles.fakeCaretContainer}>
31+
<Animated.View style={[styles.fakeCaret, animatedStyle]} />
32+
</View>
33+
);
34+
}
35+
36+
const styles = StyleSheet.create({
37+
fakeCaretContainer: {
38+
position: 'absolute',
39+
width: '100%',
40+
height: '100%',
41+
alignItems: 'center',
42+
justifyContent: 'center',
43+
},
44+
fakeCaret: {
45+
width: 2,
46+
height: 32,
47+
backgroundColor: '#000',
48+
borderRadius: 1,
49+
},
50+
});

example/src/otp-input-example.tsx

Lines changed: 0 additions & 120 deletions
This file was deleted.

example/src/stripe.tsx

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { View, Text, StyleSheet } from 'react-native';
2+
import { OTPInput, type SlotProps } from 'input-otp-native';
3+
import { FakeCaret } from './fake-caret';
4+
5+
export default function StripeOTPInput() {
6+
return (
7+
<OTPInput
8+
containerStyle={styles.container}
9+
maxLength={6}
10+
render={({ slots }) => (
11+
<>
12+
<View style={styles.slotsContainer}>
13+
{slots.slice(0, 3).map((slot, idx) => (
14+
<Slot key={idx} {...slot} index={idx} />
15+
))}
16+
</View>
17+
18+
<FakeDash />
19+
20+
<View style={styles.slotsContainer}>
21+
{slots.slice(3).map((slot, idx) => (
22+
<Slot key={idx} {...slot} index={idx} />
23+
))}
24+
</View>
25+
</>
26+
)}
27+
/>
28+
);
29+
}
30+
31+
function Slot({
32+
char,
33+
isActive,
34+
hasFakeCaret,
35+
index,
36+
}: SlotProps & { index: number }) {
37+
return (
38+
<View
39+
style={[
40+
styles.slot,
41+
isActive && styles.activeSlot,
42+
{ borderLeftWidth: index === 0 ? 0 : 1 },
43+
]}
44+
>
45+
{char !== null && <Text style={styles.char}>{char}</Text>}
46+
{hasFakeCaret && <FakeCaret />}
47+
</View>
48+
);
49+
}
50+
51+
function FakeDash() {
52+
return (
53+
<View style={styles.fakeDashContainer}>
54+
<View style={styles.fakeDash} />
55+
</View>
56+
);
57+
}
58+
59+
const styles = StyleSheet.create({
60+
container: {
61+
flexDirection: 'row',
62+
alignItems: 'center',
63+
justifyContent: 'center',
64+
},
65+
slotsContainer: {
66+
flexDirection: 'row',
67+
borderWidth: 1,
68+
borderColor: '#E5E7EB',
69+
borderRadius: 8,
70+
overflow: 'hidden',
71+
},
72+
slot: {
73+
width: 48,
74+
height: 64,
75+
alignItems: 'center',
76+
justifyContent: 'center',
77+
borderLeftWidth: 1,
78+
borderColor: '#E5E7EB',
79+
backgroundColor: '#F9FAFB',
80+
},
81+
activeSlot: {
82+
backgroundColor: '#FFF',
83+
},
84+
char: {
85+
fontSize: 24,
86+
fontWeight: '500',
87+
color: '#111827',
88+
},
89+
fakeDashContainer: {
90+
width: 32,
91+
alignItems: 'center',
92+
justifyContent: 'center',
93+
},
94+
fakeDash: {
95+
width: 8,
96+
height: 2,
97+
backgroundColor: '#E5E7EB',
98+
borderRadius: 1,
99+
},
100+
});

example/src/title.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Text, StyleSheet } from 'react-native';
2+
3+
interface TitleProps {
4+
children: string;
5+
}
6+
7+
export function Title({ children }: TitleProps) {
8+
return <Text style={styles.title}>{children}</Text>;
9+
}
10+
11+
const styles = StyleSheet.create({
12+
title: {
13+
fontSize: 18,
14+
fontWeight: 'bold',
15+
marginBottom: 16,
16+
color: '#111827',
17+
},
18+
});

0 commit comments

Comments
 (0)
0