diff --git a/packages/react-native-web/src/exports/TextInput/__tests__/index-test.js b/packages/react-native-web/src/exports/TextInput/__tests__/index-test.js
index f8d2c3f6..1f3ab24a 100644
--- a/packages/react-native-web/src/exports/TextInput/__tests__/index-test.js
+++ b/packages/react-native-web/src/exports/TextInput/__tests__/index-test.js
@@ -42,6 +42,7 @@ function createKeyboardEvent(
ctrlKey = false,
isComposing = false,
key = '',
+ keyCode = 0,
metaKey = false,
preventDefault = () => {},
shiftKey = false
@@ -52,6 +53,7 @@ function createKeyboardEvent(
ctrlKey,
isComposing,
key,
+ keyCode,
metaKey,
preventDefault,
shiftKey
@@ -271,14 +273,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'ArrowLeft',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -293,14 +295,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'Backspace',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -315,14 +317,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'Enter',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -337,14 +339,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'Escape',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -359,14 +361,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: ' ',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -381,14 +383,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'Tab',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -403,14 +405,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: false,
ctrlKey: false,
key: 'a',
metaKey: false,
shiftKey: false,
target: expect.anything()
- }
+ })
})
);
});
@@ -433,14 +435,14 @@ describe('components/TextInput', () => {
expect(onKeyPress).toHaveBeenCalledTimes(1);
expect(onKeyPress).toBeCalledWith(
expect.objectContaining({
- nativeEvent: {
+ nativeEvent: expect.objectContaining({
altKey: true,
ctrlKey: true,
key: ' ',
metaKey: true,
shiftKey: true,
target: expect.anything()
- }
+ })
})
);
});
@@ -500,6 +502,17 @@ describe('components/TextInput', () => {
}
});
+ test('single-line input while composing', () => {
+ const onSubmitEditing = jest.fn();
+ const { container } = render(
+
+ );
+ const input = findInput(container);
+ input.dispatchEvent(keydown({ key: 'Enter', isComposing: true, keyCode: 13 }));
+ input.dispatchEvent(keydown({ key: 'Enter', isComposing: false, keyCode: 229 }));
+ expect(onSubmitEditing).not.toHaveBeenCalled();
+ });
+
test('multi-line input', () => {
const onSubmitEditing = jest.fn();
const { container } = render(
@@ -567,17 +580,15 @@ describe('components/TextInput', () => {
test('set cursor location', () => {
const cursorLocation = { start: 3, end: 3 };
const { container: defaultContainer } = render();
- const { container: customContainer } = render(
-
- );
-
const inputDefaultSelection = findInput(defaultContainer);
- const inputCustomSelection = findInput(customContainer);
-
// default selection is 0
expect(inputDefaultSelection.selectionStart).toEqual(0);
expect(inputDefaultSelection.selectionEnd).toEqual(0);
+ const { container: customContainer } = render(
+
+ );
+ const inputCustomSelection = findInput(customContainer);
// custom selection sets cursor at custom position
expect(inputCustomSelection.selectionStart).toEqual(cursorLocation.start);
expect(inputCustomSelection.selectionEnd).toEqual(cursorLocation.end);
diff --git a/packages/react-native-web/src/exports/TextInput/index.js b/packages/react-native-web/src/exports/TextInput/index.js
index 13f46a48..4e1a8f6f 100644
--- a/packages/react-native-web/src/exports/TextInput/index.js
+++ b/packages/react-native-web/src/exports/TextInput/index.js
@@ -104,6 +104,12 @@ const forwardPropsList = {
const pickProps = props => pick(props, forwardPropsList);
+// If an Input Method Editor is processing key input, the 'keyCode' is 229.
+// https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
+function isEventComposing(nativeEvent) {
+ return nativeEvent.isComposing || nativeEvent.keyCode === 229;
+}
+
const TextInput = forwardRef((props, forwardedRef) => {
const {
autoCapitalize = 'sentences',
@@ -267,31 +273,27 @@ const TextInput = forwardRef((props, forwardedRef) => {
const blurOnSubmitDefault = !multiline;
const shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
- if (onKeyPress) {
- const keyValue = e.key;
+ const nativeEvent = e.nativeEvent;
+ const isComposing = isEventComposing(nativeEvent);
- if (keyValue) {
- e.nativeEvent = {
- altKey: e.altKey,
- ctrlKey: e.ctrlKey,
- key: keyValue,
- metaKey: e.metaKey,
- shiftKey: e.shiftKey,
- target: e.target
- };
- onKeyPress(e);
- }
+ if (onKeyPress) {
+ onKeyPress(e);
}
- if (!e.isDefaultPrevented() && e.key === 'Enter' && !e.shiftKey) {
+ if (
+ e.key === 'Enter' &&
+ !e.shiftKey &&
+ // Do not call submit if composition is occuring.
+ !isComposing &&
+ !e.isDefaultPrevented()
+ ) {
if ((blurOnSubmit || !multiline) && onSubmitEditing) {
- // prevent "Enter" from inserting a newline
+ // prevent "Enter" from inserting a newline or submitting a form
e.preventDefault();
- e.nativeEvent = { target: e.target, text: e.target.value };
+ nativeEvent.text = e.target.value;
onSubmitEditing(e);
}
if (shouldBlurOnSubmit && hostRef.current != null) {
- // $FlowFixMe
hostRef.current.blur();
}
}