diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 266fa84eaa6a..597a1d8fef3d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -872,7 +872,7 @@ SPEC CHECKSUMS: DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de EXHaptics: 337c160c148baa6f0e7166249f368965906e346b FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53 - FBReactNativeSpec: 825b0f0851f5cc5c6268a920286281f62fc96c37 + FBReactNativeSpec: c783a75db87c963c60afcd461fc38358805fe5ba Firebase: 54cdc8bc9c9b3de54f43dab86e62f5a76b47034f FirebaseABTesting: 4cb61aeeb50f60680af1c01fff781dfaf9293916 FirebaseAnalytics: 4751d6a49598a2b58da678cc07df696bcd809ab9 @@ -899,9 +899,9 @@ SPEC CHECKSUMS: Onfido: 116a268e4cb8b767c15285e8071c2e8304673cdf onfido-react-native-sdk: b8f1b7cbe1adab6479d735275772390161630dcd OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b - Permission-LocationAccuracy: 76669f87b4c276f5ae803cc0ddd1862a4c0e9dd8 - Permission-LocationAlways: a274bc04bb386068782468dbdaca3859f51634ca - Permission-LocationWhenInUse: 3a2b0dbc167d79e8e920a4377ff9520cdc108407 + Permission-LocationAccuracy: e8adff9ede1b23b43b7054a4500113d515fc87a8 + Permission-LocationAlways: 7f7f373d086af7a81b2f4f20d65d29266ca2043b + Permission-LocationWhenInUse: 3ae82a9feb5da4e94e386dba17c7dd3531af9feb Plaid: f55c6acdc249245c6778a4045757eb4e839cca61 PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58 Protobuf: 7327d4444215b5f18e560a97f879ff5503c4581c @@ -917,15 +917,15 @@ SPEC CHECKSUMS: React-jsiexecutor: 124e8f99992490d0d13e0649d950d3e1aae06fe9 React-jsinspector: 500a59626037be5b3b3d89c5151bc3baa9abf1a9 react-native-config: d8b45133fd13d4f23bd2064b72f6e2c08b2763ed - react-native-document-picker: f2f73db94328c84e22144e369fb4a3ede47bc1f5 + react-native-document-picker: 0e3602a4064da040321bafad6848d8b0edcb1d55 react-native-flipper: 1943b82f2e494c77b741eb1ed257b6734a334b83 - react-native-image-picker: 474cf2c33c2b6671da53d293a16c97995f0aec15 - react-native-netinfo: 30fb89fa913c342be82a887b56e96be6d71201dd + react-native-image-picker: 4089335b89b625d4e34d53fb249c48a7a791b3ea + react-native-netinfo: 52cf0ee8342548a485e28f4b09e56b477567244d react-native-pdf: 4b5a9e4465a6a3b399e91dc4838eb44ddf716d1f - react-native-plaid-link-sdk: 59b7376efca9f00e9693321c5cf7c6ab2c567635 - react-native-progress-bar-android: be43138ab7da30d51fc038bafa98e9ed594d0c40 - react-native-progress-view: 21b1e29e70c7559c16c9e0a04c4adc19fce6ede2 - react-native-safe-area-context: 79fea126c6830c85f65947c223a5e3058a666937 + react-native-plaid-link-sdk: 1a6593e2d3d790e8113c29178d883eb883f8c032 + react-native-progress-bar-android: ce95a69f11ac580799021633071368d08aaf9ad8 + react-native-progress-view: 5816e8a6be812c2b122c6225a2a3db82d9008640 + react-native-safe-area-context: 01158a92c300895d79dee447e980672dc3fb85a6 React-perflogger: aad6d4b4a267936b3667260d1f649b6f6069a675 React-RCTActionSheet: fc376be462c9c8d6ad82c0905442fd77f82a9d2a React-RCTAnimation: ba0a1c3a2738be224a08092fa7f1b444ab77d309 @@ -939,17 +939,17 @@ SPEC CHECKSUMS: React-runtimeexecutor: ff951a0c241bfaefc4940a3f1f1a229e7cb32fa6 ReactCommon: bedc99ed4dae329c4fcf128d0c31b9115e5365ca rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba - RNBootSplash: 24175aa28fe203b10c48dc34e78d946fd33c77af + RNBootSplash: 3123ba68fe44d8be09a014e89cc8f0f55b68a521 RNCAsyncStorage: 8324611026e8dc3706f829953aa6e3899f581589 - RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 - RNCMaskedView: fc29d354a40316a990e8fb46391f08aea829c3aa + RNCClipboard: 5e299c6df8e0c98f3d7416b86ae563d3a9f768a3 + RNCMaskedView: 138134c4d8a9421b4f2bf39055a79aa05c2d47b1 RNCPicker: 6780c753e9e674065db90d9c965920516402579d RNFBAnalytics: 8ba84c2d31c64374d054c8621b998f25145ffddc RNFBApp: 64c90ab78b6010ed5c3ade026dfe5ff6442c21fd RNFBCrashlytics: 1de18b8cc36d9bcf86407c4a354399228cc84a61 RNFBPerf: e3a7269f573a4787810a32de51647cdcbe08dfb4 RNGestureHandler: 9b7e605a741412e20e13c512738a31bd1611759b - RNPermissions: 4c8a37b4dde50f1f152bf8cd08c4a43d2355829e + RNPermissions: eb94f9fdc0a8ecd02fcce0676d56ffb1395d41e1 RNReanimated: 833ebd229b31e18a8933ebd0cd744a0f47d88c42 RNScreens: e8e8dd0588b5da0ab57dcca76ab9b2d8987757e0 RNSVG: ce9d996113475209013317e48b05c21ee988d42e @@ -966,7 +966,7 @@ SPEC CHECKSUMS: UMReactNativeAdapter: 7b458ca3d4497b5114e6bb766b223432bad22d8a UMSensorsInterface: 50439b47826e716a514cbd7384aebe9ab4fde5f4 UMTaskManagerInterface: 482155764886069beb1bc7fcf6036f12e4ad0751 - urbanairship-react-native: a05a913d6f9559141d477ff4d380bcd616b5c59d + urbanairship-react-native: d415a12e67ba93bf3ce914df9a310b66a88a5cc3 Yoga: a7de31c64fe738607e7a3803e3f591a4b1df7393 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 8c1829e79105..995d83607b6e 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -3,7 +3,6 @@ import React from 'react'; import { ActivityIndicator, View, - TextInput, } from 'react-native'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; @@ -20,8 +19,9 @@ import canFocusInputOnScreenFocus from '../libs/canFocusInputOnScreenFocus'; import compose from '../libs/compose'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import Button from './Button'; -import Picker from './Picker'; +import ExpensiPicker from './ExpensiPicker'; import Text from './Text'; +import ExpensiTextInput from './ExpensiTextInput'; const propTypes = { ...withLocalizePropTypes, @@ -161,7 +161,7 @@ class AddPlaidBankAccount extends React.Component { https://d2k5nsl2zxldvw.cloudfront.net/images/plaid/bg_plaidLogos_12@2x.png */} {this.state.institution.name} - { this.setState({selectedIndex: Number(index)}); }} @@ -175,12 +175,9 @@ class AddPlaidBankAccount extends React.Component { {!_.isUndefined(this.state.selectedIndex) && ( - - {this.props.translate('addPersonalBankAccountPage.enterPassword')} - - + {label && ( + {label} + )} + this.setState({isOpen: true})} + onClose={() => this.setState({isOpen: false})} + disabled={isDisabled} + // eslint-disable-next-line react/jsx-props-no-spreading + {...pickerProps} + /> + + ); + } +} + +ExpensiPicker.propTypes = propTypes; +ExpensiPicker.defaultProps = defaultProps; + +export default ExpensiPicker; diff --git a/src/components/ExpensiTextInput/BaseExpensiTextInput.js b/src/components/ExpensiTextInput/BaseExpensiTextInput.js new file mode 100644 index 000000000000..7194a35fe27c --- /dev/null +++ b/src/components/ExpensiTextInput/BaseExpensiTextInput.js @@ -0,0 +1,139 @@ +import React, {Component} from 'react'; +import { + Animated, TextInput, View, TouchableWithoutFeedback, +} from 'react-native'; +import ExpensiTextInputLabel from './ExpensiTextInputLabel'; +import {propTypes, defaultProps} from './propTypes'; +import themeColors from '../../styles/themes/default'; +import styles from '../../styles/styles'; + +const ACTIVE_LABEL_TRANSLATE_Y = -10; +const ACTIVE_LABEL_TRANSLATE_X = (translateX = -22) => translateX; +const ACTIVE_LABEL_SCALE = 0.8668; + +const INACTIVE_LABEL_TRANSLATE_Y = 0; +const INACTIVE_LABEL_TRANSLATE_X = 0; +const INACTIVE_LABEL_SCALE = 1; + +class BaseExpensiTextInput extends Component { + constructor(props) { + super(props); + + const hasValue = props.value.length > 0; + + this.state = { + isFocused: false, + labelTranslateY: new Animated.Value(hasValue ? ACTIVE_LABEL_TRANSLATE_Y : INACTIVE_LABEL_TRANSLATE_Y), + labelTranslateX: new Animated.Value(hasValue + ? ACTIVE_LABEL_TRANSLATE_X(props.translateX) : INACTIVE_LABEL_TRANSLATE_X), + labelScale: new Animated.Value(hasValue ? ACTIVE_LABEL_SCALE : INACTIVE_LABEL_SCALE), + }; + + this.input = null; + this.onFocus = this.onFocus.bind(this); + this.onBlur = this.onBlur.bind(this); + } + + onFocus() { + if (this.props.onFocus) { this.props.onFocus(); } + this.setState({isFocused: true}); + if (this.props.value.length === 0) { + this.animateLabel( + ACTIVE_LABEL_TRANSLATE_Y, + ACTIVE_LABEL_TRANSLATE_X(this.props.translateX), + ACTIVE_LABEL_SCALE, + ); + } + } + + onBlur() { + if (this.props.onBlur) { this.props.onBlur(); } + this.setState({isFocused: false}); + if (this.props.value.length === 0) { + this.animateLabel(INACTIVE_LABEL_TRANSLATE_Y, INACTIVE_LABEL_TRANSLATE_X, INACTIVE_LABEL_SCALE); + } + } + + animateLabel(translateY, translateX, scale) { + Animated.parallel([ + Animated.spring(this.state.labelTranslateY, { + toValue: translateY, + duration: 80, + useNativeDriver: true, + }), + Animated.spring(this.state.labelTranslateX, { + toValue: translateX, + duration: 80, + useNativeDriver: true, + }), + Animated.spring(this.state.labelScale, { + toValue: scale, + duration: 80, + useNativeDriver: true, + }), + ]).start(); + } + + render() { + const { + label, + value, + placeholder, + hasError, + containerStyles, + inputStyle, + ignoreLabelTranslateX, + innerRef, + ...inputProps + } = this.props; + + const hasLabel = Boolean(label.length); + return ( + + this.input.focus()}> + + {hasLabel ? ( + + ) : null} + { + if (typeof innerRef === 'function') { innerRef(ref); } + this.input = ref; + }} + // eslint-disable-next-line + {...inputProps} + value={value} + placeholder={(this.state.isFocused || !label) ? placeholder : null} + placeholderTextColor={themeColors.placeholderText} + underlineColorAndroid="transparent" + style={inputStyle} + onFocus={this.onFocus} + onBlur={this.onBlur} + /> + + + + ); + } +} + +BaseExpensiTextInput.propTypes = propTypes; +BaseExpensiTextInput.defaultProps = defaultProps; + +export default BaseExpensiTextInput; diff --git a/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.js b/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.js new file mode 100644 index 000000000000..b0ed11c58bb7 --- /dev/null +++ b/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.js @@ -0,0 +1,30 @@ +import React, {memo} from 'react'; +import {Animated} from 'react-native'; +import styles from '../../../styles/styles'; +import propTypes from './propTypes'; + +const ExpensiTextInputLabel = ({ + label, + labelTranslateY, + labelTranslateX, + labelScale, +}) => ( + + {label} + +); + +ExpensiTextInputLabel.propTypes = propTypes; +ExpensiTextInputLabel.displayName = 'ExpensiTextInputLabel'; + +export default memo(ExpensiTextInputLabel); diff --git a/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.native.js b/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.native.js new file mode 100644 index 000000000000..4e8159d5e2a3 --- /dev/null +++ b/src/components/ExpensiTextInput/ExpensiTextInputLabel/index.native.js @@ -0,0 +1,29 @@ +import React, {memo} from 'react'; +import {Animated} from 'react-native'; +import styles from '../../../styles/styles'; +import propTypes from './propTypes'; + +const ExpensiTextInputLabel = ({ + label, + labelTranslateX, + labelTranslateY, + labelScale, +}) => ( + + {label} + +); + +ExpensiTextInputLabel.propTypes = propTypes; +ExpensiTextInputLabel.displayName = 'ExpensiTextInputLabel'; + +export default memo(ExpensiTextInputLabel); diff --git a/src/components/ExpensiTextInput/ExpensiTextInputLabel/propTypes.js b/src/components/ExpensiTextInput/ExpensiTextInputLabel/propTypes.js new file mode 100644 index 000000000000..cfaf5f14d37c --- /dev/null +++ b/src/components/ExpensiTextInput/ExpensiTextInputLabel/propTypes.js @@ -0,0 +1,18 @@ +import PropTypes from 'prop-types'; +import {Animated} from 'react-native'; + +const propTypes = { + /** Label */ + label: PropTypes.string, + + /** Label vertical translate */ + labelTranslateY: PropTypes.instanceOf(Animated.Value).isRequired, + + /** Label horizontal translate */ + labelTranslateX: PropTypes.instanceOf(Animated.Value).isRequired, + + /** Label scale */ + labelScale: PropTypes.instanceOf(Animated.Value).isRequired, +}; + +export default propTypes; diff --git a/src/components/ExpensiTextInput/index.android.js b/src/components/ExpensiTextInput/index.android.js new file mode 100644 index 000000000000..35b9a15cfd89 --- /dev/null +++ b/src/components/ExpensiTextInput/index.android.js @@ -0,0 +1,23 @@ +import React, {forwardRef} from 'react'; +import styles from '../../styles/styles'; +import BaseExpensiTextInput from './BaseExpensiTextInput'; +import {propTypes, defaultProps} from './propTypes'; + +const ExpensiTextInput = forwardRef((props, ref) => ( + +)); + +ExpensiTextInput.propTypes = propTypes; +ExpensiTextInput.defaultProps = defaultProps; +ExpensiTextInput.displayName = 'ExpensiTextInput'; + +export default ExpensiTextInput; diff --git a/src/components/ExpensiTextInput/index.ios.js b/src/components/ExpensiTextInput/index.ios.js new file mode 100644 index 000000000000..9e84b12d1355 --- /dev/null +++ b/src/components/ExpensiTextInput/index.ios.js @@ -0,0 +1,19 @@ +import React, {forwardRef} from 'react'; +import styles from '../../styles/styles'; +import BaseExpensiTextInput from './BaseExpensiTextInput'; +import {propTypes, defaultProps} from './propTypes'; + +const ExpensiTextInput = forwardRef((props, ref) => ( + +)); + +ExpensiTextInput.propTypes = propTypes; +ExpensiTextInput.defaultProps = defaultProps; +ExpensiTextInput.displayName = 'ExpensiTextInput'; + +export default ExpensiTextInput; diff --git a/src/components/ExpensiTextInput/index.js b/src/components/ExpensiTextInput/index.js new file mode 100644 index 000000000000..c56aaee213ef --- /dev/null +++ b/src/components/ExpensiTextInput/index.js @@ -0,0 +1,20 @@ +import React, {forwardRef} from 'react'; +import styles from '../../styles/styles'; +import BaseExpensiTextInput from './BaseExpensiTextInput'; +import {propTypes, defaultProps} from './propTypes'; + +const ExpensiTextInput = forwardRef((props, ref) => ( + +)); + +ExpensiTextInput.propTypes = propTypes; +ExpensiTextInput.defaultProps = defaultProps; +ExpensiTextInput.displayName = 'ExpensiTextInput'; + +export default ExpensiTextInput; diff --git a/src/components/ExpensiTextInput/propTypes.js b/src/components/ExpensiTextInput/propTypes.js new file mode 100644 index 000000000000..6231018ccee5 --- /dev/null +++ b/src/components/ExpensiTextInput/propTypes.js @@ -0,0 +1,39 @@ +import PropTypes from 'prop-types'; + +const propTypes = { + /** Input label */ + label: PropTypes.string, + + /** Input value */ + value: PropTypes.string.isRequired, + + /** Input value placeholder */ + placeholder: PropTypes.string, + + /** Should the input be styled for errors */ + hasError: PropTypes.bool, + + /** Customize the ExpensiTextInput container */ + containerStyles: PropTypes.arrayOf(PropTypes.object), + + /** label translate x */ + translateX: PropTypes.number, + + /** input style */ + inputStyle: PropTypes.arrayOf(PropTypes.object), + + /** should ignore labels translate x? */ + ignoreLabelTranslateX: PropTypes.bool, +}; + +const defaultProps = { + label: '', + placeholder: '', + error: false, + containerStyles: [], + translateX: -22, + inputStyle: [], + ignoreLabelTranslateX: false, +}; + +export {propTypes, defaultProps}; diff --git a/src/components/FullNameInputRow.js b/src/components/FullNameInputRow.js index 180a642c5261..6ed98c5be043 100644 --- a/src/components/FullNameInputRow.js +++ b/src/components/FullNameInputRow.js @@ -1,11 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {TextInput, View} from 'react-native'; +import {View} from 'react-native'; import _ from 'underscore'; import styles from '../styles/styles'; -import Text from './Text'; -import themeColors from '../styles/themes/default'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import ExpensiTextInput from './ExpensiTextInput'; const propTypes = { ...withLocalizePropTypes, @@ -19,15 +18,9 @@ const propTypes = { /** Used to prefill the firstName input, can also be used to make it a controlled input */ firstName: PropTypes.string, - /** Placeholder text for the firstName input */ - firstNamePlaceholder: PropTypes.string, - /** Used to prefill the lastName input, can also be used to make it a controlled input */ lastName: PropTypes.string, - /** Placeholder text for the lastName input */ - lastNamePlaceholder: PropTypes.string, - /** Additional styles to add after local styles */ style: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.object), @@ -36,9 +29,7 @@ const propTypes = { }; const defaultProps = { firstName: '', - firstNamePlaceholder: null, lastName: '', - lastNamePlaceholder: null, style: {}, }; @@ -46,35 +37,27 @@ const FullNameInputRow = ({ translate, onChangeFirstName, onChangeLastName, firstName, lastName, - firstNamePlaceholder, - lastNamePlaceholder, style, }) => { const additionalStyles = _.isArray(style) ? style : [style]; return ( - - {translate('common.firstName')} - - - - {translate('common.lastName')} - - diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index 5d3de1ee96e3..33ba326f2042 100755 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; -import {ScrollView, TextInput} from 'react-native-gesture-handler'; +import {ScrollView} from 'react-native-gesture-handler'; import {withOnyx} from 'react-native-onyx'; import {withSafeAreaInsets} from 'react-native-safe-area-context'; import _ from 'underscore'; @@ -20,6 +20,7 @@ import SafeAreaInsetPropTypes from '../pages/SafeAreaInsetPropTypes'; import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; import compose from '../libs/compose'; import FixedFooter from './FixedFooter'; +import ExpensiTextInput from './ExpensiTextInput'; import CONST from '../CONST'; const propTypes = { @@ -345,12 +346,9 @@ class IOUConfirmationList extends Component { disableRowInteractivity={!this.props.hasMultipleParticipants} optionHoveredStyle={hoverStyle} /> - - {this.props.translate('iOUConfirmationList.whatsItFor')} - - - {size === 'normal' && ( - - {translate('preferencesPage.language')} - - )} - { - if (locale !== preferredLocale) { - setLocale(locale); - } - }} - items={Object.values(localesToLanguages)} - size={size} - value={preferredLocale} - /> - + { + if (locale !== preferredLocale) { + setLocale(locale); + } + }} + items={Object.values(localesToLanguages)} + size={size} + value={preferredLocale} + /> ); }; diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index f046068643e1..77440b9e3457 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -140,7 +140,7 @@ const MenuItem = ({ {title} {description && ( - + {description} )} @@ -151,7 +151,7 @@ const MenuItem = ({ {subtitle && ( {subtitle} diff --git a/src/components/OptionsSelector.js b/src/components/OptionsSelector.js index beb39197ac8d..fe246d6b4f3d 100755 --- a/src/components/OptionsSelector.js +++ b/src/components/OptionsSelector.js @@ -2,12 +2,11 @@ import _ from 'underscore'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; -import TextInputWithFocusStyles from './TextInputWithFocusStyles'; import OptionsList from './OptionsList'; import styles from '../styles/styles'; -import themeColors from '../styles/themes/default'; import optionPropTypes from './optionPropTypes'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import ExpensiTextInput from './ExpensiTextInput'; const propTypes = { /** Callback to fire when a row is tapped */ @@ -195,16 +194,13 @@ class OptionsSelector extends Component { return ( - this.textInput = el} - style={[styles.textInput]} value={this.props.value} onChangeText={this.props.onChangeText} onKeyPress={this.handleKeyPress} placeholder={this.props.placeholderText || this.props.translate('optionsSelector.nameEmailOrPhoneNumber')} - placeholderTextColor={themeColors.placeholderText} /> ), + size: 'normal', }; export { diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index b963c81601b8..28ff3ff877ea 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -2,40 +2,35 @@ import React from 'react'; import RNPickerSelect from 'react-native-picker-select'; import styles from '../../styles/styles'; -import pickerDisabledStyles from './pickerDisabledStyles'; import * as pickerPropTypes from './PickerPropTypes'; +import pickerStyles from './pickerStyles'; const Picker = ({ onChange, items, - useDisabledStyles, placeholder, value, icon, disabled, + onOpen, + onClose, size, -}) => { - let pickerStyles; - if (size === 'small') { - pickerStyles = styles.pickerSmall; - } else { - pickerStyles = useDisabledStyles ? pickerDisabledStyles : styles.picker; - } +}) => ( + icon(size)} + disabled={disabled} + fixAndroidTouchableBug + onOpen={onOpen} + onClose={onClose} + /> +); - return ( - icon(size)} - disabled={disabled} - fixAndroidTouchableBug - /> - ); -}; Picker.propTypes = pickerPropTypes.propTypes; Picker.defaultProps = pickerPropTypes.defaultProps; diff --git a/src/components/Picker/pickerDisabledStyles/index.android.js b/src/components/Picker/pickerDisabledStyles/index.android.js deleted file mode 100644 index d978155e75d2..000000000000 --- a/src/components/Picker/pickerDisabledStyles/index.android.js +++ /dev/null @@ -1,6 +0,0 @@ -import styles from '../../../styles/styles'; - -export default { - ...styles.picker, - inputAndroid: [styles.picker.inputAndroid, styles.textInput, styles.disabledTextInput], -}; diff --git a/src/components/Picker/pickerDisabledStyles/index.ios.js b/src/components/Picker/pickerDisabledStyles/index.ios.js deleted file mode 100644 index 83a8b81de736..000000000000 --- a/src/components/Picker/pickerDisabledStyles/index.ios.js +++ /dev/null @@ -1,6 +0,0 @@ -import styles from '../../../styles/styles'; - -export default { - ...styles.picker, - inputIOS: [styles.picker.inputIOS, styles.textInput, styles.disabledTextInput], -}; diff --git a/src/components/Picker/pickerDisabledStyles/index.js b/src/components/Picker/pickerDisabledStyles/index.js deleted file mode 100644 index 6fc2e9f3bbd1..000000000000 --- a/src/components/Picker/pickerDisabledStyles/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import styles from '../../../styles/styles'; - -export default { - ...styles.picker, - inputWeb: [styles.picker.inputWeb, styles.textInput, styles.disabledTextInput], -}; diff --git a/src/components/Picker/pickerStyles/index.android.js b/src/components/Picker/pickerStyles/index.android.js new file mode 100644 index 000000000000..ea9a2882a098 --- /dev/null +++ b/src/components/Picker/pickerStyles/index.android.js @@ -0,0 +1,8 @@ +import styles from '../../../styles/styles'; + +const pickerStyles = disabled => ({ + ...styles.expensiPicker(disabled), + inputAndroid: styles.expensiPicker(disabled).inputNative, +}); + +export default pickerStyles; diff --git a/src/components/Picker/pickerStyles/index.ios.js b/src/components/Picker/pickerStyles/index.ios.js new file mode 100644 index 000000000000..0c144fd8ad25 --- /dev/null +++ b/src/components/Picker/pickerStyles/index.ios.js @@ -0,0 +1,8 @@ +import styles from '../../../styles/styles'; + +const pickerStyles = disabled => ({ + ...styles.expensiPicker(disabled), + inputIOS: styles.expensiPicker(disabled).inputNative, +}); + +export default pickerStyles; diff --git a/src/components/Picker/pickerStyles/index.js b/src/components/Picker/pickerStyles/index.js new file mode 100644 index 000000000000..7c11a9f8ed86 --- /dev/null +++ b/src/components/Picker/pickerStyles/index.js @@ -0,0 +1,5 @@ +import styles from '../../../styles/styles'; + +const pickerStyles = disabled => styles.expensiPicker(disabled); + +export default pickerStyles; diff --git a/src/components/TextInputWithLabel.js b/src/components/TextInputWithLabel.js index 63cdd87dbb89..40ac02a9fcbc 100644 --- a/src/components/TextInputWithLabel.js +++ b/src/components/TextInputWithLabel.js @@ -54,7 +54,7 @@ const TextInputWithLabel = props => ( )} diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index e647bb1f3d80..dd65d99b9a4c 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -12,12 +12,12 @@ import Navigation from '../../libs/Navigation/Navigation'; import styles from '../../styles/styles'; import Button from '../../components/Button'; import Text from '../../components/Text'; -import TextInputWithLabel from '../../components/TextInputWithLabel'; import {activateWallet} from '../../libs/actions/BankAccounts'; import CONST from '../../CONST'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import TextLink from '../../components/TextLink'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; const propTypes = { ...withLocalizePropTypes, @@ -128,7 +128,7 @@ class AdditionalDetailsStep extends React.Component { {_.map(this.fields, field => ( - this.setState({[field.fieldName]: val})} diff --git a/src/pages/EnablePayments/TermsPage/LongTermsForm.js b/src/pages/EnablePayments/TermsPage/LongTermsForm.js index af7e7b1363b3..ae22740a3de8 100644 --- a/src/pages/EnablePayments/TermsPage/LongTermsForm.js +++ b/src/pages/EnablePayments/TermsPage/LongTermsForm.js @@ -85,7 +85,7 @@ const getLongTermsSections = () => termsData.map((section, index) => ( } - + {section.details} diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index b38563acdef0..bcedfdb74cd2 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -15,12 +15,12 @@ import Icon from '../../components/Icon'; import colors from '../../styles/colors'; import Navigation from '../../libs/Navigation/Navigation'; import CONST from '../../CONST'; -import TextInputWithLabel from '../../components/TextInputWithLabel'; import AddPlaidBankAccount from '../../components/AddPlaidBankAccount'; import CheckboxWithLabel from '../../components/CheckboxWithLabel'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import exampleCheckImage from '../../../assets/images/example-check-image.png'; import Text from '../../components/Text'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; import { goToWithdrawalAccountSetupStep, hideExistingOwnersError, @@ -207,14 +207,14 @@ class BankAccountStep extends React.Component { style={[styles.exampleCheckImage, styles.mb5]} source={exampleCheckImage} /> - this.setState({routingNumber})} disabled={shouldDisableInputs} /> - {this.props.translate('companyStep.subtitle')} - this.setState({companyName})} value={this.state.companyName} disabled={shouldDisableCompanyName} /> - this.setState({addressStreet})} @@ -156,7 +156,7 @@ class CompanyStep extends React.Component { /> - this.setState({addressCity})} value={this.state.addressCity} @@ -170,13 +170,13 @@ class CompanyStep extends React.Component { /> - this.setState({addressZipCode})} value={this.state.addressZipCode} /> - - this.setState({website})} value={this.state.website} /> - - - {this.props.translate('companyStep.companyType')} - - ({value, label}))} - onChange={incorporationType => this.setState({incorporationType})} - value={this.state.incorporationType} - placeholder={{value: '', label: 'Type'}} - /> + + ({value, label}))} + onChange={incorporationType => this.setState({incorporationType})} + value={this.state.incorporationType} + placeholder={{value: '', label: 'Type'}} + /> + {/* TODO: Replace with date picker */} - this.setState({incorporationDate})} value={this.state.incorporationDate} @@ -226,7 +226,7 @@ class CompanyStep extends React.Component { {/* TODO: Replace with NAICS picker */} - this.setState({industryCode})} value={this.state.industryCode} /> - - onFieldChange('firstName', val)} /> - onFieldChange('lastName', val)} /> - onFieldChange('dob', val)} /> - onFieldChange('ssnLast4', val)} /> - - onFieldChange('city', val)} @@ -117,7 +117,7 @@ const IdentityForm = ({ /> - - this.setState({amount1})} /> - this.setState({amount2})} /> - {defaultRoomSubtitle} @@ -159,11 +164,10 @@ class ReportDetailsPage extends Component { - - {this.props.translate('reportDetailsPage.notificationPreferencesDescription')} - - { updateNotificationPreference( this.props.report.reportID, diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index 5a1ea5eb0e55..3d5a1e195057 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {ScrollView, TextInput} from 'react-native'; +import {View, ScrollView} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; @@ -19,6 +19,7 @@ import Growl from '../libs/Growl'; import {requestConciergeDMCall} from '../libs/actions/Inbox'; import {fetchOrCreateChatReport} from '../libs/actions/Report'; import personalDetailsPropType from './personalDetailsPropType'; +import ExpensiTextInput from '../components/ExpensiTextInput'; import Text from '../components/Text'; import KeyboardAvoidingView from '../components/KeyboardAvoidingView'; @@ -168,17 +169,16 @@ class RequestCallPage extends Component { onChangeLastName={lastName => this.setState({lastName})} style={[styles.mt4, styles.mb4]} /> - - {this.props.translate('common.phoneNumber')} - - this.setState({phoneNumber})} - /> + + this.setState({phoneNumber})} + /> + {this.props.translate('requestCallPage.availabilityText')} diff --git a/src/pages/ValidateLogin2FANewWorkspacePage.js b/src/pages/ValidateLogin2FANewWorkspacePage.js index 6e9c07d44b9b..f8443e39452f 100644 --- a/src/pages/ValidateLogin2FANewWorkspacePage.js +++ b/src/pages/ValidateLogin2FANewWorkspacePage.js @@ -101,7 +101,7 @@ class ValidateLogin2FANewWorkspacePage extends Component { return ( - + diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 94950b258baa..4f3149f02fee 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -141,7 +141,12 @@ const HeaderView = (props) => { /> {isDefaultChatRoom && ( {subtitle} diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 245e646ad2fe..ed51211b9691 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -105,8 +105,8 @@ const OptionRow = ({ ? [styles.optionDisplayName, ...textUnreadStyle, styles.optionDisplayNameCompact, styles.mr2] : [styles.optionDisplayName, ...textUnreadStyle]; const alternateTextStyle = mode === 'compact' - ? [textStyle, styles.optionAlternateText, styles.optionAlternateTextCompact] - : [textStyle, styles.optionAlternateText, styles.mt1]; + ? [textStyle, styles.optionAlternateText, styles.textLabelSupporting, styles.optionAlternateTextCompact] + : [textStyle, styles.optionAlternateText, styles.textLabelSupporting, styles.mt1]; const contentContainerStyles = mode === 'compact' ? [styles.flex1, styles.flexRow, styles.overflowHidden, styles.alignItemsCenter] : [styles.flex1]; diff --git a/src/pages/settings/AddSecondaryLoginPage.js b/src/pages/settings/AddSecondaryLoginPage.js index 3731aa043e3c..5dae82dec11c 100755 --- a/src/pages/settings/AddSecondaryLoginPage.js +++ b/src/pages/settings/AddSecondaryLoginPage.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import Onyx, {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; -import {View, TextInput, ScrollView} from 'react-native'; +import {View, ScrollView} from 'react-native'; import _ from 'underscore'; import Str from 'expensify-common/lib/str'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; @@ -18,6 +18,7 @@ import KeyboardAvoidingView from '../../components/KeyboardAvoidingView'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import compose from '../../libs/compose'; import FixedFooter from '../../components/FixedFooter'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; const propTypes = { /* Onyx Props */ @@ -126,14 +127,11 @@ class AddSecondaryLoginPage extends Component { : 'addSecondaryLoginPage.enterPreferredEmailToSendValidationLink')} - - {this.props.translate(this.formType === CONST.LOGIN_TYPE.PHONE + - this.phoneNumberInputRef = el} - style={styles.textInput} value={this.state.login} onChangeText={login => this.setState({login})} keyboardType={this.formType === CONST.LOGIN_TYPE.PHONE @@ -142,11 +140,8 @@ class AddSecondaryLoginPage extends Component { /> - - {this.props.translate('common.password')} - - this.setState({password})} secureTextEntry diff --git a/src/pages/settings/InitialPage.js b/src/pages/settings/InitialPage.js index 9305ba6a6e63..73e4a522a988 100755 --- a/src/pages/settings/InitialPage.js +++ b/src/pages/settings/InitialPage.js @@ -182,7 +182,7 @@ const InitialSettingsPage = ({ {myPersonalDetails.displayName && ( {Str.removeSMSDomain(session.email)} diff --git a/src/pages/settings/NewPasswordForm.js b/src/pages/settings/NewPasswordForm.js index b1f595ce65b0..a17d1bc7d560 100644 --- a/src/pages/settings/NewPasswordForm.js +++ b/src/pages/settings/NewPasswordForm.js @@ -1,12 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {TextInput, View} from 'react-native'; +import {View} from 'react-native'; import Text from '../../components/Text'; import withLocalize, { withLocalizePropTypes, } from '../../components/withLocalize'; import CONST from '../../CONST'; import styles from '../../styles/styles'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; const propTypes = { /** String to control the first password box in the form */ @@ -92,31 +93,25 @@ class NewPasswordForm extends React.Component { return ( <> - - {`${this.props.translate('setPasswordPage.enterPassword')}`} - - this.props.updatePassword(password)} onBlur={() => this.onBlurNewPassword()} /> - + {this.props.translate('setPasswordPage.newPasswordPrompt')} - - {`${this.props.translate('setPasswordPage.confirmNewPassword')}*`} - - this.setState({confirmNewPassword})} onSubmitEditing={() => this.props.onSubmitEditing()} diff --git a/src/pages/settings/PasswordPage.js b/src/pages/settings/PasswordPage.js index a10c43c9d877..76f71c383699 100755 --- a/src/pages/settings/PasswordPage.js +++ b/src/pages/settings/PasswordPage.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {View, TextInput, ScrollView} from 'react-native'; +import {View, ScrollView} from 'react-native'; import Onyx, {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import {isEmpty} from 'underscore'; @@ -18,6 +18,7 @@ import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize import compose from '../../libs/compose'; import KeyboardAvoidingView from '../../components/KeyboardAvoidingView'; import FixedFooter from '../../components/FixedFooter'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; const propTypes = { /* Onyx Props */ @@ -88,49 +89,40 @@ class PasswordPage extends Component { {this.props.translate('passwordPage.changingYourPasswordPrompt')} - - {`${this.props.translate('passwordPage.currentPassword')}*`} - - this.currentPasswordInputRef = el} secureTextEntry autoCompleteType="password" textContentType="password" - style={styles.textInput} value={this.state.currentPassword} onChangeText={currentPassword => this.setState({currentPassword})} returnKeyType="done" /> - - {`${this.props.translate('passwordPage.newPassword')}*`} - - this.setState({newPassword})} onFocus={() => this.setState({isPasswordRequirementsVisible: true})} onBlur={() => this.setState({isPasswordRequirementsVisible: false})} /> {this.state.isPasswordRequirementsVisible && ( - + {this.props.translate('passwordPage.newPasswordPrompt')} )} - - {`${this.props.translate('passwordPage.confirmNewPassword')}*`} - - this.setState({confirmNewPassword})} onSubmitEditing={this.handleChangePassword} diff --git a/src/pages/settings/Payments/AddPayPalMePage.js b/src/pages/settings/Payments/AddPayPalMePage.js index 97edbe423773..65cd22071df2 100644 --- a/src/pages/settings/Payments/AddPayPalMePage.js +++ b/src/pages/settings/Payments/AddPayPalMePage.js @@ -1,5 +1,5 @@ import React from 'react'; -import {TextInput, View} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import CONST from '../../../CONST'; @@ -18,6 +18,7 @@ import Button from '../../../components/Button'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView'; import FixedFooter from '../../../components/FixedFooter'; import Growl from '../../../libs/Growl'; +import ExpensiTextInput from '../../../components/ExpensiTextInput'; const propTypes = { /** Username for PayPal.Me */ @@ -82,14 +83,11 @@ class AddPayPalMePage extends React.Component { {this.props.translate('addPayPalMePage.enterYourUsernameToGetPaidViaPayPal')} - - {this.props.translate('addPayPalMePage.payPalMe')} - - this.paypalUsernameInputRef = el} autoCompleteType="off" autoCorrect={false} - style={[styles.textInput]} value={this.state.payPalMeUsername} placeholder={this.props.translate('addPayPalMePage.yourPayPalUsername')} onChangeText={text => this.setState({payPalMeUsername: text})} diff --git a/src/pages/settings/PreferencesPage.js b/src/pages/settings/PreferencesPage.js index 03e8c23c017c..f09d8e7b39c4 100755 --- a/src/pages/settings/PreferencesPage.js +++ b/src/pages/settings/PreferencesPage.js @@ -15,9 +15,9 @@ import CONST from '../../CONST'; import {setExpensifyNewsStatus} from '../../libs/actions/User'; import ScreenWrapper from '../../components/ScreenWrapper'; import Switch from '../../components/Switch'; -import Picker from '../../components/Picker'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import compose from '../../libs/compose'; +import ExpensiPicker from '../../components/ExpensiPicker'; const propTypes = { /** The chat priority mode */ @@ -79,11 +79,9 @@ const PreferencesPage = ({ /> - - {translate('preferencesPage.priorityMode')} - - - + NameValuePair.set(CONST.NVP.PRIORITY_MODE, mode, ONYXKEYS.NVP_PRIORITY_MODE) } diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js index 9190dc420bf9..c636d999a01d 100755 --- a/src/pages/settings/Profile/ProfilePage.js +++ b/src/pages/settings/Profile/ProfilePage.js @@ -1,11 +1,7 @@ import React, {Component} from 'react'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; -import { - View, - TextInput, - ScrollView, -} from 'react-native'; +import {View, ScrollView} from 'react-native'; import Str from 'expensify-common/lib/str'; import moment from 'moment-timezone'; import _ from 'underscore'; @@ -18,15 +14,15 @@ import ONYXKEYS from '../../../ONYXKEYS'; import CONST from '../../../CONST'; import styles from '../../../styles/styles'; import Text from '../../../components/Text'; -import themeColors from '../../../styles/themes/default'; import LoginField from './LoginField'; -import Picker from '../../../components/Picker'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import compose from '../../../libs/compose'; import Button from '../../../components/Button'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView'; import FixedFooter from '../../../components/FixedFooter'; import Growl from '../../../libs/Growl'; +import ExpensiTextInput from '../../../components/ExpensiTextInput'; +import ExpensiPicker from '../../../components/ExpensiPicker'; import FullNameInputRow from '../../../components/FullNameInputRow'; import CheckboxWithLabel from '../../../components/CheckboxWithLabel'; import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker'; @@ -228,11 +224,9 @@ class ProfilePage extends Component { style={[styles.mt4, styles.mb4]} /> - - {this.props.translate('profilePage.preferredPronouns')} - - this.setState({pronouns, selfSelectedPronouns: ''})} items={this.pronounDropdownValues} placeholder={{ @@ -243,13 +237,11 @@ class ProfilePage extends Component { /> {this.state.pronouns === this.props.translate('pronouns.selfSelect') && ( - this.setState({selfSelectedPronouns})} - placeholder={this.props.translate('profilePage.selfSelectYourPronoun')} - placeholderTextColor={themeColors.placeholderText} - /> + this.setState({selfSelectedPronouns})} + placeholder={this.props.translate('profilePage.selfSelectYourPronoun')} + /> )} - - {this.props.translate('profilePage.timezone')} - - this.setState({selectedTimezone})} items={timezones} - useDisabledStyles={this.state.isAutomaticTimezone} + isDisabled={this.state.isAutomaticTimezone} value={this.state.selectedTimezone} - disabled={this.state.isAutomaticTimezone} /> - {this.props.translate('loginForm.enterYourPhoneOrEmail')} - {this.state.formError && ( diff --git a/src/pages/signin/PasswordForm.js b/src/pages/signin/PasswordForm.js index fc2cf2e804e6..6bc9e5303b1c 100755 --- a/src/pages/signin/PasswordForm.js +++ b/src/pages/signin/PasswordForm.js @@ -1,6 +1,6 @@ import React from 'react'; import { - TextInput, TouchableOpacity, View, + TouchableOpacity, View, } from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; @@ -15,6 +15,7 @@ import CONST from '../../CONST'; import ChangeExpensifyLoginLink from './ChangeExpensifyLoginLink'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import compose from '../../libs/compose'; +import ExpensiTextInput from '../../components/ExpensiTextInput'; const propTypes = { /* Onyx Props */ @@ -73,20 +74,8 @@ class PasswordForm extends React.Component { return ( <> - - {this.props.translate('common.password')} - - - {this.props.translate('passwordForm.forgot')} - - - - this.setState({password: text})} onSubmitEditing={this.validateAndSubmitForm} autoFocus + translateX={-18} /> + + + {this.props.translate('passwordForm.forgot')} + + {this.props.account.requiresTwoFactorAuth && ( - {this.props.translate('passwordForm.twoFactorCode')} - this.setState({twoFactorAuthCode: text})} onSubmitEditing={this.validateAndSubmitForm} keyboardType={CONST.KEYBOARD_TYPE.NUMERIC} + translateX={-18} /> )} diff --git a/src/pages/signin/SignInPageLayout/SignInPageLayoutNarrow.js b/src/pages/signin/SignInPageLayout/SignInPageLayoutNarrow.js index e6c2ad568064..74d213eff0ca 100755 --- a/src/pages/signin/SignInPageLayout/SignInPageLayoutNarrow.js +++ b/src/pages/signin/SignInPageLayout/SignInPageLayoutNarrow.js @@ -41,7 +41,7 @@ const SignInPageLayoutNarrow = props => ( styles.mt40Percentage, ]} > - + - this.setState({name})} @@ -68,7 +68,6 @@ class NewWorkspacePage extends React.Component { /> {this.props.translate('workspace.new.helpText')} -