diff --git a/assets/images/eye-disabled.svg b/assets/images/eye-disabled.svg new file mode 100644 index 000000000000..804a36c63777 --- /dev/null +++ b/assets/images/eye-disabled.svg @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/src/components/ExpensiTextInput/BaseExpensiTextInput.js b/src/components/ExpensiTextInput/BaseExpensiTextInput.js index 3462064303f1..f22b84d24f23 100644 --- a/src/components/ExpensiTextInput/BaseExpensiTextInput.js +++ b/src/components/ExpensiTextInput/BaseExpensiTextInput.js @@ -1,13 +1,15 @@ import _ from 'underscore'; import React, {Component} from 'react'; import { - Animated, TextInput, View, TouchableWithoutFeedback, + Animated, TextInput, View, TouchableWithoutFeedback, Pressable, } from 'react-native'; import Str from 'expensify-common/lib/str'; import ExpensiTextInputLabel from './ExpensiTextInputLabel'; import {propTypes, defaultProps} from './baseExpensiTextInputPropTypes'; import themeColors from '../../styles/themes/default'; import styles from '../../styles/styles'; +import Icon from '../Icon'; +import * as Expensicons from '../Icon/Expensicons'; import InlineErrorText from '../InlineErrorText'; const ACTIVE_LABEL_TRANSLATE_Y = -12; @@ -31,6 +33,7 @@ class BaseExpensiTextInput extends Component { labelTranslateX: new Animated.Value(activeLabel ? ACTIVE_LABEL_TRANSLATE_X(props.translateX) : INACTIVE_LABEL_TRANSLATE_X), labelScale: new Animated.Value(activeLabel ? ACTIVE_LABEL_SCALE : INACTIVE_LABEL_SCALE), + passwordHidden: props.secureTextEntry, }; this.input = null; @@ -39,6 +42,7 @@ class BaseExpensiTextInput extends Component { this.onFocus = this.onFocus.bind(this); this.onBlur = this.onBlur.bind(this); this.setValue = this.setValue.bind(this); + this.togglePasswordVisibility = this.togglePasswordVisibility.bind(this); } componentDidMount() { @@ -145,6 +149,10 @@ class BaseExpensiTextInput extends Component { ]).start(); } + togglePasswordVisibility() { + this.setState(prevState => ({passwordHidden: !prevState.passwordHidden})); + } + render() { const inputProps = _.omit(this.props, _.keys(propTypes)); const hasLabel = Boolean(this.props.label.length); @@ -167,7 +175,7 @@ class BaseExpensiTextInput extends Component { {hasLabel ? ( <> {/* Adding this background to the label only for multiline text input, - to prevent text overlaping with label when scrolling */} + to prevent text overlapping with label when scrolling */} {this.props.multiline && } ) : null} - { - if (typeof this.props.innerRef === 'function') { this.props.innerRef(ref); } - this.input = ref; - }} - // eslint-disable-next-line - {...inputProps} - value={this.props.value} - placeholder={(this.state.isFocused || !this.props.label) ? this.props.placeholder : null} - placeholderTextColor={themeColors.placeholderText} - underlineColorAndroid="transparent" - style={[this.props.inputStyle, !hasLabel && styles.pv0]} - multiline={this.props.multiline} - onFocus={this.onFocus} - onBlur={this.onBlur} - onChangeText={this.setValue} - onPressOut={this.props.onPress} - translateX={this.props.translateX} - /> + + { + if (typeof this.props.innerRef === 'function') { this.props.innerRef(ref); } + this.input = ref; + }} + // eslint-disable-next-line + {...inputProps} + value={this.props.value} + placeholder={(this.state.isFocused || !this.props.label) ? this.props.placeholder : null} + placeholderTextColor={themeColors.placeholderText} + underlineColorAndroid="transparent" + style={[this.props.inputStyle, styles.flex1, styles.w100, !hasLabel && styles.pv0, this.props.secureTextEntry && styles.expensiTextInputWithIcon]} + multiline={this.props.multiline} + onFocus={this.onFocus} + onBlur={this.onBlur} + onChangeText={this.setValue} + secureTextEntry={this.state.passwordHidden} + onPressOut={this.props.onPress} + translateX={this.props.translateX} + /> + {this.props.secureTextEntry && ( + + + + )} + diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js index 973b61081149..27483e9cd6eb 100644 --- a/src/components/Icon/Expensicons.js +++ b/src/components/Icon/Expensicons.js @@ -21,6 +21,7 @@ import Download from '../../../assets/images/download.svg'; import Emoji from '../../../assets/images/emoji.svg'; import Exclamation from '../../../assets/images/exclamation.svg'; import Eye from '../../../assets/images/eye.svg'; +import EyeDisabled from '../../../assets/images/eye-disabled.svg'; import ExpensifyCard from '../../../assets/images/expensifycard.svg'; import Gallery from '../../../assets/images/gallery.svg'; import Gear from '../../../assets/images/gear.svg'; @@ -86,6 +87,7 @@ export { Emoji, Exclamation, Eye, + EyeDisabled, ExpensifyCard, Gallery, Gear, diff --git a/src/styles/styles.js b/src/styles/styles.js index c7ec40e0ee57..05851fc694f8 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -583,6 +583,7 @@ const styles = { componentHeightLarge: { height: variables.componentSizeLarge, }, + expensiTextInputContainer: { flex: 1, borderWidth: 1, @@ -593,6 +594,7 @@ const styles = { backgroundColor: themeColors.componentBG, overflow: 'hidden', }, + expensiTextInputLabel: { position: 'absolute', left: 11.5, @@ -602,6 +604,7 @@ const styles = { fontFamily: fontFamily.GTA, width: '100%', }, + expensiTextInputLabelBackground: { position: 'absolute', top: 0, @@ -611,9 +614,11 @@ const styles = { borderTopRightRadius: variables.componentBorderRadiusNormal, borderTopLeftRadius: variables.componentBorderRadiusNormal, }, + expensiTextInputLabelDesktop: { transformOrigin: 'left center', }, + expensiTextInputLabelTransformation: (translateY, translateX, scale) => ({ transform: [ {translateY}, @@ -621,6 +626,7 @@ const styles = { {scale}, ], }), + expensiTextInput: { fontFamily: fontFamily.GTA, fontSize: variables.fontSizeNormal, @@ -632,11 +638,23 @@ const styles = { borderRadius: variables.componentBorderRadiusNormal, zIndex: -1, }, + + expensiTextInputWithIcon: { + paddingRight: 8, + }, + expensiTextInputDesktop: addOutlineWidth({}, 0), + expensiTextInputAndroid: left => ({ padding: 0, left, }), + + secureInputEyeButton: { + paddingRight: 11.5, + justifyContent: 'center', + }, + textInput: { backgroundColor: themeColors.componentBG, borderRadius: variables.componentBorderRadiusNormal, diff --git a/web/index.html b/web/index.html index 58ef693a1a1b..f685f2b379f2 100644 --- a/web/index.html +++ b/web/index.html @@ -40,6 +40,9 @@ outline: 0; box-shadow: 0px 0px 0px 1px #0185ff; } + ::-ms-reveal { + display: none; + }