85 lines
2.1 KiB
TypeScript
85 lines
2.1 KiB
TypeScript
import { useRef, useState } from "react";
|
|
import {
|
|
Platform,
|
|
NativeSyntheticEvent,
|
|
TextInputSubmitEditingEventData,
|
|
} from "react-native";
|
|
import { TextInput, TextInputProps } from "react-native-paper";
|
|
|
|
interface PasswordInputProps {
|
|
label: string;
|
|
value: string;
|
|
onChangeText: (text: string) => void;
|
|
onBlur?: () => void;
|
|
disabled?: boolean;
|
|
style?: any;
|
|
onSubmitEditing?: (
|
|
e?: NativeSyntheticEvent<TextInputSubmitEditingEventData>
|
|
) => void;
|
|
returnKeyType?: any;
|
|
submitBehavior?: TextInputProps["submitBehavior"];
|
|
}
|
|
|
|
export const PasswordInput = ({
|
|
label,
|
|
value,
|
|
onChangeText,
|
|
onBlur,
|
|
disabled = false,
|
|
style = {},
|
|
onSubmitEditing,
|
|
returnKeyType,
|
|
submitBehavior,
|
|
}: PasswordInputProps) => {
|
|
const [secureTextEntry, setSecureTextEntry] = useState(true);
|
|
const submitGuardRef = useRef(false);
|
|
|
|
const triggerSubmitOnce = () => {
|
|
if (submitGuardRef.current) return;
|
|
submitGuardRef.current = true;
|
|
try {
|
|
onSubmitEditing?.();
|
|
} finally {
|
|
// release guard on next tick to allow future submissions
|
|
setTimeout(() => {
|
|
submitGuardRef.current = false;
|
|
}, 0);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<TextInput
|
|
label={label}
|
|
mode="flat"
|
|
value={value}
|
|
secureTextEntry={secureTextEntry}
|
|
onChangeText={onChangeText}
|
|
onBlur={onBlur}
|
|
style={{
|
|
marginBottom: 16,
|
|
backgroundColor: "transparent",
|
|
...style,
|
|
}}
|
|
onSubmitEditing={() => triggerSubmitOnce()}
|
|
returnKeyType={returnKeyType}
|
|
submitBehavior={submitBehavior ?? "submit"}
|
|
onKeyPress={(e) => {
|
|
if (Platform.OS === "web" && e?.nativeEvent?.key === "Enter") {
|
|
triggerSubmitOnce();
|
|
}
|
|
}}
|
|
left={<TextInput.Icon icon="lock" color="#6750a4" />}
|
|
right={
|
|
<TextInput.Icon
|
|
icon={secureTextEntry ? "eye" : "eye-off"}
|
|
color="#6750a4"
|
|
onPress={() => setSecureTextEntry(!secureTextEntry)}
|
|
/>
|
|
}
|
|
theme={{ colors: { primary: "#6750a4" } }}
|
|
disabled={disabled}
|
|
placeholderTextColor="#d9d9d9"
|
|
/>
|
|
);
|
|
};
|