react-native-otp-inputs
Version:
One-time password inputs built in pure JS for React-Native
274 lines (235 loc) • 9.44 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "OtpInputsRef", {
enumerable: true,
get: function () {
return _types.OtpInputsRef;
}
});
exports.default = void 0;
var _clipboard = _interopRequireDefault(require("@react-native-clipboard/clipboard"));
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _helpers = require("./helpers");
var _OtpInput = _interopRequireDefault(require("./OtpInput"));
var _reducer = _interopRequireDefault(require("./reducer"));
var _types = require("./types");
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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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 supportAutofillFromClipboard = _reactNative.Platform.OS === 'android' || parseInt(_reactNative.Platform.Version, 10) < 14;
const styles = _reactNative.StyleSheet.create({
container: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between'
}
});
const OtpInputs = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
let {
autoFocus,
autofillFromClipboard = supportAutofillFromClipboard,
autofillListenerIntervalMS = 1000,
autoCapitalize = 'none',
clearTextOnFocus = false,
defaultValue,
focusStyles,
handleChange = console.log,
inputContainerStyles,
inputStyles,
isRTL = false,
keyboardType = 'phone-pad',
numberOfInputs = 4,
placeholder = '',
secureTextEntry = false,
selectTextOnFocus = true,
style,
testIDPrefix = 'otpInput',
...restProps
} = _ref;
const previousCopiedText = (0, _react.useRef)('');
const inputs = (0, _react.useRef)([]);
const [{
otpCode,
hasKeySupport
}, dispatch] = (0, _react.useReducer)(_reducer.default, {}, () => ({
otpCode: (0, _helpers.fillOtpCode)(numberOfInputs, defaultValue),
handleChange,
hasKeySupport: _reactNative.Platform.OS === 'ios'
}));
(0, _react.useEffect)(() => {
if (defaultValue) {
dispatch({
type: 'setOtpCode',
payload: {
numberOfInputs,
code: defaultValue
}
});
}
}, [defaultValue, numberOfInputs]);
(0, _react.useEffect)(() => {
dispatch({
type: 'setHandleChange',
payload: handleChange
});
}, [handleChange]);
(0, _react.useImperativeHandle)(ref, () => ({
reset: () => {
dispatch({
type: 'clearOtp',
payload: numberOfInputs
});
inputs.current.forEach(input => {
var _input$current;
return input === null || input === void 0 ? void 0 : (_input$current = input.current) === null || _input$current === void 0 ? void 0 : _input$current.clear();
});
previousCopiedText.current = '';
_clipboard.default.setString('');
},
focus: () => {
var _firstInput$current;
const firstInput = inputs.current[0];
firstInput === null || firstInput === void 0 ? void 0 : (_firstInput$current = firstInput.current) === null || _firstInput$current === void 0 ? void 0 : _firstInput$current.focus();
}
}), [numberOfInputs]);
const handleInputTextChange = (text, index) => {
if (!text.length) {
handleClearInput(index);
}
if (text.length > 1) {
handleClearInput(index);
_reactNative.Keyboard.dismiss();
return fillInputs(text);
}
if (text) {
dispatch({
type: 'setOtpTextForIndex',
payload: {
text,
index
}
});
focusInput(index + 1);
}
if (index === numberOfInputs - 1 && text) {
_reactNative.Keyboard.dismiss();
}
};
const handleTextChange = (text, index) => {
if (_reactNative.Platform.OS === 'android' && !hasKeySupport || // Pasted from input accessory
_reactNative.Platform.OS === 'ios' && text.length > 1) {
handleInputTextChange(text, index);
}
};
const handleKeyPress = (_ref2, index) => {
let {
nativeEvent: {
key
}
} = _ref2;
const text = key === 'Backspace' || key.length > 1 ? '' : key;
handleInputTextChange(text, index);
if (_reactNative.Platform.OS === 'android' && !hasKeySupport && !isNaN(parseInt(key))) dispatch({
type: 'setHasKeySupport',
payload: true
});
};
const focusInput = (0, _react.useCallback)(index => {
if (index >= 0 && index < numberOfInputs) {
var _input$current2;
const input = inputs.current[index];
input === null || input === void 0 ? void 0 : (_input$current2 = input.current) === null || _input$current2 === void 0 ? void 0 : _input$current2.focus();
}
}, [numberOfInputs]);
const handleClearInput = (0, _react.useCallback)(inputIndex => {
var _input$current3;
const input = inputs.current[inputIndex];
input === null || input === void 0 ? void 0 : (_input$current3 = input.current) === null || _input$current3 === void 0 ? void 0 : _input$current3.clear();
dispatch({
type: 'setOtpTextForIndex',
payload: {
index: inputIndex,
text: ''
}
});
focusInput(inputIndex - 1);
}, [focusInput]);
const fillInputs = (0, _react.useCallback)(code => {
dispatch({
type: 'setOtpCode',
payload: {
numberOfInputs,
code
}
});
}, [numberOfInputs]);
const listenOnCopiedText = (0, _react.useCallback)(async () => {
const copiedText = await _clipboard.default.getString();
const otpCodeValue = Object.values(otpCode).join('');
if ((copiedText === null || copiedText === void 0 ? void 0 : copiedText.length) === numberOfInputs && copiedText !== otpCodeValue && copiedText !== previousCopiedText.current) {
previousCopiedText.current = copiedText;
fillInputs(copiedText);
}
}, [fillInputs, numberOfInputs, otpCode]);
(0, _react.useEffect)(() => {
let interval;
if (autofillFromClipboard) {
interval = setInterval(() => {
listenOnCopiedText();
}, autofillListenerIntervalMS);
}
return () => {
clearInterval(interval);
};
}, [autofillFromClipboard, autofillListenerIntervalMS, listenOnCopiedText, numberOfInputs]);
const renderInputs = () => {
const iterationArray = Array(numberOfInputs).fill(0);
return iterationArray.map((_, index) => {
let inputIndex = index;
if (isRTL) {
inputIndex = numberOfInputs - 1 - index;
}
const inputValue = otpCode[`${inputIndex}`];
if (!inputs.current[inputIndex]) {
inputs.current[inputIndex] = /*#__PURE__*/_react.default.createRef();
}
return /*#__PURE__*/_react.default.createElement(_OtpInput.default, _extends({
accessible: true,
accessibilityLabel: `${testIDPrefix}-${inputIndex}`,
autoCapitalize: autoCapitalize,
autoFocus: index === 0 && autoFocus,
clearTextOnFocus: clearTextOnFocus,
firstInput: index === 0,
focusStyles: focusStyles,
handleKeyPress: keyPressEvent => handleKeyPress(keyPressEvent, inputIndex),
handleTextChange: text => handleTextChange(text, inputIndex),
inputContainerStyles: inputContainerStyles,
inputStyles: inputStyles,
inputValue: inputValue,
key: inputIndex,
keyboardType: keyboardType,
maxLength: _reactNative.Platform.select({
android: 1,
ios: index === 0 ? numberOfInputs : 1
}),
numberOfInputs: numberOfInputs,
placeholder: placeholder,
ref: inputs.current[inputIndex],
secureTextEntry: secureTextEntry,
selectTextOnFocus: selectTextOnFocus,
testID: `${testIDPrefix}-${inputIndex}`
}, restProps));
});
}; // @ts-expect-error
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: style || styles.container
}, renderInputs());
});
var _default = OtpInputs;
exports.default = _default;
//# sourceMappingURL=index.js.map