mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
feat: Support iOS 17 text content types (#38354)
Summary: While setting up a credit card form in RN, I discovered that iOS 17 supports a number of new content types ([`UITextContentType` docs](https://developer.apple.com/documentation/uikit/uitextcontenttype?language=objc)). In the docs these are marked with the `Beta` flag. Setting up the new content types is relatively straightforward, but a change is required in https://github.com/facebook/react-native-deprecated-modules to update the `TextInput` prop types. ~~I will open a PR in that repo shortly.~~ I have [opened a PR](https://github.com/facebook/react-native-deprecated-modules/pull/23) to update the prop types. ~~Once that PR is merged, a version bump for that dependency will need to be added to this PR.~~ The PR is merged and the dependency in this PR has been updated. ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [IOS] [ADDED] - Added support for iOS 17+ text content types For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: https://github.com/facebook/react-native/pull/38354 Test Plan: The `rn-tester` app builds and runs successfully. I have added a few new examples of inputs using the new text content types. Reviewed By: javache Differential Revision: D47554161 Pulled By: philIip fbshipit-source-id: 8d4414dc6229063f81164f2d8727921c8294c92e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0527aea3d9
commit
216865cdb7
@@ -205,13 +205,6 @@ export interface TextInputIOSProps {
|
||||
* Give the keyboard and the system information about the expected
|
||||
* semantic meaning for the content that users enter.
|
||||
*
|
||||
* For iOS 11+ you can set `textContentType` to `username` or `password` to
|
||||
* enable autofill of login details from the device keychain.
|
||||
*
|
||||
* For iOS 12+ `newPassword` can be used to indicate a new password input the
|
||||
* user may want to save in the keychain, and `oneTimeCode` can be used to indicate
|
||||
* that a field can be autofilled by a code arriving in an SMS.
|
||||
*
|
||||
* To disable autofill, set textContentType to `none`.
|
||||
*
|
||||
* Possible values for `textContentType` are:
|
||||
@@ -223,6 +216,15 @@ export interface TextInputIOSProps {
|
||||
* - `'addressState'`
|
||||
* - `'countryName'`
|
||||
* - `'creditCardNumber'`
|
||||
* - `'creditCardExpiration'` (iOS 17+)
|
||||
* - `'creditCardExpirationMonth'` (iOS 17+)
|
||||
* - `'creditCardExpirationYear'` (iOS 17+)
|
||||
* - `'creditCardSecurityCode'` (iOS 17+)
|
||||
* - `'creditCardType'` (iOS 17+)
|
||||
* - `'creditCardName'` (iOS 17+)
|
||||
* - `'creditCardGivenName'` (iOS 17+)
|
||||
* - `'creditCardMiddleName'` (iOS 17+)
|
||||
* - `'creditCardFamilyName'` (iOS 17+)
|
||||
* - `'emailAddress'`
|
||||
* - `'familyName'`
|
||||
* - `'fullStreetAddress'`
|
||||
@@ -244,6 +246,10 @@ export interface TextInputIOSProps {
|
||||
* - `'password'`
|
||||
* - `'newPassword'`
|
||||
* - `'oneTimeCode'`
|
||||
* - `'birthdate'` (iOS 17+)
|
||||
* - `'birthdateDay'` (iOS 17+)
|
||||
* - `'birthdateMonth'` (iOS 17+)
|
||||
* - `'birthdateYear'` (iOS 17+)
|
||||
*
|
||||
*/
|
||||
textContentType?:
|
||||
@@ -254,6 +260,15 @@ export interface TextInputIOSProps {
|
||||
| 'addressState'
|
||||
| 'countryName'
|
||||
| 'creditCardNumber'
|
||||
| 'creditCardExpiration'
|
||||
| 'creditCardExpirationMonth'
|
||||
| 'creditCardExpirationYear'
|
||||
| 'creditCardSecurityCode'
|
||||
| 'creditCardType'
|
||||
| 'creditCardName'
|
||||
| 'creditCardGivenName'
|
||||
| 'creditCardMiddleName'
|
||||
| 'creditCardFamilyName'
|
||||
| 'emailAddress'
|
||||
| 'familyName'
|
||||
| 'fullStreetAddress'
|
||||
@@ -275,6 +290,10 @@ export interface TextInputIOSProps {
|
||||
| 'password'
|
||||
| 'newPassword'
|
||||
| 'oneTimeCode'
|
||||
| 'birthdate'
|
||||
| 'birthdateDay'
|
||||
| 'birthdateMonth'
|
||||
| 'birthdateYear'
|
||||
| undefined;
|
||||
|
||||
/**
|
||||
@@ -569,6 +588,11 @@ export interface TextInputProps
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'cc-name'
|
||||
| 'cc-given-name'
|
||||
| 'cc-middle-name'
|
||||
| 'cc-family-name'
|
||||
| 'cc-type'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
|
||||
@@ -162,6 +162,15 @@ export type TextContentType =
|
||||
| 'addressState'
|
||||
| 'countryName'
|
||||
| 'creditCardNumber'
|
||||
| 'creditCardExpiration'
|
||||
| 'creditCardExpirationMonth'
|
||||
| 'creditCardExpirationYear'
|
||||
| 'creditCardSecurityCode'
|
||||
| 'creditCardType'
|
||||
| 'creditCardName'
|
||||
| 'creditCardGivenName'
|
||||
| 'creditCardMiddleName'
|
||||
| 'creditCardFamilyName'
|
||||
| 'emailAddress'
|
||||
| 'familyName'
|
||||
| 'fullStreetAddress'
|
||||
@@ -182,7 +191,11 @@ export type TextContentType =
|
||||
| 'username'
|
||||
| 'password'
|
||||
| 'newPassword'
|
||||
| 'oneTimeCode';
|
||||
| 'oneTimeCode'
|
||||
| 'birthdate'
|
||||
| 'birthdateDay'
|
||||
| 'birthdateMonth'
|
||||
| 'birthdateYear';
|
||||
|
||||
export type enterKeyHintType =
|
||||
| 'enter'
|
||||
@@ -418,7 +431,16 @@ export type Props = $ReadOnly<{|
|
||||
* - `additional-name`
|
||||
* - `address-line1`
|
||||
* - `address-line2`
|
||||
* - `birthdate-day` (iOS 17+)
|
||||
* - `birthdate-full` (iOS 17+)
|
||||
* - `birthdate-month` (iOS 17+)
|
||||
* - `birthdate-year` (iOS 17+)
|
||||
* - `cc-number`
|
||||
* - `cc-csc` (iOS 17+)
|
||||
* - `cc-exp` (iOS 17+)
|
||||
* - `cc-exp-day` (iOS 17+)
|
||||
* - `cc-exp-month` (iOS 17+)
|
||||
* - `cc-exp-year` (iOS 17+)
|
||||
* - `country`
|
||||
* - `current-password`
|
||||
* - `email`
|
||||
@@ -437,6 +459,11 @@ export type Props = $ReadOnly<{|
|
||||
*
|
||||
* The following values work on iOS only:
|
||||
*
|
||||
* - `cc-name` (iOS 17+)
|
||||
* - `cc-given-name` (iOS 17+)
|
||||
* - `cc-middle-name` (iOS 17+)
|
||||
* - `cc-family-name` (iOS 17+)
|
||||
* - `cc-type` (iOS 17+)
|
||||
* - `nickname`
|
||||
* - `organization`
|
||||
* - `organization-title`
|
||||
@@ -444,15 +471,6 @@ export type Props = $ReadOnly<{|
|
||||
*
|
||||
* The following values work on Android only:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `gender`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
@@ -488,6 +506,11 @@ export type Props = $ReadOnly<{|
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'cc-name'
|
||||
| 'cc-given-name'
|
||||
| 'cc-middle-name'
|
||||
| 'cc-family-name'
|
||||
| 'cc-type'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
|
||||
@@ -200,6 +200,15 @@ export type TextContentType =
|
||||
| 'addressState'
|
||||
| 'countryName'
|
||||
| 'creditCardNumber'
|
||||
| 'creditCardExpiration'
|
||||
| 'creditCardExpirationMonth'
|
||||
| 'creditCardExpirationYear'
|
||||
| 'creditCardSecurityCode'
|
||||
| 'creditCardType'
|
||||
| 'creditCardName'
|
||||
| 'creditCardGivenName'
|
||||
| 'creditCardMiddleName'
|
||||
| 'creditCardFamilyName'
|
||||
| 'emailAddress'
|
||||
| 'familyName'
|
||||
| 'fullStreetAddress'
|
||||
@@ -220,7 +229,11 @@ export type TextContentType =
|
||||
| 'username'
|
||||
| 'password'
|
||||
| 'newPassword'
|
||||
| 'oneTimeCode';
|
||||
| 'oneTimeCode'
|
||||
| 'birthdate'
|
||||
| 'birthdateDay'
|
||||
| 'birthdateMonth'
|
||||
| 'birthdateYear';
|
||||
|
||||
export type enterKeyHintType =
|
||||
// Cross Platform
|
||||
@@ -462,7 +475,16 @@ export type Props = $ReadOnly<{|
|
||||
* - `additional-name`
|
||||
* - `address-line1`
|
||||
* - `address-line2`
|
||||
* - `birthdate-day` (iOS 17+)
|
||||
* - `birthdate-full` (iOS 17+)
|
||||
* - `birthdate-month` (iOS 17+)
|
||||
* - `birthdate-year` (iOS 17+)
|
||||
* - `cc-number`
|
||||
* - `cc-csc` (iOS 17+)
|
||||
* - `cc-exp` (iOS 17+)
|
||||
* - `cc-exp-day` (iOS 17+)
|
||||
* - `cc-exp-month` (iOS 17+)
|
||||
* - `cc-exp-year` (iOS 17+)
|
||||
* - `country`
|
||||
* - `current-password`
|
||||
* - `email`
|
||||
@@ -481,6 +503,11 @@ export type Props = $ReadOnly<{|
|
||||
*
|
||||
* The following values work on iOS only:
|
||||
*
|
||||
* - `cc-name` (iOS 17+)
|
||||
* - `cc-given-name` (iOS 17+)
|
||||
* - `cc-middle-name` (iOS 17+)
|
||||
* - `cc-family-name` (iOS 17+)
|
||||
* - `cc-type` (iOS 17+)
|
||||
* - `nickname`
|
||||
* - `organization`
|
||||
* - `organization-title`
|
||||
@@ -488,15 +515,6 @@ export type Props = $ReadOnly<{|
|
||||
*
|
||||
* The following values work on Android only:
|
||||
*
|
||||
* - `birthdate-day`
|
||||
* - `birthdate-full`
|
||||
* - `birthdate-month`
|
||||
* - `birthdate-year`
|
||||
* - `cc-csc`
|
||||
* - `cc-exp`
|
||||
* - `cc-exp-day`
|
||||
* - `cc-exp-month`
|
||||
* - `cc-exp-year`
|
||||
* - `gender`
|
||||
* - `name-family`
|
||||
* - `name-given`
|
||||
@@ -532,6 +550,11 @@ export type Props = $ReadOnly<{|
|
||||
| 'cc-exp-month'
|
||||
| 'cc-exp-year'
|
||||
| 'cc-number'
|
||||
| 'cc-name'
|
||||
| 'cc-given-name'
|
||||
| 'cc-middle-name'
|
||||
| 'cc-family-name'
|
||||
| 'cc-type'
|
||||
| 'country'
|
||||
| 'current-password'
|
||||
| 'email'
|
||||
@@ -1572,7 +1595,20 @@ const autoCompleteWebToAutoCompleteAndroidMap = {
|
||||
const autoCompleteWebToTextContentTypeMap = {
|
||||
'address-line1': 'streetAddressLine1',
|
||||
'address-line2': 'streetAddressLine2',
|
||||
bday: 'birthdate',
|
||||
'bday-day': 'birthdateDay',
|
||||
'bday-month': 'birthdateMonth',
|
||||
'bday-year': 'birthdateYear',
|
||||
'cc-csc': 'creditCardSecurityCode',
|
||||
'cc-exp-month': 'creditCardExpirationMonth',
|
||||
'cc-exp-year': 'creditCardExpirationYear',
|
||||
'cc-exp': 'creditCardExpiration',
|
||||
'cc-given-name': 'creditCardGivenName',
|
||||
'cc-additional-name': 'creditCardMiddleName',
|
||||
'cc-family-name': 'creditCardFamilyName',
|
||||
'cc-name': 'creditCardName',
|
||||
'cc-number': 'creditCardNumber',
|
||||
'cc-type': 'creditCardType',
|
||||
'current-password': 'password',
|
||||
country: 'countryName',
|
||||
email: 'emailAddress',
|
||||
|
||||
@@ -235,7 +235,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
static NSDictionary<NSString *, NSString *> *contentTypeMap;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
contentTypeMap = @{
|
||||
NSDictionary<NSString *, NSString *> *mutableContentTypeMap = @{
|
||||
@"none" : @"",
|
||||
@"URL" : UITextContentTypeURL,
|
||||
@"addressCity" : UITextContentTypeAddressCity,
|
||||
@@ -265,6 +265,28 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
||||
@"newPassword" : UITextContentTypeNewPassword,
|
||||
@"oneTimeCode" : UITextContentTypeOneTimeCode,
|
||||
};
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
|
||||
if (@available(iOS 17.0, *)) {
|
||||
mutableContentTypeMap = [[mutableContentTypeMap mutableCopy] addEntriesFromDictionary:@{
|
||||
@"creditCardExpiration" : UITextContentTypeCreditCardExpiration,
|
||||
@"creditCardExpirationMonth" : UITextContentTypeCreditCardExpirationMonth,
|
||||
@"creditCardExpirationYear" : UITextContentTypeCreditCardExpirationYear,
|
||||
@"creditCardSecurityCode" : UITextContentTypeCreditCardSecurityCode,
|
||||
@"creditCardType" : UITextContentTypeCreditCardType,
|
||||
@"creditCardName" : UITextContentTypeCreditCardName,
|
||||
@"creditCardGivenName" : UITextContentTypeCreditCardGivenName,
|
||||
@"creditCardMiddleName" : UITextContentTypeCreditCardMiddleName,
|
||||
@"creditCardFamilyName" : UITextContentTypeCreditCardFamilyName,
|
||||
@"birthdate" : UITextContentTypeBirthdate,
|
||||
@"birthdateDay" : UITextContentTypeBirthdateDay,
|
||||
@"birthdateMonth" : UITextContentTypeBirthdateMonth,
|
||||
@"birthdateYear" : UITextContentTypeBirthdateYear,
|
||||
}];
|
||||
}
|
||||
#endif
|
||||
|
||||
contentTypeMap = mutableContentTypeMap;
|
||||
});
|
||||
|
||||
// Setting textContentType to an empty string will disable any
|
||||
|
||||
+23
-1
@@ -181,7 +181,7 @@ UITextContentType RCTUITextContentTypeFromString(std::string const &contentType)
|
||||
static NSDictionary<NSString *, NSString *> *contentTypeMap;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
contentTypeMap = @{
|
||||
NSDictionary<NSString *, NSString *> *mutableContentTypeMap = @{
|
||||
@"" : @"",
|
||||
@"none" : @"",
|
||||
@"URL" : UITextContentTypeURL,
|
||||
@@ -212,6 +212,28 @@ UITextContentType RCTUITextContentTypeFromString(std::string const &contentType)
|
||||
@"newPassword" : UITextContentTypeNewPassword,
|
||||
@"oneTimeCode" : UITextContentTypeOneTimeCode,
|
||||
};
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
|
||||
if (@available(iOS 17.0, *)) {
|
||||
mutableContentTypeMap = [[mutableContentTypeMap mutableCopy] addEntriesFromDictionary:@{
|
||||
@"creditCardExpiration" : UITextContentTypeCreditCardExpiration,
|
||||
@"creditCardExpirationMonth" : UITextContentTypeCreditCardExpirationMonth,
|
||||
@"creditCardExpirationYear" : UITextContentTypeCreditCardExpirationYear,
|
||||
@"creditCardSecurityCode" : UITextContentTypeCreditCardSecurityCode,
|
||||
@"creditCardType" : UITextContentTypeCreditCardType,
|
||||
@"creditCardName" : UITextContentTypeCreditCardName,
|
||||
@"creditCardGivenName" : UITextContentTypeCreditCardGivenName,
|
||||
@"creditCardMiddleName" : UITextContentTypeCreditCardMiddleName,
|
||||
@"creditCardFamilyName" : UITextContentTypeCreditCardFamilyName,
|
||||
@"birthdate" : UITextContentTypeBirthdate,
|
||||
@"birthdateDay" : UITextContentTypeBirthdateDay,
|
||||
@"birthdateMonth" : UITextContentTypeBirthdateMonth,
|
||||
@"birthdateYear" : UITextContentTypeBirthdateYear,
|
||||
}];
|
||||
}
|
||||
#endif
|
||||
|
||||
contentTypeMap = mutableContentTypeMap;
|
||||
});
|
||||
|
||||
return contentTypeMap[RCTNSStringFromString(contentType)] ?: @"";
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"deprecated-react-native-prop-types": "4.1.0",
|
||||
"deprecated-react-native-prop-types": "4.2.0",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"flow-enums-runtime": "^0.0.6",
|
||||
"invariant": "^2.2.4",
|
||||
|
||||
@@ -807,6 +807,12 @@ exports.examples = ([
|
||||
<WithLabel label="one-time-code">
|
||||
<TextInput autoComplete="one-time-code" style={styles.default} />
|
||||
</WithLabel>
|
||||
<WithLabel label="birthdate-full">
|
||||
<TextInput autoComplete="birthdate-full" style={styles.default} />
|
||||
</WithLabel>
|
||||
<WithLabel label="cc-name">
|
||||
<TextInput autoComplete="cc-name" style={styles.default} />
|
||||
</WithLabel>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
@@ -829,6 +835,15 @@ exports.examples = ([
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="creditCardExpiration">
|
||||
<TextInput
|
||||
textContentType="creditCardExpiration"
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="birthdate">
|
||||
<TextInput textContentType="birthdate" style={styles.default} />
|
||||
</WithLabel>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -4133,10 +4133,10 @@ depd@~1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||
|
||||
deprecated-react-native-prop-types@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.1.0.tgz#8ed03a64c21b7fbdd2d000957b6838d4f38d2c66"
|
||||
integrity sha512-WfepZHmRbbdTvhcolb8aOKEvQdcmTMn5tKLbqbXmkBvjFjRVWAYqsXk/DBsV8TZxws8SdGHLuHaJrHSQUPRdfw==
|
||||
deprecated-react-native-prop-types@4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-4.2.0.tgz#2d7f2a2bb3cf39fb873286a85eb04bc3e1f2e4d5"
|
||||
integrity sha512-DjFQDPM2osEm9CEjxMSjAIGFf6D9kXiPZ8+EhHf4oU0PK2KNktp0Rv1kobdbOS0B9kQQ9QpqmmZQuZN7lI3P5g==
|
||||
dependencies:
|
||||
"@react-native/normalize-colors" "*"
|
||||
invariant "*"
|
||||
|
||||
Reference in New Issue
Block a user