Repository navigation
Conversation
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>
|
Warning JavaScript API change detected This PR commits an update to
This change was flagged as: |
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:
Android 13 (API 33) added
LineBreakConfig, which controls two things CJK text needs and React Native cannot reach today:LINE_BREAK_STYLE_LOOSE | NORMAL | STRICT) — CSSline-break. Strict kinsoku keeps characters such as small kana (ッ,ャ) andーoff the start of a line.LINE_BREAK_WORD_STYLE_PHRASE) — CSSword-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 Android-only paragraph props, plumbed exactly like the existing
android_hyphenationFrequency:TextProps,TextNativeComponentview config,Text.d.ts, regeneratedReactNativeApi.d.ts.LineBreakStyle/LineBreakWordStyleenums, 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. When both are
'none'(the default) noLineBreakConfigis set at all, and below API 33 the props are ignored. iOS has no equivalent API, so this is Android-only, likeandroid_hyphenationFrequency.'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.TextInputis intentionally left out to keep the change reviewable.Motivation and design notes: iray-tno/hozo#813
Open question for reviewers — naming. I used the
android_prefix to matchandroid_hyphenationFrequency, the sibling paragraph prop this mirrors.lineBreakStyleAndroid(matchinglineBreakStrategyIOS) is the other option; happy to rename.Changelog:
[ANDROID] [ADDED] - Add
android_lineBreakStyleandandroid_lineBreakWordStyleprops toTextfor 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— 241 suites, 6130 tests passedyarn format-check-{javascript,cpp,kotlin,java}— cleanyarn cxx-api-validate(Doxygen 1.16.1, as in CI) — all 12 snapshots match; before regenerating, the 3*FrameworksCxx.apisnapshots failedAdded:
ParagraphAttributesTest.cpp(equality/hash include the new fields, defaults areNone,toStringvalues match the JS prop values).TextLayoutManagerinternals for the new parameters. They passNONEonly, so they cover the plumbing, not the effect ofstrict/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:
strict/looseandphrasechange the break positionsTextdoes not keep a previous valuephrasehas no effect, and nothing breaks🤖 Generated with Claude Code