[change] Support W3C props on TextInput

* Add support for 'enterKeyHint' prop.
* Add support for 'inputMode' prop.
* Add support for 'readOnly' prop.
* Add support for 'rows' prop.
* Deprecate 'keyboardType' prop.
* Deprecate 'returnKeyType' prop.
* Deprecate 'editable' prop.
* Deprecate 'numberOfLines' prop.

Ref #2379
This commit is contained in:
Nicolas Gallagher
2022-11-07 14:49:58 -08:00
committed by Nicolas Gallagher
parent 67d52a43a9
commit 42bf402929
3 changed files with 157 additions and 44 deletions
@@ -160,6 +160,62 @@ describe('components/TextInput', () => {
});
});
describe('prop "inputMode"', () => {
test('value "decimal"', () => {
const { container } = render(<TextInput inputMode="decimal" />);
const input = findInput(container);
expect(input.inputMode).toEqual('decimal');
});
test('value "email"', () => {
const { container } = render(<TextInput inputMode="email" />);
const input = findInput(container);
expect(input.inputMode).toEqual('email');
expect(input.type).toEqual('email');
});
test('default value', () => {
const { container } = render(<TextInput inputMode="none" />);
const input = findInput(container);
expect(input.inputMode).toEqual('none');
expect(input.type).toEqual('text');
});
test('value "numeric"', () => {
const { container } = render(<TextInput inputMode="numeric" />);
const input = findInput(container);
expect(input.inputMode).toEqual('numeric');
});
test('value "search"', () => {
const { container } = render(<TextInput inputMode="search" />);
const input = findInput(container);
expect(input.inputMode).toEqual('search');
expect(input.type).toEqual('search');
});
test('value "tel"', () => {
const { container } = render(<TextInput inputMode="tel" />);
const input = findInput(container);
expect(input.inputMode).toEqual('tel');
expect(input.type).toEqual('tel');
});
test('value "text"', () => {
const { container } = render(<TextInput inputMode="text" />);
const input = findInput(container);
expect(input.inputMode).toEqual('text');
expect(input.type).toEqual('text');
});
test('value "url"', () => {
const { container } = render(<TextInput inputMode="url" />);
const input = findInput(container);
expect(input.inputMode).toEqual('url');
expect(input.type).toEqual('url');
});
});
describe('prop "keyboardType"', () => {
test('default value', () => {
const { container } = render(<TextInput keyboardType="default" />);
+60 -23
View File
@@ -23,6 +23,7 @@ import useResponderEvents from '../../modules/useResponderEvents';
import { getLocaleDirection, useLocaleContext } from '../../modules/useLocale';
import StyleSheet from '../StyleSheet';
import TextInputState from '../../modules/TextInputState';
import { warnOnce } from '../../modules/warnOnce';
/**
* Determines whether a 'selection' prop differs from a node's existing
@@ -101,6 +102,8 @@ const TextInput: React.AbstractComponent<
clearTextOnFocus,
dir,
editable = true,
enterKeyHint,
inputMode,
keyboardType = 'default',
multiline = false,
numberOfLines = 1,
@@ -130,7 +133,9 @@ const TextInput: React.AbstractComponent<
onStartShouldSetResponderCapture,
onSubmitEditing,
placeholderTextColor,
readOnly,
returnKeyType,
rows,
secureTextEntry = false,
selection,
selectTextOnFocus,
@@ -138,31 +143,47 @@ const TextInput: React.AbstractComponent<
} = props;
let type;
let inputMode;
let _inputMode;
switch (keyboardType) {
case 'email-address':
if (inputMode != null) {
_inputMode = inputMode;
if (inputMode === 'email') {
type = 'email';
break;
case 'number-pad':
case 'numeric':
inputMode = 'numeric';
break;
case 'decimal-pad':
inputMode = 'decimal';
break;
case 'phone-pad':
} else if (inputMode === 'tel') {
type = 'tel';
break;
case 'search':
case 'web-search':
} else if (inputMode === 'search') {
type = 'search';
break;
case 'url':
} else if (inputMode === 'url') {
type = 'url';
break;
default:
} else {
type = 'text';
}
} else if (keyboardType != null) {
warnOnce('keyboardType', 'keyboardType is deprecated. Use inputMode.');
switch (keyboardType) {
case 'email-address':
type = 'email';
break;
case 'number-pad':
case 'numeric':
_inputMode = 'numeric';
break;
case 'decimal-pad':
_inputMode = 'decimal';
break;
case 'phone-pad':
type = 'tel';
break;
case 'search':
case 'web-search':
type = 'search';
break;
case 'url':
type = 'url';
break;
default:
type = 'text';
}
}
if (secureTextEntry) {
@@ -355,15 +376,31 @@ const TextInput: React.AbstractComponent<
supportedProps.autoCorrect = autoCorrect ? 'on' : 'off';
// 'auto' by default allows browsers to infer writing direction
supportedProps.dir = dir !== undefined ? dir : 'auto';
supportedProps.enterKeyHint = returnKeyType;
supportedProps.inputMode = inputMode;
if (returnKeyType != null) {
warnOnce('returnKeyType', 'returnKeyType is deprecated. Use enterKeyHint.');
}
supportedProps.enterKeyHint = enterKeyHint || returnKeyType;
supportedProps.inputMode = _inputMode;
supportedProps.onBlur = handleBlur;
supportedProps.onChange = handleChange;
supportedProps.onFocus = handleFocus;
supportedProps.onKeyDown = handleKeyDown;
supportedProps.onSelect = handleSelectionChange;
supportedProps.readOnly = !editable;
supportedProps.rows = multiline ? numberOfLines : undefined;
if (editable != null) {
warnOnce('editable', 'editable is deprecated. Use readOnly.');
}
supportedProps.readOnly = readOnly || !editable;
if (numberOfLines != null) {
warnOnce(
'numberOfLines',
'TextInput numberOfLines is deprecated. Use rows.'
);
}
supportedProps.rows = multiline
? rows != null
? rows
: numberOfLines
: undefined;
supportedProps.spellCheck = spellCheck != null ? spellCheck : autoCorrect;
supportedProps.style = [
{ '--placeholderTextColor': placeholderTextColor },
+41 -21
View File
@@ -29,21 +29,26 @@ export type TextInputProps = {
defaultValue?: ?string,
dir?: ?('auto' | 'ltr' | 'rtl'),
disabled?: ?boolean,
editable?: ?boolean,
inputAccessoryViewID?: ?string,
keyboardType?:
| 'default'
| 'email-address'
| 'number-pad'
| 'numbers-and-punctuation'
| 'numeric'
| 'phone-pad'
enterKeyHint?:
| 'enter'
| 'done'
| 'go'
| 'next'
| 'previous'
| 'search'
| 'url'
| 'web-search',
| 'send',
inputAccessoryViewID?: ?string,
inputMode?:
| 'decimal'
| 'email'
| 'none'
| 'numeric'
| 'search'
| 'tel'
| 'text'
| 'url',
maxLength?: ?number,
multiline?: ?boolean,
numberOfLines?: ?number,
onChange?: (e: any) => void,
onChangeText?: (e: string) => void,
onContentSizeChange?: (e: any) => void,
@@ -54,14 +59,8 @@ export type TextInputProps = {
onSubmitEditing?: (e: any) => void,
placeholder?: ?string,
placeholderTextColor?: ?ColorValue,
returnKeyType?:
| 'enter'
| 'done'
| 'go'
| 'next'
| 'previous'
| 'search'
| 'send',
readOnly?: ?boolean,
rows?: ?number,
secureTextEntry?: ?boolean,
selectTextOnFocus?: ?boolean,
selection?: {|
@@ -71,5 +70,26 @@ export type TextInputProps = {
selectionColor?: ?ColorValue,
spellCheck?: ?boolean,
style?: ?GenericStyleProp<TextInputStyle>,
value?: ?string
value?: ?string,
// deprecated
editable?: ?boolean,
keyboardType?:
| 'default'
| 'email-address'
| 'number-pad'
| 'numbers-and-punctuation'
| 'numeric'
| 'phone-pad'
| 'search'
| 'url'
| 'web-search',
numberOfLines?: ?number,
returnKeyType?:
| 'enter'
| 'done'
| 'go'
| 'next'
| 'previous'
| 'search'
| 'send'
};