Vertical Step indicator
May 06, 2023
1 min
An UI module for user-side pincode verification.
🔮 Simple and tiny 1.55 KB
. Easy to use;
🚮 Clearing part of the code by clicking on the cell;
🍎 Support “fast paste SMS-code” on iOS. And custom code paste for Android;
⚡ TextInput ref
support;
🛠 Highly customizable. Can be used as masked TextInput;
🤓 Readable
Name | Type | Description | Default |
---|---|---|---|
descriptionText | String | A description text | Please enter pincode for entry |
spaceColor | Color | Color of line under digit | #FF0000 |
closeButtonColor | Color | Color of X - close button | #FF0000 |
onEnteredPincode | Function | A function that returns entered code | - |
onCloseView | Function | On press close button, will be useful to close view | - |
onPressTouchId | Function | Touch Id is not available, but you can make it by yourself | - |
withTouchId | Boolean | If you do not neet touch id, you can set it to false | TRUE |
npm i react-native-code-verification --save --force
import {Animated, Image, SafeAreaView, Text, View} from 'react-native'; import React, {useState} from 'react'; import { CodeField, Cursor, useBlurOnFulfill, useClearByFocusCell, } from 'react-native-confirmation-code-field'; import styles, { ACTIVE_CELL_BG_COLOR, CELL_BORDER_RADIUS, CELL_SIZE, DEFAULT_CELL_BG_COLOR, NOT_EMPTY_CELL_BG_COLOR, } from './styles'; const {Value, Text: AnimatedText} = Animated; const CELL_COUNT = 4; const source = { uri: 'https://user-images.githubusercontent.com/4661784/56352614-4631a680-61d8-11e9-880d-86ecb053413d.png', }; const animationsColor = [...new Array(CELL_COUNT)].map(() => new Value(0)); const animationsScale = [...new Array(CELL_COUNT)].map(() => new Value(1)); const animateCell = ({hasValue, index, isFocused}) => { Animated.parallel([ Animated.timing(animationsColor[index], { useNativeDriver: false, toValue: isFocused ? 1 : 0, duration: 250, }), Animated.spring(animationsScale[index], { useNativeDriver: false, toValue: hasValue ? 0 : 1, duration: hasValue ? 300 : 250, }), ]).start(); }; const AnimatedExample = () => { const [value, setValue] = useState(''); const ref = useBlurOnFulfill({value, cellCount: CELL_COUNT}); const [props, getCellOnLayoutHandler] = useClearByFocusCell({ value, setValue, }); const renderCell = ({index, symbol, isFocused}) => { const hasValue = Boolean(symbol); const animatedCellStyle = { backgroundColor: hasValue ? animationsScale[index].interpolate({ inputRange: [0, 1], outputRange: [NOT_EMPTY_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR], }) : animationsColor[index].interpolate({ inputRange: [0, 1], outputRange: [DEFAULT_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR], }), borderRadius: animationsScale[index].interpolate({ inputRange: [0, 1], outputRange: [CELL_SIZE, CELL_BORDER_RADIUS], }), transform: [ { scale: animationsScale[index].interpolate({ inputRange: [0, 1], outputRange: [0.2, 1], }), }, ], }; // Run animation on next event loop tik // Because we need first return new style prop and then animate this value setTimeout(() => { animateCell({hasValue, index, isFocused}); }, 0); return ( <AnimatedText key={index} style={[styles.cell, animatedCellStyle]} onLayout={getCellOnLayoutHandler(index)}> {symbol || (isFocused ? <Cursor /> : null)} </AnimatedText> ); }; return ( <SafeAreaView style={styles.root}> <Text style={styles.title}>Verification</Text> <Image style={styles.icon} source={source} /> <Text style={styles.subTitle}> Please enter the verification code{'\n'} we send to your email address </Text> <CodeField ref={ref} {...props} value={value} onChangeText={setValue} cellCount={CELL_COUNT} rootStyle={styles.codeFiledRoot} keyboardType="number-pad" textContentType="oneTimeCode" renderCell={renderCell} /> <View style={styles.nextButton}> <Text style={styles.nextButtonText}>Verify</Text> </View> </SafeAreaView> ); }; export default AnimatedExample;
Coming Soon…
import {StyleSheet, Platform} from 'react-native'; export const CELL_SIZE = 55; export const CELL_BORDER_RADIUS = 8; export const DEFAULT_CELL_BG_COLOR = '#fff'; export const NOT_EMPTY_CELL_BG_COLOR = '#3557b7'; export const ACTIVE_CELL_BG_COLOR = '#f7fafe'; const styles = StyleSheet.create({ codeFiledRoot: { height: CELL_SIZE, marginTop: 30, paddingHorizontal: 20, justifyContent: 'center', }, cell: { marginHorizontal: 8, height: CELL_SIZE, width: CELL_SIZE, lineHeight: CELL_SIZE - 5, fontSize: 30, textAlign: 'center', borderRadius: CELL_BORDER_RADIUS, color: '#3759b8', backgroundColor: '#fff', // IOS shadowColor: '#000', shadowOffset: { width: 0, height: 1, }, shadowOpacity: 0.22, shadowRadius: 2.22, // Android elevation: 3, }, // ======================= root: { minHeight: 800, padding: 20, }, title: { paddingTop: 50, color: '#000', fontSize: 25, fontWeight: '700', textAlign: 'center', paddingBottom: 40, }, icon: { width: 217 / 2.4, height: 158 / 2.4, marginLeft: 'auto', marginRight: 'auto', }, subTitle: { paddingTop: 30, color: '#000', textAlign: 'center', }, nextButton: { marginTop: 30, borderRadius: 60, height: 60, backgroundColor: '#3557b7', justifyContent: 'center', minWidth: 300, marginBottom: 100, }, nextButtonText: { textAlign: 'center', fontSize: 20, color: '#fff', fontWeight: '700', }, }); export default styles;
Quick Links
Legal Stuff