From fc42d5bbb9906c37c2f62d26c46f6e3191cccd01 Mon Sep 17 00:00:00 2001 From: Daksh Bhardwaj Date: Thu, 8 Sep 2022 03:09:11 -0700 Subject: [PATCH] feat: add userSelect style equivalent to selectable (#34575) Summary: This adds support for the `userSelect` style attribute, mapping the already existing selectable attribute as requested on https://github.com/facebook/react-native/issues/34425. This PR also updates the TextExample.android and TestExample.ios on the RNTester in order to facilitate the manual QA of this. ## Changelog [General] [Added] - Add support for `userSelect` style Pull Request resolved: https://github.com/facebook/react-native/pull/34575 Test Plan: - open the RNTester app and navigate to the Text page - Check the `Selectable Text` through the Selectable text section Reviewed By: yungsters Differential Revision: D39252798 Pulled By: jacdebug fbshipit-source-id: f7fabf20ee68778d75461f511c56f94d0d756d9c --- .../View/ReactNativeStyleAttributes.js | 1 + Libraries/StyleSheet/StyleSheetTypes.js | 1 + Libraries/Text/Text.js | 19 ++++++++++++++++++- .../js/examples/Text/TextExample.android.js | 10 ++++++++++ .../js/examples/Text/TextExample.ios.js | 10 ++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/View/ReactNativeStyleAttributes.js b/Libraries/Components/View/ReactNativeStyleAttributes.js index 620dd8fdad98e8..dbf500a25925fd 100644 --- a/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -134,6 +134,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { textShadowOffset: true, textShadowRadius: true, textTransform: true, + userSelect: true, writingDirection: true, /** diff --git a/Libraries/StyleSheet/StyleSheetTypes.js b/Libraries/StyleSheet/StyleSheetTypes.js index a78e58061d8be5..ee11fab8aa5d26 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.js +++ b/Libraries/StyleSheet/StyleSheetTypes.js @@ -632,6 +632,7 @@ export type ____TextStyle_InternalCore = $ReadOnly<{ textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed', textDecorationColor?: ____ColorValue_Internal, textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase', + userSelect?: 'auto' | 'text' | 'none' | 'contain' | 'all', writingDirection?: 'auto' | 'ltr' | 'rtl', }>; diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 57b6a2ea82ca28..2337efee07d3c1 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -20,6 +20,7 @@ import {NativeText, NativeVirtualText} from './TextNativeComponent'; import {type TextProps} from './TextProps'; import * as React from 'react'; import {useContext, useMemo, useState} from 'react'; +import flattenStyle from '../StyleSheet/flattenStyle'; /** * Text is the fundamental component for displaying text. @@ -152,7 +153,13 @@ const Text: React.AbstractComponent< ? null : processColor(restProps.selectionColor); - let style = restProps.style; + let style = flattenStyle(restProps.style); + + let _selectable = restProps.selectable; + if (style?.userSelect != null) { + _selectable = userSelectToSelectableMap[style.userSelect]; + } + if (__DEV__) { if (PressabilityDebug.isEnabled() && onPress != null) { style = StyleSheet.compose(restProps.style, { @@ -182,6 +189,7 @@ const Text: React.AbstractComponent< {...eventHandlersForText} isHighlighted={isHighlighted} isPressable={isPressable} + selectable={_selectable} numberOfLines={numberOfLines} selectionColor={selectionColor} style={style} @@ -193,6 +201,7 @@ const Text: React.AbstractComponent< {...restProps} {...eventHandlersForText} disabled={_disabled} + selectable={_selectable} accessible={_accessible} accessibilityState={_accessibilityState} allowFontScaling={allowFontScaling !== false} @@ -222,4 +231,12 @@ function useLazyInitialization(newValue: boolean): boolean { return oldValue; } +const userSelectToSelectableMap = { + auto: true, + text: true, + none: false, + contain: true, + all: true, +}; + module.exports = Text; diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js index 8980335aba1361..45826991731aca 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -982,4 +982,14 @@ exports.examples = [ return ; }, }, + { + title: 'Selectable Text', + render: function (): React.Node { + return ( + + Text element is selectable + + ); + }, + }, ]; diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 96c19353c25c5c..d24c35ca1638eb 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1227,4 +1227,14 @@ exports.examples = [ ); }, }, + { + title: 'Selectable Text', + render: function (): React.Node { + return ( + + Text element is selectable + + ); + }, + }, ];