From 1f4e9317e522fe0967f1176b497cdc792eaf02e3 Mon Sep 17 00:00:00 2001 From: Alan Lee Date: Tue, 20 Jan 2026 10:26:26 -0800 Subject: [PATCH] Add selection types to TextInput onChange event (#55043) Summary: This change adds TypeScript/Flow types and RNTester examples for the `selection` data in `TextInput.onChange` event. This is the JS companion to the native changes that add selection data to the onChange event. NOTE:selection only represents the cursor location when returned via onChange as this will not be invoked on a pure selection change without text change. We should also add this note to the documentation. ## Why On the web, text input elements provide `selectionStart` and `selectionEnd` properties that are always accessible during input events. This change exposes the selection data that native now provides, allowing developers to access cursor position during onChange. ## What Changed 1. **Flow Types**: Added optional `selection?: Selection` to `TextInputChangeEventData` 2. **TypeScript Types**: Updated `ReactNativeApi.d.ts` with selection type 3. **RNTester**: Updated examples to display selection in event logs Changelog: [General][Added] - TextInput onChange event types now include optional selection data Reviewed By: cipolleschi, necolas Differential Revision: D90123294 --- .../Libraries/Components/TextInput/TextInput.flow.js | 1 + packages/react-native/ReactNativeApi.d.ts | 9 +++++---- .../js/examples/TextInput/TextInputSharedExamples.js | 9 ++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js index 665a21250d42..50a794ebe3c8 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.flow.js @@ -29,6 +29,7 @@ type TextInputChangeEventData = Readonly<{ eventCount: number, target: number, text: string, + selection?: Selection, }>; export type TextInputChangeEvent = diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index 4a8a22f45831..8793980356c0 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -5304,6 +5304,7 @@ declare type TextInputChangeEvent = NativeSyntheticEvent declare type TextInputChangeEventData = { readonly eventCount: number + readonly selection?: Selection readonly target: number readonly text: string } @@ -6218,15 +6219,15 @@ export { TaskProvider, // 266dedf2 Text, // e55ac2e2 TextContentType, // 239b3ecc - TextInput, // cf7a3331 + TextInput, // 2e89b91d TextInputAndroidProps, // 3f09ce49 - TextInputChangeEvent, // 380cbe93 + TextInputChangeEvent, // 6821f629 TextInputContentSizeChangeEvent, // 5fba3f54 TextInputEndEditingEvent, // 8c22fac3 TextInputFocusEvent, // c36e977c TextInputIOSProps, // 0d05a855 TextInputKeyPressEvent, // 967178c2 - TextInputProps, // a817a7f7 + TextInputProps, // c75f0362 TextInputSelectionChangeEvent, // a1a7622f TextInputSubmitEditingEvent, // 48d903af TextLayoutEvent, // 45b0a8d7 diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 47849ca84052..324c13e31710 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -393,7 +393,14 @@ class TextEventsExample extends React.Component<{...}, $FlowFixMe> { onFocus={() => this.updateText('onFocus')} onBlur={() => this.updateText('onBlur')} onChange={event => - this.updateText('onChange text: ' + event.nativeEvent.text) + this.updateText( + 'onChange text: ' + + event.nativeEvent.text + + ', selection: ' + + (event.nativeEvent.selection != null + ? JSON.stringify(event.nativeEvent.selection) + : 'undefined'), + ) } onContentSizeChange={event => this.updateText(