Repository navigation
Conversation
…r it (software-mansion#184) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The private registry integration lacks dismissal regression coverage and Android runtime validation.
1 open issue
What changed in this PR
Integrates native EnrichedTextInput with React Native’s focus registry to address #184 without changing web behavior.
Changes:
- Register inputs and synchronize focus, blur, and unmount cleanup.
- Add a compatibility wrapper for the internal
TextInputStatemodule. - Document keyboard dismissal support and remove the previous limitation.
| File | Description |
|---|---|
| src/utils/textInputState.ts | Wraps internal registry exports. |
| src/native/EnrichedTextInput.tsx | Adds registry lifecycle and focus tracking. |
| docs/docs/misc/known-limitations.md | Removes the global blur limitation. |
| docs/docs/api-reference/enriched-text-input.md | Documents native dismissal behavior. |
Review effort: Balanced
Comment on lines
+160
to
+164
| useLayoutEffect(() => { | ||
| const instance = nativeRef.current; | ||
| if (instance == null) return; | ||
|
|
||
| TextInputState.registerInput(instance); |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Fixes #184.
When an
EnrichedTextInputis focused inside aScrollView/FlatList, tapping outside it leaves the input focused and the keyboard up, andKeyboard.dismiss()does nothing. The built-inTextInputblurs in both cases.React Native's tap-to-dismiss is implemented in JS:
ScrollView's responder handlers checkTextInputState, a JS registry of text input host instances, to decide whether a tap should dismiss the keyboard.Keyboard.dismiss()also goes through it. An input that never registers is invisible to that logic, soScrollViewconcludes no text input is focused and does nothing.This PR mirrors what
TextInputdoes, in the same wayreact-native-enriched-markdown#597 already does forEnrichedMarkdownTextInput:focusInput/blurInputfrom the native focus and blur events, so every focus source is tracked (tap,ref.focus(),autoFocus)The registry functions aren't part of the public
TextInput.State, so this uses the same smallutils/textInputState.tswrapper as enriched-markdown: a rawrequireof the internal module that handles both of its export shapes. Other libraries with custom native inputs do the same (see Prior art below). Registering a non-TextInputhost is safe because Fabric command dispatch is name-based, andEnrichedTextInputalready implementsfocusandblurcommands on iOS and Android.It also removes the "No global blur support on mobile" section from known limitations (added in #785), since the limitation no longer applies, and notes the behavior under
onBlurin the API reference.Only the native component changes; web is untouched.
Context
This picks up @exploIF's draft #192, which paused this approach to avoid the deprecated deep import while asking RN to expose
TextInputState. Since then, RN has declined to make it public (react/react-native#50321: "TextInputStateshould remain a private API"), and the internal module still resolves at runtime on RN main. Meanwhile, the libraries below have shipped the same registration. If you'd rather continue in #192, I'm happy to close this one.Prior art
Libraries with custom native text inputs register them in
TextInputStatethe same way:react-native-enriched-markdown: the same fix forEnrichedMarkdownTextInput, PR #597 (issue #577). See thetextInputState.tswrapper, which this PR copies.expo-ui: SwiftUI/Compose text fields join keyboard coordination throughTextInputState, expo/expo#48788 (source).stripe-react-native:CardField/CardFormcallregisterInput,focusInputandblurInput(source).react-native-paste-input: registers and unregisters its native input (source).Test Plan
EnrichedTextInputinside aScrollViewwithkeyboardShouldPersistTaps="handled", with the soft keyboard open (in the iOS Simulator, turn off Connect Hardware Keyboard).onBlurfires and the keyboard is dismissed.'handled'semantics).keyboardShouldPersistTaps(default'never'): the first tap outside only dismisses, the next tap presses (stockTextInputbehavior).Keyboard.dismiss()while the input is focused: it blurs.ScrollViewtap isn't swallowed.With a hardware keyboard there's no soft keyboard to dismiss, so outside taps leave the input focused, matching
TextInput.Verified the same change on iOS (Simulator, RN 0.86, library 1.1.1) in a production app: steps 2 and 4 behave as above. I haven't run it on Android or run the Maestro suite.
yarn typecheck:liband eslint pass.Screenshots / Videos
N/A. The change is a behavior fix with no UI.
Compatibility
Web is not affected (the browser handles focus and blur natively).
Checklist
🤖 Generated with Claude Code