From 32b6f319bafbd6bc2fdab458d38f2d83b0514ad2 Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Dall'Agnol Date: Mon, 3 Oct 2022 05:57:30 -0700 Subject: [PATCH] feat: Add support for verticalAlign style (#34567) Summary: This adds support for the `verticalAlign` style attribute, mapping the already existing `textAlignVertical` attribute as requested on https://github.com/facebook/react-native/issues/34425. This PR also updates the TextExample.android on the RNTester in order to facilitate the manual QA of this. ## Changelog [Android] [Added] - Add support for verticalAlign style Pull Request resolved: https://github.com/facebook/react-native/pull/34567 Test Plan: 1. On Android open the RNTester app and navigate to the Text page 2. Check the text alignment through the `Text alignment` section https://user-images.githubusercontent.com/11707729/188051914-bf15f7eb-e53f-4de5-8033-d1b572352935.mov Reviewed By: jacdebug Differential Revision: D39771237 Pulled By: cipolleschi fbshipit-source-id: d2a81bec1edd8d49a0fcd36a42fea53734909739 --- Libraries/Components/TextInput/TextInput.d.ts | 5 +++++ Libraries/Components/TextInput/TextInput.js | 16 ++++++++++++++ .../View/ReactNativeStyleAttributes.js | 1 + Libraries/StyleSheet/StyleSheetTypes.d.ts | 1 + Libraries/StyleSheet/StyleSheetTypes.js | 1 + Libraries/Text/Text.js | 14 ++++++++++++ .../js/examples/Text/TextExample.android.js | 22 +++++++++++++++++++ 7 files changed, 60 insertions(+) diff --git a/Libraries/Components/TextInput/TextInput.d.ts b/Libraries/Components/TextInput/TextInput.d.ts index 9cbcebaaac82ae..3ad310bd8ced7f 100644 --- a/Libraries/Components/TextInput/TextInput.d.ts +++ b/Libraries/Components/TextInput/TextInput.d.ts @@ -435,6 +435,11 @@ export interface TextInputAndroidProps { * When false, it will prevent the soft keyboard from showing when the field is focused. The default value is true */ showSoftInputOnFocus?: boolean | undefined; + + /** + * Vertically align text when `multiline` is set to true + */ + verticalAlign?: 'auto' | 'top' | 'bottom' | 'middle' | undefined; } /** diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 91b8e22f6d7169..31ebc1f81497bf 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -18,6 +18,7 @@ import type {ViewProps} from '../View/ViewPropTypes'; import type {TextInputType} from './TextInput.flow'; import usePressability from '../../Pressability/usePressability'; +import flattenStyle from '../../StyleSheet/flattenStyle'; import StyleSheet, { type ColorValue, type TextStyleProp, @@ -1599,6 +1600,13 @@ const ExportedForwardRef: React.AbstractComponent< React.ElementRef> & ImperativeMethods, >, ) { + const style = flattenStyle(restProps.style); + + if (style?.verticalAlign != null) { + style.textAlignVertical = + verticalAlignToTextAlignVerticalMap[style.verticalAlign]; + } + return ( ); }); @@ -1659,5 +1668,12 @@ const styles = StyleSheet.create({ }, }); +const verticalAlignToTextAlignVerticalMap = { + auto: 'auto', + top: 'top', + bottom: 'bottom', + middle: 'center', +}; + // $FlowFixMe[unclear-type] Unclear type. Using `any` type is not safe. module.exports = ((ExportedForwardRef: any): TextInputType); diff --git a/Libraries/Components/View/ReactNativeStyleAttributes.js b/Libraries/Components/View/ReactNativeStyleAttributes.js index 1c1818fa5221d9..2511ad4755d851 100644 --- a/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -138,6 +138,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { textShadowRadius: true, textTransform: true, userSelect: true, + verticalAlign: true, writingDirection: true, /** diff --git a/Libraries/StyleSheet/StyleSheetTypes.d.ts b/Libraries/StyleSheet/StyleSheetTypes.d.ts index 1346e434f61b33..1df286e2141cc5 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -261,6 +261,7 @@ export interface TextStyleIOS extends ViewStyle { export interface TextStyleAndroid extends ViewStyle { textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center' | undefined; + verticalAlign?: 'auto' | 'top' | 'bottom' | 'middle' | undefined; includeFontPadding?: boolean | undefined; } diff --git a/Libraries/StyleSheet/StyleSheetTypes.js b/Libraries/StyleSheet/StyleSheetTypes.js index 5ade22fdf0d29b..5099d49f313d47 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.js +++ b/Libraries/StyleSheet/StyleSheetTypes.js @@ -671,6 +671,7 @@ export type ____TextStyle_InternalCore = $ReadOnly<{ textDecorationColor?: ____ColorValue_Internal, textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase', userSelect?: 'auto' | 'text' | 'none' | 'contain' | 'all', + verticalAlign?: 'auto' | 'top' | 'bottom' | 'middle', writingDirection?: 'auto' | 'ltr' | 'rtl', }>; diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 10692df2e9aaee..ac427bf8c736ae 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -178,6 +178,13 @@ const Text: React.AbstractComponent< _selectable = userSelectToSelectableMap[style.userSelect]; } + if (style?.verticalAlign != null) { + style = StyleSheet.compose(style, { + textAlignVertical: + verticalAlignToTextAlignVerticalMap[style.verticalAlign], + }); + } + if (__DEV__) { if (PressabilityDebug.isEnabled() && onPress != null) { style = StyleSheet.compose(restProps.style, { @@ -275,4 +282,11 @@ const userSelectToSelectableMap = { all: true, }; +const verticalAlignToTextAlignVerticalMap = { + auto: 'auto', + top: 'top', + bottom: 'bottom', + middle: 'center', +}; + 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 6779684096e8b8..5f5b4a1f7f2d5a 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -1001,4 +1001,26 @@ exports.examples = [ ); }, }, + { + title: 'Text alignment', + render: function (): React.Node { + return ( + + + Text element aligned to the top via textAlignVertical + + + Text element aligned to the top via verticalAlign + + + Text element aligned to the middle via textAlignVertical + + + Text element aligned to the middle via verticalAlign + + + ); + }, + }, ];