input-otp-native
Version:
One time passcode Input For React Native/Expo. Unstyled and fully customizable.
79 lines (78 loc) • 2.37 kB
JavaScript
import * as React from 'react';
export function useInput({
onChange: _onChange,
maxLength,
pattern,
placeholder,
defaultValue,
onComplete,
pasteTransformer
}) {
const [value, setValue] = React.useState(typeof defaultValue === 'string' ? defaultValue : '');
const regexp = React.useMemo(() => pattern ? typeof pattern === 'string' ? new RegExp(pattern) : pattern : null, [pattern]);
const inputRef = React.useRef(null);
const [isFocused, setIsFocused] = React.useState(false);
const onChangeText = React.useCallback(text => {
// Detect paste operation: if text length increases by more than 1 character
// it's likely a paste operation rather than normal typing
const isPaste = text.length > value.length + 1;
const transformedText = isPaste && pasteTransformer ? pasteTransformer(text) : text;
const newValue = transformedText.slice(0, maxLength);
if (newValue.length > 0 && regexp && !regexp.test(newValue)) {
return;
}
setValue(newValue);
_onChange?.(newValue);
if (newValue.length === maxLength) {
onComplete?.(newValue);
}
}, [maxLength, regexp, _onChange, onComplete, pasteTransformer, value.length]);
const onFocus = React.useCallback(() => {
setIsFocused(true);
}, []);
const onBlur = React.useCallback(() => {
setIsFocused(false);
}, []);
const clear = React.useCallback(() => {
inputRef.current?.clear();
setValue('');
}, []);
const focus = React.useCallback(() => {
inputRef.current?.focus();
}, []);
const contextValue = React.useMemo(() => {
return {
slots: Array.from({
length: maxLength
}).map((_, slotIdx) => {
const isActive = isFocused && slotIdx === value.length;
const char = value[slotIdx] !== undefined ? value[slotIdx] : null;
const placeholderChar = value[0] !== undefined ? null : placeholder?.[slotIdx] ?? null;
return {
char,
placeholderChar,
isActive,
hasFakeCaret: isActive && char === null
};
}),
isFocused
};
}, [isFocused, maxLength, value, placeholder]);
return {
inputRef,
contextValue,
value,
isFocused,
handlers: {
onChangeText,
onFocus,
onBlur
},
actions: {
clear,
focus
}
};
}
//# sourceMappingURL=use-input.js.map
;