import React, { useState, useEffect, useCallback, useMemo } from 'react' import { View, TouchableOpacity, Text, Animated, StyleSheet, FlatList } from 'react-native' import { styles } from './styles' import { types } from './types' import { defaultProps } from './defaultProps' const numbers = ['1', '2', '3', '4', '5', '6', '7', '8', '9', "", "0", "delete"]; export const CustomPincode = ({ leftElement, leftElementCallback, rightElement, rightElementCallback, bottomElement, bottomCallback, bottomElementStyle, isBottom, pinButtonStyle, pinTextStyle, leftButtonStyle, rightButtonStyle, leftContainerStyle, rightContainerStyle, isDeleteButton, buttonDeleteElement, buttonDeletePosition, pinContainerStyles, containerStyles, isLeft, isRight, zeroButtonStyle, completeCallback, pinLength, keyButtons, pointStyle, pointActiveStyle, pointsStyle, keyPoints, pointsLength, isPinError, errorPointStyles, defaultPin }) => { const [pinValues, setPinValues] = useState(''); const [shakeAnim, setShakeAnim] = useState(new Animated.Value(0)) const mergeStyles = useCallback((a, b) => ([a, b]), []); const handleOnPressNumber = useCallback( newVal => { if (pinValues.length <= pinLength) { setPinValues(v => `${v}${newVal}`) } }, [pinLength, pinValues.length], ); const handleOnDeleteLatestValue = useCallback( /** * @param {boolean} isClearAll */ isClearAll => { //typeof like guard here setPinValues(v => (typeof isClearAll !== 'object' && isClearAll ? '' : (pinValues.length <= pinLength && isClearAll) ? v.slice(0, -1) : '')) }, [], ); const handleShake = () => { const values = [10, -7.5, 5, -2.5, 0]; const duration = 75; Animated.sequence( values.map(toValue => Animated.timing(shakeAnim, { toValue, duration, useNativeDriver: false })) ).start(); }; const renderDelete = useMemo( () => ( {buttonDeleteElement} ), [buttonDeleteElement, handleOnDeleteLatestValue, pinValues], ); const buttonStyles = useMemo(() => mergeStyles(styles.button, pinButtonStyle), [ mergeStyles, pinButtonStyle, ]); const blankStyles = useMemo(() => mergeStyles(styles.blank, pinButtonStyle), [ mergeStyles, pinButtonStyle, ]); const buttonTextStyle = useMemo(() => mergeStyles(styles.buttonText, pinTextStyle), [ mergeStyles, pinTextStyle, ]); const renderNumbers = () => { return ( { if(item === "") { return isDeleteButton && buttonDeletePosition === 'left' ? renderDelete : isLeft ? ( {leftElement} ) : handleOnPressNumber(item)} > {item} } if(item === "delete") { return isDeleteButton ? renderDelete : isRight && ( {rightElement} ) } return ( handleOnPressNumber(item)} > {item} )} } /> ) } useEffect(() => { if (pinValues.length >= pinLength) { let isValid = (defaultPin == pinValues) completeCallback(pinValues, isValid, handleOnDeleteLatestValue) if(!isValid) handleShake() } }, [completeCallback, handleOnDeleteLatestValue, pinLength, pinValues]); const pinStyles = useMemo( () => ({ points: mergeStyles(styles.points, pointsStyle), viewContainer: mergeStyles(styles.viewContainer, containerStyles), viewPinContainer: mergeStyles(styles.viewPinContainer, pinContainerStyles), zeroButton: mergeStyles(buttonStyles, zeroButtonStyle), leftButton: mergeStyles(styles.anotherButtons, leftContainerStyle), rightButton: mergeStyles(styles.anotherButtons, rightContainerStyle), pointActive: mergeStyles(styles.pointActive, pointActiveStyle), }), [ mergeStyles, pointsStyle, containerStyles, pinContainerStyles, buttonStyles, zeroButtonStyle, leftContainerStyle, rightContainerStyle, pointActiveStyle, ], ); return ( <> {[...Array(pointsLength || pinLength).keys()].map(point => { let currentPointStyle = pointStyle; if (isPinError) { currentPointStyle = errorPointStyles } else if (pinValues[point]) { currentPointStyle = pinStyles.pointActive } currentPointStyle = mergeStyles(styles.point, currentPointStyle); return })} {renderNumbers()} {/* {isDeleteButton && buttonDeletePosition === 'left' ? renderDelete : isLeft && ( {leftElement} )} handleOnPressNumber('0')}> 0 {isDeleteButton && buttonDeletePosition === 'right' ? renderDelete : isRight && ( {rightElement} )} */} {isBottom && ( {bottomElement} )} ) }; CustomPincode.defaultProps = defaultProps; CustomPincode.propTypes = types;