1
1
import _ from 'underscore' ;
2
2
import React , { Component } from 'react' ;
3
3
import {
4
- Animated , TextInput , View , TouchableWithoutFeedback ,
4
+ Animated , TextInput , View , TouchableWithoutFeedback , Pressable ,
5
5
} from 'react-native' ;
6
6
import Str from 'expensify-common/lib/str' ;
7
7
import ExpensiTextInputLabel from './ExpensiTextInputLabel' ;
8
8
import { propTypes , defaultProps } from './baseExpensiTextInputPropTypes' ;
9
9
import themeColors from '../../styles/themes/default' ;
10
10
import styles from '../../styles/styles' ;
11
+ import Icon from '../Icon' ;
12
+ import * as Expensicons from '../Icon/Expensicons' ;
11
13
import InlineErrorText from '../InlineErrorText' ;
12
14
13
15
const ACTIVE_LABEL_TRANSLATE_Y = - 12 ;
@@ -31,6 +33,7 @@ class BaseExpensiTextInput extends Component {
31
33
labelTranslateX : new Animated . Value ( activeLabel
32
34
? ACTIVE_LABEL_TRANSLATE_X ( props . translateX ) : INACTIVE_LABEL_TRANSLATE_X ) ,
33
35
labelScale : new Animated . Value ( activeLabel ? ACTIVE_LABEL_SCALE : INACTIVE_LABEL_SCALE ) ,
36
+ passwordHidden : props . secureTextEntry ,
34
37
} ;
35
38
36
39
this . input = null ;
@@ -39,6 +42,7 @@ class BaseExpensiTextInput extends Component {
39
42
this . onFocus = this . onFocus . bind ( this ) ;
40
43
this . onBlur = this . onBlur . bind ( this ) ;
41
44
this . setValue = this . setValue . bind ( this ) ;
45
+ this . togglePasswordVisibility = this . togglePasswordVisibility . bind ( this ) ;
42
46
}
43
47
44
48
componentDidMount ( ) {
@@ -145,6 +149,10 @@ class BaseExpensiTextInput extends Component {
145
149
] ) . start ( ) ;
146
150
}
147
151
152
+ togglePasswordVisibility ( ) {
153
+ this . setState ( prevState => ( { passwordHidden : ! prevState . passwordHidden } ) ) ;
154
+ }
155
+
148
156
render ( ) {
149
157
const inputProps = _ . omit ( this . props , _ . keys ( propTypes ) ) ;
150
158
const hasLabel = Boolean ( this . props . label . length ) ;
@@ -167,8 +175,8 @@ class BaseExpensiTextInput extends Component {
167
175
{ hasLabel ? (
168
176
< >
169
177
{ /* Adding this background to the label only for multiline text input,
170
- to prevent text overlaping with label when scrolling */ }
171
- { this . props . multiline && < View style = { styles . expensiTextInputLabelBackground } /> }
178
+ to prevent text overlapping with label when scrolling */ }
179
+ { this . props . multiline && < View style = { styles . expensiTextInputLabelBackground } pointerEvents = "none" /> }
172
180
< ExpensiTextInputLabel
173
181
label = { this . props . label }
174
182
labelTranslateX = {
@@ -181,25 +189,40 @@ class BaseExpensiTextInput extends Component {
181
189
/>
182
190
</ >
183
191
) : null }
184
- < TextInput
185
- ref = { ( ref ) => {
186
- if ( typeof this . props . innerRef === 'function' ) { this . props . innerRef ( ref ) ; }
187
- this . input = ref ;
188
- } }
189
- // eslint-disable-next-line
190
- { ...inputProps }
191
- value = { this . value }
192
- placeholder = { ( this . state . isFocused || ! this . props . label ) ? this . props . placeholder : null }
193
- placeholderTextColor = { themeColors . placeholderText }
194
- underlineColorAndroid = "transparent"
195
- style = { [ this . props . inputStyle , ! hasLabel && styles . pv0 ] }
196
- multiline = { this . props . multiline }
197
- onFocus = { this . onFocus }
198
- onBlur = { this . onBlur }
199
- onChangeText = { this . setValue }
200
- onPressOut = { this . props . onPress }
201
- translateX = { this . props . translateX }
202
- />
192
+ < View style = { [ styles . expensiTextInputAndIconContainer ] } >
193
+ < TextInput
194
+ ref = { ( ref ) => {
195
+ if ( typeof this . props . innerRef === 'function' ) { this . props . innerRef ( ref ) ; }
196
+ this . input = ref ;
197
+ } }
198
+ // eslint-disable-next-line
199
+ { ...inputProps }
200
+ value = { this . value }
201
+ placeholder = { ( this . state . isFocused || ! this . props . label ) ? this . props . placeholder : null }
202
+ placeholderTextColor = { themeColors . placeholderText }
203
+ underlineColorAndroid = "transparent"
204
+ style = { [ this . props . inputStyle , styles . flex1 , styles . w100 , ! hasLabel && styles . pv0 , this . props . secureTextEntry && styles . pr2 ] }
205
+ multiline = { this . props . multiline }
206
+ onFocus = { this . onFocus }
207
+ onBlur = { this . onBlur }
208
+ onChangeText = { this . setValue }
209
+ secureTextEntry = { this . state . passwordHidden }
210
+ onPressOut = { this . props . onPress }
211
+ translateX = { this . props . translateX }
212
+ />
213
+ { this . props . secureTextEntry && (
214
+ < Pressable
215
+ accessibilityRole = "button"
216
+ style = { styles . secureInputEyeButton }
217
+ onPress = { this . togglePasswordVisibility }
218
+ >
219
+ < Icon
220
+ src = { this . state . passwordHidden ? Expensicons . Eye : Expensicons . EyeDisabled }
221
+ fill = { themeColors . icon }
222
+ />
223
+ </ Pressable >
224
+ ) }
225
+ </ View >
203
226
</ View >
204
227
</ TouchableWithoutFeedback >
205
228
</ View >
0 commit comments