UNPKG

@pakenfit/react-native-pin-input

Version:
161 lines (160 loc) 6.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PinInput = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _Input = require("./Input"); var Clipboard = _interopRequireWildcard(require("expo-clipboard")); var _constants = require("../constants"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const PinInput = exports.PinInput = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => { let { length = 4, inputProps, inputStyle, containerProps, containerStyle, onFillEnded, autoFocus = true } = _ref; const pins = Array.from({ length }).map((_, i) => i); const inputRefs = (0, _react.useRef)([]); const pinsValues = (0, _react.useRef)([]); const iosOTP = (0, _react.useRef)({ key: '', index: null }); const [keyPressed, setKeyPressed] = (0, _react.useState)(false); const handleOTP = (0, _react.useCallback)(otp => { const regexp = new RegExp(`[0-9]{${length}}`); const otps = otp.match(regexp); if (otps !== null && otps !== void 0 && otps.length) { const otpSplits = otp.split(''); otpSplits.forEach((otpSplit, i) => { var _inputRefs$current$i; return inputRefs === null || inputRefs === void 0 || (_inputRefs$current$i = inputRefs.current[i]) === null || _inputRefs$current$i === void 0 ? void 0 : _inputRefs$current$i.setNativeProps({ text: otpSplit }); }); onFillEnded === null || onFillEnded === void 0 || onFillEnded(otp); iosOTP.current = { key: '', index: null }; _reactNative.Keyboard.dismiss(); return true; } return false; }, [length, onFillEnded]); const handleChangeText = (0, _react.useCallback)(async (text, index) => { const copiedText = await Clipboard.getStringAsync(); if (copiedText.includes(text) && !keyPressed) { const otpHandled = handleOTP(copiedText); if (otpHandled) { return; } } pinsValues.current[index] = text; if (index + 1 <= pins.length - 1) { var _inputRefs$current; inputRefs === null || inputRefs === void 0 || (_inputRefs$current = inputRefs.current[index + 1]) === null || _inputRefs$current === void 0 || _inputRefs$current.focus(); } else { onFillEnded === null || onFillEnded === void 0 || onFillEnded(pinsValues.current.join('')); setKeyPressed(false); _reactNative.Keyboard.dismiss(); } }, [handleOTP, keyPressed, onFillEnded, pins.length]); const onKeyPress = (0, _react.useCallback)((event, index) => { event.persist(); setKeyPressed(true); if (_constants.IS_IOS && Number.isInteger(Number(event.nativeEvent.key))) { if (iosOTP.current.index === null) { iosOTP.current = { key: event.nativeEvent.key, index }; } else { if (iosOTP.current.index === index) { iosOTP.current = { key: `${iosOTP.current.key}${event.nativeEvent.key}`, index }; } else { iosOTP.current = { key: '', index: null }; } } if (iosOTP.current.key.length === length) { handleOTP(iosOTP.current.key); return; } } if (event.nativeEvent.key === 'Backspace') { // Clear only the current digit if it has value if (pinsValues.current[index]) { pinsValues.current[index] = ''; // Don't move focus - stay on current field // We only reset partial state, not the entire PIN } else { // Only move to previous field when current field is empty if (index - 1 >= 0) { var _inputRefs$current2; inputRefs === null || inputRefs === void 0 || (_inputRefs$current2 = inputRefs.current[index - 1]) === null || _inputRefs$current2 === void 0 || _inputRefs$current2.focus(); } } setKeyPressed(false); iosOTP.current = { key: '', index: null }; } }, [handleOTP, length]); const clear = (0, _react.useCallback)(() => { var _inputRefs$current$; pinsValues.current = []; inputRefs.current.forEach(input => { input === null || input === void 0 || input.setNativeProps({ text: '', placeholder: '0' }); }); (_inputRefs$current$ = inputRefs.current[0]) === null || _inputRefs$current$ === void 0 || _inputRefs$current$.focus(); }, []); (0, _react.useImperativeHandle)(ref, () => ({ clear }), [clear]); return /*#__PURE__*/_react.default.createElement(_reactNative.View, _extends({ style: [styles.container, containerStyle] }, containerProps), pins.map(pin => { return /*#__PURE__*/_react.default.createElement(_Input.Input, _extends({}, inputProps, { autoFocus: autoFocus && pin === 0, ref: input => inputRefs === null || inputRefs === void 0 ? void 0 : inputRefs.current.push(input), key: pin, style: inputStyle, onChangeText: text => handleChangeText(text, pin), onKeyPress: event => onKeyPress(event, pin), autoComplete: "sms-otp", textContentType: "oneTimeCode", keyboardType: "numeric" })); })); }); PinInput.displayName = 'PinInput'; const styles = _reactNative.StyleSheet.create({ container: { display: 'flex', flexDirection: 'row', gap: 5, alignItems: 'center', justifyContent: 'center' } }); //# sourceMappingURL=PinInput.js.map