Skip to content

Commit 5827fec

Browse files
authored
Merge pull request #76332 from daledah/follow-up-74150
Migrate deprecated blurOnSubmit to submitBehavior
2 parents d1f9b2d + 0978da4 commit 5827fec

9 files changed

Lines changed: 211 additions & 14 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
diff --git a/node_modules/@expensify/react-native-live-markdown/lib/module/MarkdownTextInput.web.js b/node_modules/@expensify/react-native-live-markdown/lib/module/MarkdownTextInput.web.js
2+
index e36195f..3a3ae72 100644
3+
--- a/node_modules/@expensify/react-native-live-markdown/lib/module/MarkdownTextInput.web.js
4+
+++ b/node_modules/@expensify/react-native-live-markdown/lib/module/MarkdownTextInput.web.js
5+
@@ -21,6 +21,7 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
6+
autoCapitalize = 'sentences',
7+
autoCorrect = true,
8+
blurOnSubmit = false,
9+
+ submitBehavior,
10+
caretHidden,
11+
clearTextOnFocus,
12+
dir = 'auto',
13+
@@ -359,8 +360,19 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
14+
handleOnChangeText(e);
15+
return;
16+
}
17+
- const blurOnSubmitDefault = !multiline;
18+
- const shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
19+
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
20+
+ let shouldBlurOnSubmit;
21+
+ let shouldSubmit;
22+
+ if (submitBehavior != null) {
23+
+ // submitBehavior takes precedence over blurOnSubmit
24+
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
25+
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
26+
+ } else {
27+
+ // Fallback to blurOnSubmit logic for backwards compatibility
28+
+ const blurOnSubmitDefault = !multiline;
29+
+ shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
30+
+ shouldSubmit = blurOnSubmit || !multiline;
31+
+ }
32+
const nativeEvent = e.nativeEvent;
33+
const isComposing = isEventComposing(nativeEvent);
34+
const event = e;
35+
@@ -373,18 +385,19 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
36+
!isComposing && !e.isDefaultPrevented()) {
37+
// prevent "Enter" from inserting a newline or submitting a form
38+
e.preventDefault();
39+
- if (!e.shiftKey && (blurOnSubmit || !multiline) && onSubmitEditing) {
40+
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
41+
+ if (!e.shiftKey && shouldSubmit && onSubmitEditing) {
42+
onSubmitEditing(event);
43+
- } else if (multiline) {
44+
+ } else if (multiline && (!shouldSubmit || e.shiftKey)) {
45+
// We need to change normal behavior of "Enter" key to insert a line breaks, to prevent wrapping contentEditable text in <div> tags.
46+
// Thanks to that in every situation we have proper amount of new lines in our parsed text. Without it pressing enter in empty lines will add 2 more new lines.
47+
insertText(e, '\n');
48+
}
49+
- if (!e.shiftKey && (shouldBlurOnSubmit && hostNode !== null || !multiline)) {
50+
+ if (!e.shiftKey && shouldBlurOnSubmit && hostNode !== null) {
51+
setTimeout(() => divRef.current && divRef.current.blur(), 0);
52+
}
53+
}
54+
- }, [multiline, blurOnSubmit, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText]);
55+
+ }, [multiline, blurOnSubmit, submitBehavior, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText]);
56+
const handleFocus = useCallback(event => {
57+
hasJustBeenFocused.current = true;
58+
const e = event;
59+
diff --git a/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx b/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx
60+
index fa3283d..59f02c6 100644
61+
--- a/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx
62+
+++ b/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx
63+
@@ -87,6 +87,7 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
64+
autoCapitalize = 'sentences',
65+
autoCorrect = true,
66+
blurOnSubmit = false,
67+
+ submitBehavior,
68+
caretHidden,
69+
clearTextOnFocus,
70+
dir = 'auto',
71+
@@ -518,8 +519,20 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
72+
return;
73+
}
74+
75+
- const blurOnSubmitDefault = !multiline;
76+
- const shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
77+
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
78+
+ let shouldBlurOnSubmit: boolean;
79+
+ let shouldSubmit: boolean;
80+
+
81+
+ if (submitBehavior != null) {
82+
+ // submitBehavior takes precedence over blurOnSubmit
83+
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
84+
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
85+
+ } else {
86+
+ // Fallback to blurOnSubmit logic for backwards compatibility
87+
+ const blurOnSubmitDefault = !multiline;
88+
+ shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
89+
+ shouldSubmit = blurOnSubmit || !multiline;
90+
+ }
91+
92+
const nativeEvent = e.nativeEvent;
93+
const isComposing = isEventComposing(nativeEvent);
94+
@@ -538,19 +551,20 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
95+
) {
96+
// prevent "Enter" from inserting a newline or submitting a form
97+
e.preventDefault();
98+
- if (!e.shiftKey && (blurOnSubmit || !multiline) && onSubmitEditing) {
99+
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
100+
+ if (!e.shiftKey && shouldSubmit && onSubmitEditing) {
101+
onSubmitEditing(event as unknown as NativeSyntheticEvent<TextInputSubmitEditingEventData>);
102+
- } else if (multiline) {
103+
+ } else if (multiline && (!shouldSubmit || e.shiftKey)) {
104+
// We need to change normal behavior of "Enter" key to insert a line breaks, to prevent wrapping contentEditable text in <div> tags.
105+
// Thanks to that in every situation we have proper amount of new lines in our parsed text. Without it pressing enter in empty lines will add 2 more new lines.
106+
insertText(e, '\n');
107+
}
108+
- if (!e.shiftKey && ((shouldBlurOnSubmit && hostNode !== null) || !multiline)) {
109+
+ if (!e.shiftKey && shouldBlurOnSubmit && hostNode !== null) {
110+
setTimeout(() => divRef.current && divRef.current.blur(), 0);
111+
}
112+
}
113+
},
114+
- [multiline, blurOnSubmit, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText],
115+
+ [multiline, blurOnSubmit, submitBehavior, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText],
116+
);
117+
118+
const handleFocus: FocusEventHandler<HTMLDivElement> = useCallback(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# # `react-native-live-markdown` patches
2+
3+
### [@expensify+react-native-live-markdown+0.1.317.patch](@expensify+react-native-live-markdown+0.1.317.patch)
4+
5+
- Reason:
6+
```
7+
Adds support for the `submitBehavior` prop in MarkdownTextInput component for web.
8+
React Native deprecated `blurOnSubmit` in favor of `submitBehavior` (React Native 0.73+),
9+
but @expensify/react-native-live-markdown's MarkdownTextInput on web doesn't natively
10+
support this prop. This patch implements the web equivalent behavior, mapping
11+
`submitBehavior` values ('submit', 'blurAndSubmit', 'newline') to the appropriate
12+
keyboard handling logic in handleKeyPress while maintaining backwards compatibility with
13+
the deprecated `blurOnSubmit` prop. This aligns MarkdownTextInput with React Native's
14+
TextInput API and react-native-web's TextInput implementation.
15+
```
16+
- Upstream PR/issue: https://github.com/Expensify/react-native-live-markdown/issues/744
17+
- E/App issue: https://github.com/Expensify/App/issues/73782
18+
- PR introducing patch: https://github.com/Expensify/App/pull/76332

patches/react-native-web/details.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,19 @@
130130
131131
- Upstream PR/issue: This was a patch on top of patches 008 and 009 of react-native-web.
132132
- E/App issue: https://github.com/Expensify/App/issues/66821
133-
- PR introducing patch: https://github.com/Expensify/App/pull/69820
133+
- PR introducing patch: https://github.com/Expensify/App/pull/69820
134+
135+
### [react-native-web+0.21.2+012+submitBehavior-support.patch](react-native-web+0.21.2+012+submitBehavior-support.patch)
136+
137+
- Reason:
138+
```
139+
Adds support for the `submitBehavior` prop in TextInput component for web.
140+
React Native deprecated `blurOnSubmit` in favor of `submitBehavior` (React Native 0.73+),
141+
but React Native Web doesn't natively support this prop. This patch implements the web
142+
equivalent behavior, mapping `submitBehavior` values ('submit', 'blurAndSubmit', 'newline')
143+
to the appropriate keyboard handling logic while maintaining backwards compatibility with
144+
the deprecated `blurOnSubmit` prop.
145+
```
146+
- Upstream PR/issue: https://github.com/necolas/react-native-web/issues/2817
147+
- E/App issue: https://github.com/Expensify/App/issues/73782
148+
- PR introducing patch: https://github.com/Expensify/App/pull/76332
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
diff --git a/node_modules/react-native-web/dist/exports/TextInput/index.js b/node_modules/react-native-web/dist/exports/TextInput/index.js
2+
index 0f476a7..51555b5 100644
3+
--- a/node_modules/react-native-web/dist/exports/TextInput/index.js
4+
+++ b/node_modules/react-native-web/dist/exports/TextInput/index.js
5+
@@ -84,6 +89,7 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
6+
_props$autoCorrect = props.autoCorrect,
7+
autoCorrect = _props$autoCorrect === void 0 ? true : _props$autoCorrect,
8+
blurOnSubmit = props.blurOnSubmit,
9+
+ submitBehavior = props.submitBehavior,
10+
caretHidden = props.caretHidden,
11+
clearTextOnFocus = props.clearTextOnFocus,
12+
dir = props.dir,
13+
@@ -271,8 +277,19 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
14+
var hostNode = e.target;
15+
// Prevent key events bubbling (see #612)
16+
e.stopPropagation();
17+
- var blurOnSubmitDefault = !multiline;
18+
- var shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
19+
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
20+
+ var shouldBlurOnSubmit;
21+
+ var shouldSubmit;
22+
+ if (submitBehavior != null) {
23+
+ // submitBehavior takes precedence over blurOnSubmit
24+
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
25+
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
26+
+ } else {
27+
+ // Fallback to blurOnSubmit logic for backwards compatibility
28+
+ var blurOnSubmitDefault = !multiline;
29+
+ shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
30+
+ shouldSubmit = blurOnSubmit || !multiline;
31+
+ }
32+
var nativeEvent = e.nativeEvent;
33+
var isComposing = isEventComposing(nativeEvent);
34+
if (onKeyPress) {
35+
@@ -281,7 +298,8 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
36+
if (e.key === 'Enter' && !e.shiftKey &&
37+
// Do not call submit if composition is occuring.
38+
!isComposing && !e.isDefaultPrevented()) {
39+
- if ((blurOnSubmit || !multiline) && onSubmitEditing) {
40+
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
41+
+ if (shouldSubmit && onSubmitEditing) {
42+
// prevent "Enter" from inserting a newline or submitting a form
43+
e.preventDefault();
44+
nativeEvent.text = e.target.value;

src/components/Form/InputWrapper.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {ComponentPropsWithoutRef, ComponentType, ForwardedRef} from 'react';
22
import React, {useContext} from 'react';
3+
import type {SubmitBehavior} from 'react-native';
34
import type {AnimatedTextInputRef} from '@components/RNTextInput';
45
import RoomNameInput from '@components/RoomNameInput';
56
import type RoomNameInputProps from '@components/RoomNameInput/types';
@@ -17,15 +18,15 @@ const textInputBasedComponents: TextInputBasedComponents = new Set([TextInput, R
1718
type ComputedComponentSpecificRegistrationParams = {
1819
shouldSubmitForm: boolean;
1920
shouldSetTouchedOnBlurOnly: boolean;
20-
blurOnSubmit: boolean | undefined;
21+
submitBehavior?: SubmitBehavior;
2122
};
2223

2324
function computeComponentSpecificRegistrationParams({
2425
InputComponent,
2526
shouldSubmitForm,
2627
multiline,
2728
autoGrowHeight,
28-
blurOnSubmit,
29+
submitBehavior,
2930
}: InputComponentBaseProps): ComputedComponentSpecificRegistrationParams {
3031
if (textInputBasedComponents.has(InputComponent)) {
3132
const isEffectivelyMultiline = !!multiline || !!autoGrowHeight;
@@ -46,15 +47,15 @@ function computeComponentSpecificRegistrationParams({
4647
// calling some methods too early or twice, so we had to add this check to prevent that side effect.
4748
// For now this side effect happened only in `TextInput` components.
4849
shouldSetTouchedOnBlurOnly: true,
49-
blurOnSubmit: (isEffectivelyMultiline && shouldReallySubmitForm) || blurOnSubmit,
50+
submitBehavior: isEffectivelyMultiline && shouldReallySubmitForm ? 'blurAndSubmit' : submitBehavior,
5051
shouldSubmitForm: shouldReallySubmitForm,
5152
};
5253
}
5354

5455
return {
5556
shouldSetTouchedOnBlurOnly: false,
5657
// Forward the originally provided value
57-
blurOnSubmit,
58+
submitBehavior,
5859
shouldSubmitForm: !!shouldSubmitForm,
5960
};
6061
}
@@ -80,9 +81,9 @@ function InputWrapper<TInput extends ValidInputs, TValue extends ValueTypeKey>({
8081
const {InputComponent, inputID, valueType = 'string', shouldSubmitForm: propShouldSubmitForm, ...rest} = props as InputComponentBaseProps;
8182
const {registerInput} = useContext(FormContext);
8283

83-
const {shouldSetTouchedOnBlurOnly, blurOnSubmit, shouldSubmitForm} = computeComponentSpecificRegistrationParams(props as InputComponentBaseProps);
84+
const {shouldSetTouchedOnBlurOnly, submitBehavior, shouldSubmitForm} = computeComponentSpecificRegistrationParams(props as InputComponentBaseProps);
8485
// eslint-disable-next-line react-compiler/react-compiler
85-
const {key, ...registerInputProps} = registerInput(inputID, shouldSubmitForm, {ref, valueType, ...rest, shouldSetTouchedOnBlurOnly, blurOnSubmit});
86+
const {key, ...registerInputProps} = registerInput(inputID, shouldSubmitForm, {ref, valueType, ...rest, shouldSetTouchedOnBlurOnly, submitBehavior});
8687

8788
return (
8889
<InputComponent

src/components/Form/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type {ComponentType, FocusEvent, Key, ReactNode, Ref, RefObject} from 'react';
2-
import type {GestureResponderEvent, StyleProp, TextInputSubmitEditingEvent, ViewStyle} from 'react-native';
2+
import type {GestureResponderEvent, StyleProp, SubmitBehavior, TextInputSubmitEditingEvent, ViewStyle} from 'react-native';
33
import type {ValueOf} from 'type-fest';
44
import type AddPlaidBankAccount from '@components/AddPlaidBankAccount';
55
import type AddressSearch from '@components/AddressSearch';
@@ -121,7 +121,7 @@ type InputComponentBaseProps<TValue extends ValueTypeKey = ValueTypeKey> = Input
121121
ref?: Ref<unknown>;
122122
multiline?: boolean;
123123
autoGrowHeight?: boolean;
124-
blurOnSubmit?: boolean;
124+
submitBehavior?: SubmitBehavior;
125125
shouldSubmitForm?: boolean;
126126
uncontrolled?: boolean;
127127
};

src/pages/signin/LoginForm/BaseLoginForm.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import type LoginFormProps from './types';
4040

4141
type BaseLoginFormProps = WithToggleVisibilityViewProps & LoginFormProps;
4242

43-
function BaseLoginForm({blurOnSubmit = false, isVisible, ref}: BaseLoginFormProps) {
43+
function BaseLoginForm({submitBehavior = 'submit', isVisible, ref}: BaseLoginFormProps) {
4444
const {login, setLogin} = useLogin();
4545
const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: true});
4646
const [closeAccount] = useOnyx(ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM, {canBeMissing: true});
@@ -175,7 +175,7 @@ function BaseLoginForm({blurOnSubmit = false, isVisible, ref}: BaseLoginFormProp
175175
}, [account?.isLoading]);
176176

177177
useEffect(() => {
178-
if (blurOnSubmit) {
178+
if (submitBehavior === 'blurAndSubmit') {
179179
input.current?.blur();
180180
}
181181

@@ -184,7 +184,7 @@ function BaseLoginForm({blurOnSubmit = false, isVisible, ref}: BaseLoginFormProp
184184
return;
185185
}
186186
input.current?.focus();
187-
}, [blurOnSubmit, isVisible, prevIsVisible]);
187+
}, [submitBehavior, isVisible, prevIsVisible]);
188188

189189
useImperativeHandle(ref, () => ({
190190
isInputFocused() {

src/pages/signin/LoginForm/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type {ForwardedRef} from 'react';
2+
import type {SubmitBehavior} from 'react-native';
23

34
type LoginFormProps = {
45
/** Function used to scroll to the top of the page */
56
scrollPageToTop?: () => void;
67

78
/** Should we dismiss the keyboard when transitioning away from the page? */
8-
blurOnSubmit?: boolean;
9+
submitBehavior?: SubmitBehavior;
910

1011
/** Whether the content is visible. */
1112
isVisible: boolean;

src/pages/signin/SignInPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ function SignInPage({ref}: SignInPageProps) {
314314
<LoginForm
315315
ref={loginFormRef}
316316
isVisible={shouldShowLoginForm}
317-
blurOnSubmit={isAccountValidated === false}
317+
submitBehavior={isAccountValidated === false ? 'blurAndSubmit' : 'submit'}
318318
// eslint-disable-next-line react-compiler/react-compiler
319319
scrollPageToTop={signInPageLayoutRef.current?.scrollPageToTop}
320320
/>

0 commit comments

Comments
 (0)