Rocket.Chat.ReactNative/app/containers/TextInput.tsx

190 lines
4.5 KiB
TypeScript

import React from 'react';
import { StyleProp, StyleSheet, Text, TextInputProps, TextInput as RNTextInput, TextStyle, View, ViewStyle } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import sharedStyles from '../views/Styles';
import TextInput from '../presentation/TextInput';
import { themes } from '../lib/constants';
import { CustomIcon } from '../lib/Icons';
import ActivityIndicator from './ActivityIndicator';
const styles = StyleSheet.create({
error: {
...sharedStyles.textAlignCenter,
paddingTop: 5
},
inputContainer: {
marginBottom: 10
},
label: {
marginBottom: 10,
fontSize: 14,
...sharedStyles.textSemibold
},
input: {
...sharedStyles.textRegular,
height: 48,
fontSize: 16,
padding: 14,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 2
},
inputIconLeft: {
paddingLeft: 45
},
inputIconRight: {
paddingRight: 45
},
wrap: {
position: 'relative'
},
iconContainer: {
position: 'absolute',
top: 14
},
iconLeft: {
left: 15
},
iconRight: {
right: 15
}
});
export interface IRCTextInputProps extends TextInputProps {
label?: string;
error?: any;
loading?: boolean;
containerStyle?: StyleProp<ViewStyle>;
inputStyle?: StyleProp<TextStyle>;
inputRef?: React.Ref<RNTextInput>;
testID?: string;
iconLeft?: string;
iconRight?: string;
left?: JSX.Element;
onIconRightPress?(): void;
theme: string;
}
interface IRCTextInputState {
showPassword: boolean;
}
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, IRCTextInputState> {
static defaultProps = {
error: {},
theme: 'light'
};
state = {
showPassword: false
};
get iconLeft() {
const { testID, iconLeft, theme } = this.props;
return (
<CustomIcon
name={iconLeft}
testID={testID ? `${testID}-icon-left` : null}
style={[styles.iconContainer, styles.iconLeft, { color: themes[theme].bodyText }]}
size={20}
/>
);
}
get iconRight() {
const { iconRight, onIconRightPress, theme } = this.props;
return (
<Touchable onPress={onIconRightPress} style={[styles.iconContainer, styles.iconRight]}>
<CustomIcon name={iconRight} style={{ color: themes[theme].bodyText }} size={20} />
</Touchable>
);
}
get iconPassword() {
const { showPassword } = this.state;
const { testID, theme } = this.props;
return (
<Touchable onPress={this.tooglePassword} style={[styles.iconContainer, styles.iconRight]}>
<CustomIcon
name={showPassword ? 'unread-on-top' : 'unread-on-top-disabled'}
testID={testID ? `${testID}-icon-right` : null}
style={{ color: themes[theme].auxiliaryText }}
size={20}
/>
</Touchable>
);
}
get loading() {
const { theme } = this.props;
return <ActivityIndicator style={[styles.iconContainer, styles.iconRight]} color={themes[theme].bodyText} />;
}
tooglePassword = () => {
this.setState(prevState => ({ showPassword: !prevState.showPassword }));
};
render() {
const { showPassword } = this.state;
const {
label,
left,
error,
loading,
secureTextEntry,
containerStyle,
inputRef,
iconLeft,
iconRight,
inputStyle,
testID,
placeholder,
theme,
...inputProps
} = this.props;
const { dangerColor } = themes[theme];
return (
<View style={[styles.inputContainer, containerStyle]}>
{label ? (
<Text style={[styles.label, { color: themes[theme].titleText }, error?.error && { color: dangerColor }]}>{label}</Text>
) : null}
<View style={styles.wrap}>
<TextInput
style={[
styles.input,
iconLeft && styles.inputIconLeft,
(secureTextEntry || iconRight) && styles.inputIconRight,
{
backgroundColor: themes[theme].backgroundColor,
borderColor: themes[theme].separatorColor,
color: themes[theme].titleText
},
error?.error && {
color: dangerColor,
borderColor: dangerColor
},
inputStyle
]}
ref={inputRef}
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'
secureTextEntry={secureTextEntry && !showPassword}
testID={testID}
accessibilityLabel={placeholder}
placeholder={placeholder}
theme={theme}
{...inputProps}
/>
{iconLeft ? this.iconLeft : null}
{iconRight ? this.iconRight : null}
{secureTextEntry ? this.iconPassword : null}
{loading ? this.loading : null}
{left}
</View>
{error && error.reason ? <Text style={[styles.error, { color: dangerColor }]}>{error.reason}</Text> : null}
</View>
);
}
}