diff --git a/packages/react-native/Libraries/Text/TextNativeComponent.js b/packages/react-native/Libraries/Text/TextNativeComponent.js index 50815d71d91f..5d77cf14fe75 100644 --- a/packages/react-native/Libraries/Text/TextNativeComponent.js +++ b/packages/react-native/Libraries/Text/TextNativeComponent.js @@ -47,6 +47,8 @@ const textViewConfig = { onTextLayout: true, dataDetectorType: true, android_hyphenationFrequency: true, + android_lineBreakStyle: true, + android_lineBreakWordStyle: true, lineBreakStrategyIOS: true, }, directEventTypes: { diff --git a/packages/react-native/Libraries/Text/TextProps.js b/packages/react-native/Libraries/Text/TextProps.js index c8f28ddc4b49..9e4cd29b1116 100644 --- a/packages/react-native/Libraries/Text/TextProps.js +++ b/packages/react-native/Libraries/Text/TextProps.js @@ -149,6 +149,29 @@ type TextBaseProps = Readonly<{ */ android_hyphenationFrequency?: ?('normal' | 'none' | 'full'), + /** + * Sets the strictness of the line-breaking rules, such as which characters + * may start or end a line in Chinese and Japanese text (kinsoku). Matches CSS + * `line-break`. Ignored below Android 13 (API level 33). + * + * @default `'none'` + * @platform android + */ + android_lineBreakStyle?: ?('none' | 'loose' | 'normal' | 'strict'), + + /** + * Sets word-based line breaking. `'phrase'` breaks Japanese text at phrase + * boundaries instead of between any two characters. Matches CSS + * `word-break: auto-phrase`. Ignored below Android 13 (API level 33). + * + * Support depends on the locale, and text is laid out in the device locale: + * where that locale has no phrase-based breaking, `'phrase'` has no effect. + * + * @default `'none'` + * @platform android + */ + android_lineBreakWordStyle?: ?('none' | 'phrase'), + children?: ?React.Node, /** diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 6c76d3a2197f..85346a6d3370 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -6042,6 +6042,8 @@ public class com/facebook/react/views/text/ReactTextView : androidx/appcompat/wi public fun setHyphenationFrequency (I)V public fun setIncludeFontPadding (Z)V public fun setLetterSpacing (F)V + public fun setLineBreakStyle (I)V + public fun setLineBreakWordStyle (I)V public fun setLinkifyMask (I)V public fun setMinimumFontScale (F)V public fun setMinimumFontSize (F)V @@ -6077,6 +6079,8 @@ public class com/facebook/react/views/text/ReactTextViewManager : com/facebook/r public final fun setAccessible (Lcom/facebook/react/views/text/ReactTextView;Z)V public final fun setAdjustFontSizeToFit (Lcom/facebook/react/views/text/ReactTextView;Z)V public final fun setAndroidHyphenationFrequency (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V + public final fun setAndroidLineBreakStyle (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V + public final fun setAndroidLineBreakWordStyle (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V public final fun setBorderColor (Lcom/facebook/react/views/text/ReactTextView;ILjava/lang/Integer;)V public final fun setBorderRadius (Lcom/facebook/react/views/text/ReactTextView;IF)V public final fun setBorderRadius (Lcom/facebook/react/views/text/ReactTextView;ILcom/facebook/react/bridge/Dynamic;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 677eb472660b..aa0eef59b400 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -7,9 +7,11 @@ package com.facebook.react.views.text; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.text.LineBreakConfig; import android.os.Build; import android.text.Layout; import android.text.Spannable; @@ -26,6 +28,7 @@ import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import androidx.appcompat.widget.AppCompatTextView; import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; @@ -194,6 +197,10 @@ private void initView() { } setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE); + setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE); + } updateView(); // call after changing ellipsizeLocation in particular } @@ -246,6 +253,8 @@ protected void onDraw(Canvas canvas) { getIncludeFontPadding(), getBreakStrategy(), getHyphenationFrequency(), + getLineBreakStyleCompat(), + getLineBreakWordStyleCompat(), // always passing ALIGN_NORMAL here should be fine, since this method doesn't depend on // how exactly lines are aligned, just their width Layout.Alignment.ALIGN_NORMAL, @@ -575,6 +584,34 @@ public void setHyphenationFrequency(int hyphenationFrequency) { mShouldAdjustSpannableFontSize = true; } + @Override + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + public void setLineBreakStyle(int lineBreakStyle) { + super.setLineBreakStyle(lineBreakStyle); + mShouldAdjustSpannableFontSize = true; + } + + @Override + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + public void setLineBreakWordStyle(int lineBreakWordStyle) { + super.setLineBreakWordStyle(lineBreakWordStyle); + mShouldAdjustSpannableFontSize = true; + } + + @SuppressLint("InlinedApi") + private int getLineBreakStyleCompat() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + ? getLineBreakStyle() + : LineBreakConfig.LINE_BREAK_STYLE_NONE; + } + + @SuppressLint("InlinedApi") + private int getLineBreakWordStyleCompat() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + ? getLineBreakWordStyle() + : LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE; + } + @Override public void setLetterSpacing(float letterSpacing) { if (Float.isNaN(letterSpacing)) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt index 92d781317a8d..3f36228decfd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt @@ -339,6 +339,20 @@ public constructor( } } + @ReactProp(name = "android_lineBreakStyle") + public fun setAndroidLineBreakStyle(view: ReactTextView, lineBreakStyle: String?) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + view.lineBreakStyle = TextAttributeProps.getLineBreakStyle(lineBreakStyle) + } + } + + @ReactProp(name = "android_lineBreakWordStyle") + public fun setAndroidLineBreakWordStyle(view: ReactTextView, lineBreakWordStyle: String?) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + view.lineBreakWordStyle = TextAttributeProps.getLineBreakWordStyle(lineBreakWordStyle) + } + } + @ReactPropGroup( names = [ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt index 4ebaa5630c09..fdae4da63f66 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.kt @@ -7,6 +7,8 @@ package com.facebook.react.views.text +import android.annotation.SuppressLint +import android.graphics.text.LineBreakConfig import android.os.Build import android.text.Layout import android.text.TextUtils.TruncateAt @@ -608,6 +610,34 @@ public class TextAttributeProps private constructor() { else -> Layout.HYPHENATION_FREQUENCY_FULL } + // The LineBreakConfig constants are inlined at compile time, so reading them is safe below API + // 33. Callers apply the result only on API 33+. + @SuppressLint("InlinedApi") + internal fun getLineBreakStyle(lineBreakStyle: String?): Int = + when (lineBreakStyle) { + null, + "none" -> LineBreakConfig.LINE_BREAK_STYLE_NONE + "loose" -> LineBreakConfig.LINE_BREAK_STYLE_LOOSE + "normal" -> LineBreakConfig.LINE_BREAK_STYLE_NORMAL + "strict" -> LineBreakConfig.LINE_BREAK_STYLE_STRICT + else -> { + FLog.w(ReactConstants.TAG, "Invalid android_lineBreakStyle: $lineBreakStyle") + LineBreakConfig.LINE_BREAK_STYLE_NONE + } + } + + @SuppressLint("InlinedApi") + internal fun getLineBreakWordStyle(lineBreakWordStyle: String?): Int = + when (lineBreakWordStyle) { + null, + "none" -> LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE + "phrase" -> LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE + else -> { + FLog.w(ReactConstants.TAG, "Invalid android_lineBreakWordStyle: $lineBreakWordStyle") + LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE + } + } + public fun getEllipsizeMode(ellipsizeMode: String?): TruncateAt? = when (ellipsizeMode) { "head" -> TruncateAt.START diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt index d9c28ca5fa20..2712612bf8ed 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt @@ -11,6 +11,7 @@ import android.content.res.AssetManager import android.graphics.Color import android.graphics.RectF import android.graphics.Typeface +import android.graphics.text.LineBreakConfig import android.os.Build import android.text.BoringLayout import android.text.Layout @@ -99,6 +100,8 @@ internal object TextLayoutManager { const val PA_KEY_TEXT_ALIGN_VERTICAL: Int = 8 const val PA_KEY_TEXT_WIDTH_MODE: Int = 9 const val PA_KEY_MINIMUM_FONT_SCALE: Int = 10 + const val PA_KEY_LINE_BREAK_STYLE: Int = 11 + const val PA_KEY_LINE_BREAK_WORD_STYLE: Int = 12 private val TAG: String = TextLayoutManager::class.java.simpleName @@ -847,6 +850,8 @@ internal object TextLayoutManager { includeFontPadding: Boolean, textBreakStrategy: Int, hyphenationFrequency: Int, + lineBreakStyle: Int, + lineBreakWordStyle: Int, alignment: Layout.Alignment, justificationMode: Int, ellipsizeMode: TextUtils.TruncateAt?, @@ -893,6 +898,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, ellipsizeMode, @@ -911,6 +918,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, ellipsizeMode, @@ -961,6 +970,8 @@ internal object TextLayoutManager { includeFontPadding: Boolean, textBreakStrategy: Int, hyphenationFrequency: Int, + lineBreakStyle: Int, + lineBreakWordStyle: Int, alignment: Layout.Alignment, justificationMode: Int, ellipsizeMode: TextUtils.TruncateAt?, @@ -988,6 +999,21 @@ internal object TextLayoutManager { builder.setUseLineSpacingFromFallbacks(true) } + // Leave the platform default in place unless a style was requested, so text without these props + // lays out exactly as before. + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + (lineBreakStyle != LineBreakConfig.LINE_BREAK_STYLE_NONE || + lineBreakWordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE) + ) { + builder.setLineBreakConfig( + LineBreakConfig.Builder() + .setLineBreakStyle(lineBreakStyle) + .setLineBreakWordStyle(lineBreakWordStyle) + .build() + ) + } + // Android shifts negative (left-side) start overhang itself. RTL start overhang is on the // right, so createLayout reserves that space in a second pass while preserving the EXACT Yoga // measurement returned to the caller. @@ -1147,6 +1173,18 @@ internal object TextLayoutManager { TextAttributeProps.getHyphenationFrequency( paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY), ) + val lineBreakStyle = + TextAttributeProps.getLineBreakStyle( + if (paragraphAttributes.contains(PA_KEY_LINE_BREAK_STYLE)) + paragraphAttributes.getString(PA_KEY_LINE_BREAK_STYLE) + else null, + ) + val lineBreakWordStyle = + TextAttributeProps.getLineBreakWordStyle( + if (paragraphAttributes.contains(PA_KEY_LINE_BREAK_WORD_STYLE)) + paragraphAttributes.getString(PA_KEY_LINE_BREAK_WORD_STYLE) + else null, + ) val adjustFontSizeToFit = if (paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)) paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) @@ -1189,6 +1227,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, paint, @@ -1204,6 +1244,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, ellipsizeMode, @@ -1227,6 +1269,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, ellipsizeMode, @@ -1349,6 +1393,8 @@ internal object TextLayoutManager { includeFontPadding: Boolean, textBreakStrategy: Int, hyphenationFrequency: Int, + lineBreakStyle: Int, + lineBreakWordStyle: Int, alignment: Layout.Alignment, justificationMode: Int, paint: TextPaint, @@ -1413,6 +1459,8 @@ internal object TextLayoutManager { includeFontPadding, textBreakStrategy, hyphenationFrequency, + lineBreakStyle, + lineBreakWordStyle, alignment, justificationMode, null, diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest.kt index 33e00f0af10c..5d2702725743 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest.kt @@ -8,6 +8,7 @@ package com.facebook.react.views.text import android.annotation.SuppressLint +import android.graphics.text.LineBreakConfig import android.text.BoringLayout import android.text.Layout import android.text.SpannableString @@ -104,6 +105,8 @@ class TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest { java.lang.Boolean.TYPE, java.lang.Integer.TYPE, java.lang.Integer.TYPE, + java.lang.Integer.TYPE, + java.lang.Integer.TYPE, Layout.Alignment::class.java, java.lang.Integer.TYPE, TextUtils.TruncateAt::class.java, @@ -121,6 +124,8 @@ class TextLayoutManagerAbsoluteLayoutWithFractionalPixelTest { /* includeFontPadding = */ false, /* textBreakStrategy = */ Layout.BREAK_STRATEGY_HIGH_QUALITY, /* hyphenationFrequency = */ Layout.HYPHENATION_FREQUENCY_NONE, + /* lineBreakStyle = */ LineBreakConfig.LINE_BREAK_STYLE_NONE, + /* lineBreakWordStyle = */ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, Layout.Alignment.ALIGN_NORMAL, /* justificationMode = */ 0, /* ellipsizeMode = */ null, diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerMinimumFontScaleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerMinimumFontScaleTest.kt index 1fba91156cb6..fe2018802595 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerMinimumFontScaleTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerMinimumFontScaleTest.kt @@ -7,6 +7,7 @@ package com.facebook.react.views.text +import android.graphics.text.LineBreakConfig import android.text.Layout import android.text.SpannableString import android.text.Spanned @@ -123,6 +124,8 @@ class TextLayoutManagerMinimumFontScaleTest { true, Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE, + /* lineBreakStyle = */ LineBreakConfig.LINE_BREAK_STYLE_NONE, + /* lineBreakWordStyle = */ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, Layout.Alignment.ALIGN_NORMAL, 0, newPaint(), @@ -149,6 +152,8 @@ class TextLayoutManagerMinimumFontScaleTest { true, Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE, + /* lineBreakStyle = */ LineBreakConfig.LINE_BREAK_STYLE_NONE, + /* lineBreakWordStyle = */ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, Layout.Alignment.ALIGN_NORMAL, 0, newPaint(), diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerStartOverhangTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerStartOverhangTest.kt index 2f23db9c3047..db1cf120fc0b 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerStartOverhangTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerStartOverhangTest.kt @@ -9,6 +9,7 @@ package com.facebook.react.views.text import android.annotation.SuppressLint import android.graphics.RectF +import android.graphics.text.LineBreakConfig import android.text.BoringLayout import android.text.Layout import android.text.SpannableString @@ -145,6 +146,8 @@ class TextLayoutManagerStartOverhangTest { java.lang.Boolean.TYPE, java.lang.Integer.TYPE, java.lang.Integer.TYPE, + java.lang.Integer.TYPE, + java.lang.Integer.TYPE, Layout.Alignment::class.java, java.lang.Integer.TYPE, TextUtils.TruncateAt::class.java, @@ -162,6 +165,8 @@ class TextLayoutManagerStartOverhangTest { /* includeFontPadding = */ false, /* textBreakStrategy = */ Layout.BREAK_STRATEGY_HIGH_QUALITY, /* hyphenationFrequency = */ Layout.HYPHENATION_FREQUENCY_NONE, + /* lineBreakStyle = */ LineBreakConfig.LINE_BREAK_STYLE_NONE, + /* lineBreakWordStyle = */ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, Layout.Alignment.ALIGN_NORMAL, /* justificationMode = */ 0, /* ellipsizeMode = */ ellipsizeMode, diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp index af4c92f85611..820f9a88413c 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp @@ -23,6 +23,8 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes& rhs) const { adjustsFontSizeToFit, includeFontPadding, android_hyphenationFrequency, + android_lineBreakStyle, + android_lineBreakWordStyle, textAlignVertical) == std::tie( rhs.maximumNumberOfLines, @@ -32,6 +34,8 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes& rhs) const { rhs.adjustsFontSizeToFit, rhs.includeFontPadding, rhs.android_hyphenationFrequency, + rhs.android_lineBreakStyle, + rhs.android_lineBreakWordStyle, rhs.textAlignVertical) && floatEquality(minimumFontSize, rhs.minimumFontSize) && floatEquality(minimumFontScale, rhs.minimumFontScale); @@ -75,6 +79,14 @@ SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { "android_hyphenationFrequency", android_hyphenationFrequency, paragraphAttributes.android_hyphenationFrequency), + debugStringConvertibleItem( + "android_lineBreakStyle", + android_lineBreakStyle, + paragraphAttributes.android_lineBreakStyle), + debugStringConvertibleItem( + "android_lineBreakWordStyle", + android_lineBreakWordStyle, + paragraphAttributes.android_lineBreakWordStyle), debugStringConvertibleItem( "textAlignVertical", textAlignVertical, diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h index a944b9e14ff8..b0593210aec7 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h @@ -68,6 +68,16 @@ class ParagraphAttributes : public DebugStringConvertible { */ HyphenationFrequency android_hyphenationFrequency{}; + /* + * (Android only) Strictness of the line-breaking rules. + */ + LineBreakStyle android_lineBreakStyle{}; + + /* + * (Android only) Word-based line breaking. + */ + LineBreakWordStyle android_lineBreakWordStyle{}; + /* * In case of font size adjustment enabled, defines the minimum font size. * Deprecated in favor of minimumFontScale. @@ -112,6 +122,8 @@ struct hash { attributes.minimumFontSize, attributes.includeFontPadding, attributes.android_hyphenationFrequency, + attributes.android_lineBreakStyle, + attributes.android_lineBreakWordStyle, attributes.minimumFontScale, attributes.textAlignVertical); } diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h index 263d53e9b864..5a0e20918b71 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h @@ -1034,6 +1034,88 @@ inline void fromRawValue(const PropsParserContext &context, const RawValue &valu result = HyphenationFrequency::None; } +inline std::string toString(const LineBreakStyle &lineBreakStyle) +{ + switch (lineBreakStyle) { + case LineBreakStyle::None: + return "none"; + case LineBreakStyle::Loose: + return "loose"; + case LineBreakStyle::Normal: + return "normal"; + case LineBreakStyle::Strict: + return "strict"; + } + + LOG(ERROR) << "Unsupported LineBreakStyle value"; + react_native_expect(false); + return "none"; +} + +inline void fromRawValue(const PropsParserContext &context, const RawValue &value, LineBreakStyle &result) +{ + react_native_expect(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = LineBreakStyle::None; + } else if (string == "loose") { + result = LineBreakStyle::Loose; + } else if (string == "normal") { + result = LineBreakStyle::Normal; + } else if (string == "strict") { + result = LineBreakStyle::Strict; + } else { + // sane default + LOG(ERROR) << "Unsupported LineBreakStyle value: " << string; + react_native_expect(false); + result = LineBreakStyle::None; + } + return; + } + + LOG(ERROR) << "Unsupported LineBreakStyle type"; + react_native_expect(false); + result = LineBreakStyle::None; +} + +inline std::string toString(const LineBreakWordStyle &lineBreakWordStyle) +{ + switch (lineBreakWordStyle) { + case LineBreakWordStyle::None: + return "none"; + case LineBreakWordStyle::Phrase: + return "phrase"; + } + + LOG(ERROR) << "Unsupported LineBreakWordStyle value"; + react_native_expect(false); + return "none"; +} + +inline void fromRawValue(const PropsParserContext &context, const RawValue &value, LineBreakWordStyle &result) +{ + react_native_expect(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = LineBreakWordStyle::None; + } else if (string == "phrase") { + result = LineBreakWordStyle::Phrase; + } else { + // sane default + LOG(ERROR) << "Unsupported LineBreakWordStyle value: " << string; + react_native_expect(false); + result = LineBreakWordStyle::None; + } + return; + } + + LOG(ERROR) << "Unsupported LineBreakWordStyle type"; + react_native_expect(false); + result = LineBreakWordStyle::None; +} + inline ParagraphAttributes convertRawProp( const PropsParserContext &context, const RawProps &rawProps, @@ -1096,6 +1178,18 @@ inline ParagraphAttributes convertRawProp( "android_hyphenationFrequency", sourceParagraphAttributes.android_hyphenationFrequency, defaultParagraphAttributes.android_hyphenationFrequency); + paragraphAttributes.android_lineBreakStyle = convertRawProp( + context, + rawProps, + "android_lineBreakStyle", + sourceParagraphAttributes.android_lineBreakStyle, + defaultParagraphAttributes.android_lineBreakStyle); + paragraphAttributes.android_lineBreakWordStyle = convertRawProp( + context, + rawProps, + "android_lineBreakWordStyle", + sourceParagraphAttributes.android_lineBreakWordStyle, + defaultParagraphAttributes.android_lineBreakWordStyle); paragraphAttributes.textAlignVertical = convertRawProp( context, rawProps, @@ -1190,6 +1284,8 @@ constexpr static MapBuffer::Key PA_KEY_MINIMUM_FONT_SIZE = 6; constexpr static MapBuffer::Key PA_KEY_TEXT_ALIGN_VERTICAL = 8; constexpr static MapBuffer::Key PA_KEY_TEXT_WIDTH_MODE = 9; constexpr static MapBuffer::Key PA_KEY_MINIMUM_FONT_SCALE = 10; +constexpr static MapBuffer::Key PA_KEY_LINE_BREAK_STYLE = 11; +constexpr static MapBuffer::Key PA_KEY_LINE_BREAK_WORD_STYLE = 12; inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { @@ -1201,6 +1297,8 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) builder.putBool(PA_KEY_ADJUST_FONT_SIZE_TO_FIT, paragraphAttributes.adjustsFontSizeToFit); builder.putBool(PA_KEY_INCLUDE_FONT_PADDING, paragraphAttributes.includeFontPadding); builder.putString(PA_KEY_HYPHENATION_FREQUENCY, toString(paragraphAttributes.android_hyphenationFrequency)); + builder.putString(PA_KEY_LINE_BREAK_STYLE, toString(paragraphAttributes.android_lineBreakStyle)); + builder.putString(PA_KEY_LINE_BREAK_WORD_STYLE, toString(paragraphAttributes.android_lineBreakWordStyle)); if (paragraphAttributes.textAlignVertical.has_value()) { builder.putString(PA_KEY_TEXT_ALIGN_VERTICAL, toString(*paragraphAttributes.textAlignVertical)); } diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h index b96661bd4dd4..fb612bf005cc 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h @@ -163,4 +163,24 @@ enum class HyphenationFrequency { Full // Standard amount of hyphenation. }; +/* + * (Android only) Strictness of the line-breaking rules, as CSS `line-break`. + * Values match `android.graphics.text.LineBreakConfig.LINE_BREAK_STYLE_*`. + */ +enum class LineBreakStyle { + None, // The platform's default rules. + Loose, // The least restrictive rules. + Normal, // The most common rules. + Strict // The most restrictive rules. +}; + +/* + * (Android only) Word-based line breaking, as CSS `word-break: auto-phrase`. + * Values match `android.graphics.text.LineBreakConfig.LINE_BREAK_WORD_STYLE_*`. + */ +enum class LineBreakWordStyle { + None, // No word-based line breaking. + Phrase // Break Japanese text at phrase boundaries. +}; + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp index 3478df3f838b..db4a1c17e198 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp @@ -93,4 +93,36 @@ TEST(ParagraphAttributesTest, testAutoTextWidthModeSerializesAsAuto) { EXPECT_EQ(toString(TextWidthMode::Auto), "auto"); } +TEST(ParagraphAttributesTest, testOperatorEqualsIncludesLineBreakStyles) { + ParagraphAttributes defaults{}; + ParagraphAttributes strict{}; + strict.android_lineBreakStyle = LineBreakStyle::Strict; + ParagraphAttributes phrase{}; + phrase.android_lineBreakWordStyle = LineBreakWordStyle::Phrase; + + EXPECT_FALSE(defaults == strict); + EXPECT_FALSE(defaults == phrase); + EXPECT_NE( + std::hash{}(defaults), + std::hash{}(strict)); +} + +TEST(ParagraphAttributesTest, testLineBreakStylesDefaultToNone) { + ParagraphAttributes defaults{}; + + EXPECT_EQ(defaults.android_lineBreakStyle, LineBreakStyle::None); + EXPECT_EQ(defaults.android_lineBreakWordStyle, LineBreakWordStyle::None); +} + +// The Android TextLayoutManager parses these strings, so they must match the +// values accepted from JavaScript. +TEST(ParagraphAttributesTest, testLineBreakStylesSerializeToPropValues) { + EXPECT_EQ(toString(LineBreakStyle::None), "none"); + EXPECT_EQ(toString(LineBreakStyle::Loose), "loose"); + EXPECT_EQ(toString(LineBreakStyle::Normal), "normal"); + EXPECT_EQ(toString(LineBreakStyle::Strict), "strict"); + EXPECT_EQ(toString(LineBreakWordStyle::None), "none"); + EXPECT_EQ(toString(LineBreakWordStyle::Phrase), "phrase"); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp index dbe0ba096cbe..de7bc6e5cb7f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp @@ -116,6 +116,18 @@ void BaseParagraphProps::setProp( paragraphAttributes, android_hyphenationFrequency, "android_hyphenationFrequency"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + android_lineBreakStyle, + "android_lineBreakStyle"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + android_lineBreakWordStyle, + "android_lineBreakWordStyle"); REBUILD_FIELD_SWITCH_CASE( paDefaults, value, diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/HostPlatformParagraphProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/HostPlatformParagraphProps.cpp index 9cba413645c2..e91e700c6377 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/HostPlatformParagraphProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/HostPlatformParagraphProps.cpp @@ -140,6 +140,18 @@ folly::dynamic HostPlatformParagraphProps::getDiffProps( toString(paragraphAttributes.android_hyphenationFrequency); } + if (paragraphAttributes.android_lineBreakStyle != + oldProps->paragraphAttributes.android_lineBreakStyle) { + result["android_lineBreakStyle"] = + toString(paragraphAttributes.android_lineBreakStyle); + } + + if (paragraphAttributes.android_lineBreakWordStyle != + oldProps->paragraphAttributes.android_lineBreakWordStyle) { + result["android_lineBreakWordStyle"] = + toString(paragraphAttributes.android_lineBreakWordStyle); + } + if (paragraphAttributes.textAlignVertical != oldProps->paragraphAttributes.textAlignVertical) { result["textAlignVertical"] = diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index cb67856cb4b3..903c741654ee 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<<2ceaa8e472a53fc667994edb63ccd995>> + * @generated SignedSource<<9a2d069de549e0b4b9879dbd63ab8295>> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -4857,6 +4857,8 @@ declare type Text = typeof Text declare type TextBaseProps = { readonly allowFontScaling?: boolean readonly android_hyphenationFrequency?: "full" | "none" | "normal" + readonly android_lineBreakStyle?: "loose" | "none" | "normal" | "strict" + readonly android_lineBreakWordStyle?: "none" | "phrase" readonly children?: React.ReactNode readonly ellipsizeMode?: "clip" | "head" | "middle" | "tail" readonly id?: string @@ -5779,7 +5781,7 @@ export { AlertOptions, // 8a116d2a AlertType, // 5ab91217 AndroidKeyboardEvent, // e03becc8 - Animated, // ed4648e6 + Animated, // 1b75aea1 AppConfig, // 35c0ca70 AppRegistry, // edec2a30 AppState, // 12012be5 @@ -6013,7 +6015,7 @@ export { TVViewPropsIOS, // 1c612e4e TargetedEvent, // 16e98910 TaskProvider, // 266dedf2 - Text, // 39a4d091 + Text, // 66e53c98 TextContentType, // 239b3ecc TextInput, // 9981d7ab TextInputAndroidProps, // 9ebbc103 @@ -6030,7 +6032,7 @@ export { TextInputSubmitEditingEvent, // e811fdbd TextInstance, // 7c7e2069 TextLayoutEvent, // 1a21e24a - TextProps, // e4fdaaad + TextProps, // 12437236 TextStyle, // 898adfd1 ToastAndroid, // 88a8969a TouchableHighlight, // c5f5b1c2 diff --git a/packages/react-native/types_DEPRECATED/Libraries/Text/Text.d.ts b/packages/react-native/types_DEPRECATED/Libraries/Text/Text.d.ts index 25d8d8abe1ef..ab5221da77d2 100644 --- a/packages/react-native/types_DEPRECATED/Libraries/Text/Text.d.ts +++ b/packages/react-native/types_DEPRECATED/Libraries/Text/Text.d.ts @@ -88,6 +88,19 @@ export interface TextPropsAndroid { * Hyphenation strategy */ android_hyphenationFrequency?: 'normal' | 'none' | 'full' | undefined; + + /** + * Strictness of the line-breaking rules (CSS `line-break`). + * Ignored below Android 13 (API level 33). + */ + android_lineBreakStyle?: 'none' | 'loose' | 'normal' | 'strict' | undefined; + + /** + * Word-based line breaking (CSS `word-break: auto-phrase`). + * Ignored below Android 13 (API level 33). Has no effect where the device + * locale has no phrase-based breaking. + */ + android_lineBreakWordStyle?: 'none' | 'phrase' | undefined; } // https://reactnative.dev/docs/text#props diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js index 39b1c94aa248..c3da1f7f9536 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -595,6 +595,42 @@ function HyphenationExample(props: {}): React.Node { ); } +const LINE_BREAK_SAMPLE = + 'キャッシュをチェックしてショートカットからコンピューターのメモリーをクリーンアップします。'; + +function LineBreakStyleExample(props: {}): React.Node { + // Each paragraph has a background so that a mismatch between the measured + // height and the drawn lines is visible. Requires Android 13 (API 33). + return ( + <> + {(['none', 'loose', 'normal', 'strict'] as const).map(lineBreakStyle => ( + + + android_lineBreakStyle="{lineBreakStyle}" + + + {LINE_BREAK_SAMPLE} + + + ))} + {(['none', 'phrase'] as const).map(lineBreakWordStyle => ( + + + android_lineBreakWordStyle="{lineBreakWordStyle}" + + + {LINE_BREAK_SAMPLE} + + + ))} + + ); +} + function FontWeightExample(props: {}): React.Node { return ( @@ -1447,6 +1483,13 @@ const examples = [ return ; }, }, + { + title: 'Line break style', + name: 'lineBreakStyle', + render(): React.Node { + return ; + }, + }, { title: 'Padding', name: 'padding', @@ -1931,6 +1974,11 @@ const styles = StyleSheet.create({ wrappedText: { maxWidth: 300, }, + lineBreakSample: { + backgroundColor: '#eee', + fontSize: 16, + width: 150, + }, }); module.exports = { diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api index 88cc6107ec19..d0915383047c 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api @@ -411,6 +411,8 @@ static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_ADJUST_ static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_ELLIPSIZE_MODE; static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_HYPHENATION_FREQUENCY; static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_INCLUDE_FONT_PADDING; +static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_LINE_BREAK_STYLE; +static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_LINE_BREAK_WORD_STYLE; static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_MAX_NUMBER_OF_LINES; static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_MINIMUM_FONT_SCALE; static constexpr facebook::react::MapBuffer::Key facebook::react::PA_KEY_MINIMUM_FONT_SIZE; @@ -803,6 +805,8 @@ std::string facebook::react::toString(const facebook::react::ImportantForAccessi std::string facebook::react::toString(const facebook::react::LayoutDirection& layoutDirection); std::string facebook::react::toString(const facebook::react::LineBreakMode& lineBreakMode); std::string facebook::react::toString(const facebook::react::LineBreakStrategy& lineBreakStrategy); +std::string facebook::react::toString(const facebook::react::LineBreakStyle& lineBreakStyle); +std::string facebook::react::toString(const facebook::react::LineBreakWordStyle& lineBreakWordStyle); std::string facebook::react::toString(const facebook::react::Role& role); std::string facebook::react::toString(const facebook::react::ScrollViewSnapToAlignment& value); std::string facebook::react::toString(const facebook::react::SharedColor& value); @@ -899,6 +903,8 @@ void facebook::react::fromRawValue(const facebook::react::PropsParserContext& co void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::HyphenationFrequency& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::ImportantForAccessibility& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStrategy& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStyle& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakWordStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::OutlineStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::PointerEventsMode& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::Role& result); @@ -3149,6 +3155,8 @@ class facebook::react::ParagraphAttributes : public facebook::react::DebugString public facebook::react::Float minimumFontScale; public facebook::react::Float minimumFontSize; public facebook::react::HyphenationFrequency android_hyphenationFrequency; + public facebook::react::LineBreakStyle android_lineBreakStyle; + public facebook::react::LineBreakWordStyle android_lineBreakWordStyle; public facebook::react::TextBreakStrategy textBreakStrategy; public facebook::react::TextWidthMode textWidthMode; public int maximumNumberOfLines; @@ -5146,6 +5154,18 @@ enum facebook::react::LineBreakStrategy : uint8_t { Standard, } +enum facebook::react::LineBreakStyle { + Loose, + None, + Normal, + Strict, +} + +enum facebook::react::LineBreakWordStyle { + None, + Phrase, +} + enum facebook::react::ModalHostViewAnimationType { Fade, None, diff --git a/scripts/cxx-api/api-snapshots/ReactAppleFrameworksCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleFrameworksCxx.api index fa368ff91c6c..edce1e365717 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleFrameworksCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleFrameworksCxx.api @@ -3588,6 +3588,8 @@ std::string facebook::react::toString(const facebook::react::ImportantForAccessi std::string facebook::react::toString(const facebook::react::LayoutDirection& layoutDirection); std::string facebook::react::toString(const facebook::react::LineBreakMode& lineBreakMode); std::string facebook::react::toString(const facebook::react::LineBreakStrategy& lineBreakStrategy); +std::string facebook::react::toString(const facebook::react::LineBreakStyle& lineBreakStyle); +std::string facebook::react::toString(const facebook::react::LineBreakWordStyle& lineBreakWordStyle); std::string facebook::react::toString(const facebook::react::Role& role); std::string facebook::react::toString(const facebook::react::ScrollViewSnapToAlignment& value); std::string facebook::react::toString(const facebook::react::SharedColor& value); @@ -3684,6 +3686,8 @@ void facebook::react::fromRawValue(const facebook::react::PropsParserContext& co void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::KeyboardAppearance& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::KeyboardType& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStrategy& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStyle& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakWordStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::OutlineStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::PointerEventsMode& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::ReturnKeyType& result); @@ -5362,6 +5366,8 @@ class facebook::react::ParagraphAttributes : public facebook::react::DebugString public facebook::react::Float minimumFontScale; public facebook::react::Float minimumFontSize; public facebook::react::HyphenationFrequency android_hyphenationFrequency; + public facebook::react::LineBreakStyle android_lineBreakStyle; + public facebook::react::LineBreakWordStyle android_lineBreakWordStyle; public facebook::react::TextBreakStrategy textBreakStrategy; public facebook::react::TextWidthMode textWidthMode; public int maximumNumberOfLines; @@ -7313,6 +7319,18 @@ enum facebook::react::LineBreakStrategy : uint8_t { Standard, } +enum facebook::react::LineBreakStyle { + Loose, + None, + Normal, + Strict, +} + +enum facebook::react::LineBreakWordStyle { + None, + Phrase, +} + enum facebook::react::ModalHostViewAnimationType { Fade, None, diff --git a/scripts/cxx-api/api-snapshots/ReactCommonFrameworksCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonFrameworksCxx.api index b8fbabd4a816..1d6a4e8bad67 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonFrameworksCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonFrameworksCxx.api @@ -378,6 +378,8 @@ std::string facebook::react::toString(const facebook::react::ImportantForAccessi std::string facebook::react::toString(const facebook::react::LayoutDirection& layoutDirection); std::string facebook::react::toString(const facebook::react::LineBreakMode& lineBreakMode); std::string facebook::react::toString(const facebook::react::LineBreakStrategy& lineBreakStrategy); +std::string facebook::react::toString(const facebook::react::LineBreakStyle& lineBreakStyle); +std::string facebook::react::toString(const facebook::react::LineBreakWordStyle& lineBreakWordStyle); std::string facebook::react::toString(const facebook::react::Role& role); std::string facebook::react::toString(const facebook::react::ScrollViewSnapToAlignment& value); std::string facebook::react::toString(const facebook::react::SharedColor& value); @@ -465,6 +467,8 @@ void facebook::react::fromRawValue(const facebook::react::PropsParserContext& co void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::HyphenationFrequency& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::ImportantForAccessibility& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStrategy& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakStyle& result); +void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::LineBreakWordStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::OutlineStyle& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::PointerEventsMode& result); void facebook::react::fromRawValue(const facebook::react::PropsParserContext& context, const facebook::react::RawValue& value, facebook::react::Role& result); @@ -1812,6 +1816,8 @@ class facebook::react::ParagraphAttributes : public facebook::react::DebugString public bool operator==(const facebook::react::ParagraphAttributes& rhs) const; public facebook::react::EllipsizeMode ellipsizeMode; public facebook::react::HyphenationFrequency android_hyphenationFrequency; + public facebook::react::LineBreakStyle android_lineBreakStyle; + public facebook::react::LineBreakWordStyle android_lineBreakWordStyle; public facebook::react::TextBreakStrategy textBreakStrategy; public facebook::react::TextWidthMode textWidthMode; public int maximumNumberOfLines; @@ -3536,6 +3542,18 @@ enum facebook::react::LineBreakStrategy : uint8_t { Standard, } +enum facebook::react::LineBreakStyle { + Loose, + None, + Normal, + Strict, +} + +enum facebook::react::LineBreakWordStyle { + None, + Phrase, +} + enum facebook::react::NullValueStrategy { Ignore, Override,