diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.h b/packages/react-native/Libraries/Text/RCTTextAttributes.h index 22fb646d434940..c6923928d2d224 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.h +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.h @@ -44,6 +44,7 @@ extern NSString *const RCTTextAttributesTagAttributeName; @property (nonatomic, assign) NSTextAlignment alignment; @property (nonatomic, assign) NSWritingDirection baseWritingDirection; @property (nonatomic, assign) NSLineBreakStrategy lineBreakStrategy; +@property (nonatomic, assign) NSLineBreakMode lineBreakMode; // Decoration @property (nonatomic, strong, nullable) UIColor *textDecorationColor; @property (nonatomic, assign) NSUnderlineStyle textDecorationStyle; diff --git a/packages/react-native/Libraries/Text/RCTTextAttributes.mm b/packages/react-native/Libraries/Text/RCTTextAttributes.mm index c8323388ce684b..2480ebf6b38ba5 100644 --- a/packages/react-native/Libraries/Text/RCTTextAttributes.mm +++ b/packages/react-native/Libraries/Text/RCTTextAttributes.mm @@ -28,6 +28,7 @@ - (instancetype)init _alignment = NSTextAlignmentNatural; _baseWritingDirection = NSWritingDirectionNatural; _lineBreakStrategy = NSLineBreakStrategyNone; + _lineBreakMode = NSLineBreakByWordWrapping; _textShadowRadius = NAN; _opacity = NAN; _textTransform = RCTTextTransformUndefined; @@ -70,6 +71,7 @@ - (void)applyTextAttributes:(RCTTextAttributes *)textAttributes ? textAttributes->_baseWritingDirection : _baseWritingDirection; // * _lineBreakStrategy = textAttributes->_lineBreakStrategy ?: _lineBreakStrategy; + _lineBreakMode = textAttributes->_lineBreakMode ?: _lineBreakMode; // Decoration _textDecorationColor = textAttributes->_textDecorationColor ?: _textDecorationColor; @@ -127,6 +129,11 @@ - (NSParagraphStyle *)effectiveParagraphStyle isParagraphStyleUsed = YES; } } + + if (_lineBreakMode != NSLineBreakByWordWrapping) { + paragraphStyle.lineBreakMode = _lineBreakMode; + isParagraphStyleUsed = YES; + } if (!isnan(_lineHeight)) { CGFloat lineHeight = _lineHeight * self.effectiveFontSizeMultiplier; @@ -336,6 +343,7 @@ - (BOOL)isEqual:(RCTTextAttributes *)textAttributes // Paragraph Styles RCTTextAttributesCompareFloats(_lineHeight) && RCTTextAttributesCompareFloats(_alignment) && RCTTextAttributesCompareOthers(_baseWritingDirection) && RCTTextAttributesCompareOthers(_lineBreakStrategy) && + RCTTextAttributesCompareOthers(_lineBreakMode) && // Decoration RCTTextAttributesCompareObjects(_textDecorationColor) && RCTTextAttributesCompareOthers(_textDecorationStyle) && RCTTextAttributesCompareOthers(_textDecorationLine) && diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h index c8ff0cbd40a4d8..37db36656f8d67 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -60,6 +60,7 @@ class TextAttributes : public DebugStringConvertible { std::optional alignment{}; std::optional baseWritingDirection{}; std::optional lineBreakStrategy{}; + std::optional lineBreakMode{}; // Decoration SharedColor textDecorationColor{}; @@ -128,6 +129,7 @@ struct hash { textAttributes.textAlignVertical, textAttributes.baseWritingDirection, textAttributes.lineBreakStrategy, + textAttributes.lineBreakMode, textAttributes.textDecorationColor, textAttributes.textDecorationLineType, textAttributes.textDecorationStyle, diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h index 49afdff3525f51..9bc23079e43359 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/primitives.h @@ -103,6 +103,15 @@ enum class LineBreakStrategy { // system uses for standard UI labels. }; +enum class LineBreakMode { + Word, // Wrap at word boundaries, default + Char, // Wrap at character boundaries + Clip, // Simply clip + Head, // Truncate at head of line: "...wxyz" + Middle, // Truncate middle of line: "ab...yz" + Tail // Truncate at tail of line: "abcd..." +}; + enum class TextDecorationLineType { None, Underline, diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index 5bdeac31b493c1..47684899fb5406 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -232,6 +232,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex RCTNSLineBreakStrategyFromLineBreakStrategy(textAttributes.lineBreakStrategy.value()); isParagraphStyleUsed = YES; } + + if (textAttributes.lineBreakMode.has_value()) { + paragraphStyle.lineBreakMode = RCTNSLineBreakModeFromLineBreakMode(textAttributes.lineBreakMode.value()); + isParagraphStyleUsed = YES; + } if (!isnan(textAttributes.lineHeight)) { CGFloat lineHeight = textAttributes.lineHeight * RCTEffectiveFontSizeMultiplierFromTextAttributes(textAttributes); diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h index c3f3ac20bd8597..42bcc30cc1886d 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h @@ -63,6 +63,25 @@ inline static NSLineBreakStrategy RCTNSLineBreakStrategyFromLineBreakStrategy( } } +inline static NSLineBreakMode RCTNSLineBreakModeFromLineBreakMode( + facebook::react::LineBreakMode lineBreakMode) +{ + switch (lineBreakMode) { + case facebook::react::LineBreakMode::Word: + return NSLineBreakByWordWrapping; + case facebook::react::LineBreakMode::Char: + return NSLineBreakByCharWrapping; + case facebook::react::LineBreakMode::Clip: + return NSLineBreakByClipping; + case facebook::react::LineBreakMode::Head: + return NSLineBreakByTruncatingHead; + case facebook::react::LineBreakMode::Middle: + return NSLineBreakByTruncatingMiddle; + case facebook::react::LineBreakMode::Tail: + return NSLineBreakByTruncatingTail; + } +} + inline static RCTFontStyle RCTFontStyleFromFontStyle(facebook::react::FontStyle fontStyle) { switch (fontStyle) {