@@ -12,6 +12,8 @@ import type {HostInstance} from '../../../src/private/types/HostInstance';
1212import type { ____TextStyle_Internal as TextStyleInternal } from '../../StyleSheet/StyleSheetTypes' ;
1313import type {
1414 GestureResponderEvent ,
15+ KeyEvent ,
16+ HandledKeyEvent ,
1517 NativeSyntheticEvent ,
1618 ScrollEvent ,
1719} from '../../Types/CoreEventTypes' ;
@@ -1134,6 +1136,34 @@ export type TextInputProps = $ReadOnly<{
11341136 * unwanted edits without flicker.
11351137 */
11361138 value ?: ?Stringish ,
1139+
1140+ // [macOS
1141+ /**
1142+ * An array of key events that should be handled by the TextInput.
1143+ * When a key event matches one of these specifications, event propagation will be stopped.
1144+ * @platform macos
1145+ */
1146+ keyDownEvents ?: ?$ReadOnlyArray < HandledKeyEvent > ,
1147+
1148+ /**
1149+ * An array of key events that should be handled by the TextInput.
1150+ * When a key event matches one of these specifications, event propagation will be stopped.
1151+ * @platform macos
1152+ */
1153+ keyUpEvents ?: ?$ReadOnlyArray < HandledKeyEvent > ,
1154+
1155+ /**
1156+ * Callback that is called when a key is pressed down.
1157+ * @platform macos
1158+ */
1159+ onKeyDown ?: ?( e : KeyEvent ) => mixed ,
1160+
1161+ /**
1162+ * Callback that is called when a key is released.
1163+ * @platform macos
1164+ */
1165+ onKeyUp ?: ?( e : KeyEvent ) => mixed ,
1166+ // macOS]
11371167} > ;
11381168
11391169type ViewCommands = $NonMaybeType <
@@ -1640,6 +1670,42 @@ function InternalTextInput(props: TextInputProps): React.Node {
16401670 props . onScroll && props . onScroll ( event ) ;
16411671 } ;
16421672
1673+ const _keyDown = ( event : KeyEvent ) => {
1674+ if ( props . keyDownEvents && event . isPropagationStopped ( ) !== true ) {
1675+ const isHandled = props . keyDownEvents . some ( ( { key, metaKey, ctrlKey, altKey, shiftKey} : HandledKeyEvent ) => {
1676+ return (
1677+ event . nativeEvent . key === key &&
1678+ ( metaKey ?? event . nativeEvent . metaKey ) === event . nativeEvent . metaKey &&
1679+ ( ctrlKey ?? event . nativeEvent . ctrlKey ) === event . nativeEvent . ctrlKey &&
1680+ ( altKey ?? event . nativeEvent . altKey ) === event . nativeEvent . altKey &&
1681+ ( shiftKey ?? event . nativeEvent . shiftKey ) === event . nativeEvent . shiftKey
1682+ ) ;
1683+ } ) ;
1684+ if ( isHandled ) {
1685+ event . stopPropagation ( ) ;
1686+ }
1687+ }
1688+ props . onKeyDown && props . onKeyDown ( event ) ;
1689+ } ;
1690+
1691+ const _keyUp = ( event : KeyEvent ) => {
1692+ if ( props . keyUpEvents && event . isPropagationStopped ( ) !== true ) {
1693+ const isHandled = props . keyUpEvents . some ( ( { key, metaKey, ctrlKey, altKey, shiftKey} : HandledKeyEvent ) => {
1694+ return (
1695+ event . nativeEvent . key === key &&
1696+ ( metaKey ?? event . nativeEvent . metaKey ) === event . nativeEvent . metaKey &&
1697+ ( ctrlKey ?? event . nativeEvent . ctrlKey ) === event . nativeEvent . ctrlKey &&
1698+ ( altKey ?? event . nativeEvent . altKey ) === event . nativeEvent . altKey &&
1699+ ( shiftKey ?? event . nativeEvent . shiftKey ) === event . nativeEvent . shiftKey
1700+ ) ;
1701+ } ) ;
1702+ if ( isHandled ) {
1703+ event . stopPropagation ( ) ;
1704+ }
1705+ }
1706+ props . onKeyUp && props . onKeyUp ( event ) ;
1707+ } ;
1708+
16431709 let textInput = null ;
16441710
16451711 const multiline = props . multiline ?? false ;
@@ -1795,8 +1861,8 @@ function InternalTextInput(props: TextInputProps): React.Node {
17951861 onChange = { _onChange }
17961862 onContentSizeChange = { props . onContentSizeChange }
17971863 onFocus = { _onFocus }
1798- onKeyDown = { props . onKeyDown } // [macOS]
1799- onKeyUp = { props . onKeyUp } // [macOS]
1864+ onKeyDown = { _keyDown } // [macOS]
1865+ onKeyUp = { _keyUp } // [macOS]
18001866 onScroll = { _onScroll }
18011867 onSelectionChange = { _onSelectionChange }
18021868 onSelectionChangeShouldSetResponder = { emptyFunctionThatReturnsTrue }
0 commit comments