@uiw/react-native
Version:
UIW for React Native
171 lines (158 loc) • 3.91 kB
JavaScript
import React from 'react';
import { TextInput, View, StyleSheet, Text, TouchableOpacity } from 'react-native';
import Icon from '../Icon'; // StyleProp<ViewStyle>
export default class Input extends React.Component {
ref = React.createRef();
state = {
value: this.props.value,
control: 'state'
};
static getDerivedStateFromProps(props, state) {
if (state.control === 'state' && props.value === state.value) {
return {
control: 'props'
};
}
if (props.value !== state.value) {
if (state.control === 'state') {
return {
control: 'props'
};
}
return {
value: props.value,
control: 'props'
};
}
return null;
}
onChangeText = value => {
let flag = true;
if (this.props.rule instanceof RegExp) {
flag = this.props.rule.test(value);
}
if (typeof this.props.rule === 'function') {
flag = this.props.rule(value);
}
if (flag) {
this.setState({
value,
control: 'state'
});
this.props.onChangeText?.(value);
return false;
}
this.setState({
value: this.state.value || '',
control: 'state'
});
this.props.onChangeText?.(this.state.value || '');
this.props.wrongfulHandle?.();
};
onFocus = e => {
if (this.props.clearText) {
this.setState({
value: '',
control: 'state'
});
this.props.onChangeText?.('');
}
this.props.onFocus?.(e);
};
render() {
const {
wrongfulHandle,
rule,
value,
onChangeText,
clearText,
disabled = false,
clear,
clearStyle,
renderClear,
extraStart,
extraEnd,
style,
containerStyle,
border = 'bottom',
borderColor = '#ccc',
error = false,
renderError,
inputRef,
...others
} = this.props;
const fontSize = StyleSheet.flatten(style).fontSize || 14;
const minHeight = StyleSheet.flatten(containerStyle)?.height || 30;
return <View style={[{
flexDirection: 'row',
backgroundColor: '#fff',
alignItems: 'center',
paddingVertical: 0,
height: minHeight
}, containerStyle]}>
<View style={[inputStyles.container, {
flex: 1,
borderColor: borderColor
}, border ? inputStyles[border] : {}]}>
{typeof extraEnd === 'string' ? <Text style={{
color: '#888888',
fontSize
}}>{extraStart}</Text> : extraStart}
<TextInput {...others} ref={inputRef} editable={!disabled} value={this.state.value} onChangeText={this.onChangeText} onFocus={this.onFocus} style={[{
fontSize
}, inputStyles.input, style]} />
{typeof extraEnd === 'string' ? <Text style={{
color: '#888888',
fontSize
}}>{extraEnd}</Text> : extraEnd}
{error && (renderError || <Icon name="circle-close" color="#dc3545" />)}
</View>
{clear && <TouchableOpacity onPress={() => {
this.setState({
value: '',
control: 'state'
});
this.props.onChangeText?.('');
}}>
{renderClear || <Text style={[{
color: '#888888',
fontSize
}, clearStyle]}>清除</Text>}
</TouchableOpacity>}
</View>;
}
}
const inputStyles = StyleSheet.create({
container: {
height: '100%',
marginTop: 0,
marginBottom: 0,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'transparent'
},
input: {
flex: 1,
color: '#000',
backgroundColor: 'transparent',
paddingVertical: 0
},
always: {
borderWidth: 1
},
bottom: {
borderBottomWidth: 1
},
top: {
borderTopWidth: 1
},
left: {
borderLeftWidth: 1
},
right: {
borderRightWidth: 1
},
inputErrorColor: {
color: '#f50'
}
});