From 77e0a7fd6d09b341e9a7ab568249c44630a6925a Mon Sep 17 00:00:00 2001 From: Youssouf EL Azizi Date: Mon, 13 Jan 2025 22:58:37 +0100 Subject: [PATCH] chore: improve docs examples --- README.md | 307 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 297 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b601f09..3b23800 100644 --- a/README.md +++ b/README.md @@ -24,23 +24,310 @@ yarn add input-otp-native pnpm add input-otp-native ``` -## Examples ( copy paste) - -> [Apple OTP Input](./example/src/examples/apple.tsx) +## Examples + +We create a few examples that you can copy paste and use in your project. + +💳 [Stripe OTP Input with Nativewind](./example/src/examples/stripe-nativewind.tsx) + +```tsx +import { View, Text } from 'react-native'; +import { OTPInput, type SlotProps } from 'input-otp-native'; +import type { OTPInputRef } from 'input-otp-native'; +import { useRef } from 'react'; +import { Alert } from 'react-native'; + +import Animated, { + useAnimatedStyle, + withRepeat, + withTiming, + withSequence, + useSharedValue, +} from 'react-native-reanimated'; +import { useEffect } from 'react'; +import { cn } from './utils'; + +export default function StripeOTPInput() { + const ref = useRef(null); + const onComplete = (code: string) => { + Alert.alert('Completed with code:', code); + ref.current?.clear(); + }; + + return ( + ( + + + {slots.slice(0, 3).map((slot, idx) => ( + + ))} + + + + {slots.slice(3).map((slot, idx) => ( + + ))} + + + )} + /> + ); +} + +function Slot({ + char, + isActive, + hasFakeCaret, + index, +}: SlotProps & { index: number }) { + const isFirst = index === 0; + const isLast = index === 2; + return ( + + {char !== null && ( + {char} + )} + {hasFakeCaret && } + + ); +} + +function FakeDash() { + return ( + + + + ); +} + +function FakeCaret() { + const opacity = useSharedValue(1); + + useEffect(() => { + opacity.value = withRepeat( + withSequence( + withTiming(0, { duration: 500 }), + withTiming(1, { duration: 500 }) + ), + -1, + true + ); + }, [opacity]); + + const animatedStyle = useAnimatedStyle(() => ({ + opacity: opacity.value, + })); + + const baseStyle = { + width: 2, + height: 32, + backgroundColor: 'black', + borderRadius: 1, + }; + + return ( + + + + ); +} +``` -> [Apple OTP Input with Nativewind](./example/src/examples/apple-nativewind.tsx) +💳 [Stripe OTP Input](./example/src/examples/stripe.tsx) + +```tsx +import { View, Text, StyleSheet, type ViewStyle, Alert } from 'react-native'; +import { OTPInput, type SlotProps } from 'input-otp-native'; +import type { OTPInputRef } from 'input-otp-native'; +import { useRef } from 'react'; + +import Animated, { + useAnimatedStyle, + withRepeat, + withTiming, + withSequence, + useSharedValue, +} from 'react-native-reanimated'; +import { useEffect } from 'react'; + +export default function StripeOTPInput() { + const ref = useRef(null); + const onComplete = (code: string) => { + Alert.alert('Completed with code:', code); + ref.current?.clear(); + }; + + return ( + ( + + + {slots.slice(0, 3).map((slot, idx) => ( + + ))} + + + + {slots.slice(3).map((slot, idx) => ( + + ))} + + + )} + /> + ); +} + +function Slot({ + char, + isActive, + hasFakeCaret, + index, +}: SlotProps & { index: number }) { + const isFirst = index === 0; + const isLast = index === 2; + + return ( + + {char !== null && {char}} + {hasFakeCaret && } + + ); +} + +function FakeDash() { + return ( + + + + ); +} + +function FakeCaret({ style }: { style?: ViewStyle }) { + const opacity = useSharedValue(1); + + useEffect(() => { + opacity.value = withRepeat( + withSequence( + withTiming(0, { duration: 500 }), + withTiming(1, { duration: 500 }) + ), + -1, + true + ); + }, [opacity]); + + const animatedStyle = useAnimatedStyle(() => ({ + opacity: opacity.value, + })); + + return ( + + + + ); +} + +const styles = StyleSheet.create({ + mainContainer: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + marginVertical: 16, + }, + slotsContainer: { + flexDirection: 'row', + }, + slot: { + width: 42, + height: 52, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#F9FAFB', + borderWidth: 1, + borderColor: '#E5E7EB', + }, + slotFirst: { + borderTopLeftRadius: 8, + borderBottomLeftRadius: 8, + }, + slotLast: { + borderTopRightRadius: 8, + borderBottomRightRadius: 8, + }, + activeSlot: { + backgroundColor: '#FFF', + borderColor: '#000', + }, + char: { + fontSize: 22, + fontWeight: '500', + color: '#111827', + }, + fakeDashContainer: { + width: 32, + alignItems: 'center', + justifyContent: 'center', + }, + fakeDash: { + width: 8, + height: 2, + backgroundColor: '#E5E7EB', + borderRadius: 1, + }, + /* Caret */ + fakeCaretContainer: { + position: 'absolute', + width: '100%', + height: '100%', + alignItems: 'center', + justifyContent: 'center', + }, + fakeCaret: { + width: 2, + height: 32, + backgroundColor: '#000', + borderRadius: 1, + }, +}); +``` -> [Stripe OTP Input](./example/src/examples/stripe.tsx) +🍏 [Apple OTP Input with Nativewind](./example/src/examples/apple-nativewind.tsx) -> [Stripe OTP Input with Nativewind](./example/src/examples/stripe-nativewind.tsx) +🍎 [Apple OTP Input](./example/src/examples/apple.tsx) -> [Revolt OTP Input](./example/src/examples/revolt.tsx) +🔄 [Revolt OTP Input](./example/src/examples/revolt.tsx) -> [Revolt OTP Input with Nativewind](./example/src/examples/revolt-nativewind.tsx) +🔄 [Revolt OTP Input with Nativewind](./example/src/examples/revolt-nativewind.tsx) -> [Dashed OTP Input](./example/src/examples/dashed.tsx) +〰️ [Dashed OTP Input](./example/src/examples/dashed.tsx) -> [Dashed OTP Input with Nativewind](./example/src/examples/dashed-nativewind.tsx) +〰️ [Dashed OTP Input with Nativewind](./example/src/examples/dashed-nativewind.tsx) ## API Reference