-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create custom TextInput #3414
Create custom TextInput #3414
Changes from 32 commits
1d1847a
39a395c
32ac54d
9bb3acc
0001f43
2e21718
e95de93
587328d
1a9687c
c9ed8ee
edbfcea
3ac6d2c
57de005
f2e5667
dc7b471
28fa320
b3303c3
0db97b8
8bdc856
f0a779e
229e704
4edf386
54e20a0
d5a0b00
7495a56
f7a4b49
dc9ab22
048436f
90db061
9cfd7e3
7271cf1
388d015
1c582ce
b6e36ea
4662b06
27c967b
f3c1c79
19f3257
221565d
f6fc27a
598f0cc
9a74f0a
bd5c05b
83c7d18
abf866f
739ce4d
2f0281a
b2067e4
3c2cd72
bc5ce35
ca971f3
7976869
dd461b5
31a9efd
adeddc7
534651e
8a0df8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.expensify.chat.generated; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import org.unimodules.core.interfaces.Package; | ||
|
||
public class BasePackageList { | ||
public List<Package> getPackageList() { | ||
return Arrays.<Package>asList( | ||
new expo.modules.haptics.HapticsPackage() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const expensiPickerDefaultProps = { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
label: '', | ||
value: '', | ||
placeholder: {}, | ||
useDisabledStyles: false, | ||
size: 'normal', | ||
}; | ||
|
||
export default expensiPickerDefaultProps; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React, {PureComponent} from 'react'; | ||
import {Text, View} from 'react-native'; | ||
import Picker from '../Picker'; | ||
import styles from '../../styles/styles'; | ||
import propTypes from './propTypes'; | ||
import defaultProps from './defaultProps'; | ||
|
||
class ExpensiPicker extends PureComponent { | ||
constructor() { | ||
super(); | ||
this.state = { | ||
isOpen: false, | ||
}; | ||
} | ||
|
||
toggleFocus = open => this.setState({ | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
isOpen: open, | ||
}) | ||
|
||
render() { | ||
const { | ||
label, value, placeholder, useDisabledStyles, ...pickerProps | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} = this.props; | ||
const {isOpen} = this.state; | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return ( | ||
<View | ||
style={[ | ||
styles.expensiPickerContainer, | ||
isOpen && styles.expensiPickerContainerOnFocus, | ||
useDisabledStyles && styles.expensiPickerContainerDisabled, | ||
]} | ||
> | ||
{label && ( | ||
<Text style={styles.expensiPickerLabel}>{label}</Text> | ||
)} | ||
<Picker | ||
placeholder={placeholder} | ||
value={value} | ||
onOpen={() => this.toggleFocus(true)} | ||
onClose={() => this.toggleFocus(false)} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...pickerProps} | ||
/> | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
ExpensiPicker.propTypes = propTypes; | ||
ExpensiPicker.defaultProps = defaultProps; | ||
|
||
export default ExpensiPicker; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import PropTypes from 'prop-types'; | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const propTypes = { | ||
label: PropTypes.string, | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
value: PropTypes.string, | ||
|
||
/** Something to show as the placeholder before something is selected */ | ||
placeholder: PropTypes.shape({ | ||
/** The value of the placeholder item, usually an empty string */ | ||
value: PropTypes.string, | ||
|
||
/** The text to be displayed as the placeholder */ | ||
label: PropTypes.string, | ||
}), | ||
|
||
/** Picker disabled style */ | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
useDisabledStyles: PropTypes.boolean, | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** Picker size */ | ||
size: PropTypes.oneOf(['normal', 'small']), | ||
}; | ||
|
||
export default propTypes; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const expensiTextInputDefaultProps = { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
label: '', | ||
placeholder: '', | ||
error: false, | ||
onFocusExtra: null, | ||
onBlurExtra: null, | ||
containerStyles: [], | ||
translateX: -22, | ||
androidStyle: [], | ||
}; | ||
|
||
export default expensiTextInputDefaultProps; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import PropTypes from 'prop-types'; | ||
import {Animated} from 'react-native'; | ||
|
||
const expensiTextInputLabelPropTypes = { | ||
label: PropTypes.string, | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** 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 expensiTextInputLabelPropTypes; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React, {PureComponent} from 'react'; | ||
import {Animated} from 'react-native'; | ||
import styles from '../../../styles/styles'; | ||
import expensiTextInputLabelPropTypes from './ExpensiTextInputLabelPropTypes'; | ||
|
||
class ExpensiTextInputLabel extends PureComponent { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
render() { | ||
const { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
label, labelTranslateX, labelTranslateY, labelScale, | ||
} = this.props; | ||
return ( | ||
<Animated.Text | ||
style={[ | ||
styles.expensiTextInputLabel, | ||
styles.expensiTextInputLabelDesktop, | ||
styles.expensiTextInputLabelTransformation( | ||
labelTranslateY, | ||
labelTranslateX, | ||
labelScale, | ||
), | ||
]} | ||
> | ||
{label} | ||
</Animated.Text> | ||
); | ||
} | ||
} | ||
|
||
ExpensiTextInputLabel.propTypes = expensiTextInputLabelPropTypes; | ||
|
||
export default ExpensiTextInputLabel; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React, {PureComponent} from 'react'; | ||
import {Animated} from 'react-native'; | ||
import styles from '../../../styles/styles'; | ||
import expensiTextInputLabelPropTypes from './ExpensiTextInputLabelPropTypes'; | ||
|
||
class ExpensiTextInputLabel extends PureComponent { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
render() { | ||
const { | ||
label, labelTranslateX, labelTranslateY, labelScale, | ||
} = this.props; | ||
return ( | ||
<Animated.Text | ||
style={[ | ||
styles.expensiTextInputLabel, | ||
styles.expensiTextInputLabelTransformation( | ||
labelTranslateY, | ||
labelTranslateX, | ||
labelScale, | ||
), | ||
]} | ||
> | ||
{label} | ||
</Animated.Text> | ||
); | ||
} | ||
} | ||
|
||
ExpensiTextInputLabel.propTypes = expensiTextInputLabelPropTypes; | ||
|
||
export default ExpensiTextInputLabel; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,32 @@ | ||||||
import PropTypes from 'prop-types'; | ||||||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
const expensiTextInputPropTypes = { | ||||||
/** Input label */ | ||||||
label: PropTypes.string, | ||||||
|
||||||
/** Input value */ | ||||||
value: PropTypes.string.isRequired, | ||||||
|
||||||
/** Input value placeholder */ | ||||||
placeholder: PropTypes.string, | ||||||
|
||||||
/** Callback that is called when the text input is focused. */ | ||||||
onFocusExtra: PropTypes.func, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's rename this and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kind of need it.
example usage here: (src/pages/settings/PasswordPage.js) <ExpensiTextInput
label={`${this.props.translate('passwordPage.newPassword')}*`}
secureTextEntry
autoCompleteType="password"
textContentType="password"
value={this.state.newPassword}
onChangeText={newPassword => this.setState({newPassword})}
onFocusExtra={() => this.setState({isPasswordRequirementsVisible: true})}
onBlurExtra={() => this.setState({isPasswordRequirementsVisible: false})}
/> Do you have suggestion about how to refactor? |
||||||
|
||||||
/** Callback that is called when the text input is blurred. */ | ||||||
onBlurExtra: PropTypes.func, | ||||||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
/** Input with error */ | ||||||
error: PropTypes.bool, | ||||||
|
||||||
/** Styles for the outermost container for this component. */ | ||||||
containerStyles: PropTypes.arrayOf(PropTypes.object), | ||||||
|
||||||
/** label translate x */ | ||||||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
translateX: PropTypes.number, | ||||||
|
||||||
/** android specific styles */ | ||||||
androidStyle: PropTypes.arrayOf(PropTypes.object), | ||||||
}; | ||||||
|
||||||
export default expensiTextInputPropTypes; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import PropTypes from 'prop-types'; | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const expensiTextInputWrapperPropTypes = { | ||
/** Input label */ | ||
children: PropTypes.node.isRequired, | ||
|
||
/** Has Label */ | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
hasLabel: PropTypes.bool.isRequired, | ||
|
||
/** On press to wrapper */ | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
onPress: PropTypes.func.isRequired, | ||
|
||
/** Is input in focus? */ | ||
isFocused: PropTypes.bool.isRequired, | ||
|
||
/** Has error? */ | ||
error: PropTypes.bool.isRequired, | ||
|
||
/** Styles for the outermost container for this component. */ | ||
containerStyles: PropTypes.arrayOf(PropTypes.object), | ||
}; | ||
|
||
export default expensiTextInputWrapperPropTypes; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React, {PureComponent} from 'react'; | ||
import {TouchableWithoutFeedback, View} from 'react-native'; | ||
import expensiTextInputWrapperPropTypes from './ExpensiTextInputWrapperPropTypes'; | ||
import styles from '../../../styles/styles'; | ||
|
||
const defaultProps = { | ||
containerStyles: [], | ||
}; | ||
|
||
class ExpensiTextInputWrapper extends PureComponent { | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
render() { | ||
const { | ||
children, onPress, containerStyles, isFocused, error, hasLabel, | ||
} = this.props; | ||
|
||
return ( | ||
<View style={[styles.expensiTextInputWrapper, ...containerStyles]}> | ||
<TouchableWithoutFeedback onPress={onPress}> | ||
<View | ||
style={[ | ||
styles.expensiTextInputContainer, | ||
!hasLabel && styles.expensiTextInputContainerWithoutLabel, | ||
isFocused && styles.expensiTextInputContainerOnFocus, | ||
error && styles.expensiTextInputContainerOnError, | ||
]} | ||
> | ||
{children} | ||
</View> | ||
</TouchableWithoutFeedback> | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
ExpensiTextInputWrapper.propTypes = expensiTextInputWrapperPropTypes; | ||
ExpensiTextInputWrapper.defaultProps = defaultProps; | ||
|
||
export default ExpensiTextInputWrapper; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import styles from '../../styles/styles'; | ||
import ExpensiTextInput from './index.ios'; | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import expensiTextInputPropTypes from './ExpensiTextInputPropTypes'; | ||
import expensiTextInputDefaultProps from './ExpensiTextInputDefaultProps'; | ||
|
||
const ExpensiTextInputAndroid = ({ | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
androidStyles, | ||
translateX, | ||
...props | ||
}) => ( | ||
<ExpensiTextInput | ||
androidStyles={styles.expensiTextInputAndroid(Math.abs(translateX))} | ||
translateX={translateX} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...props} | ||
/> | ||
); | ||
|
||
ExpensiTextInputAndroid.propTypes = expensiTextInputPropTypes; | ||
ExpensiTextInputAndroid.defaultProps = expensiTextInputDefaultProps; | ||
roryabraham marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export default ExpensiTextInputAndroid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unsure if this generated file should be included in version control. And I mean that earnestly – I don't know if it should be included or not, but I would think no.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed, but I think we should add it to .gitignore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, feel free to add
android/app/src/main/java/com/expensify/chat/generated/*
to the.gitignore