diff --git a/packages/react-native/Libraries/Text/React-RCTText.podspec b/packages/react-native/Libraries/Text/React-RCTText.podspec index 6766c335abe6d6..16c080a7dcc9bd 100644 --- a/packages/react-native/Libraries/Text/React-RCTText.podspec +++ b/packages/react-native/Libraries/Text/React-RCTText.podspec @@ -34,4 +34,5 @@ Pod::Spec.new do |s| s.dependency "Yoga" s.dependency "React-Core/RCTTextHeaders", version + add_dependency(s, "React-featureflags") end diff --git a/packages/react-native/Libraries/Text/Text/RCTTextView.mm b/packages/react-native/Libraries/Text/Text/RCTTextView.mm index 47632aa885cdb3..280c39197a3636 100644 --- a/packages/react-native/Libraries/Text/Text/RCTTextView.mm +++ b/packages/react-native/Libraries/Text/Text/RCTTextView.mm @@ -11,6 +11,7 @@ #import #import +#import #import @@ -98,6 +99,42 @@ - (void)setTextStorage:(NSTextStorage *)textStorage [self setNeedsDisplay]; } +- (CGPoint)calculateDrawingPointWithTextStorage:(NSTextStorage *)textStorage + contentFrame:(CGRect)contentFrame { + if ([textStorage length] == 0) { + return contentFrame.origin; + } + + UIFont *font = [textStorage attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL]; + if (!font) { + font = [UIFont systemFontOfSize:14]; + } + + NSParagraphStyle *paragraphStyle = [textStorage attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:NULL]; + + CGFloat lineHeight = font.lineHeight; + if (paragraphStyle && paragraphStyle.minimumLineHeight > 0) { + lineHeight = paragraphStyle.minimumLineHeight; + } + + CGFloat ascent = font.ascender; + CGFloat descent = fabs(font.descender); + CGFloat textHeight = ascent + descent; + + CGFloat verticalOffset = 0; + // Adjust vertical offset to ensure text is vertically centered relative to the line height. + // Positive offset when text height exceeds line height, negative when line height exceeds text height. + if (textHeight > lineHeight) { + CGFloat difference = textHeight - lineHeight; + verticalOffset = difference / 2.0; + } else if (textHeight < lineHeight) { + CGFloat difference = lineHeight - textHeight; + verticalOffset = -(difference / 2.0); + } + + return CGPointMake(contentFrame.origin.x, contentFrame.origin.y + verticalOffset); +} + - (void)drawRect:(CGRect)rect { [super drawRect:rect]; @@ -118,8 +155,15 @@ - (void)drawRect:(CGRect)rect #endif NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer]; - [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:_contentFrame.origin]; - [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:_contentFrame.origin]; + + if (facebook::react::ReactNativeFeatureFlags::enableLineHeightCenteringOnIOS()) { + CGPoint drawingPoint = [self calculateDrawingPointWithTextStorage:_textStorage contentFrame:_contentFrame]; + [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:drawingPoint]; + [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:drawingPoint]; + } else { + [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:_contentFrame.origin]; + [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:_contentFrame.origin]; + } __block UIBezierPath *highlightPath = nil; NSRange characterRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index 3f87fcec845487..8f4cc3a8ad3dbc 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -9,6 +9,7 @@ #import "RCTParagraphComponentAccessibilityProvider.h" #import +#import #import #import #import @@ -326,6 +327,40 @@ @implementation RCTParagraphTextView { CAShapeLayer *_highlightLayer; } +- (CGRect)calculateCenteredFrameWithAttributedText:(NSAttributedString *)attributedText + frame:(CGRect)frame { + UIFont *font = [attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL]; + if (!font) { + font = [UIFont systemFontOfSize:14]; + } + + NSParagraphStyle *paragraphStyle = [attributedText attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:NULL]; + CGFloat lineHeight = font.lineHeight; + + if (paragraphStyle && paragraphStyle.minimumLineHeight > 0) { + lineHeight = paragraphStyle.minimumLineHeight; + } + + CGFloat ascent = font.ascender; + CGFloat descent = fabs(font.descender); + CGFloat textHeight = ascent + descent; + + CGFloat verticalOffset = 0; + // Adjust vertical offset to ensure text is vertically centered relative to the line height. + // Positive offset when text height exceeds line height, negative when line height exceeds text height. + if (textHeight > lineHeight) { + CGFloat difference = textHeight - lineHeight; + verticalOffset = difference / 2.0; + } else if (textHeight < lineHeight) { + CGFloat difference = lineHeight - textHeight; + verticalOffset = -(difference / 2.0); + } + + frame.origin.y += verticalOffset; + + return frame; +} + - (void)drawRect:(CGRect)rect { if (!_state) { @@ -343,6 +378,11 @@ - (void)drawRect:(CGRect)rect CGRect frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame()); + if (ReactNativeFeatureFlags::enableLineHeightCenteringOnIOS()) { + NSAttributedString *attributedText = RCTNSAttributedStringFromAttributedString(_state->getData().attributedString); + frame = [self calculateCenteredFrameWithAttributedText:attributedText frame:frame]; + } + [nativeTextLayoutManager drawAttributedString:_state->getData().attributedString paragraphAttributes:_paragraphAttributes frame:frame diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index e5c04d36dae216..47a3afb0ce4725 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -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<> + * @generated SignedSource<<1ac20a64883288436912fa6931bcecdb>> */ /** @@ -148,6 +148,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableLayoutAnimationsOnIOS(): Boolean = accessor.enableLayoutAnimationsOnIOS() + /** + * When enabled, custom line height calculation will be centered from top to bottom. + */ + @JvmStatic + public fun enableLineHeightCenteringOnIOS(): Boolean = accessor.enableLineHeightCenteringOnIOS() + /** * Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index a9ee50c652323a..98f1b42ee9d9e2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -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<> + * @generated SignedSource<<93e22ef74bcde3a2c3fd217027018521>> */ /** @@ -40,6 +40,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableImagePrefetchingAndroidCache: Boolean? = null private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null + private var enableLineHeightCenteringOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null private var enablePreciseSchedulingForPremountItemsOnAndroidCache: Boolean? = null @@ -248,6 +249,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun enableLineHeightCenteringOnIOS(): Boolean { + var cached = enableLineHeightCenteringOnIOSCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableLineHeightCenteringOnIOS() + enableLineHeightCenteringOnIOSCache = cached + } + return cached + } + override fun enableLongTaskAPI(): Boolean { var cached = enableLongTaskAPICache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 5906b21d8db5af..388a07f5e5dbb6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -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<> + * @generated SignedSource<> */ /** @@ -68,6 +68,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableLineHeightCenteringOnIOS(): Boolean + @DoNotStrip @JvmStatic public external fun enableLongTaskAPI(): Boolean @DoNotStrip @JvmStatic public external fun enableNewBackgroundAndBorderDrawables(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 15bc50ad10e9ea..635f82a3073edf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -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<<7075974bc541d91e275ee370f2a3709b>> + * @generated SignedSource<<92985a8aaff4a9a76e22c2df708a51a7>> */ /** @@ -63,6 +63,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableLayoutAnimationsOnIOS(): Boolean = true + override fun enableLineHeightCenteringOnIOS(): Boolean = false + override fun enableLongTaskAPI(): Boolean = false override fun enableNewBackgroundAndBorderDrawables(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index c410a196077af1..37adbee1a6243c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -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<<0b570bc8931ec25f16ee777f0bfcd04f>> + * @generated SignedSource<> */ /** @@ -44,6 +44,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableImagePrefetchingAndroidCache: Boolean? = null private var enableLayoutAnimationsOnAndroidCache: Boolean? = null private var enableLayoutAnimationsOnIOSCache: Boolean? = null + private var enableLineHeightCenteringOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null private var enableNewBackgroundAndBorderDrawablesCache: Boolean? = null private var enablePreciseSchedulingForPremountItemsOnAndroidCache: Boolean? = null @@ -272,6 +273,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableLineHeightCenteringOnIOS(): Boolean { + var cached = enableLineHeightCenteringOnIOSCache + if (cached == null) { + cached = currentProvider.enableLineHeightCenteringOnIOS() + accessedFeatureFlags.add("enableLineHeightCenteringOnIOS") + enableLineHeightCenteringOnIOSCache = cached + } + return cached + } + override fun enableLongTaskAPI(): Boolean { var cached = enableLongTaskAPICache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 66b1f6d6cfb346..f3f87dd89247c9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -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<<080245bea6e8535f2e8a91c1559e2fcc>> + * @generated SignedSource<<403ad97220298f77a4610fe3cd9a95f6>> */ /** @@ -63,6 +63,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableLayoutAnimationsOnIOS(): Boolean + @DoNotStrip public fun enableLineHeightCenteringOnIOS(): Boolean + @DoNotStrip public fun enableLongTaskAPI(): Boolean @DoNotStrip public fun enableNewBackgroundAndBorderDrawables(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 9ea7faffc66e88..fa6b509a91592f 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -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<<5b4977559c424312ed8bd791a96da52d>> + * @generated SignedSource<<019ee84673771436057f3df9b43ed079>> */ /** @@ -159,6 +159,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool enableLineHeightCenteringOnIOS() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableLineHeightCenteringOnIOS"); + return method(javaProvider_); + } + bool enableLongTaskAPI() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableLongTaskAPI"); @@ -425,6 +431,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableLayoutAnimationsOnIOS( return ReactNativeFeatureFlags::enableLayoutAnimationsOnIOS(); } +bool JReactNativeFeatureFlagsCxxInterop::enableLineHeightCenteringOnIOS( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableLineHeightCenteringOnIOS(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableLongTaskAPI( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableLongTaskAPI(); @@ -651,6 +662,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableLayoutAnimationsOnIOS", JReactNativeFeatureFlagsCxxInterop::enableLayoutAnimationsOnIOS), + makeNativeMethod( + "enableLineHeightCenteringOnIOS", + JReactNativeFeatureFlagsCxxInterop::enableLineHeightCenteringOnIOS), makeNativeMethod( "enableLongTaskAPI", JReactNativeFeatureFlagsCxxInterop::enableLongTaskAPI), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index fd601f5829f3ba..6dd1bc4a82603a 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -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<> + * @generated SignedSource<<64cf0422c4fcec2c6d105f4b45a3e12c>> */ /** @@ -90,6 +90,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableLayoutAnimationsOnIOS( facebook::jni::alias_ref); + static bool enableLineHeightCenteringOnIOS( + facebook::jni::alias_ref); + static bool enableLongTaskAPI( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 77d170295774c8..da1310e03569a7 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -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<> + * @generated SignedSource<> */ /** @@ -106,6 +106,10 @@ bool ReactNativeFeatureFlags::enableLayoutAnimationsOnIOS() { return getAccessor().enableLayoutAnimationsOnIOS(); } +bool ReactNativeFeatureFlags::enableLineHeightCenteringOnIOS() { + return getAccessor().enableLineHeightCenteringOnIOS(); +} + bool ReactNativeFeatureFlags::enableLongTaskAPI() { return getAccessor().enableLongTaskAPI(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 1ececa0ba32128..1b4361b17102bd 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -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<<8af906cf2c1799274d66979fd2532c57>> + * @generated SignedSource<> */ /** @@ -139,6 +139,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableLayoutAnimationsOnIOS(); + /** + * When enabled, custom line height calculation will be centered from top to bottom. + */ + RN_EXPORT static bool enableLineHeightCenteringOnIOS(); + /** * Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 3ffacb7c4eb513..9d8ee8de8f1282 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -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<<3b9204d0f66ab73f11e67f7d33f0d472>> + * @generated SignedSource<<9efb3f79c7cd753f9ad9d57f47336537>> */ /** @@ -389,6 +389,24 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableLineHeightCenteringOnIOS() { + auto flagValue = enableLineHeightCenteringOnIOS_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(20, "enableLineHeightCenteringOnIOS"); + + flagValue = currentProvider_->enableLineHeightCenteringOnIOS(); + enableLineHeightCenteringOnIOS_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableLongTaskAPI() { auto flagValue = enableLongTaskAPI_.load(); @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLongTaskAPI() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableLongTaskAPI"); + markFlagAsAccessed(21, "enableLongTaskAPI"); flagValue = currentProvider_->enableLongTaskAPI(); enableLongTaskAPI_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "enableNewBackgroundAndBorderDrawables"); + markFlagAsAccessed(22, "enableNewBackgroundAndBorderDrawables"); flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables(); enableNewBackgroundAndBorderDrawables_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreciseSchedulingForPremountItemsOnA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enablePreciseSchedulingForPremountItemsOnAndroid"); + markFlagAsAccessed(23, "enablePreciseSchedulingForPremountItemsOnAndroid"); flagValue = currentProvider_->enablePreciseSchedulingForPremountItemsOnAndroid(); enablePreciseSchedulingForPremountItemsOnAndroid_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(24, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableReportEventPaintTime() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableReportEventPaintTime"); + markFlagAsAccessed(25, "enableReportEventPaintTime"); flagValue = currentProvider_->enableReportEventPaintTime(); enableReportEventPaintTime_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableSynchronousStateUpdates"); + markFlagAsAccessed(26, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableUIConsistency"); + markFlagAsAccessed(27, "enableUIConsistency"); flagValue = currentProvider_->enableUIConsistency(); enableUIConsistency_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableViewRecycling"); + markFlagAsAccessed(28, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::excludeYogaFromRawProps() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "excludeYogaFromRawProps"); + markFlagAsAccessed(29, "excludeYogaFromRawProps"); flagValue = currentProvider_->excludeYogaFromRawProps(); excludeYogaFromRawProps_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::fixDifferentiatorEmittingUpdatesWithWrongP // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "fixDifferentiatorEmittingUpdatesWithWrongParentTag"); + markFlagAsAccessed(30, "fixDifferentiatorEmittingUpdatesWithWrongParentTag"); flagValue = currentProvider_->fixDifferentiatorEmittingUpdatesWithWrongParentTag(); fixDifferentiatorEmittingUpdatesWithWrongParentTag_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(31, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMountingCoordinatorReportedPendingTrans // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); + markFlagAsAccessed(32, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); flagValue = currentProvider_->fixMountingCoordinatorReportedPendingTransactionsOnAndroid(); fixMountingCoordinatorReportedPendingTransactionsOnAndroid_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "fuseboxEnabledRelease"); + markFlagAsAccessed(33, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::initEagerTurboModulesOnNativeModulesQueueA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "initEagerTurboModulesOnNativeModulesQueueAndroid"); + markFlagAsAccessed(34, "initEagerTurboModulesOnNativeModulesQueueAndroid"); flagValue = currentProvider_->initEagerTurboModulesOnNativeModulesQueueAndroid(); initEagerTurboModulesOnNativeModulesQueueAndroid_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "lazyAnimationCallbacks"); + markFlagAsAccessed(35, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "loadVectorDrawablesOnImages"); + markFlagAsAccessed(36, "loadVectorDrawablesOnImages"); flagValue = currentProvider_->loadVectorDrawablesOnImages(); loadVectorDrawablesOnImages_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(37, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(38, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "useFabricInterop"); + markFlagAsAccessed(39, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(40, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(41, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useOptimisedViewPreallocationOnAndroid"); + markFlagAsAccessed(42, "useOptimisedViewPreallocationOnAndroid"); flagValue = currentProvider_->useOptimisedViewPreallocationOnAndroid(); useOptimisedViewPreallocationOnAndroid_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(43, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useRawPropsJsiValue"); + markFlagAsAccessed(44, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(45, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "useTurboModuleInterop"); + markFlagAsAccessed(46, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "useTurboModules"); + markFlagAsAccessed(47, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index f9d534749167ed..8684669e109776 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -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<> + * @generated SignedSource<> */ /** @@ -52,6 +52,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableImagePrefetchingAndroid(); bool enableLayoutAnimationsOnAndroid(); bool enableLayoutAnimationsOnIOS(); + bool enableLineHeightCenteringOnIOS(); bool enableLongTaskAPI(); bool enableNewBackgroundAndBorderDrawables(); bool enablePreciseSchedulingForPremountItemsOnAndroid(); @@ -90,7 +91,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 47> accessedFeatureFlags_; + std::array, 48> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> completeReactInstanceCreationOnBgThreadOnAndroid_; @@ -112,6 +113,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableImagePrefetchingAndroid_; std::atomic> enableLayoutAnimationsOnAndroid_; std::atomic> enableLayoutAnimationsOnIOS_; + std::atomic> enableLineHeightCenteringOnIOS_; std::atomic> enableLongTaskAPI_; std::atomic> enableNewBackgroundAndBorderDrawables_; std::atomic> enablePreciseSchedulingForPremountItemsOnAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 1741eb4812697a..fa5e25296fbfb3 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -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<<243cad39bb9ef10ee4c7941a64c553fb>> + * @generated SignedSource<<36caa4d81c790147714ea6ced92bbe23>> */ /** @@ -107,6 +107,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return true; } + bool enableLineHeightCenteringOnIOS() override { + return false; + } + bool enableLongTaskAPI() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index b466b5223fc941..b89338ac643e6e 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -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<<9c277fbfd1a24ccac9c232015758a431>> + * @generated SignedSource<<40dec53a2f91804a0601564d471f5f4a>> */ /** @@ -225,6 +225,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::enableLayoutAnimationsOnIOS(); } + bool enableLineHeightCenteringOnIOS() override { + auto value = values_["enableLineHeightCenteringOnIOS"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::enableLineHeightCenteringOnIOS(); + } + bool enableLongTaskAPI() override { auto value = values_["enableLongTaskAPI"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 913d6ed41d6a82..827dd264fd17b8 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -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<<8b3463fbed7d11f7f067593afdd662c9>> + * @generated SignedSource<> */ /** @@ -45,6 +45,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableImagePrefetchingAndroid() = 0; virtual bool enableLayoutAnimationsOnAndroid() = 0; virtual bool enableLayoutAnimationsOnIOS() = 0; + virtual bool enableLineHeightCenteringOnIOS() = 0; virtual bool enableLongTaskAPI() = 0; virtual bool enableNewBackgroundAndBorderDrawables() = 0; virtual bool enablePreciseSchedulingForPremountItemsOnAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index e0c9034857f0c7..d77c2924b5d945 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -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<> + * @generated SignedSource<<8a3d09022213ac2273459881becad4fe>> */ /** @@ -144,6 +144,11 @@ bool NativeReactNativeFeatureFlags::enableLayoutAnimationsOnIOS( return ReactNativeFeatureFlags::enableLayoutAnimationsOnIOS(); } +bool NativeReactNativeFeatureFlags::enableLineHeightCenteringOnIOS( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableLineHeightCenteringOnIOS(); +} + bool NativeReactNativeFeatureFlags::enableLongTaskAPI( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableLongTaskAPI(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index a697c658cef90b..31cae9f8d2d88e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -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<<9d947be615f76c0f0bd4b7ce1dcbf390>> + * @generated SignedSource<> */ /** @@ -77,6 +77,8 @@ class NativeReactNativeFeatureFlags bool enableLayoutAnimationsOnIOS(jsi::Runtime& runtime); + bool enableLineHeightCenteringOnIOS(jsi::Runtime& runtime); + bool enableLongTaskAPI(jsi::Runtime& runtime); bool enableNewBackgroundAndBorderDrawables(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 9fb90dfc4f5075..28a841d4aed4a8 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -236,6 +236,16 @@ const definitions: FeatureFlagDefinitions = { purpose: 'release', }, }, + enableLineHeightCenteringOnIOS: { + defaultValue: false, + metadata: { + dateAdded: '2024-10-11', + description: + 'When enabled, custom line height calculation will be centered from top to bottom.', + expectedReleaseValue: true, + purpose: 'experimentation', + }, + }, enableLongTaskAPI: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 0c4afa300f19e0..6bd9ea767d4cf1 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -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<> + * @generated SignedSource<<0fcce70503da6bc18f90507d620c2cc2>> * @flow strict */ @@ -71,6 +71,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ enableImagePrefetchingAndroid: Getter, enableLayoutAnimationsOnAndroid: Getter, enableLayoutAnimationsOnIOS: Getter, + enableLineHeightCenteringOnIOS: Getter, enableLongTaskAPI: Getter, enableNewBackgroundAndBorderDrawables: Getter, enablePreciseSchedulingForPremountItemsOnAndroid: Getter, @@ -269,6 +270,10 @@ export const enableLayoutAnimationsOnAndroid: Getter = createNativeFlag * When enabled, LayoutAnimations API will animate state changes on iOS. */ export const enableLayoutAnimationsOnIOS: Getter = createNativeFlagGetter('enableLayoutAnimationsOnIOS', true); +/** + * When enabled, custom line height calculation will be centered from top to bottom. + */ +export const enableLineHeightCenteringOnIOS: Getter = createNativeFlagGetter('enableLineHeightCenteringOnIOS', false); /** * Enables the reporting of long tasks through `PerformanceObserver`. Only works if the event loop is enabled. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 1d81cb6141c9a3..f0a71d26216961 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -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<<4acd86272bdd0199f1d160c21144d5b5>> + * @generated SignedSource<> * @flow strict */ @@ -44,6 +44,7 @@ export interface Spec extends TurboModule { +enableImagePrefetchingAndroid?: () => boolean; +enableLayoutAnimationsOnAndroid?: () => boolean; +enableLayoutAnimationsOnIOS?: () => boolean; + +enableLineHeightCenteringOnIOS?: () => boolean; +enableLongTaskAPI?: () => boolean; +enableNewBackgroundAndBorderDrawables?: () => boolean; +enablePreciseSchedulingForPremountItemsOnAndroid?: () => boolean;