diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js
index a31b20a918f8..9bfc163f9f5d 100644
--- a/packages/react-native/Libraries/Text/Text.js
+++ b/packages/react-native/Libraries/Text/Text.js
@@ -20,14 +20,18 @@ import flattenStyle from '../StyleSheet/flattenStyle';
import processColor from '../StyleSheet/processColor';
import Platform from '../Utilities/Platform';
import TextAncestorContext from './TextAncestorContext';
-import {NativeText, NativeVirtualText} from './TextNativeComponent';
+import {
+ NativeSelectableText,
+ NativeText,
+ NativeVirtualText,
+} from './TextNativeComponent';
import * as React from 'react';
import {useContext, useMemo, useState} from 'react';
export type {TextProps} from './TextProps';
type TextForwardRef = React.ElementRef<
- typeof NativeText | typeof NativeVirtualText,
+ typeof NativeText | typeof NativeVirtualText | typeof NativeSelectableText,
>;
/**
@@ -263,7 +267,7 @@ const TextImpl: component(
processedProps.children = children;
if (isPressable) {
return (
-
);
} else {
- nativeText = ;
+ nativeText =
+ _selectable === true ? (
+
+ ) : (
+
+ );
}
if (children == null) {
@@ -457,28 +467,17 @@ function useTextPressability({
);
}
-type NativePressableTextProps = Readonly<{
- textProps: NativeTextProps,
- textPressabilityProps: TextPressabilityProps,
-}>;
-
/**
* Wrap the NativeVirtualText component and initialize pressability.
*
* This logic is split out from the main Text component to enable the more
* expensive pressability logic to be only initialized when needed.
*/
-const NativePressableVirtualText: component(
- ref: React.RefSetter,
- ...props: NativePressableTextProps
-) = ({
- ref: forwardedRef,
- textProps,
- textPressabilityProps,
-}: {
+component PressableVirtualText(
ref?: React.RefSetter,
- ...NativePressableTextProps,
-}) => {
+ textProps: NativeTextProps,
+ textPressabilityProps: TextPressabilityProps,
+) {
const [isHighlighted, eventHandlersForText] = useTextPressability(
textPressabilityProps,
);
@@ -489,42 +488,40 @@ const NativePressableVirtualText: component(
{...eventHandlersForText}
isHighlighted={isHighlighted}
isPressable={true}
- ref={forwardedRef}
+ ref={ref}
/>
);
-};
+}
/**
- * Wrap the NativeText component and initialize pressability.
+ * Wrap a NativeText component and initialize pressability.
*
* This logic is split out from the main Text component to enable the more
* expensive pressability logic to be only initialized when needed.
*/
-const NativePressableText: component(
- ref: React.RefSetter,
- ...props: NativePressableTextProps
-) = ({
- ref: forwardedRef,
- textProps,
- textPressabilityProps,
-}: {
+component PressableText(
ref?: React.RefSetter,
- ...NativePressableTextProps,
-}) => {
+ selectable?: ?boolean,
+ textProps: NativeTextProps,
+ textPressabilityProps: TextPressabilityProps,
+) {
const [isHighlighted, eventHandlersForText] = useTextPressability(
textPressabilityProps,
);
+ const NativeComponent =
+ selectable === true ? NativeSelectableText : NativeText;
+
return (
-
);
-};
+}
const userSelectToSelectableMap = {
auto: true,
diff --git a/packages/react-native/Libraries/Text/TextNativeComponent.js b/packages/react-native/Libraries/Text/TextNativeComponent.js
index 020d5ceea8b6..01b7c690fd81 100644
--- a/packages/react-native/Libraries/Text/TextNativeComponent.js
+++ b/packages/react-native/Libraries/Text/TextNativeComponent.js
@@ -13,6 +13,7 @@ import type {ProcessedColorValue} from '../StyleSheet/processColor';
import type {GestureResponderEvent} from '../Types/CoreEventTypes';
import type {TextProps} from './TextProps';
+import {enablePreparedTextLayout} from '../../src/private/featureflags/ReactNativeFeatureFlags';
import {createViewConfig} from '../NativeComponent/ViewConfig';
import UIManager from '../ReactNative/UIManager';
import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass';
@@ -90,3 +91,15 @@ export const NativeVirtualText: HostComponent =
* https://fburl.com/workplace/6291gfvu */
createViewConfig(virtualTextViewConfig),
): any);
+
+export const NativeSelectableText: HostComponent =
+ enablePreparedTextLayout()
+ ? (createReactNativeComponentClass('RCTSelectableText', () =>
+ /* $FlowFixMe[incompatible-type] Natural Inference rollout. See
+ * https://fburl.com/workplace/6291gfvu */
+ createViewConfig({
+ ...textViewConfig,
+ uiViewClassName: 'RCTSelectableText',
+ }),
+ ): any)
+ : NativeText;
diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api
index 80c168cd95d1..18d8f7aafaa8 100644
--- a/packages/react-native/ReactAndroid/api/ReactAndroid.api
+++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api
@@ -6112,7 +6112,7 @@ public class com/facebook/react/views/text/ReactTextView : androidx/appcompat/wi
public fun updateView ()V
}
-public final class com/facebook/react/views/text/ReactTextViewManager : com/facebook/react/uimanager/BaseViewManager, com/facebook/react/uimanager/IViewManagerWithChildren, com/facebook/react/views/text/ReactTextViewManagerCallback {
+public class com/facebook/react/views/text/ReactTextViewManager : com/facebook/react/uimanager/BaseViewManager, com/facebook/react/uimanager/IViewManagerWithChildren, com/facebook/react/views/text/ReactTextViewManagerCallback {
public static final field Companion Lcom/facebook/react/views/text/ReactTextViewManager$Companion;
public static final field REACT_CLASS Ljava/lang/String;
public fun ()V
@@ -6125,11 +6125,14 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/text/ReactTextView;
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
public fun getName ()Ljava/lang/String;
+ protected final fun getReactTextViewManagerCallback ()Lcom/facebook/react/views/text/ReactTextViewManagerCallback;
public fun getShadowNodeClass ()Ljava/lang/Class;
public fun needsCustomLayoutForChildren ()Z
public synthetic fun onAfterUpdateTransaction (Landroid/view/View;)V
+ protected fun onAfterUpdateTransaction (Lcom/facebook/react/views/text/ReactTextView;)V
public fun onPostProcessSpannable (Landroid/text/Spannable;)V
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
+ protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/text/ReactTextView;)Lcom/facebook/react/views/text/ReactTextView;
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
@@ -6147,6 +6150,7 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public final fun setOverflow (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V
public synthetic fun setPadding (Landroid/view/View;IIII)V
public fun setPadding (Lcom/facebook/react/views/text/ReactTextView;IIII)V
+ protected final fun setReactTextViewManagerCallback (Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)V
public final fun setSelectable (Lcom/facebook/react/views/text/ReactTextView;Z)V
public final fun setSelectionColor (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/Integer;)V
public final fun setTextAlignVertical (Lcom/facebook/react/views/text/ReactTextView;Ljava/lang/String;)V
@@ -6155,6 +6159,7 @@ public final class com/facebook/react/views/text/ReactTextViewManager : com/face
public synthetic fun updateState (Landroid/view/View;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
public fun updateState (Lcom/facebook/react/views/text/ReactTextView;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
public synthetic fun updateViewAccessibility (Landroid/view/View;)V
+ protected fun updateViewAccessibility (Lcom/facebook/react/views/text/ReactTextView;)V
}
public final class com/facebook/react/views/text/ReactTextViewManager$Companion {
@@ -6172,6 +6177,9 @@ public final class com/facebook/react/views/text/ReactTypefaceUtils {
public static final fun parseFontWeight (Ljava/lang/String;)I
}
+public final class com/facebook/react/views/text/SelectableTextViewManager$Companion {
+}
+
public final class com/facebook/react/views/text/TextAttributeProps {
public static final field Companion Lcom/facebook/react/views/text/TextAttributeProps$Companion;
public static final field TA_KEY_ACCESSIBILITY_ROLE I
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.kt
index c032448a7a33..31d93c32b695 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/FabricNameComponentMapping.kt
@@ -18,6 +18,7 @@ internal object FabricNameComponentMapping {
"Slider" to "RCTSlider",
"ModalHostView" to "RCTModalHostView",
"Paragraph" to "RCTText",
+ "SelectableParagraph" to "RCTSelectableText",
"Text" to "RCTText",
"RawText" to "RCTRawText",
"ActivityIndicatorView" to "AndroidProgressBar",
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt
index 9927bf571536..b3baad46a9aa 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt
@@ -15,6 +15,7 @@ import com.facebook.react.bridge.ModuleSpec
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.common.ClassFinder
+import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.module.annotations.ReactModuleList
@@ -58,6 +59,7 @@ import com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager
import com.facebook.react.views.switchview.ReactSwitchManager
import com.facebook.react.views.text.PreparedLayoutTextViewManager
import com.facebook.react.views.text.ReactTextViewManager
+import com.facebook.react.views.text.SelectableTextViewManager
import com.facebook.react.views.textinput.ReactTextInputManager
import com.facebook.react.views.unimplementedview.ReactUnimplementedViewManager
import com.facebook.react.views.view.ReactViewManager
@@ -96,6 +98,7 @@ import com.facebook.react.views.view.ReactViewManager
WebSocketModule::class,
]
)
+@OptIn(UnstableReactNativeAPI::class)
public class MainReactPackage
@JvmOverloads
constructor(private val config: MainPackageConfig? = null) :
@@ -150,6 +153,7 @@ constructor(private val config: MainPackageConfig? = null) :
ReactTextInputManager(),
if (ReactNativeFeatureFlags.enablePreparedTextLayout()) PreparedLayoutTextViewManager()
else ReactTextViewManager(),
+ SelectableTextViewManager(),
ReactViewManager(),
ReactUnimplementedViewManager(),
)
@@ -192,6 +196,8 @@ constructor(private val config: MainPackageConfig? = null) :
PreparedLayoutTextViewManager()
else ReactTextViewManager()
},
+ SelectableTextViewManager.REACT_CLASS to
+ ModuleSpec.viewManagerSpec { SelectableTextViewManager() },
ReactViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactViewManager() },
ReactUnimplementedViewManager.REACT_CLASS to
ModuleSpec.viewManagerSpec { ReactUnimplementedViewManager() },
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/PreparedLayoutTextViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/PreparedLayoutTextViewManager.kt
index ede2a678a1fe..66a2bf753135 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/PreparedLayoutTextViewManager.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/PreparedLayoutTextViewManager.kt
@@ -118,8 +118,9 @@ internal class PreparedLayoutTextViewManager :
@ReactProp(name = "selectable", defaultBoolean = false)
fun setSelectable(view: PreparedLayoutTextView, isSelectable: Boolean): Unit {
- // T222052152: Implement fine-grained text selection for PreparedLayoutTextView
- // view.setTextIsSelectable(isSelectable);
+ check(!isSelectable) {
+ "selectable Text should use SelectableTextViewManager instead of PreparedLayoutViewManager"
+ }
}
@ReactProp(name = "selectionColor", customType = "Color")
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 2e3669c113d7..e616cf5f6e75 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
@@ -12,6 +12,7 @@ package com.facebook.react.views.text
import android.os.Build
import android.text.Layout
import android.text.Spannable
+import android.text.SpannableString
import android.text.Spanned
import android.text.TextUtils
import android.text.util.Linkify
@@ -31,6 +32,7 @@ import com.facebook.react.uimanager.LayoutShadowNode
import com.facebook.react.uimanager.LengthPercentage
import com.facebook.react.uimanager.LengthPercentageType
import com.facebook.react.uimanager.ReactStylesDiffMap
+import com.facebook.react.uimanager.ReferenceStateWrapper
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewDefaults
@@ -46,7 +48,7 @@ import java.util.HashMap
/** View manager for `` nodes. */
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
@OptIn(UnstableReactNativeAPI::class)
-public class ReactTextViewManager
+public open class ReactTextViewManager
@JvmOverloads
public constructor(
protected var reactTextViewManagerCallback: ReactTextViewManagerCallback? = null
@@ -131,6 +133,11 @@ public constructor(
stateWrapper: StateWrapper,
): Any? {
SystraceSection("ReactTextViewManager.updateState").use { s ->
+ val refState = (stateWrapper as? ReferenceStateWrapper)?.stateDataReference
+ if (refState is PreparedLayout) {
+ return getReactTextUpdateFromPreparedLayout(view, refState)
+ }
+
val stateMapBuffer = stateWrapper.stateDataMapBuffer
return if (stateMapBuffer != null) {
getReactTextUpdate(view, props, stateMapBuffer)
@@ -176,6 +183,34 @@ public constructor(
)
}
+ /**
+ * Constructs a [ReactTextUpdate] from a [PreparedLayout] received via [ReferenceStateWrapper].
+ */
+ private fun getReactTextUpdateFromPreparedLayout(
+ view: ReactTextView,
+ preparedLayout: PreparedLayout,
+ ): ReactTextUpdate {
+ val layout = preparedLayout.layout
+ val text = layout.text
+ val spanned = if (text is Spannable) text else SpannableString(text)
+ view.setSpanned(spanned)
+
+ val textAlign =
+ when (layout.alignment) {
+ Layout.Alignment.ALIGN_CENTER -> Gravity.CENTER_HORIZONTAL
+ Layout.Alignment.ALIGN_OPPOSITE -> Gravity.END
+ else -> Gravity.START
+ }
+
+ return ReactTextUpdate(
+ spanned,
+ -1,
+ textAlign,
+ Layout.BREAK_STRATEGY_HIGH_QUALITY,
+ 0,
+ )
+ }
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap? {
val baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants()
val eventTypeConstants = baseEventTypeConstants ?: HashMap()
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/SelectableTextViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/SelectableTextViewManager.kt
new file mode 100644
index 000000000000..b1f15c461903
--- /dev/null
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/SelectableTextViewManager.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+package com.facebook.react.views.text
+
+import com.facebook.react.common.annotations.UnstableReactNativeAPI
+
+/**
+ * A [ReactTextViewManager] registered under the name "RCTSelectableText". Used to route selectable
+ * text through [ReactTextView] (a real [android.widget.TextView]) instead of
+ * [PreparedLayoutTextView] when enablePreparedTextLayout is on, since [PreparedLayoutTextView] does
+ * not support native text selection.
+ */
+@UnstableReactNativeAPI
+public class SelectableTextViewManager
+@JvmOverloads
+public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? = null) :
+ ReactTextViewManager(reactTextViewManagerCallback) {
+
+ override fun getName(): String = REACT_CLASS
+
+ public companion object {
+ public const val REACT_CLASS: String = "RCTSelectableText"
+ }
+}
diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp
index 03d455ee92f4..3b15aa501986 100644
--- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp
+++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -71,6 +72,9 @@ void addCoreComponents(
AndroidHorizontalScrollContentViewComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider());
+ providerRegistry->add(
+ concreteComponentDescriptorProvider<
+ SelectableParagraphComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<
AndroidDrawerLayoutComponentDescriptor>());
diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp
index 25e3b2cb1072..fe63407de827 100644
--- a/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp
@@ -27,6 +27,9 @@ std::string componentNameByReactViewName(std::string viewName) {
if (viewName == "Text") {
return "Paragraph";
}
+ if (viewName == "SelectableText") {
+ return "SelectableParagraph";
+ }
if (viewName == "VirtualText") {
return "Text";
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h
new file mode 100644
index 000000000000..8c7c8aab798f
--- /dev/null
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace facebook::react {
+
+constexpr const char *const TextLayoutManagerKey = "TextLayoutManager";
+
+template
+class BaseParagraphComponentDescriptor : public ConcreteComponentDescriptor {
+ public:
+ explicit BaseParagraphComponentDescriptor(const ComponentDescriptorParameters ¶meters)
+ : ConcreteComponentDescriptor(parameters),
+ textLayoutManager_(getManagerByName(this->contextContainer_, TextLayoutManagerKey))
+ {
+ }
+
+ ComponentName getComponentName() const override
+ {
+ return ShadowNodeT::Name();
+ }
+
+ protected:
+ void adopt(ShadowNode &shadowNode) const override
+ {
+ ConcreteComponentDescriptor::adopt(shadowNode);
+
+ auto ¶graphShadowNode = static_cast(shadowNode);
+
+ // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content
+ // and communicate text rendering metrics to mounting layer.
+ paragraphShadowNode.setTextLayoutManager(textLayoutManager_);
+ }
+
+ private:
+ // Every `ParagraphShadowNode` has a reference to a shared `TextLayoutManager`
+ const std::shared_ptr textLayoutManager_;
+};
+
+} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp
deleted file mode 100644
index ee4e014b6564..000000000000
--- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-#include "ParagraphComponentDescriptor.h"
-
-namespace facebook::react {
-
-extern const char TextLayoutManagerKey[] = "TextLayoutManager";
-
-} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h
index 3ed1a2a7aefc..3f64c6e8cb7a 100644
--- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h
@@ -7,41 +7,16 @@
#pragma once
+#include
#include
-#include
-#include
-#include
namespace facebook::react {
-
-extern const char TextLayoutManagerKey[];
-
/*
* Descriptor for component.
*/
-class ParagraphComponentDescriptor final : public ConcreteComponentDescriptor {
+class ParagraphComponentDescriptor final : public BaseParagraphComponentDescriptor {
public:
- explicit ParagraphComponentDescriptor(const ComponentDescriptorParameters ¶meters)
- : ConcreteComponentDescriptor(parameters),
- textLayoutManager_(getManagerByName(contextContainer_, TextLayoutManagerKey))
- {
- }
-
- protected:
- void adopt(ShadowNode &shadowNode) const override
- {
- ConcreteComponentDescriptor::adopt(shadowNode);
-
- auto ¶graphShadowNode = static_cast(shadowNode);
-
- // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content
- // and communicate text rendering metrics to mounting layer.
- paragraphShadowNode.setTextLayoutManager(textLayoutManager_);
- }
-
- private:
- // Every `ParagraphShadowNode` has a reference to a shared `TextLayoutManager`
- const std::shared_ptr textLayoutManager_;
+ using BaseParagraphComponentDescriptor::BaseParagraphComponentDescriptor;
};
} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h
index 91709d035d05..c518ccf4b90b 100644
--- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h
@@ -26,7 +26,7 @@ extern const char ParagraphComponentName[];
* containing and displaying text. Text content is represented as nested
* and components.
*/
-class ParagraphShadowNode final
+class ParagraphShadowNode
: public ConcreteViewShadowNode,
public BaseTextShadowNode {
public:
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphComponentDescriptor.h
new file mode 100644
index 000000000000..b008580f5885
--- /dev/null
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphComponentDescriptor.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace facebook::react {
+/*
+ * Descriptor for component, which may render to a
+ * different native view than .
+ */
+class SelectableParagraphComponentDescriptor final
+ : public BaseParagraphComponentDescriptor {
+ public:
+ using BaseParagraphComponentDescriptor::BaseParagraphComponentDescriptor;
+};
+
+} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphShadowNode.h
new file mode 100644
index 000000000000..8574dd601abd
--- /dev/null
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/SelectableParagraphShadowNode.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#pragma once
+
+#include
+
+namespace facebook::react {
+
+/*
+ * ShadowNode for selectable Paragraph components, which may map to different native component than Paragraph.
+ */
+class SelectableParagraphShadowNode : public ParagraphShadowNode {
+ public:
+ using ParagraphShadowNode::ParagraphShadowNode;
+
+ static constexpr ComponentName Name()
+ {
+ return "SelectableParagraph";
+ }
+
+ static ComponentHandle Handle()
+ {
+ return ComponentHandle(Name());
+ }
+};
+
+} // namespace facebook::react
diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts
index 9229bb4336ff..3cb8fa700fc8 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<<6463b0a4f3acbeb07e6759c345b927d8>>
+ * @generated SignedSource<>
*
* This file was generated by scripts/js-api/build-types/index.js.
*/
@@ -322,6 +322,7 @@ declare const NativeModules: typeof NativeModules_default
declare let NativeModules_default: {
[moduleName: string]: any
}
+declare const NativeSelectableText: HostComponent
declare const NativeText: HostComponent
declare const NativeTouchable:
| typeof TouchableNativeFeedback
@@ -3368,6 +3369,7 @@ declare type NativeScrollVelocity = {
readonly x: number
readonly y: number
}
+declare type NativeSelectableText = typeof NativeSelectableText
declare type NativeSwitchChangeEvent = {
readonly target: Int32
readonly value: boolean
@@ -5160,7 +5162,7 @@ declare type TextContentType =
| "URL"
| "username"
declare type TextForwardRef = React.ComponentRef<
- typeof NativeText | typeof NativeVirtualText
+ typeof NativeSelectableText | typeof NativeText | typeof NativeVirtualText
>
declare type TextInput = typeof TextInput
declare type TextInputAndroidProps = {
@@ -5995,7 +5997,7 @@ export {
AlertOptions, // a0cdac0f
AlertType, // 5ab91217
AndroidKeyboardEvent, // e03becc8
- Animated, // ed7eb912
+ Animated, // f39d3c6f
AppConfig, // ebddad4b
AppRegistry, // 6cdee1d6
AppState, // 12012be5
@@ -6215,7 +6217,7 @@ export {
TVViewPropsIOS, // 330ce7b5
TargetedEvent, // 16e98910
TaskProvider, // 266dedf2
- Text, // e55ac2e2
+ Text, // 0620c789
TextContentType, // 239b3ecc
TextInput, // 2e89b91d
TextInputAndroidProps, // 3f09ce49