Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
79cb9cc
Add Prefix input props
parasharrajat Feb 28, 2022
f13c9b9
force label on textinput when there is a prefix
parasharrajat Feb 28, 2022
b4ff932
Add prefix to BaseTextInput
parasharrajat Feb 28, 2022
84745d7
show placeholder when input has prefix
parasharrajat Feb 28, 2022
d97fb0e
No pointer to prefix
parasharrajat Feb 28, 2022
028eedb
fix new Roompage design
parasharrajat Feb 28, 2022
cfbb02f
Merge branch 'main' of github.com:Expensify/Expensify.cash into texti…
parasharrajat Feb 28, 2022
3c79c64
refactor to const
parasharrajat Feb 28, 2022
9e54739
Fix ReportSettings page design
parasharrajat Feb 28, 2022
b983e91
Cleanup
parasharrajat Feb 28, 2022
a10af79
Remove extra warnings
parasharrajat Feb 28, 2022
f097d95
No selectable text
parasharrajat Feb 28, 2022
c0b8729
fix settings page margin
parasharrajat Feb 28, 2022
ccb0b51
fix prefix input gap
parasharrajat Feb 28, 2022
7bc9ee8
Fix outline for TextInputs
parasharrajat Feb 28, 2022
2d6c848
Fix: box-shadow styles for outline to override the default styles
parasharrajat Feb 28, 2022
a91902b
Change the button styles on Report page
parasharrajat Mar 1, 2022
375c8f9
Fix: styling issues
parasharrajat Mar 1, 2022
4e7d6d1
Don't override the native TextInput prop in Form component.
parasharrajat Mar 1, 2022
b8abe7e
Change default prop value of TextInput prop prefixCharacter
parasharrajat Mar 1, 2022
69eb3a3
Merge branch 'main' of github.com:Expensify/Expensify.cash into texti…
parasharrajat Mar 1, 2022
8f75d05
Add another story for Form Component
parasharrajat Mar 1, 2022
c47130e
Change prop name
parasharrajat Mar 1, 2022
62d179d
refactor prop definition
parasharrajat Mar 1, 2022
6984a47
more refactor
parasharrajat Mar 1, 2022
151c0d1
Auto calculate the prefix Width
parasharrajat Mar 2, 2022
7bf1f99
Use Correct padding style object
parasharrajat Mar 2, 2022
aa07d10
styling change
parasharrajat Mar 2, 2022
e872468
Small tweaks
parasharrajat Mar 4, 2022
791758e
Remove hardcode width of prefix
parasharrajat Mar 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Form extends React.Component {
this.setTouchedInput(inputID);
this.validate(this.inputValues);
},
onChange: (value) => {
onInputChange: (value) => {
this.inputValues[inputID] = value;
if (child.props.shouldSaveDraft) {
FormActions.setDraftValues(this.props.formID, {[inputID]: value});
Expand Down
8 changes: 3 additions & 5 deletions src/components/RoomNameInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import CONST from '../CONST';
import ONYXKEYS from '../ONYXKEYS';
import styles from '../styles/styles';
import compose from '../libs/compose';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import withFullPolicy, {fullPolicyDefaultProps, fullPolicyPropTypes} from '../pages/workspace/withFullPolicy';
import TextInputWithPrefix from './TextInputWithPrefix';
import TextInput from './TextInput';

const propTypes = {
/** Callback to execute when the text input is modified correctly */
Expand Down Expand Up @@ -103,12 +102,11 @@ class RoomNameInput extends Component {

render() {
return (
<TextInputWithPrefix
<TextInput
disabled={this.props.disabled}
label={this.props.translate('newRoomPage.roomName')}
prefixCharacter="#"
prefixCharacter={CONST.POLICY.ROOM_PREFIX}
placeholder={this.props.translate('newRoomPage.social')}
containerStyles={[styles.mb5]}
onChange={this.setModifiedRoomName}
value={this.state.roomName.substring(1)}
errorText={this.props.errorText}
Expand Down
32 changes: 26 additions & 6 deletions src/components/TextInput/BaseTextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ class BaseTextInput extends Component {
super(props);

this.value = props.value || props.defaultValue || '';
const activeLabel = props.forceActiveLabel || this.value.length > 0;
const activeLabel = props.forceActiveLabel || this.value.length > 0 || props.prefixCharacter;

this.state = {
isFocused: false,
labelTranslateY: new Animated.Value(activeLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y),
labelScale: new Animated.Value(activeLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE),
passwordHidden: props.secureTextEntry,
textInputWidth: 0,
prefixWidth: 0,
};

this.input = null;
Expand All @@ -38,6 +39,7 @@ class BaseTextInput extends Component {
this.setValue = this.setValue.bind(this);
this.togglePasswordVisibility = this.togglePasswordVisibility.bind(this);
this.dismissKeyboardWhenBackgrounded = this.dismissKeyboardWhenBackgrounded.bind(this);
this.storePrefixLayoutDimensions = this.storePrefixLayoutDimensions.bind(this);
}

componentDidMount() {
Expand Down Expand Up @@ -120,8 +122,8 @@ class BaseTextInput extends Component {
* @memberof BaseTextInput
*/
setValue(value) {
if (this.props.onChange) {
this.props.onChange(value);
if (this.props.onInputChange) {
this.props.onInputChange(value);
}
this.value = value;
Str.result(this.props.onChangeText, value);
Expand All @@ -141,7 +143,7 @@ class BaseTextInput extends Component {
}

deactivateLabel() {
if (this.props.forceActiveLabel || this.value.length !== 0) {
if (this.props.forceActiveLabel || this.value.length !== 0 || this.props.prefixCharacter) {
return;
}

Expand Down Expand Up @@ -176,6 +178,10 @@ class BaseTextInput extends Component {
this.setState(prevState => ({passwordHidden: !prevState.passwordHidden}));
}

storePrefixLayoutDimensions(event) {
this.setState({prefixWidth: Math.abs(event.nativeEvent.layout.width)});
}

render() {
// eslint-disable-next-line react/forbid-foreign-prop-types
const inputProps = _.omit(this.props, _.keys(baseTextInputPropTypes.propTypes));
Expand Down Expand Up @@ -215,7 +221,20 @@ class BaseTextInput extends Component {
/>
</>
) : null}
<View style={[styles.textInputAndIconContainer]}>
<View style={[styles.textInputAndIconContainer]} pointerEvents="box-none">
{Boolean(this.props.prefixCharacter) && (
<Text
pointerEvents="none"
selectable={false}
style={[
styles.textInputPrefix,
!hasLabel && styles.pv0,
]}
onLayout={this.storePrefixLayoutDimensions}
>
{this.props.prefixCharacter}
</Text>
)}
<RNTextInput
ref={(ref) => {
if (typeof this.props.innerRef === 'function') { this.props.innerRef(ref); }
Expand All @@ -224,14 +243,15 @@ class BaseTextInput extends Component {
// eslint-disable-next-line
{...inputProps}
defaultValue={this.value}
placeholder={(this.state.isFocused || !this.props.label) ? this.props.placeholder : null}
placeholder={(this.props.prefixCharacter || this.state.isFocused || !this.props.label) ? this.props.placeholder : null}
placeholderTextColor={themeColors.placeholderText}
underlineColorAndroid="transparent"
style={[
styles.flex1,
styles.w100,
this.props.inputStyle,
!hasLabel && styles.pv0,
this.props.prefixCharacter && StyleUtils.getPaddingLeft(this.state.prefixWidth + styles.pl1.paddingLeft),
this.props.secureTextEntry && styles.pr2,
]}
multiline={this.props.multiline}
Expand Down
20 changes: 15 additions & 5 deletions src/components/TextInput/baseTextInputPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ const propTypes = {
/** Forward the inner ref */
innerRef: PropTypes.func,

/** Maximum characters allowed */
maxLength: PropTypes.number,

/** Hint text to display below the TextInput */
hint: PropTypes.string,

/** Prefix character */
prefixCharacter: PropTypes.string,

/** Form props */

/** Indicates that the input is being used with the Form component */
isFormInput: PropTypes.bool,

Expand All @@ -61,11 +72,8 @@ const propTypes = {
/** Saves a draft of the input value when used in a form */
shouldSaveDraft: PropTypes.bool,

/** Maximum characters allowed */
maxLength: PropTypes.number,

/** Hint text to display below the TextInput */
hint: PropTypes.string,
/** Callback to update the value on Form when input is used in the Form component. */
onInputChange: PropTypes.func,
};

const defaultProps = {
Expand Down Expand Up @@ -94,6 +102,8 @@ const defaultProps = {
shouldSaveDraft: false,
maxLength: null,
hint: '',
prefixCharacter: '',
onInputChange: () => {},
};

export {propTypes, defaultProps};
58 changes: 0 additions & 58 deletions src/components/TextInputWithPrefix/index.android.js

This file was deleted.

56 changes: 0 additions & 56 deletions src/components/TextInputWithPrefix/index.js

This file was deleted.

5 changes: 3 additions & 2 deletions src/pages/ReportSettingsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class ReportSettingsPage extends Component {
<Text style={[styles.formLabel]} numberOfLines={1}>
{this.props.translate('newRoomPage.roomName')}
</Text>
<View style={[styles.flexRow]}>
<View style={[styles.flexRow, styles.mb1]}>
<View style={[styles.flex3]}>
<RoomNameInput
initialValue={this.state.newRoomName}
Expand All @@ -199,12 +199,13 @@ class ReportSettingsPage extends Component {
/>
</View>
<Button
large
success={!shouldDisableRename}
text={this.props.translate('common.save')}
onPress={this.validateAndRenameReport}
style={[styles.ml2, styles.flex1]}
textStyles={[styles.label]}
innerStyles={[styles.reportSettingsChangeNameButton]}
innerStyles={[styles.ph5]}
isLoading={this.props.isLoadingRenamePolicyRoom}
isDisabled={shouldDisableRename}
/>
Expand Down
1 change: 0 additions & 1 deletion src/pages/workspace/WorkspaceNewRoomPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ class WorkspaceNewRoomPage extends React.Component {
/>
<ScrollView style={styles.flex1} contentContainerStyle={styles.p5}>
<View style={styles.mb5}>
<Text style={[styles.formLabel]}>{this.props.translate('newRoomPage.roomName')}</Text>
<RoomNameInput
initialValue={this.state.roomName}
policyID={this.state.policyID}
Expand Down
35 changes: 34 additions & 1 deletion src/stories/Form.stories.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import React, {useState} from 'react';
import {View} from 'react-native';
import TextInput from '../components/TextInput';
import AddressSearch from '../components/AddressSearch';
import Form from '../components/Form';
import * as FormActions from '../libs/actions/FormActions';
import styles from '../styles/styles';
import Text from '../components/Text';

/**
* We use the Component Story Format for writing stories. Follow the docs here:
Expand Down Expand Up @@ -50,6 +51,36 @@ const Template = (args) => {
);
};

/**
* Story to exhibit the native event handlers for TextInput in the Form Component
* @param {Object} args
* @returns {JSX}
*/
const WithNativeEventHandler = (args) => {
const [log, setLog] = useState('');

// Form consumes data from Onyx, so we initialize Onyx with the necessary data here
FormActions.setIsSubmitting(args.formID, args.formState.isSubmitting);
FormActions.setServerErrorMessage(args.formID, args.formState.serverErrorMessage);
FormActions.setDraftValues(args.formID, args.draftValues);

return (
// eslint-disable-next-line react/jsx-props-no-spreading
<Form {...args}>
<TextInput
label="Routing number"
inputID="routingNumber"
onChangeText={setLog}
isFormInput
shouldSaveDraft
/>
<Text>
{`Entered routing number: ${log}`}
</Text>
</Form>
);
};

// Arguments can be passed to the component by binding
// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Default = Template.bind({});
Expand Down Expand Up @@ -90,11 +121,13 @@ Default.args = defaultArgs;
Loading.args = {...defaultArgs, formState: {isSubmitting: true}};
ServerError.args = {...defaultArgs, formState: {isSubmitting: false, serverErrorMessage: 'There was an unexpected error. Please try again later.'}};
InputError.args = {...defaultArgs, draftValues: {routingNumber: '', accountNumber: ''}};
WithNativeEventHandler.args = {...defaultArgs, draftValues: {routingNumber: '', accountNumber: ''}};

export default story;
export {
Default,
Loading,
ServerError,
InputError,
WithNativeEventHandler,
};
Loading