Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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
index e36195f..3a3ae72 100644
--- 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
@@ -21,6 +21,7 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
autoCapitalize = 'sentences',
autoCorrect = true,
blurOnSubmit = false,
+ submitBehavior,
caretHidden,
clearTextOnFocus,
dir = 'auto',
@@ -359,8 +360,19 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
handleOnChangeText(e);
return;
}
- const blurOnSubmitDefault = !multiline;
- const shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
+ let shouldBlurOnSubmit;
+ let shouldSubmit;
+ if (submitBehavior != null) {
+ // submitBehavior takes precedence over blurOnSubmit
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
+ } else {
+ // Fallback to blurOnSubmit logic for backwards compatibility
+ const blurOnSubmitDefault = !multiline;
+ shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
+ shouldSubmit = blurOnSubmit || !multiline;
+ }
const nativeEvent = e.nativeEvent;
const isComposing = isEventComposing(nativeEvent);
const event = e;
@@ -373,18 +385,19 @@ const MarkdownTextInput = /*#__PURE__*/React.forwardRef(({
!isComposing && !e.isDefaultPrevented()) {
// prevent "Enter" from inserting a newline or submitting a form
e.preventDefault();
- if (!e.shiftKey && (blurOnSubmit || !multiline) && onSubmitEditing) {
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
+ if (!e.shiftKey && shouldSubmit && onSubmitEditing) {
onSubmitEditing(event);
- } else if (multiline) {
+ } else if (multiline && (!shouldSubmit || e.shiftKey)) {
// We need to change normal behavior of "Enter" key to insert a line breaks, to prevent wrapping contentEditable text in <div> tags.
// 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.
insertText(e, '\n');
}
- if (!e.shiftKey && (shouldBlurOnSubmit && hostNode !== null || !multiline)) {
+ if (!e.shiftKey && shouldBlurOnSubmit && hostNode !== null) {
setTimeout(() => divRef.current && divRef.current.blur(), 0);
}
}
- }, [multiline, blurOnSubmit, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText]);
+ }, [multiline, blurOnSubmit, submitBehavior, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText]);
const handleFocus = useCallback(event => {
hasJustBeenFocused.current = true;
const e = event;
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
index fa3283d..59f02c6 100644
--- a/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx
+++ b/node_modules/@expensify/react-native-live-markdown/src/MarkdownTextInput.web.tsx
@@ -87,6 +87,7 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
autoCapitalize = 'sentences',
autoCorrect = true,
blurOnSubmit = false,
+ submitBehavior,
caretHidden,
clearTextOnFocus,
dir = 'auto',
@@ -518,8 +519,20 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
return;
}

- const blurOnSubmitDefault = !multiline;
- const shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
+ let shouldBlurOnSubmit: boolean;
+ let shouldSubmit: boolean;
+
+ if (submitBehavior != null) {
+ // submitBehavior takes precedence over blurOnSubmit
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
+ } else {
+ // Fallback to blurOnSubmit logic for backwards compatibility
+ const blurOnSubmitDefault = !multiline;
+ shouldBlurOnSubmit = blurOnSubmit === null ? blurOnSubmitDefault : blurOnSubmit;
+ shouldSubmit = blurOnSubmit || !multiline;
+ }

const nativeEvent = e.nativeEvent;
const isComposing = isEventComposing(nativeEvent);
@@ -538,19 +551,20 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
) {
// prevent "Enter" from inserting a newline or submitting a form
e.preventDefault();
- if (!e.shiftKey && (blurOnSubmit || !multiline) && onSubmitEditing) {
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
+ if (!e.shiftKey && shouldSubmit && onSubmitEditing) {
onSubmitEditing(event as unknown as NativeSyntheticEvent<TextInputSubmitEditingEventData>);
- } else if (multiline) {
+ } else if (multiline && (!shouldSubmit || e.shiftKey)) {
// We need to change normal behavior of "Enter" key to insert a line breaks, to prevent wrapping contentEditable text in <div> tags.
// 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.
insertText(e, '\n');
}
- if (!e.shiftKey && ((shouldBlurOnSubmit && hostNode !== null) || !multiline)) {
+ if (!e.shiftKey && shouldBlurOnSubmit && hostNode !== null) {
setTimeout(() => divRef.current && divRef.current.blur(), 0);
}
}
},
- [multiline, blurOnSubmit, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText],
+ [multiline, blurOnSubmit, submitBehavior, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText],
);

const handleFocus: FocusEventHandler<HTMLDivElement> = useCallback(
18 changes: 18 additions & 0 deletions patches/@expensify/react-native-live-markdown/details.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# # `react-native-live-markdown` patches

### [@expensify+react-native-live-markdown+0.1.317.patch](@expensify+react-native-live-markdown+0.1.317.patch)

- Reason:
```
Adds support for the `submitBehavior` prop in MarkdownTextInput component for web.
React Native deprecated `blurOnSubmit` in favor of `submitBehavior` (React Native 0.73+),
but @expensify/react-native-live-markdown's MarkdownTextInput on web doesn't natively
support this prop. This patch implements the web equivalent behavior, mapping
`submitBehavior` values ('submit', 'blurAndSubmit', 'newline') to the appropriate
keyboard handling logic in handleKeyPress while maintaining backwards compatibility with
the deprecated `blurOnSubmit` prop. This aligns MarkdownTextInput with React Native's
TextInput API and react-native-web's TextInput implementation.
```
- Upstream PR/issue: https://github.com/Expensify/react-native-live-markdown/issues/744
- E/App issue: https://github.com/Expensify/App/issues/73782
- PR introducing patch: https://github.com/Expensify/App/pull/76332
17 changes: 16 additions & 1 deletion patches/react-native-web/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,19 @@

- Upstream PR/issue: This was a patch on top of patches 008 and 009 of react-native-web.
- E/App issue: https://github.com/Expensify/App/issues/66821
- PR introducing patch: https://github.com/Expensify/App/pull/69820
- PR introducing patch: https://github.com/Expensify/App/pull/69820

### [react-native-web+0.21.2+012+submitBehavior-support.patch](react-native-web+0.21.2+012+submitBehavior-support.patch)

- Reason:
```
Adds support for the `submitBehavior` prop in TextInput component for web.
React Native deprecated `blurOnSubmit` in favor of `submitBehavior` (React Native 0.73+),
but React Native Web doesn't natively support this prop. This patch implements the web
equivalent behavior, mapping `submitBehavior` values ('submit', 'blurAndSubmit', 'newline')
to the appropriate keyboard handling logic while maintaining backwards compatibility with
the deprecated `blurOnSubmit` prop.
```
- Upstream PR/issue: https://github.com/necolas/react-native-web/issues/2817
- E/App issue: https://github.com/Expensify/App/issues/73782
- PR introducing patch: https://github.com/Expensify/App/pull/76332
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
diff --git a/node_modules/react-native-web/dist/exports/TextInput/index.js b/node_modules/react-native-web/dist/exports/TextInput/index.js
index 0f476a7..51555b5 100644
--- a/node_modules/react-native-web/dist/exports/TextInput/index.js
+++ b/node_modules/react-native-web/dist/exports/TextInput/index.js
@@ -84,6 +89,7 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
_props$autoCorrect = props.autoCorrect,
autoCorrect = _props$autoCorrect === void 0 ? true : _props$autoCorrect,
blurOnSubmit = props.blurOnSubmit,
+ submitBehavior = props.submitBehavior,
caretHidden = props.caretHidden,
clearTextOnFocus = props.clearTextOnFocus,
dir = props.dir,
@@ -271,8 +277,19 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
var hostNode = e.target;
// Prevent key events bubbling (see #612)
e.stopPropagation();
- var blurOnSubmitDefault = !multiline;
- var shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
+ // Support submitBehavior prop (React Native 0.73+), fallback to blurOnSubmit for backwards compatibility
+ var shouldBlurOnSubmit;
+ var shouldSubmit;
+ if (submitBehavior != null) {
+ // submitBehavior takes precedence over blurOnSubmit
+ shouldSubmit = submitBehavior === 'submit' || submitBehavior === 'blurAndSubmit';
+ shouldBlurOnSubmit = submitBehavior === 'blurAndSubmit';
+ } else {
+ // Fallback to blurOnSubmit logic for backwards compatibility
+ var blurOnSubmitDefault = !multiline;
+ shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
+ shouldSubmit = blurOnSubmit || !multiline;
+ }
var nativeEvent = e.nativeEvent;
var isComposing = isEventComposing(nativeEvent);
if (onKeyPress) {
@@ -281,7 +298,8 @@ var TextInput = /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
if (e.key === 'Enter' && !e.shiftKey &&
// Do not call submit if composition is occuring.
!isComposing && !e.isDefaultPrevented()) {
- if ((blurOnSubmit || !multiline) && onSubmitEditing) {
+ // submitBehavior === 'newline' means don't submit, just insert newline (default behavior)
+ if (shouldSubmit && onSubmitEditing) {
// prevent "Enter" from inserting a newline or submitting a form
e.preventDefault();
nativeEvent.text = e.target.value;
13 changes: 7 additions & 6 deletions src/components/Form/InputWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {ComponentPropsWithoutRef, ComponentType, ForwardedRef} from 'react';
import React, {useContext} from 'react';
import type {SubmitBehavior} from 'react-native';
import type {AnimatedTextInputRef} from '@components/RNTextInput';
import RoomNameInput from '@components/RoomNameInput';
import type RoomNameInputProps from '@components/RoomNameInput/types';
Expand All @@ -17,15 +18,15 @@ const textInputBasedComponents: TextInputBasedComponents = new Set([TextInput, R
type ComputedComponentSpecificRegistrationParams = {
shouldSubmitForm: boolean;
shouldSetTouchedOnBlurOnly: boolean;
blurOnSubmit: boolean | undefined;
submitBehavior?: SubmitBehavior;
};

function computeComponentSpecificRegistrationParams({
InputComponent,
shouldSubmitForm,
multiline,
autoGrowHeight,
blurOnSubmit,
submitBehavior,
}: InputComponentBaseProps): ComputedComponentSpecificRegistrationParams {
if (textInputBasedComponents.has(InputComponent)) {
const isEffectivelyMultiline = !!multiline || !!autoGrowHeight;
Expand All @@ -46,15 +47,15 @@ function computeComponentSpecificRegistrationParams({
// calling some methods too early or twice, so we had to add this check to prevent that side effect.
// For now this side effect happened only in `TextInput` components.
shouldSetTouchedOnBlurOnly: true,
blurOnSubmit: (isEffectivelyMultiline && shouldReallySubmitForm) || blurOnSubmit,
submitBehavior: isEffectivelyMultiline && shouldReallySubmitForm ? 'blurAndSubmit' : submitBehavior,
shouldSubmitForm: shouldReallySubmitForm,
};
}

return {
shouldSetTouchedOnBlurOnly: false,
// Forward the originally provided value
blurOnSubmit,
submitBehavior,
shouldSubmitForm: !!shouldSubmitForm,
};
}
Expand All @@ -80,9 +81,9 @@ function InputWrapper<TInput extends ValidInputs, TValue extends ValueTypeKey>({
const {InputComponent, inputID, valueType = 'string', shouldSubmitForm: propShouldSubmitForm, ...rest} = props as InputComponentBaseProps;
const {registerInput} = useContext(FormContext);

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

return (
<InputComponent
Expand Down
4 changes: 2 additions & 2 deletions src/components/Form/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {ComponentType, FocusEvent, Key, ReactNode, Ref, RefObject} from 'react';
import type {GestureResponderEvent, StyleProp, TextInputSubmitEditingEvent, ViewStyle} from 'react-native';
import type {GestureResponderEvent, StyleProp, SubmitBehavior, TextInputSubmitEditingEvent, ViewStyle} from 'react-native';
import type {ValueOf} from 'type-fest';
import type AddPlaidBankAccount from '@components/AddPlaidBankAccount';
import type AddressSearch from '@components/AddressSearch';
Expand Down Expand Up @@ -121,7 +121,7 @@ type InputComponentBaseProps<TValue extends ValueTypeKey = ValueTypeKey> = Input
ref?: Ref<unknown>;
multiline?: boolean;
autoGrowHeight?: boolean;
blurOnSubmit?: boolean;
submitBehavior?: SubmitBehavior;
shouldSubmitForm?: boolean;
uncontrolled?: boolean;
};
Expand Down
6 changes: 3 additions & 3 deletions src/pages/signin/LoginForm/BaseLoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import type LoginFormProps from './types';

type BaseLoginFormProps = WithToggleVisibilityViewProps & LoginFormProps;

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

useEffect(() => {
if (blurOnSubmit) {
if (submitBehavior === 'blurAndSubmit') {
input.current?.blur();
}

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

useImperativeHandle(ref, () => ({
isInputFocused() {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/signin/LoginForm/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type {ForwardedRef} from 'react';
import type {SubmitBehavior} from 'react-native';

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

/** Should we dismiss the keyboard when transitioning away from the page? */
blurOnSubmit?: boolean;
submitBehavior?: SubmitBehavior;

/** Whether the content is visible. */
isVisible: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/signin/SignInPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ function SignInPage({ref}: SignInPageProps) {
<LoginForm
ref={loginFormRef}
isVisible={shouldShowLoginForm}
blurOnSubmit={isAccountValidated === false}
submitBehavior={isAccountValidated === false ? 'blurAndSubmit' : 'submit'}
// eslint-disable-next-line react-compiler/react-compiler
scrollPageToTop={signInPageLayoutRef.current?.scrollPageToTop}
/>
Expand Down
Loading