Repository navigation
Conversation
|
Warning JavaScript API change detected This PR commits an update to
This change was flagged as: |
|
/review |
🤖 AI code reviewDecision: Ready for human review Overall PR risk: Medium. The change modifies existing behavior in the Android Text measurement and rendering path, with blast radius limited to Android Text and direct revert. No critical or warning findings remain. The most plausible break is measured height and drawn lines differing if view state and layout config differ.
No findings. This review is advisory — it never blocks a merge and never auto-approves. |
|
@javache has imported this pull request. If you are a Meta employee, you can view this in D124966798. |
|
Can we align naming here with iOS and call this |
|
Even better, align the style names and values with CSS wherever possible and document as android-only for now. |
Android 13 (API 33) added LineBreakConfig, which selects the strictness of the line-breaking rules (CSS `line-break`: loose, normal, strict) and phrase-based breaking for Japanese (CSS `word-break: auto-phrase`). React Native measures and draws Text with a StaticLayout it builds itself, so neither setting can be reached from outside: a native module could only change the drawn TextView, which would then disagree with the height Yoga measured. Add two Android-only paragraph props, plumbed the same way as android_hyphenationFrequency: - android_lineBreakStyle: 'none' | 'loose' | 'normal' | 'strict' - android_lineBreakWordStyle: 'none' | 'phrase' They go into ParagraphAttributes and the paragraph MapBuffer, are applied to the StaticLayout.Builder in TextLayoutManager (measurement and the prepared layout), and to ReactTextView through @ReactProp setters (drawing). Both are ignored below API 33. When both are 'none' (the default) no LineBreakConfig is set, so existing text lays out exactly as before. TextInput is left out: it does not list the props in its view config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerate the Frameworks C++ API snapshots (Common, Android, Apple) for the new LineBreakStyle and LineBreakWordStyle enums, their conversions, the ParagraphAttributes fields and the paragraph MapBuffer keys. Generated with `yarn cxx-api-build` using Doxygen 1.16.1, the version the validation workflow pins. Document that android_lineBreakWordStyle="phrase" depends on the locale: Android Text is laid out in the device locale, and where that locale has no phrase-based breaking the setting has no effect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Per review, align the props with CSS `line-break` and `word-break`
instead of Android's LineBreakConfig terms, and document them as
Android-only for now:
- android_lineBreakStyle ('none' | 'loose' | 'normal' | 'strict')
-> lineBreak ('auto' | 'loose' | 'normal' | 'strict')
- android_lineBreakWordStyle ('none' | 'phrase')
-> wordBreak ('normal' | 'auto-phrase')
The C++ enums, ParagraphAttributes fields and MapBuffer keys follow
the CSS names. 'auto' and 'normal' still set no LineBreakConfig, so
default layout is unchanged. Regenerate the TypeScript and C++ API
snapshots.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0f0a658 to
c4f4b9e
Compare
lineBreak and wordBreak props to Text on Android
|
@javache Thanks for the review!
I also rebased on |
Summary:
Android 13 (API 33) added
LineBreakConfig, which controls two things CJK text needs and React Native cannot reach today:line-break. Strict kinsoku keeps characters such as small kana (ッ,ャ) andーoff the start of a line.word-break: auto-phrase. Japanese breaks at phrase (文節) boundaries instead of between any two characters, which reads much better in short lines such as buttons and headings.This cannot be done from a library. React Native builds the
StaticLayoutthat both measures text for Yoga and is drawn, insideTextLayoutManager. A native module can only change the drawnTextView, which then disagrees with the measured height (clipped or extra lines). So the setting has to go through React Native's own text pipeline.This PR adds two
Textprops named after the CSS properties, documented as Android-only for now:CSS values with no Android equivalent (
anywhere,keep-all,break-all) are left out for now.TextProps,TextNativeComponentview config,Text.d.ts, regeneratedReactNativeApi.d.ts.LineBreak/WordBreakenums, conversions,ParagraphAttributesfields (equality, hash, debug props),BaseParagraphPropsparsing, Android props diffing, and two new paragraph MapBuffer keys. C++ API snapshots regenerated.TextLayoutManagerapplies the config to theStaticLayout.Builderon API 33+.ReactTextViewManager@ReactPropsetters apply the same values toReactTextView, so drawing matches measurement; recycled views reset them.Behavior is unchanged unless the props are set. With the defaults (
'auto'/'normal') noLineBreakConfigis set at all, and below API 33 the props are ignored. iOS has no equivalent API, so this is Android-only for now.TextInputis intentionally left out to keep the change reviewable.'auto-phrase'depends on locale. Per the Android docs, it has no effect in a locale without phrase-based breaking. AndroidTextis laid out in the device locale, so in practice it takes effect only when that locale supports it (e.g. Japanese). The prop docs say so.Naming follows review feedback: CSS names and values rather than
lineBreakStrategyAndroid, sincelineBreakStrategyIOSandtextBreakStrategycontrol different things.Motivation and design notes: iray-tno/hozo#813
Changelog:
[ANDROID] [ADDED] - Add
lineBreakandwordBreakprops toText(CSSline-break/word-break) for strict/loose line breaking and phrase-based breaking on Android 13+Test Plan:
Ran locally:
yarn flow-check— 0 errorsyarn build-typesthenyarn test-generated-typescript— passesyarn test— 246 suites, 6154 tests passedyarn format-check-{javascript,cpp,kotlin,java}— cleanyarn cxx-api-validate(Doxygen 1.16.1, as in CI) — all 12 snapshots matchAdded:
ParagraphAttributesTest.cpp(equality/hash include the new fields, defaults areAuto/Normal,toStringvalues match the JS prop values).TextLayoutManagerinternals for the new parameters. They pass the default values only, so they cover the plumbing, not the effect ofstrict/auto-phrase.Not run locally: native compilation (Kotlin/Java/C++), the C++ and Robolectric unit tests, and an on-device check. The environment had no Android SDK and Gradle could not resolve its plugins. Relying on CI for the native build and tests.
Still to verify on device, with the RNTester example:
lineBreak(strict/loose) andwordBreak="auto-phrase"change the break positionsTextdoes not keep a previous valueauto-phrasehas no effect, and nothing breaks🤖 Generated with Claude Code