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