UNPKG

input-otp-native

Version:

One time passcode Input For React Native/Expo. Unstyled and fully customizable.

116 lines (114 loc) 3.1 kB
"use strict"; import * as React from 'react'; import { TextInput, StyleSheet, Pressable, Platform } from 'react-native'; import { useInput } from "./use-input.js"; /** * Default paste transformer that removes all non-numeric characters. */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const defaultPasteTransformer = maxLength => pasted => { // match exactly maxLength digits, not preceded or followed by another digit const otpRegex = new RegExp(`(?<!\\d)(\\d{${maxLength}})(?!\\d)`); const match = pasted.match(otpRegex); return match?.[1] ?? ''; }; export const OTPInput = /*#__PURE__*/React.forwardRef(({ style, onChange, maxLength, pattern, placeholder, inputMode = 'numeric', containerStyle, onComplete, render, ...props }, ref) => { const { inputRef, contextValue, value, handlers, actions } = useInput({ onChange, maxLength, pattern, placeholder, defaultValue: props.defaultValue, pasteTransformer: props.pasteTransformer ?? defaultPasteTransformer(maxLength), onComplete }); React.useImperativeHandle(ref, () => ({ setValue: newValue => { handlers.onChangeText(newValue); }, focus: () => { actions.focus(); // for test only we need to call onFocus handlers.onFocus(); }, blur: () => inputRef.current?.blur(), clear: actions.clear })); const renderedChildren = React.useMemo(() => { if (render) { return render(contextValue); } return null; }, [contextValue, render]); const onPress = React.useCallback(() => { actions.focus(); actions.clear(); }, [actions]); return /*#__PURE__*/_jsxs(Pressable, { testID: "otp-input-container", style: [styles.container, containerStyle], onPress: onPress, children: [renderedChildren, /*#__PURE__*/_jsx(TextInput, { ref: inputRef, style: [styles.input, style], value: value, onChangeText: handlers.onChangeText, onFocus: handlers.onFocus, onBlur: handlers.onBlur, placeholder: placeholder, inputMode: inputMode /** * On iOS if the input has an opacity of 0, we can't paste text into it. * As we're setting the opacity to 0.02, we need to hide the caret. */, caretHidden: Platform.OS === 'ios', textContentType: "oneTimeCode", autoComplete: Platform.OS === 'android' ? 'sms-otp' : 'one-time-code', clearTextOnFocus: true, accessible: true, accessibilityRole: "text", testID: "otp-input", ...props })] }); }); OTPInput.displayName = 'OTPInput'; const styles = StyleSheet.create({ container: { position: 'relative' }, input: { ...StyleSheet.absoluteFillObject, /** * On iOS if the input has an opacity of 0, we can't paste text into it. * This is a workaround to allow pasting text into the input. */ ...Platform.select({ ios: { opacity: 0.02, color: 'transparent' }, android: { opacity: 0 } }) } }); //# sourceMappingURL=input.js.map