Skip to content

Support textBreakStrategy and justificationMode for Selectable Facsimile TextView#55660

Closed
NickGerleman wants to merge 6 commits intofacebook:mainfrom
NickGerleman:export-D93933310
Closed

Support textBreakStrategy and justificationMode for Selectable Facsimile TextView#55660
NickGerleman wants to merge 6 commits intofacebook:mainfrom
NickGerleman:export-D93933310

Conversation

@NickGerleman
Copy link
Copy Markdown
Contributor

Summary:
getReactTextUpdateFromPreparedLayout() hardcoded textBreakStrategy to
BREAK_STRATEGY_HIGH_QUALITY and justificationMode to 0, causing
user-specified values like textBreakStrategy: "simple" or
textAlign: "justify" to be ignored when the PreparedLayout code path
is used via ReferenceStateWrapper.

This change surfaces the textBreakStrategy and justificationMode
values already computed in TextLayoutManager.createLayout() by:

  • Introducing a CreateLayoutResult wrapper to return them alongside the Layout
  • Adding both fields to PreparedLayout
  • Propagating them through FabricUIManager.reusePreparedLayoutWithNewReactTags()
  • Using the real values in ReactTextViewManager.getReactTextUpdateFromPreparedLayout()

Changelog: [Internal]

Differential Revision: D93933310

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Feb 20, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync bot commented Feb 20, 2026

@NickGerleman has exported this pull request. If you are a Meta employee, you can view the originating Diff in D93933310.

NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 23, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Differential Revision: D93933310
NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 23, 2026
…ile TextView (facebook#55660)

Summary:
Pull Request resolved: facebook#55660

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Differential Revision: D93933310
NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 25, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
@github-actions
Copy link
Copy Markdown

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 25, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 25, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
NickGerleman and others added 5 commits February 25, 2026 19:57
Summary:
Extract ParagraphComponentDescriptor logic into a template base class BaseParagraphComponentDescriptor<ShadowNodeT> so that other paragraph-like component descriptors can reuse the same TextLayoutManager wiring. Remove `final` from ParagraphShadowNode to allow subclassing. Move TextLayoutManagerKey from extern linkage in .cpp to constexpr in the new header.

This is a pure refactor with no behavioral change.

Changelog:
[Internal]

Differential Revision: D93829402
Summary:
Add the native components needed to route selectable text through ReactTextView instead of PreparedLayoutTextView when enablePreparedTextLayout is on.

C++ side: Add SelectableParagraphShadowNode (inherits ParagraphShadowNode) and SelectableParagraphComponentDescriptor (inherits BaseParagraphComponentDescriptor). Register in CoreComponentsRegistry and componentNameByReactViewName.

Android side: Make ReactTextViewManager open so it can be subclassed. Add getReactTextUpdateFromPreparedLayout to handle ReferenceStateWrapper holding PreparedLayout. Create SelectableTextViewManager (extends ReactTextViewManager, registered as RCTSelectableText). Add FabricNameComponentMapping entry for SelectableParagraph -> RCTSelectableText.

No JS code references RCTSelectableText yet, so the new components are inert.

Changelog:
[Internal]

Differential Revision: D93829400
Differential Revision: D93829403
Summary:
Wire up the JS side to use the new SelectableTextViewManager native component. When enablePreparedTextLayout() is on, NativeSelectableText resolves to RCTSelectableText, routing selectable text through ReactTextView instead of PreparedLayoutTextView. When the flag is off, NativeSelectableText falls back to NativeText, so behavior is identical to before.

Refactor NativePressableText and NativePressableVirtualText from arrow function component expressions to component declarations (PressableText and PressableVirtualText). PressableText now accepts a selectable prop to choose between NativeSelectableText and NativeText.

Add a check(!isSelectable) guard in PreparedLayoutTextViewManager.setSelectable since selectable text now routes to SelectableTextViewManager instead.

Changelog:
[Internal]

Differential Revision: D93829401
… testing/a11y for selectable Text in Facsimile) (facebook#55559)

Summary:
Pull Request resolved: facebook#55559

When enablePreparedTextLayout is true, we may reuse layouts (including backing `Spannable`), even when ShadowNode generation changes. React tags are subject to change during this period, so we have an extra layer of indirection, that users of `PreparedLayout` based state currently have to deal with.

This adds that logic so that hit testing, a11y delegate, and spans against FragmentIndex, all work in the scenario of ReactTextView with Facsimile state, used for selectable text.

Changelog: [Internal]

Differential Revision: D93346617

Reviewed By: mdvacca
NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 26, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
@NickGerleman NickGerleman force-pushed the export-D93933310 branch 2 times, most recently from b543462 to 3110bac Compare February 26, 2026 04:00
NickGerleman added a commit to NickGerleman/react-native that referenced this pull request Feb 26, 2026
…ile TextView (facebook#55660)

Summary:

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
…ile TextView (facebook#55660)

Summary:
Pull Request resolved: facebook#55660

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310
@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Feb 26, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync bot commented Feb 26, 2026

This pull request has been merged in 8bf035d.

zoontek pushed a commit to zoontek/react-native that referenced this pull request Mar 9, 2026
…ile TextView (facebook#55660)

Summary:
Pull Request resolved: facebook#55660

`getReactTextUpdateFromPreparedLayout()` hardcoded `textBreakStrategy` to
`BREAK_STRATEGY_HIGH_QUALITY` and `justificationMode` to `0`, causing
user-specified values like `textBreakStrategy: "simple"` or
`textAlign: "justify"` to be ignored when the PreparedLayout code path
is used via `ReferenceStateWrapper`.

This change surfaces the `textBreakStrategy` and `justificationMode`
values already computed in `TextLayoutManager.createLayout()` by:
- Introducing a `CreateLayoutResult` wrapper to return them alongside the `Layout`
- Adding both fields to `PreparedLayout`
- Propagating them through `FabricUIManager.reusePreparedLayoutWithNewReactTags()`
- Using the real values in `ReactTextViewManager.getReactTextUpdateFromPreparedLayout()`

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D93933310

fbshipit-source-id: 2667d76cb45b99c938290c68b00d675e56c203eb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants