UNPKG

react-native-keypad-component

Version:
224 lines (223 loc) 7.48 kB
"use strict"; import React, { Fragment, useCallback, useEffect, useState } from 'react'; import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import Animated, { LinearTransition, useAnimatedStyle, useSharedValue, withRepeat, withSequence, withTiming, ZoomIn, ZoomOut } from 'react-native-reanimated'; import { ANIMATION_VALUES, DEFAULTS } from "./constants.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export default function Keypad({ onPinEntered, onPinErrored, errorMessageComponent, pinLength = DEFAULTS.pinLength, containerStyle, buttonStyle, buttonTextStyle, keypadTextSize = DEFAULTS.keypadTextSize, disableKeypadBackground = DEFAULTS.displayKeypadBg, usesFaceId = DEFAULTS.useFaceId, keypadRadius = DEFAULTS.borderRadius, theme = DEFAULTS.theme, activeDotColor, emptyDotColor = DEFAULTS.emptyDotColor, keypadColor, textColor, dotWidth = DEFAULTS.dotWidth, dotHeight = DEFAULTS.dotHeight, gridGap = DEFAULTS.gridGap, renderFaceIdIcon, applyBackgroundToFaceIdButton = DEFAULTS.applyFaceIdButtonBackground }) { const isDarkTheme = theme === 'dark'; const dotColor = isDarkTheme ? DEFAULTS.dotColorDark : DEFAULTS.dotColorLight; const defaultTextColor = isDarkTheme ? DEFAULTS.textColorDark : DEFAULTS.textColorLight; const defaultKeypadColor = isDarkTheme ? DEFAULTS.keyboardColorDark : DEFAULTS.keyboardColorLight; const [pin, setPin] = useState(''); const offset = useSharedValue(0); const animatedStyle = useAnimatedStyle(() => { return { transform: [{ translateX: offset.value }] }; }); const dotScales = [useSharedValue(1), useSharedValue(1), useSharedValue(1), useSharedValue(1)]; const animatedDotStyles = [useAnimatedStyle(() => ({ transform: [{ scale: dotScales[0]?.value ?? 1 }] })), useAnimatedStyle(() => ({ transform: [{ scale: dotScales[1]?.value ?? 2 }] })), useAnimatedStyle(() => ({ transform: [{ scale: dotScales[2]?.value ?? 3 }] })), useAnimatedStyle(() => ({ transform: [{ scale: dotScales[3]?.value ?? 4 }] }))]; const applyShakeAnimation = useCallback(() => { offset.value = withSequence(withTiming(-ANIMATION_VALUES.offset, { duration: ANIMATION_VALUES.timing / 2 }), withRepeat(withTiming(ANIMATION_VALUES.offset, { duration: ANIMATION_VALUES.timing }), 4, true), withTiming(0, { duration: ANIMATION_VALUES.timing / 2 })); }, [offset]); useEffect(() => { if (onPinErrored) { applyShakeAnimation(); } }, [onPinErrored, applyShakeAnimation]); function handlePress(digit) { const newPin = pin + digit; if (newPin.length <= pinLength) { setPin(newPin); const nextIndex = newPin.length - 1; const dot = dotScales[nextIndex]; if (dot) { dot.value = withSequence(withTiming(1.2, { duration: 100 }), withTiming(1, { duration: 100 })); } if (newPin.length === pinLength) { onPinEntered(newPin); setTimeout(() => setPin(''), 200); } } } function handleDelete() { if (pin.length > 0) { const indexToAnimate = pin.length - 1; const dot = dotScales[indexToAnimate]; if (dot) { dot.value = withSequence(withTiming(1.2, { duration: 100 }), withTiming(1, { duration: 100 })); } setPin(prev => prev.slice(0, -1)); } } return /*#__PURE__*/_jsxs(View, { style: [styles.container, containerStyle], children: [/*#__PURE__*/_jsx(Animated.View, { style: [styles.dotsContainer, animatedStyle], children: Array.from({ length: pinLength }).map((_, index) => { return /*#__PURE__*/_jsx(Animated.View, { testID: index < pin.length ? 'pin-dot-filled' : 'pin-dot', style: [styles.dot, { backgroundColor: index < pin.length ? activeDotColor ?? dotColor : emptyDotColor, borderRadius: keypadRadius, width: dotWidth, height: dotHeight }, animatedDotStyles[index]] }, index); }) }), onPinErrored && errorMessageComponent && /*#__PURE__*/_jsx(Animated.View, { layout: LinearTransition.springify().damping(ANIMATION_VALUES.damping), entering: ZoomIn, exiting: ZoomOut, style: { marginBottom: 10 }, children: errorMessageComponent() }), /*#__PURE__*/_jsx(Animated.View, { layout: LinearTransition.springify().damping(ANIMATION_VALUES.damping), style: [styles.grid, { gap: gridGap }], children: ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'face', '0', 'del'].map((key, index) => { if (key === 'face') { return usesFaceId ? /*#__PURE__*/_jsx(Fragment, { children: /*#__PURE__*/_jsx(TouchableOpacity, { activeOpacity: 0.6, style: [styles.button, { borderRadius: keypadRadius, backgroundColor: disableKeypadBackground ? 'transparent' : applyBackgroundToFaceIdButton ? buttonStyle && buttonStyle.backgroundColor || keypadColor || defaultKeypadColor : 'transparent' }, buttonStyle], children: renderFaceIdIcon ? renderFaceIdIcon() : /*#__PURE__*/_jsx(Text, { children: "\uD83D\uDD10" }) }) }, key) : /*#__PURE__*/_jsx(View, { style: [styles.button, { backgroundColor: disableKeypadBackground ? 'transparent' : keypadColor ?? defaultKeypadColor, borderRadius: keypadRadius, opacity: 0 }] }, index); } if (key === 'del') { return /*#__PURE__*/_jsx(TouchableOpacity, { activeOpacity: 0.6, style: [styles.button, { backgroundColor: disableKeypadBackground ? 'transparent' : keypadColor ?? defaultKeypadColor, borderRadius: keypadRadius }, buttonStyle], onPress: handleDelete, children: /*#__PURE__*/_jsx(Text, { style: [{ color: textColor ?? defaultTextColor, fontSize: keypadTextSize }, buttonTextStyle], children: "\u232B" }) }, key); } return /*#__PURE__*/_jsx(TouchableOpacity, { activeOpacity: 0.6, testID: `key-${key}`, style: [styles.button, { backgroundColor: disableKeypadBackground ? 'transparent' : keypadColor ?? defaultKeypadColor, borderRadius: keypadRadius }, buttonStyle], onPress: () => handlePress(key), children: /*#__PURE__*/_jsx(Text, { style: [{ color: textColor ?? defaultTextColor, fontSize: keypadTextSize }, buttonTextStyle], children: key }) }, index); }) })] }); } const styles = StyleSheet.create({ container: { alignItems: 'center' }, dotsContainer: { flexDirection: 'row', marginBottom: 20, gap: 5 }, dot: { margin: 8, borderRadius: 8 }, grid: { flexDirection: 'row', flexWrap: 'wrap', width: 240, justifyContent: 'center' }, button: { width: 60, height: 60, margin: 5, justifyContent: 'center', alignItems: 'center' } }); //# sourceMappingURL=index.js.map