@uiw/react-native
Version:
UIW for React Native
154 lines (152 loc) • 3.94 kB
JavaScript
import React, { useEffect, useState } from 'react';
import { TextInput, View, StyleSheet, TouchableOpacity } from 'react-native';
import Icon from '../Icon';
import Text from '../Typography/Text';
import { useTheme } from '@shopify/restyle';
// StyleProp<ViewStyle>
const Input = props => {
const {
wrongfulHandle,
rule,
value,
onChangeText,
onFocus,
clearText,
disabled = false,
clear,
clearStyle,
renderClear,
extraStart,
extraEnd,
style = [],
containerStyle,
border = 'bottom',
borderColor = '#ccc',
error = false,
renderError,
inputRef,
...others
} = props;
const [defaultValue, setDefaultValue] = useState(value);
const [control, setControl] = useState('state');
const theme = useTheme();
const styles = createStyles({
bgColor: theme.colors.mask
});
useEffect(() => {
if (control === 'state' && value === defaultValue) {
setControl('props');
}
if (value !== defaultValue) {
if (control === 'state') {
setControl('props');
} else {
setDefaultValue(value);
setControl('props');
}
}
}, [value, control]);
const fontSize = StyleSheet.flatten(style).fontSize || 14;
const minHeight = StyleSheet.flatten(containerStyle)?.height || 30;
const onInputChange = value => {
let flag = true;
if (rule instanceof RegExp) {
flag = rule.test(value);
}
if (typeof rule === 'function') {
flag = rule(value);
}
if (flag) {
setDefaultValue(value);
setControl('state');
onChangeText?.(value);
return false;
}
setDefaultValue(defaultValue || '');
setControl('state');
onChangeText?.(defaultValue || '');
wrongfulHandle?.();
};
const onInputFocus = e => {
if (clearText) {
setDefaultValue('');
setControl('state');
onChangeText?.('');
}
onFocus && onFocus(e);
};
return <View style={[{
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 0,
height: minHeight
}, containerStyle]} testID="RNE__Input__wrap">
<View style={[styles.container, {
flex: 1,
borderColor: borderColor
}, border ? styles[border] : {}]} testID="RNE__Input__view">
{typeof extraStart === 'string' ? <Text color="primary_text" style={{
fontSize
}}>{extraStart}</Text> : extraStart}
<TextInput testID="RNE__Input__input" {...others} ref={inputRef} editable={!disabled} value={defaultValue} onChangeText={onInputChange} onFocus={onInputFocus} style={[{
fontSize,
color: theme.colors.text || '#000'
}, styles.input, style]} />
{typeof extraEnd === 'string' ? <Text color="primary_text" style={{
fontSize
}}>{extraEnd}</Text> : extraEnd}
{error && (renderError || <Icon name="circle-close" color="#dc3545" />)}
</View>
{clear && <TouchableOpacity onPress={() => {
setDefaultValue('');
setControl('state');
onInputChange?.('');
}}>
{renderClear || <Text color="primary_text" style={[{
fontSize
}, clearStyle]}>清除</Text>}
</TouchableOpacity>}
</View>;
};
export default Input;
function createStyles({
bgColor
}) {
return StyleSheet.create({
container: {
height: '100%',
marginTop: 0,
marginBottom: 0,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'transparent',
border: '1px solid',
paddingHorizontal: 5
},
input: {
flex: 1,
// color: 'red',
backgroundColor: 'transparent',
paddingVertical: 0,
paddingTop: 0
},
always: {
borderWidth: 1
},
bottom: {
borderBottomWidth: 1
},
top: {
borderTopWidth: 1
},
left: {
borderLeftWidth: 1
},
right: {
borderRightWidth: 1
},
inputErrorColor: {
color: '#f50'
}
});
}