Skip to content

Commit

Permalink
Add onPress prop (facebook#39701)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#39701

TextInput already uses Pressability, but doesn't expose the onPress prop. Link:https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Components/TextInput/TextInput.js#L1381-L1414.

Currently TextInput only exposes the onPressIn() and onPressOut() props from Pressability. While onPressOut() can serve the same purpose as onPress() in most cases, it doesn't fare well with PanResponder...say a swipe gesture implemented using PanResponder.

When the pointer/cursor exits the hit test bounds of TextInput, onPressOut() will be triggered even though the desired behavior could be that we only want to invoke the event handler when the user lifts their finger from the screen (while still in the hit test bounds of the TextInput).

Example of TextInput in a PanResponder:
https://snack.expo.dev/jambalaya/panresponder

Changelog: [General][Added] Add onPress prop to TextInput

Reviewed By: NickGerleman

Differential Revision: D49653011

fbshipit-source-id: 28477416c6c0f17a0737986cab49e51a55094ba7
  • Loading branch information
James Maxell Eroy authored and facebook-github-bot committed Sep 28, 2023
1 parent b138a4f commit 8e36cc0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,11 @@ export interface TextInputProps
| ((e: NativeSyntheticEvent<TextInputEndEditingEventData>) => void)
| undefined;

/**
* Called when a single tap gesture is detected.
*/
onPress?: ((e: NativeSyntheticEvent<NativeTouchEvent>) => void) | undefined;

/**
* Callback that is called when a touch is engaged.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,11 @@ export type Props = $ReadOnly<{|
*/
unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed,

/**
* Called when a single tap gesture is detected.
*/
onPress?: ?(event: PressEvent) => mixed,

/**
* Called when a touch is engaged.
*/
Expand Down
37 changes: 26 additions & 11 deletions packages/react-native/Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,11 @@ export type Props = $ReadOnly<{|
*/
unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed,

/**
* Called when a single tap gesture is detected.
*/
onPress?: ?(event: PressEvent) => mixed,

/**
* Called when a touch is engaged.
*/
Expand Down Expand Up @@ -1378,27 +1383,37 @@ function InternalTextInput(props: Props): React.Node {
const accessible = props.accessible !== false;
const focusable = props.focusable !== false;

const {
editable,
hitSlop,
onPress,
onPressIn,
onPressOut,
rejectResponderTermination,
} = props;

const config = React.useMemo(
() => ({
hitSlop: props.hitSlop,
hitSlop,
onPress: (event: PressEvent) => {
if (props.editable !== false) {
onPress?.(event);
if (editable !== false) {
if (inputRef.current != null) {
inputRef.current.focus();
}
}
},
onPressIn: props.onPressIn,
onPressOut: props.onPressOut,
cancelable:
Platform.OS === 'ios' ? !props.rejectResponderTermination : null,
onPressIn: onPressIn,
onPressOut: onPressOut,
cancelable: Platform.OS === 'ios' ? !rejectResponderTermination : null,
}),
[
props.editable,
props.hitSlop,
props.onPressIn,
props.onPressOut,
props.rejectResponderTermination,
editable,
hitSlop,
onPress,
onPressIn,
onPressOut,
rejectResponderTermination,
],
);

Expand Down

0 comments on commit 8e36cc0

Please sign in to comment.