Skip to content

Commit

Permalink
feat: Unify TextInput autoComplete and textContentType props (#34523)
Browse files Browse the repository at this point in the history
Summary:
This unifies the Android only  `autoComplete` and the iOS only `textContentType` TextInput props with the web `autoComplete` values as requested on #34424. I left the `textContentType` prop and the current supported `autoComplete` values untouched in order to avoid having a breaking change. This also updates RNTester to include test cases using the new `autoComplete` values

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Changed] - Unify TextInput autoComplete and textContentType props

Pull Request resolved: #34523

Test Plan:
1. Open the RNTester app and navigate to the TextInput page
2. Test the `TextInput` component through the `Text Auto Complete` section

https://user-images.githubusercontent.com/11707729/187118267-3b509631-7b84-47b7-a580-567a7f5b483f.mov

Reviewed By: NickGerleman

Differential Revision: D39104545

Pulled By: cipolleschi

fbshipit-source-id: a0d4b1b9ab336854a741a9efe4a62c3da0b5c0f4
  • Loading branch information
gabrieldonadel authored and facebook-github-bot committed Sep 8, 2022
1 parent 7ea54a4 commit 73abcba
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 0 deletions.
125 changes: 125 additions & 0 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,36 @@ export type enterKeyHintType =
type PasswordRules = string;

type IOSProps = $ReadOnly<{|
/**
* Give the keyboard and the system information about the
* expected semantic meaning for the content that users enter.
* @platform ios
*/
autoComplete?: ?(
| 'address-line1'
| 'address-line2'
| 'cc-number'
| 'current-password'
| 'country'
| 'email'
| 'name'
| 'additional-name'
| 'family-name'
| 'given-name'
| 'nickname'
| 'honorific-prefix'
| 'honorific-suffix'
| 'new-password'
| 'off'
| 'one-time-code'
| 'organization'
| 'organization-title'
| 'postal-code'
| 'street-address'
| 'tel'
| 'url'
| 'username'
),
/**
* When the clear button should appear on the right side of the text view.
* This property is supported only for single-line TextInput component.
Expand Down Expand Up @@ -411,6 +441,23 @@ type AndroidProps = $ReadOnly<{|
| 'username'
| 'username-new'
| 'off'
// additional HTML autocomplete values
| 'address-line1'
| 'address-line2'
| 'bday'
| 'bday-day'
| 'bday-month'
| 'bday-year'
| 'country'
| 'current-password'
| 'honorific-prefix'
| 'honorific-suffix'
| 'additional-name'
| 'family-name'
| 'given-name'
| 'new-password'
| 'one-time-code'
| 'sex'
),

/**
Expand Down Expand Up @@ -1470,6 +1517,67 @@ const inputModeToKeyboardTypeMap = {
url: 'url',
};

// Map HTML autocomplete values to Android autoComplete values
const autoCompleteWebToAutoCompleteAndroidMap = {
'address-line1': 'postal-address-region',
'address-line2': 'postal-address-locality',
bday: 'birthdate-full',
'bday-day': 'birthdate-day',
'bday-month': 'birthdate-month',
'bday-year': 'birthdate-year',
'cc-csc': 'cc-csc',
'cc-exp': 'cc-exp',
'cc-exp-month': 'cc-exp-month',
'cc-exp-year': 'cc-exp-year',
'cc-number': 'cc-number',
country: 'postal-address-country',
'current-password': 'password',
email: 'email',
'honorific-prefix': 'name-prefix',
'honorific-suffix': 'name-suffix',
name: 'name',
'additional-name': 'name-middle',
'family-name': 'name-family',
'given-name': 'name-given',
'new-password': 'password-new',
off: 'off',
'one-time-code': 'sms-otp',
'postal-code': 'postal-code',
sex: 'gender',
'street-address': 'street-address',
tel: 'tel',
'tel-country-code': 'tel-country-code',
'tel-national': 'tel-national',
username: 'username',
};

// Map HTML autocomplete values to iOS textContentType values
const autoCompleteWebToTextContentTypeMap = {
'address-line1': 'streetAddressLine1',
'address-line2': 'streetAddressLine2',
'cc-number': 'creditCardNumber',
'current-password': 'password',
country: 'countryName',
email: 'emailAddress',
name: 'name',
'additional-name': 'middleName',
'family-name': 'familyName',
'given-name': 'givenName',
nickname: 'nickname',
'honorific-prefix': 'namePrefix',
'honorific-suffix': 'nameSuffix',
'new-password': 'newPassword',
off: 'none',
'one-time-code': 'oneTimeCode',
organization: 'organizationName',
'organization-title': 'jobTitle',
'postal-code': 'postalCode',
'street-address': 'fullStreetAddress',
tel: 'telephoneNumber',
url: 'URL',
username: 'username',
};

const ExportedForwardRef: React.AbstractComponent<
React.ElementConfig<typeof InternalTextInput>,
React.ElementRef<HostComponent<mixed>> & ImperativeMethods,
Expand All @@ -1478,6 +1586,8 @@ const ExportedForwardRef: React.AbstractComponent<
allowFontScaling = true,
rejectResponderTermination = true,
underlineColorAndroid = 'transparent',
autoComplete,
textContentType,
readOnly,
editable,
enterKeyHint,
Expand All @@ -1502,6 +1612,21 @@ const ExportedForwardRef: React.AbstractComponent<
keyboardType={
inputMode ? inputModeToKeyboardTypeMap[inputMode] : keyboardType
}
autoComplete={
Platform.OS === 'android'
? // $FlowFixMe
autoCompleteWebToAutoCompleteAndroidMap[autoComplete] ??
autoComplete
: undefined
}
textContentType={
Platform.OS === 'ios' &&
autoComplete &&
autoComplete in autoCompleteWebToTextContentTypeMap
? // $FlowFixMe
autoCompleteWebToTextContentTypeMap[autoComplete]
: textContentType
}
{...restProps}
forwardedRef={forwardedRef}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,35 @@ exports.examples = ([
);
},
},
{
title: 'Text Auto Complete',
render: function (): React.Node {
return (
<View>
<TextInput
autoComplete="country"
placeholder="country"
style={styles.default}
/>
<TextInput
autoComplete="postal-address-country"
placeholder="postal-address-country"
style={styles.default}
/>
<TextInput
autoComplete="one-time-code"
placeholder="one-time-code"
style={styles.default}
/>
<TextInput
autoComplete="sms-otp"
placeholder="sms-otp"
style={styles.default}
/>
</View>
);
},
},
{
title: 'Return key',
render: function (): React.Node {
Expand Down
15 changes: 15 additions & 0 deletions packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,21 @@ exports.examples = ([
);
},
},
{
title: 'Text Auto Complete',
render: function (): React.Node {
return (
<View>
<WithLabel label="country">
<TextInput autoComplete="country" style={styles.default} />
</WithLabel>
<WithLabel label="one-time-code">
<TextInput autoComplete="one-time-code" style={styles.default} />
</WithLabel>
</View>
);
},
},
{
title: 'Text Content Type',
render: function (): React.Node {
Expand Down

0 comments on commit 73abcba

Please sign in to comment.