轻松聘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

72 lines
2.1 KiB

import { useState } from 'react';
import { Ionicons } from '@expo/vector-icons';
import { Pressable, StyleSheet, TextInput, View } from 'react-native';
import { PASSWORD_MAX_LENGTH } from '../constants';
import { colors } from '../theme';
interface Props {
value: string;
onChangeText: (t: string) => void;
placeholder?: string;
/** 最大长度,默认取密码规则上限 */
maxLength?: number;
/** 失焦回调,供页面触发规则校验提示 */
onBlur?: () => void;
}
/**
* 密码输入行:下划线样式 + 明文切换(眼睛图标)+ 一键清空。
* 登录页、重置密码页、账号安全改密页共用,避免三处各写一份输入样式。
*/
export function PasswordField({
value,
onChangeText,
placeholder = '请输入密码',
maxLength = PASSWORD_MAX_LENGTH,
onBlur,
}: Props) {
const [visible, setVisible] = useState(false);
return (
<>
<View style={styles.row}>
<TextInput
style={styles.input}
value={value}
onChangeText={onChangeText}
placeholder={placeholder}
placeholderTextColor={colors.textHint}
secureTextEntry={!visible}
autoCapitalize="none"
autoCorrect={false}
maxLength={maxLength}
onBlur={onBlur}
/>
{value.length > 0 ? (
<Pressable onPress={() => onChangeText('')} hitSlop={8}>
<Ionicons name="close-circle" size={18} color={colors.textDisabled} />
</Pressable>
) : null}
<Pressable onPress={() => setVisible((v) => !v)} hitSlop={8}>
<Ionicons
name={visible ? 'eye-off-outline' : 'eye-outline'}
size={20}
color={colors.textHint}
/>
</Pressable>
</View>
<View style={styles.underline} />
</>
);
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
height: 56,
gap: 10,
},
input: { flex: 1, fontSize: 17, color: colors.textPrimary, padding: 0 },
underline: { height: 1, backgroundColor: colors.borderLight },
});