From 4084a9bef6e26180201e1021e47acda35332cd5f Mon Sep 17 00:00:00 2001 From: pac-guerreiro <> Date: Wed, 22 Mar 2023 20:09:46 +0000 Subject: [PATCH 1/5] fix: rtl not being detected correctly on web --- docs/src/components/GetStartedButtons.tsx | 4 +- example/src/DrawerItems.tsx | 4 +- example/src/ExampleList.tsx | 4 +- .../AnimatedFABExample/AnimatedFABExample.tsx | 6 +- .../AnimatedFABExample/CustomFABControls.tsx | 2 +- example/src/Examples/ChipExample.tsx | 4 +- .../Dialogs/DialogWithLoadingIndicator.tsx | 6 +- .../Examples/Dialogs/DialogWithRadioBtns.tsx | 2 +- example/src/Examples/TeamDetails.tsx | 6 +- example/src/Examples/TextInputExample.tsx | 2 +- example/src/ScreenWrapper.tsx | 4 +- example/src/index.tsx | 11 +- src/components/Appbar/Appbar.tsx | 4 +- src/components/Appbar/AppbarBackIcon.tsx | 8 +- src/components/Appbar/utils.ts | 4 +- .../BottomNavigation/BottomNavigationBar.tsx | 2 +- src/components/Button/Button.tsx | 40 +++---- src/components/Card/CardActions.tsx | 2 +- src/components/Card/CardTitle.tsx | 8 +- src/components/Chip/Chip.tsx | 30 ++--- .../DataTable/DataTablePagination.tsx | 24 ++-- src/components/DataTable/DataTableTitle.tsx | 9 +- src/components/Dialog/DialogActions.tsx | 2 +- src/components/Divider.tsx | 8 +- src/components/Drawer/DrawerCollapsedItem.tsx | 2 +- src/components/Drawer/DrawerItem.tsx | 12 +- src/components/Drawer/DrawerSection.tsx | 2 +- src/components/FAB/AnimatedFAB.tsx | 13 ++- src/components/FAB/FABGroup.tsx | 4 +- src/components/FAB/utils.ts | 8 +- src/components/Icon.tsx | 11 +- src/components/List/ListAccordion.tsx | 7 +- src/components/List/ListImage.tsx | 4 +- src/components/List/ListItem.tsx | 10 +- src/components/List/utils.ts | 22 ++-- src/components/Menu/Menu.tsx | 36 ++++-- src/components/Menu/MenuItem.tsx | 4 +- src/components/ProgressBar.tsx | 15 ++- src/components/Searchbar.tsx | 22 ++-- .../SegmentedButtons/SegmentedButtonItem.tsx | 2 +- src/components/Snackbar.tsx | 15 ++- src/components/TextInput/Adornment/types.tsx | 2 +- src/components/TextInput/Label/InputLabel.tsx | 6 +- .../TextInput/Label/LabelBackground.tsx | 4 +- src/components/TextInput/TextInput.tsx | 2 +- src/components/TextInput/TextInputFlat.tsx | 37 +++--- .../TextInput/TextInputOutlined.tsx | 12 +- src/components/TextInput/helpers.tsx | 12 +- src/components/TextInput/types.tsx | 4 +- src/components/Typography/AnimatedText.tsx | 7 +- src/components/Typography/Text.tsx | 11 +- src/components/Typography/v2/StyledText.tsx | 6 +- .../__tests__/Appbar/Appbar.test.tsx | 4 +- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 16 +-- src/components/__tests__/Button.test.tsx | 16 +-- src/components/__tests__/Dialog.test.tsx | 4 +- .../__snapshots__/DrawerSection.test.tsx.snap | 4 +- src/components/__tests__/FABGroup.test.tsx | 2 +- src/components/__tests__/ListImage.test.tsx | 2 +- src/components/__tests__/ListUtils.test.tsx | 14 +-- src/components/__tests__/Searchbar.test.tsx | 2 +- src/components/__tests__/Snackbar.test.tsx | 2 +- src/components/__tests__/Surface.test.tsx | 8 +- src/components/__tests__/TextInput.test.tsx | 55 +-------- .../BottomNavigation.test.tsx.snap | 80 ++++++------- .../__snapshots__/Button.test.tsx.snap | 36 +++--- .../__snapshots__/Chip.test.tsx.snap | 88 +++++++------- .../__snapshots__/DataTable.test.tsx.snap | 32 +++--- .../__snapshots__/DrawerItem.test.tsx.snap | 36 +++--- .../__snapshots__/ListAccordion.test.tsx.snap | 4 +- .../__snapshots__/ListItem.test.tsx.snap | 50 ++++---- .../__snapshots__/ListSection.test.tsx.snap | 48 ++++---- .../__snapshots__/Menu.test.tsx.snap | 8 +- .../__snapshots__/MenuItem.test.tsx.snap | 10 +- .../__snapshots__/Searchbar.test.tsx.snap | 20 ++-- .../SegmentedButton.test.tsx.snap | 2 +- .../__snapshots__/Snackbar.test.tsx.snap | 8 +- .../__snapshots__/TextInput.test.tsx.snap | 108 +++++++++--------- src/core/Localization.tsx | 37 ++++++ src/core/Provider.tsx | 40 ++++++- .../views/MaterialBottomTabView.tsx | 6 +- src/utils/__tests__/splitStyles.test.ts | 2 +- 82 files changed, 637 insertions(+), 595 deletions(-) create mode 100644 src/core/Localization.tsx diff --git a/docs/src/components/GetStartedButtons.tsx b/docs/src/components/GetStartedButtons.tsx index d86e2fee97..9cfb97cebc 100644 --- a/docs/src/components/GetStartedButtons.tsx +++ b/docs/src/components/GetStartedButtons.tsx @@ -21,7 +21,7 @@ const styles = StyleSheet.create({ paddingBottom: 16, }, button: { - marginRight: 16, + marginEnd: 16, }, }); @@ -70,7 +70,7 @@ const Shimmer = () => { { toggleRTL(); - I18nManager.forceRTL(!isRTL); - if (isWeb) { + if (!isWeb) { + I18nManager.forceRTL(!isRTL); Updates.reloadAsync(); } }; diff --git a/example/src/ExampleList.tsx b/example/src/ExampleList.tsx index 5c41d671a5..dd4a8f80bd 100644 --- a/example/src/ExampleList.tsx +++ b/example/src/ExampleList.tsx @@ -153,8 +153,8 @@ export default function ExampleList({ navigation }: Props) { contentContainerStyle={{ backgroundColor: colors.background, paddingBottom: safeArea.bottom, - paddingLeft: safeArea.left, - paddingRight: safeArea.right, + paddingStart: safeArea.left, + paddingEnd: safeArea.right, }} style={{ backgroundColor: colors.background, diff --git a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx index fd190c9953..a2b1d54da1 100644 --- a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx +++ b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx @@ -177,7 +177,7 @@ const styles = StyleSheet.create({ paddingBottom: 60, }, avatar: { - marginRight: 16, + marginEnd: 16, marginTop: 8, }, flex: { @@ -204,7 +204,7 @@ const styles = StyleSheet.create({ fontWeight: 'bold', }, icon: { - marginLeft: 16, + marginStart: 16, alignSelf: 'flex-end', }, date: { @@ -212,7 +212,7 @@ const styles = StyleSheet.create({ }, header: { fontSize: 14, - marginRight: 8, + marginEnd: 8, flex: 1, }, }); diff --git a/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx b/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx index 9825be219e..57cdb51c26 100644 --- a/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx +++ b/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx @@ -139,7 +139,7 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', }, controlItem: { - marginLeft: 16, + marginStart: 16, flexDirection: 'row', alignItems: 'center', }, diff --git a/example/src/Examples/ChipExample.tsx b/example/src/Examples/ChipExample.tsx index 3a60a6c41c..fd53492b1f 100644 --- a/example/src/Examples/ChipExample.tsx +++ b/example/src/Examples/ChipExample.tsx @@ -340,8 +340,8 @@ const styles = StyleSheet.create({ }, tiny: { marginVertical: 2, - marginRight: 2, - marginLeft: 2, + marginEnd: 2, + marginStart: 2, minHeight: 19, lineHeight: 19, }, diff --git a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx index 10ce6f010b..584d748415 100644 --- a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx +++ b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx @@ -25,7 +25,7 @@ const DialogWithLoadingIndicator = ({ Loading..... @@ -40,8 +40,8 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', }, - marginRight: { - marginRight: 16, + marginEnd: { + marginEnd: 16, }, }); diff --git a/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx b/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx index 966422369e..8893cece09 100644 --- a/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx +++ b/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx @@ -106,6 +106,6 @@ const styles = StyleSheet.create({ paddingVertical: 8, }, text: { - paddingLeft: 8, + paddingStart: 8, }, }); diff --git a/example/src/Examples/TeamDetails.tsx b/example/src/Examples/TeamDetails.tsx index 5e56b5ebf3..e4907e5583 100644 --- a/example/src/Examples/TeamDetails.tsx +++ b/example/src/Examples/TeamDetails.tsx @@ -264,7 +264,7 @@ const styles = StyleSheet.create({ flexDirection: 'row', }, score: { - marginRight: 16, + marginEnd: 16, }, fab: { position: 'absolute', @@ -282,10 +282,10 @@ const styles = StyleSheet.create({ flexDirection: 'row', }, chipsContent: { - paddingLeft: 8, + paddingStart: 8, paddingVertical: 8, }, chip: { - marginRight: 8, + marginEnd: 8, }, }); diff --git a/example/src/Examples/TextInputExample.tsx b/example/src/Examples/TextInputExample.tsx index 8e4ce574fd..5e668d1a85 100644 --- a/example/src/Examples/TextInputExample.tsx +++ b/example/src/Examples/TextInputExample.tsx @@ -660,7 +660,7 @@ const styles = StyleSheet.create({ margin: 8, }, inputContentStyle: { - paddingLeft: 50, + paddingStart: 50, fontWeight: 'bold', fontStyle: 'italic', }, diff --git a/example/src/ScreenWrapper.tsx b/example/src/ScreenWrapper.tsx index bb96250899..3291c81113 100644 --- a/example/src/ScreenWrapper.tsx +++ b/example/src/ScreenWrapper.tsx @@ -35,8 +35,8 @@ export default function ScreenWrapper({ { backgroundColor: theme.colors.background, paddingBottom: insets.bottom, - paddingLeft: insets.left, - paddingRight: insets.left, + paddingStart: insets.left, + paddingEnd: insets.left, }, ]; diff --git a/example/src/index.tsx b/example/src/index.tsx index 19cff80a1d..cc24dcf04e 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -147,11 +147,9 @@ export default function PaperExample() { // ignore error } - if (I18nManager.getConstants().isRTL !== rtl) { + if (!isWeb && I18nManager.getConstants().isRTL !== rtl) { I18nManager.forceRTL(rtl); - if (!isWeb) { - Updates.reloadAsync(); - } + Updates.reloadAsync(); } }; @@ -215,7 +213,10 @@ export default function PaperExample() { }; return ( - + { + const direction = useLocaleDirection(); const iosIconSize = size - 3; return Platform.OS === 'ios' ? ( @@ -13,7 +15,7 @@ const AppbarBackIcon = ({ size, color }: { size: number; color: string }) => { { width: size, height: size, - transform: [{ scaleX: I18nManager.getConstants().isRTL ? -1 : 1 }], + transform: [{ scaleX: direction === 'rtl' ? -1 : 1 }], }, ]} > @@ -31,7 +33,7 @@ const AppbarBackIcon = ({ size, color }: { size: number; color: string }) => { name="arrow-left" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> ); }; diff --git a/src/components/Appbar/utils.ts b/src/components/Appbar/utils.ts index a78cfceeed..9d1138dd67 100644 --- a/src/components/Appbar/utils.ts +++ b/src/components/Appbar/utils.ts @@ -134,9 +134,9 @@ const styles = StyleSheet.create({ alignItems: 'center', }, v2Spacing: { - marginLeft: 8, + marginStart: 8, }, v3Spacing: { - marginLeft: 12, + marginStart: 12, }, }); diff --git a/src/components/BottomNavigation/BottomNavigationBar.tsx b/src/components/BottomNavigation/BottomNavigationBar.tsx index a3d9f6e07f..b9b5c946a1 100644 --- a/src/components/BottomNavigation/BottomNavigationBar.tsx +++ b/src/components/BottomNavigation/BottomNavigationBar.tsx @@ -1011,7 +1011,7 @@ const styles = StyleSheet.create({ }, badgeContainer: { position: 'absolute', - left: 0, + start: 0, }, v3TouchableContainer: { paddingTop: 12, diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 36ff1d5c53..b6b7215bf2 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -389,45 +389,45 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, icon: { - marginLeft: 12, - marginRight: -4, + marginStart: 12, + marginEnd: -4, }, iconReverse: { - marginRight: 12, - marginLeft: -4, + marginEnd: 12, + marginStart: -4, }, /* eslint-disable react-native/no-unused-styles */ md3Icon: { - marginLeft: 16, - marginRight: -16, + marginStart: 16, + marginEnd: -16, }, md3IconCompact: { - marginLeft: 8, - marginRight: 0, + marginStart: 8, + marginEnd: 0, }, md3IconReverse: { - marginLeft: -16, - marginRight: 16, + marginStart: -16, + marginEnd: 16, }, md3IconReverseCompact: { - marginLeft: 0, - marginRight: 8, + marginStart: 0, + marginEnd: 8, }, md3IconTextMode: { - marginLeft: 12, - marginRight: -8, + marginStart: 12, + marginEnd: -8, }, md3IconTextModeCompact: { - marginLeft: 6, - marginRight: 0, + marginStart: 6, + marginEnd: 0, }, md3IconReverseTextMode: { - marginLeft: -8, - marginRight: 12, + marginStart: -8, + marginEnd: 12, }, md3IconReverseTextModeCompact: { - marginLeft: 0, - marginRight: 6, + marginStart: 0, + marginEnd: 6, }, /* eslint-enable react-native/no-unused-styles */ label: { diff --git a/src/components/Card/CardActions.tsx b/src/components/Card/CardActions.tsx index dfefad98b7..6c874f4cd3 100644 --- a/src/components/Card/CardActions.tsx +++ b/src/components/Card/CardActions.tsx @@ -73,7 +73,7 @@ const styles = StyleSheet.create({ padding: 8, }, button: { - marginLeft: 8, + marginStart: 8, }, }); diff --git a/src/components/Card/CardTitle.tsx b/src/components/Card/CardTitle.tsx index 66dc43d146..01f7a430ae 100644 --- a/src/components/Card/CardTitle.tsx +++ b/src/components/Card/CardTitle.tsx @@ -202,12 +202,12 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - paddingLeft: 16, + paddingStart: 16, }, left: { justifyContent: 'center', - marginRight: 16, + marginEnd: 16, height: LEFT_SIZE, width: LEFT_SIZE, }, @@ -220,13 +220,13 @@ const styles = StyleSheet.create({ title: { minHeight: 30, - paddingRight: 16, + paddingEnd: 16, }, subtitle: { minHeight: 20, marginVertical: 0, - paddingRight: 16, + paddingEnd: 16, }, }); diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index fda237a968..691b98ea8b 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -230,11 +230,11 @@ const Chip = ({ const elevationStyle = isV3 || Platform.OS === 'android' ? elevation : 0; const multiplier = isV3 ? (compact ? 1.5 : 2) : 1; const labelSpacings = { - marginRight: onClose ? 0 : 8 * multiplier, - marginLeft: avatar || icon || selected ? 4 * multiplier : 8 * multiplier, + marginEnd: onClose ? 0 : 8 * multiplier, + marginStart: avatar || icon || selected ? 4 * multiplier : 8 * multiplier, }; const contentSpacings = { - paddingRight: isV3 ? (onClose ? 34 : 0) : onClose ? 32 : 4, + paddingEnd: isV3 ? (onClose ? 34 : 0) : onClose ? 32 : 4, }; const labelTextStyle = { color: textColor, @@ -395,26 +395,26 @@ const styles = StyleSheet.create({ content: { flexDirection: 'row', alignItems: 'center', - paddingLeft: 4, + paddingStart: 4, position: 'relative', flexGrow: 1, }, md3Content: { - paddingLeft: 0, + paddingStart: 0, }, icon: { padding: 4, alignSelf: 'center', }, md3Icon: { - paddingLeft: 8, - paddingRight: 0, + paddingStart: 8, + paddingEnd: 0, }, closeIcon: { - marginRight: 4, + marginEnd: 4, }, md3CloseIcon: { - marginRight: 8, + marginEnd: 8, padding: 0, }, labelText: { @@ -433,25 +433,25 @@ const styles = StyleSheet.create({ borderRadius: 12, }, avatarWrapper: { - marginRight: 4, + marginEnd: 4, }, md3AvatarWrapper: { - marginLeft: 4, - marginRight: 0, + marginStart: 4, + marginEnd: 0, }, md3SelectedIcon: { - paddingLeft: 4, + paddingStart: 4, }, // eslint-disable-next-line react-native/no-color-literals avatarSelected: { position: 'absolute', top: 4, - left: 4, + start: 4, backgroundColor: 'rgba(0, 0, 0, .29)', }, closeButtonStyle: { position: 'absolute', - right: 0, + end: 0, height: '100%', justifyContent: 'center', alignItems: 'center', diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index 767b9fa3e4..95721f75ae 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -1,15 +1,10 @@ import * as React from 'react'; -import { - I18nManager, - StyleProp, - StyleSheet, - View, - ViewStyle, -} from 'react-native'; +import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import color from 'color'; import type { ThemeProp } from 'src/types'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import Button from '../Button/Button'; import IconButton from '../IconButton/IconButton'; @@ -93,6 +88,7 @@ const PaginationControls = ({ theme: themeOverrides, }: PaginationControlsProps) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; @@ -105,7 +101,7 @@ const PaginationControls = ({ name="page-first" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -121,7 +117,7 @@ const PaginationControls = ({ name="chevron-left" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -136,7 +132,7 @@ const PaginationControls = ({ name="chevron-right" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -152,7 +148,7 @@ const PaginationControls = ({ name="page-last" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -358,7 +354,7 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', flexDirection: 'row', alignItems: 'center', - paddingLeft: 16, + paddingStart: 16, flexWrap: 'wrap', }, optionsContainer: { @@ -368,11 +364,11 @@ const styles = StyleSheet.create({ }, label: { fontSize: 12, - marginRight: 16, + marginEnd: 16, }, button: { textAlign: 'center', - marginRight: 16, + marginEnd: 16, }, iconsContainer: { flexDirection: 'row', diff --git a/src/components/DataTable/DataTableTitle.tsx b/src/components/DataTable/DataTableTitle.tsx index 0fbe3f26d3..9a45f5d7ea 100644 --- a/src/components/DataTable/DataTableTitle.tsx +++ b/src/components/DataTable/DataTableTitle.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, GestureResponderEvent, - I18nManager, StyleProp, StyleSheet, TextStyle, @@ -13,6 +12,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -97,6 +97,7 @@ const DataTableTitle = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const { current: spinAnim } = React.useRef( new Animated.Value(sortDirection === 'ascending' ? 0 : 1) ); @@ -124,7 +125,7 @@ const DataTableTitle = ({ name="arrow-up" size={16} color={textColor} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> ) : null; @@ -142,7 +143,7 @@ const DataTableTitle = ({ // if numberOfLines causes wrap, center is lost. Align directly, sensitive to numeric and RTL numberOfLines > 1 ? numeric - ? I18nManager.getConstants().isRTL + ? direction === 'rtl' ? styles.leftText : styles.rightText : styles.centerText @@ -193,7 +194,7 @@ const styles = StyleSheet.create({ }, sorted: { - marginLeft: 8, + marginStart: 8, }, icon: { diff --git a/src/components/Dialog/DialogActions.tsx b/src/components/Dialog/DialogActions.tsx index 8dd5f9fd87..972ceb84aa 100644 --- a/src/components/Dialog/DialogActions.tsx +++ b/src/components/Dialog/DialogActions.tsx @@ -67,7 +67,7 @@ const DialogActions = (props: Props) => { uppercase: !isV3, style: [ isV3 && { - marginRight: i + 1 === actionsLength ? 0 : 8, + marginEnd: i + 1 === actionsLength ? 0 : 8, }, child.props.style, ], diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx index f30c8f44e2..338283308b 100644 --- a/src/components/Divider.tsx +++ b/src/components/Divider.tsx @@ -91,14 +91,14 @@ const Divider = ({ const styles = StyleSheet.create({ leftInset: { - marginLeft: 72, + marginStart: 72, }, v3LeftInset: { - marginLeft: 16, + marginStart: 16, }, horizontalInset: { - marginLeft: 16, - marginRight: 16, + marginStart: 16, + marginEnd: 16, }, bold: { height: 1, diff --git a/src/components/Drawer/DrawerCollapsedItem.tsx b/src/components/Drawer/DrawerCollapsedItem.tsx index ed77eeded3..82255dead7 100644 --- a/src/components/Drawer/DrawerCollapsedItem.tsx +++ b/src/components/Drawer/DrawerCollapsedItem.tsx @@ -267,7 +267,7 @@ const styles = StyleSheet.create({ }, badgeContainer: { position: 'absolute', - left: 20, + start: 20, bottom: 20, zIndex: 2, }, diff --git a/src/components/Drawer/DrawerItem.tsx b/src/components/Drawer/DrawerItem.tsx index df073778c8..92beacdcc3 100644 --- a/src/components/Drawer/DrawerItem.tsx +++ b/src/components/Drawer/DrawerItem.tsx @@ -139,7 +139,7 @@ const DrawerItem = ({ styles.label, { color: contentColor, - marginLeft: labelMargin, + marginStart: labelMargin, ...font, }, ]} @@ -165,8 +165,8 @@ const styles = StyleSheet.create({ v3Container: { justifyContent: 'center', height: 56, - marginLeft: 12, - marginRight: 12, + marginStart: 12, + marginEnd: 12, marginVertical: 0, }, wrapper: { @@ -175,8 +175,8 @@ const styles = StyleSheet.create({ padding: 8, }, v3Wrapper: { - marginLeft: 16, - marginRight: 24, + marginStart: 16, + marginEnd: 24, padding: 0, }, content: { @@ -185,7 +185,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, label: { - marginRight: 32, + marginEnd: 32, }, }); diff --git a/src/components/Drawer/DrawerSection.tsx b/src/components/Drawer/DrawerSection.tsx index 27759c9e71..9a4d38a4c6 100644 --- a/src/components/Drawer/DrawerSection.tsx +++ b/src/components/Drawer/DrawerSection.tsx @@ -92,7 +92,7 @@ const DrawerSection = ({ style={[ { color: titleColor, - marginLeft: titleMargin, + marginStart: titleMargin, ...font, }, ]} diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index cc4ec0b1bb..1881c7c82f 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -8,7 +8,6 @@ import { Animated, Easing, GestureResponderEvent, - I18nManager, Platform, ScrollView, StyleProp, @@ -20,6 +19,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { $RemoveChildren, ThemeProp } from '../../types'; import type { IconSource } from '../Icon'; @@ -126,7 +126,6 @@ const SCALE = 0.9; * ScrollView, * Text, * SafeAreaView, - * I18nManager, * } from 'react-native'; * import { AnimatedFAB } from 'react-native-paper'; * @@ -209,11 +208,11 @@ const AnimatedFAB = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const uppercase: boolean = uppercaseProp ?? !theme.isV3; const isIOS = Platform.OS === 'ios'; const isAnimatedFromRight = animateFrom === 'right'; const isIconStatic = iconMode === 'static'; - const { isRTL } = I18nManager; const { current: visibility } = React.useRef( new Animated.Value(visible ? 1 : 0) ); @@ -302,6 +301,7 @@ const AnimatedFAB = ({ isIconStatic, distance, animFAB, + direction, }); const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; @@ -452,9 +452,10 @@ const AnimatedFAB = ({ ellipsizeMode={'tail'} style={[ { - [isAnimatedFromRight || isRTL ? 'right' : 'left']: isIconStatic - ? textWidth - SIZE + borderRadius / (isV3 ? 1 : 2) - : borderRadius, + [isAnimatedFromRight || direction === 'rtl' ? 'right' : 'left']: + isIconStatic + ? textWidth - SIZE + borderRadius / (isV3 ? 1 : 2) + : borderRadius, }, { minWidth: textWidth, diff --git a/src/components/FAB/FABGroup.tsx b/src/components/FAB/FABGroup.tsx index e3ff9d159c..d88b712eb4 100644 --- a/src/components/FAB/FABGroup.tsx +++ b/src/components/FAB/FABGroup.tsx @@ -298,8 +298,8 @@ const FABGroup = ({ const { top, bottom, right, left } = useSafeAreaInsets(); const containerPaddings = { paddingBottom: bottom, - paddingRight: right, - paddingLeft: left, + paddingEnd: right, + paddingStart: left, paddingTop: top, }; diff --git a/src/components/FAB/utils.ts b/src/components/FAB/utils.ts index 1ac53884d1..f7fe42038a 100644 --- a/src/components/FAB/utils.ts +++ b/src/components/FAB/utils.ts @@ -1,7 +1,8 @@ -import { Animated, ColorValue, I18nManager, ViewStyle } from 'react-native'; +import type { Animated, ColorValue, ViewStyle } from 'react-native'; import color from 'color'; +import type { Direction } from '../../core/Localization'; import { black, white } from '../../styles/themes/v2/colors'; import type { InternalTheme } from '../../types'; import getContrastingColor from '../../utils/getContrastingColor'; @@ -11,6 +12,7 @@ type GetCombinedStylesProps = { isIconStatic: boolean; distance: number; animFAB: Animated.Value; + direction: Direction; }; type CombinedStyles = { @@ -32,9 +34,9 @@ export const getCombinedStyles = ({ isIconStatic, distance, animFAB, + direction, }: GetCombinedStylesProps): CombinedStyles => { - const { isRTL } = I18nManager; - + const isRTL = direction === 'rtl'; const defaultPositionStyles = { left: -distance, right: undefined }; const combinedStyles: CombinedStyles = { diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 4d0a600f41..b391e16941 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,11 +1,7 @@ import * as React from 'react'; -import { - I18nManager, - Image, - ImageSourcePropType, - Platform, -} from 'react-native'; +import { Image, ImageSourcePropType, Platform } from 'react-native'; +import { useLocaleDirection } from '../core/Localization'; import { Consumer as SettingsConsumer } from '../core/settings'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -75,10 +71,11 @@ const Icon = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const localeDirection = useLocaleDirection(); const direction = typeof source === 'object' && source.direction && source.source ? source.direction === 'auto' - ? I18nManager.getConstants().isRTL + ? localeDirection ? 'rtl' : 'ltr' : source.direction diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index ab54276117..e4d1a2a5ef 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { GestureResponderEvent, - I18nManager, StyleProp, StyleSheet, TextStyle, @@ -10,6 +9,7 @@ import { ViewStyle, } from 'react-native'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -166,6 +166,7 @@ const ListAccordion = ({ pointerEvents = 'none', }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const [expanded, setExpanded] = React.useState( expandedProp || false ); @@ -266,7 +267,7 @@ const ListAccordion = ({ name={isExpanded ? 'chevron-up' : 'chevron-down'} color={theme.isV3 ? descriptionColor : titleColor} size={24} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} @@ -320,7 +321,7 @@ const styles = StyleSheet.create({ margin: 8, }, child: { - paddingLeft: 64, + paddingStart: 64, }, content: { flex: 1, diff --git a/src/components/List/ListImage.tsx b/src/components/List/ListImage.tsx index 92cc7b5cc8..a0ae707901 100644 --- a/src/components/List/ListImage.tsx +++ b/src/components/List/ListImage.tsx @@ -81,12 +81,12 @@ const styles = StyleSheet.create({ video: { width: 100, height: 64, - marginLeft: 0, + marginStart: 0, }, videoV3: { width: 114, height: 64, - marginLeft: 0, + marginStart: 0, }, }); diff --git a/src/components/List/ListItem.tsx b/src/components/List/ListItem.tsx index b0b4516c69..b5b9b184fc 100644 --- a/src/components/List/ListItem.tsx +++ b/src/components/List/ListItem.tsx @@ -38,8 +38,8 @@ type Description = }) => React.ReactNode); interface Style { - marginLeft?: number; - marginRight?: number; + marginStart?: number; + marginEnd?: number; marginVertical?: number; alignSelf?: FlexAlignType; } @@ -259,7 +259,7 @@ const styles = StyleSheet.create({ }, containerV3: { paddingVertical: 8, - paddingRight: 24, + paddingEnd: 24, }, row: { flexDirection: 'row', @@ -276,10 +276,10 @@ const styles = StyleSheet.create({ }, item: { marginVertical: 6, - paddingLeft: 8, + paddingStart: 8, }, itemV3: { - paddingLeft: 16, + paddingStart: 16, }, content: { flex: 1, diff --git a/src/components/List/utils.ts b/src/components/List/utils.ts index 00c6cee1b2..51c713e2c3 100644 --- a/src/components/List/utils.ts +++ b/src/components/List/utils.ts @@ -18,25 +18,25 @@ export const getLeftStyles = ( isV3: boolean ) => { const stylesV3 = { - marginRight: 0, - marginLeft: 16, + marginEnd: 0, + marginStart: 16, alignSelf: alignToTop ? 'flex-start' : 'center', }; if (!description) { return { - ...styles.iconMarginLeft, + ...styles.iconmarginStart, ...styles.marginVerticalNone, ...(isV3 && { ...stylesV3 }), }; } if (!isV3) { - return styles.iconMarginLeft; + return styles.iconmarginStart; } return { - ...styles.iconMarginLeft, + ...styles.iconmarginStart, ...stylesV3, }; }; @@ -47,32 +47,32 @@ export const getRightStyles = ( isV3: boolean ) => { const stylesV3 = { - marginLeft: 16, + marginStart: 16, alignSelf: alignToTop ? 'flex-start' : 'center', }; if (!description) { return { - ...styles.iconMarginRight, + ...styles.iconmarginEnd, ...styles.marginVerticalNone, ...(isV3 && { ...stylesV3 }), }; } if (!isV3) { - return styles.iconMarginRight; + return styles.iconmarginEnd; } return { - ...styles.iconMarginRight, + ...styles.iconmarginEnd, ...stylesV3, }; }; const styles = StyleSheet.create({ marginVerticalNone: { marginVertical: 0 }, - iconMarginLeft: { marginLeft: 0, marginRight: 16 }, - iconMarginRight: { marginRight: 0 }, + iconmarginStart: { marginStart: 0, marginEnd: 16 }, + iconmarginEnd: { marginEnd: 0 }, }); export const getAccordionColors = ({ diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 925ca50f86..ba97baa124 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -6,7 +6,6 @@ import { Easing, EmitterSubscription, findNodeHandle, - I18nManager, Keyboard, KeyboardEvent as RNKeyboardEvent, LayoutRectangle, @@ -22,6 +21,7 @@ import { } from 'react-native'; import { APPROX_STATUSBAR_HEIGHT } from '../../constants'; +import { Direction, withLocaleDirection } from '../../core/Localization'; import { withInternalTheme } from '../../core/theming'; import type { $Omit, InternalTheme } from '../../types'; import { addEventListener } from '../../utils/addEventListener'; @@ -79,6 +79,10 @@ export type Props = { * testID to be used on tests. */ testID?: string; + /** + * Indicates the text direction + */ + direction: Direction; }; type Layout = $Omit<$Omit, 'y'>; @@ -155,9 +159,6 @@ const WINDOW_LAYOUT = Dimensions.get('window'); * wrapping is not necessary if you use Paper's `Modal` instead. */ class Menu extends React.Component { - // @component ./MenuItem.tsx - static Item = MenuItem; - static defaultProps = { statusBarHeight: APPROX_STATUSBAR_HEIGHT, overlayAccessibilityLabel: 'Close menu', @@ -418,6 +419,7 @@ class Menu extends React.Component { overlayAccessibilityLabel, keyboardShouldPersistTaps, testID, + direction, } = this.props; const { @@ -457,7 +459,14 @@ class Menu extends React.Component { ]; // We need to translate menu while animating scale to imitate transform origin for scale animation - const positionTransforms = []; + const positionTransforms: ( + | { + translateX: Animated.AnimatedInterpolation; + } + | { + translateY: Animated.AnimatedInterpolation; + } + )[] = []; // Check if menu fits horizontally and if not align it to right. if (left <= windowLayout.width - menuLayout.width - SCREEN_INDENT) { @@ -598,10 +607,10 @@ class Menu extends React.Component { ...(scrollableMenuHeight ? { height: scrollableMenuHeight } : {}), }; - const positionStyle = { + const positionStyle = (isRTL: boolean) => ({ top: this.isCoordinate(anchor) ? top : top + additionalVerticalValue, - ...(I18nManager.getConstants().isRTL ? { right: left } : { left }), - }; + ...(isRTL ? { right: left } : { left }), + }); return ( { }} collapsable={false} accessibilityViewIsModal={visible} - style={[styles.wrapper, positionStyle, style]} + style={[ + styles.wrapper, + positionStyle(direction === 'rtl'), + style, + ]} pointerEvents={visible ? 'box-none' : 'none'} onAccessibilityEscape={onDismiss} > @@ -671,4 +684,7 @@ const styles = StyleSheet.create({ }, }); -export default withInternalTheme(Menu); +export default Object.assign(withInternalTheme(withLocaleDirection(Menu)), { + // @component ./MenuItem.tsx + Item: MenuItem, +}); diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index e7ec4691e8..db6228a2e1 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -238,10 +238,10 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, md3LeadingIcon: { - marginLeft: 12, + marginStart: 12, }, md3WithoutLeadingIcon: { - marginLeft: 4, + marginStart: 4, }, }); diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index b5538fdff5..37e3e20f4d 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - I18nManager, LayoutChangeEvent, Platform, StyleProp, @@ -12,6 +11,7 @@ import { import setColor from 'color'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -47,7 +47,6 @@ export type Props = React.ComponentPropsWithRef & { const INDETERMINATE_DURATION = 2000; const INDETERMINATE_MAX_WIDTH = 0.6; -const { isRTL } = I18nManager; /** * Progress bar is an indicator used to present progress of some activity in the app. @@ -78,6 +77,7 @@ const ProgressBar = ({ animatedValue, ...rest }: Props) => { + const direction = useLocaleDirection(); const theme = useInternalTheme(themeOverrides); const { current: timer } = React.useRef( new Animated.Value(0) @@ -220,17 +220,20 @@ const ProgressBar = ({ ? { inputRange: [0, 0.5, 1], outputRange: [ - (isRTL ? 1 : -1) * 0.5 * width, - (isRTL ? 1 : -1) * + (direction === 'rtl' ? 1 : -1) * 0.5 * width, + (direction === 'rtl' ? 1 : -1) * 0.5 * INDETERMINATE_MAX_WIDTH * width, - (isRTL ? -1 : 1) * 0.7 * width, + (direction === 'rtl' ? -1 : 1) * 0.7 * width, ], } : { inputRange: [0, 1], - outputRange: [(isRTL ? 1 : -1) * 0.5 * width, 0], + outputRange: [ + (direction === 'rtl' ? 1 : -1) * 0.5 * width, + 0, + ], } ), }, diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 62c77a4a1b..93c2cfabbe 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, GestureResponderEvent, - I18nManager, Platform, StyleProp, StyleSheet, @@ -15,6 +14,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; import { forwardRef } from '../utils/forwardRef'; @@ -26,7 +26,7 @@ import MaterialCommunityIcon from './MaterialCommunityIcon'; import Surface from './Surface'; interface Style { - marginRight: number; + marginEnd: number; } export type Props = React.ComponentPropsWithRef & { @@ -202,6 +202,7 @@ const Searchbar = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const root = React.useRef(null); React.useImperativeHandle(ref, () => { @@ -295,7 +296,7 @@ const Searchbar = forwardRef( name="magnify" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )) } @@ -305,7 +306,9 @@ const Searchbar = forwardRef( ( name={isV3 ? 'close' : 'close-circle-outline'} color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )) } @@ -403,17 +406,16 @@ const styles = StyleSheet.create({ input: { flex: 1, fontSize: 18, - paddingLeft: 8, + paddingStart: 8, alignSelf: 'stretch', - textAlign: I18nManager.getConstants().isRTL ? 'right' : 'left', minWidth: 0, }, barModeInput: { - paddingLeft: 0, + paddingStart: 0, minHeight: 56, }, viewModeInput: { - paddingLeft: 0, + paddingStart: 0, minHeight: 72, }, elevation: { @@ -426,12 +428,12 @@ const styles = StyleSheet.create({ marginHorizontal: 16, }, rightStyle: { - marginRight: 16, + marginEnd: 16, }, v3ClearIcon: { position: 'absolute', right: 0, - marginLeft: 16, + marginStart: 16, }, v3ClearIconHidden: { display: 'none', diff --git a/src/components/SegmentedButtons/SegmentedButtonItem.tsx b/src/components/SegmentedButtons/SegmentedButtonItem.tsx index ad33861651..6457f5c2aa 100644 --- a/src/components/SegmentedButtons/SegmentedButtonItem.tsx +++ b/src/components/SegmentedButtons/SegmentedButtonItem.tsx @@ -146,7 +146,7 @@ const SegmentedButtonItem = ({ const iconSize = isV3 ? 18 : 16; const iconStyle = { - marginRight: label ? 5 : showCheckedIcon ? 3 : 0, + marginEnd: label ? 5 : showCheckedIcon ? 3 : 0, ...(label && { transform: [ { diff --git a/src/components/Snackbar.tsx b/src/components/Snackbar.tsx index db3c4832b5..352682d8f5 100644 --- a/src/components/Snackbar.tsx +++ b/src/components/Snackbar.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, Easing, - I18nManager, StyleProp, StyleSheet, View, @@ -12,6 +11,7 @@ import { import { useSafeAreaInsets } from 'react-native-safe-area-context'; import useLatestCallback from 'use-latest-callback'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { $RemoveChildren, ThemeProp } from '../types'; import Button from './Button/Button'; @@ -146,6 +146,7 @@ const Snackbar = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const { bottom, right, left } = useSafeAreaInsets(); const { current: opacity } = React.useRef( @@ -232,7 +233,7 @@ const Snackbar = ({ const isIconButton = isV3 && onIconPress; - const marginLeft = action ? -12 : -16; + const marginStart = action ? -12 : -16; const wrapperPaddings = { paddingBottom: bottom, @@ -293,7 +294,7 @@ const Snackbar = ({ > {renderChildrenWithWrapper()} {(action || isIconButton) && ( - + {action ? ( ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 6, - marginRight: 0, + marginStart: 6, + marginEnd: 0, }); }); @@ -202,8 +202,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 8, - marginRight: 0, + marginStart: 8, + marginEnd: 0, }); }) ); @@ -215,8 +215,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 12, - marginRight: -8, + marginStart: 12, + marginEnd: -8, }); }); @@ -229,8 +229,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 16, - marginRight: -16, + marginStart: 16, + marginEnd: -16, }); }) ); diff --git a/src/components/__tests__/Dialog.test.tsx b/src/components/__tests__/Dialog.test.tsx index 7d049caa01..50ffa1d091 100644 --- a/src/components/__tests__/Dialog.test.tsx +++ b/src/components/__tests__/Dialog.test.tsx @@ -80,8 +80,8 @@ describe('DialogActions', () => { paddingBottom: 24, paddingHorizontal: 24, }); - expect(dialogActionButtons[0]).toHaveStyle({ marginRight: 8 }); - expect(dialogActionButtons[1]).toHaveStyle({ marginRight: 0 }); + expect(dialogActionButtons[0]).toHaveStyle({ marginEnd: 8 }); + expect(dialogActionButtons[1]).toHaveStyle({ marginEnd: 0 }); }); it('should apply custom styles', () => { diff --git a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap index 6be4cc0dcd..134219c377 100644 --- a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap +++ b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap @@ -21,8 +21,8 @@ exports[`DrawerSection renders properly 1`] = ` }, undefined, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, Object { "height": 1, diff --git a/src/components/__tests__/FABGroup.test.tsx b/src/components/__tests__/FABGroup.test.tsx index b735cf5166..23714af440 100644 --- a/src/components/__tests__/FABGroup.test.tsx +++ b/src/components/__tests__/FABGroup.test.tsx @@ -147,7 +147,7 @@ describe('FABActions - labelStyle - containerStyle', () => { containerStyle: { padding: 16, backgroundColor: '#687456', - marginLeft: 16, + marginStart: 16, }, onPress() {}, icon: '', diff --git a/src/components/__tests__/ListImage.test.tsx b/src/components/__tests__/ListImage.test.tsx index 5248019277..283cc6afa5 100644 --- a/src/components/__tests__/ListImage.test.tsx +++ b/src/components/__tests__/ListImage.test.tsx @@ -13,7 +13,7 @@ const styles = StyleSheet.create({ video: { width: 114, height: 64, - marginLeft: 0, + marginStart: 0, }, container: { width: 30, diff --git a/src/components/__tests__/ListUtils.test.tsx b/src/components/__tests__/ListUtils.test.tsx index 4aeefb6ca9..98fa2b0141 100644 --- a/src/components/__tests__/ListUtils.test.tsx +++ b/src/components/__tests__/ListUtils.test.tsx @@ -6,20 +6,20 @@ import Text from '../Typography/Text'; const styles = StyleSheet.create({ leftItem: { - marginLeft: 0, - marginRight: 16, + marginStart: 0, + marginEnd: 16, }, leftItemV3: { - marginLeft: 16, - marginRight: 0, + marginStart: 16, + marginEnd: 0, alignSelf: 'center', }, rightItem: { - marginRight: 0, + marginEnd: 0, }, rightItemV3: { - marginLeft: 16, - marginRight: 0, + marginStart: 16, + marginEnd: 0, alignSelf: 'center', }, }); diff --git a/src/components/__tests__/Searchbar.test.tsx b/src/components/__tests__/Searchbar.test.tsx index fffd1032c5..65f22035b2 100644 --- a/src/components/__tests__/Searchbar.test.tsx +++ b/src/components/__tests__/Searchbar.test.tsx @@ -118,7 +118,7 @@ it('renders clear icon wrapper, with appropriate style for v3', () => { expect(getByTestId('search-bar-icon-wrapper')).toHaveStyle({ position: 'absolute', right: 0, - marginLeft: 16, + marginStart: 16, }); update( diff --git a/src/components/__tests__/Snackbar.test.tsx b/src/components/__tests__/Snackbar.test.tsx index 41aec30f77..f60e566549 100644 --- a/src/components/__tests__/Snackbar.test.tsx +++ b/src/components/__tests__/Snackbar.test.tsx @@ -16,7 +16,7 @@ const styles = StyleSheet.create({ backgroundColor: red200, padding: 15, }, - text: { color: white, marginLeft: 10, flexWrap: 'wrap', flexShrink: 1 }, + text: { color: white, marginStart: 10, flexWrap: 'wrap', flexShrink: 1 }, }); // Make sure any animation finishes before checking the snapshot results diff --git a/src/components/__tests__/Surface.test.tsx b/src/components/__tests__/Surface.test.tsx index d56fea2c82..4a6a414a0e 100644 --- a/src/components/__tests__/Surface.test.tsx +++ b/src/components/__tests__/Surface.test.tsx @@ -46,8 +46,8 @@ describe('Surface', () => { ${'width'} | ${'42%'} ${'height'} | ${'32.5%'} ${'margin'} | ${13} - ${'marginLeft'} | ${13.1} - ${'marginRight'} | ${13.2} + ${'marginStart'} | ${13.1} + ${'marginEnd'} | ${13.2} ${'marginTop'} | ${13.3} ${'marginBottom'} | ${13.4} ${'marginHorizontal'} | ${13.5} @@ -77,8 +77,8 @@ describe('Surface', () => { it.each` property | value ${'padding'} | ${12} - ${'paddingLeft'} | ${12.1} - ${'paddingRight'} | ${12.2} + ${'paddingStart'} | ${12.1} + ${'paddingEnd'} | ${12.2} ${'paddingTop'} | ${12.3} ${'paddingBottom'} | ${12.4} ${'paddingHorizontal'} | ${12.5} diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index 0c228f02e2..8297c9ee72 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ import * as React from 'react'; -import { StyleSheet, Text, Platform, I18nManager } from 'react-native'; +import { StyleSheet, Text, Platform } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; import color from 'color'; @@ -27,7 +27,7 @@ const style = StyleSheet.create({ lineHeight: 22, }, contentStyle: { - paddingLeft: 20, + paddingStart: 20, }, }); @@ -181,7 +181,7 @@ it('correctly applies a component as the text label', () => { expect(toJSON()).toMatchSnapshot(); }); -it('correctly applies paddingLeft from contentStyleProp', () => { +it('correctly applies paddingStart from contentStyleProp', () => { const { toJSON } = render( { expect(getByTestId('text-input').props.placeholder).toBe(' '); }); -it('correctly applies padding offset to input label on Android when RTL', () => { - Platform.OS = 'android'; - I18nManager.isRTL = true; - - const { getByTestId } = render( - - } - right={ - - } - /> - ); - - expect(getByTestId('text-input-flat-label-active')).toHaveStyle({ - paddingLeft: 56, - paddingRight: 16, - }); - - I18nManager.isRTL = false; -}); - -it('correctly applies padding offset to input label on Android when LTR', () => { - Platform.OS = 'android'; - - const { getByTestId } = render( - - } - right={ - - } - /> - ); - - expect(getByTestId('text-input-flat-label-active')).toHaveStyle({ - paddingLeft: 16, - paddingRight: 56, - }); -}); - it('calls onLayout on right-side affix adornment', () => { const onLayoutMock = jest.fn(); const nativeEventMock = { diff --git a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap index 8078033e8f..9b132de57b 100644 --- a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap @@ -245,8 +245,8 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -479,8 +479,8 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -957,8 +957,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1150,8 +1150,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1343,8 +1343,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1705,8 +1705,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1898,8 +1898,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2091,8 +2091,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2584,8 +2584,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2892,8 +2892,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3200,8 +3200,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3508,8 +3508,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3816,8 +3816,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4298,8 +4298,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4558,8 +4558,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4818,8 +4818,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5078,8 +5078,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5338,8 +5338,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5696,8 +5696,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5869,8 +5869,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6042,8 +6042,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6389,8 +6389,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6549,8 +6549,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6709,8 +6709,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6869,8 +6869,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7029,8 +7029,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7419,8 +7419,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7727,8 +7727,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8035,8 +8035,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8517,8 +8517,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8777,8 +8777,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9037,8 +9037,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9461,8 +9461,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9769,8 +9769,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10077,8 +10077,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10559,8 +10559,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10819,8 +10819,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11079,8 +11079,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11339,8 +11339,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11599,8 +11599,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, diff --git a/src/components/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/__tests__/__snapshots__/Button.test.tsx.snap index 8b7bb4d2b8..0f15771937 100644 --- a/src/components/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Button.test.tsx.snap @@ -853,16 +853,16 @@ exports[`renders button with icon 1`] = ` style={ Array [ Object { - "marginLeft": 12, - "marginRight": -4, + "marginEnd": -4, + "marginStart": 12, }, Object { - "marginLeft": 16, - "marginRight": -16, + "marginEnd": -16, + "marginStart": 16, }, Object { - "marginLeft": 12, - "marginRight": -8, + "marginEnd": -8, + "marginStart": 12, }, ] } @@ -1061,16 +1061,16 @@ exports[`renders button with icon in reverse order 1`] = ` style={ Array [ Object { - "marginLeft": -4, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -4, }, Object { - "marginLeft": -16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": -16, }, Object { - "marginLeft": -8, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -8, }, ] } @@ -1580,16 +1580,16 @@ exports[`renders loading button 1`] = ` }, Array [ Object { - "marginLeft": 12, - "marginRight": -4, + "marginEnd": -4, + "marginStart": 12, }, Object { - "marginLeft": 16, - "marginRight": -16, + "marginEnd": -16, + "marginStart": 16, }, Object { - "marginLeft": 12, - "marginRight": -8, + "marginEnd": -8, + "marginStart": 12, }, ], ] diff --git a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap index 7706df508a..e2dcbc1067 100644 --- a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap @@ -98,14 +98,14 @@ exports[`renders chip with close button 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 34, + "paddingEnd": 34, }, ] } @@ -118,8 +118,8 @@ exports[`renders chip with close button 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -195,8 +195,8 @@ exports[`renders chip with close button 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 8, }, undefined, ], @@ -211,10 +211,10 @@ exports[`renders chip with close button 1`] = ` style={ Object { "alignItems": "center", + "end": 0, "height": "100%", "justifyContent": "center", "position": "absolute", - "right": 0, } } > @@ -237,10 +237,10 @@ exports[`renders chip with close button 1`] = ` "padding": 4, }, Object { - "marginRight": 4, + "marginEnd": 4, }, Object { - "marginRight": 8, + "marginEnd": 8, "padding": 0, }, ] @@ -386,14 +386,14 @@ exports[`renders chip with custom close button 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 34, + "paddingEnd": 34, }, ] } @@ -406,8 +406,8 @@ exports[`renders chip with custom close button 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -483,8 +483,8 @@ exports[`renders chip with custom close button 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 8, }, undefined, ], @@ -499,10 +499,10 @@ exports[`renders chip with custom close button 1`] = ` style={ Object { "alignItems": "center", + "end": 0, "height": "100%", "justifyContent": "center", "position": "absolute", - "right": 0, } } > @@ -525,10 +525,10 @@ exports[`renders chip with custom close button 1`] = ` "padding": 4, }, Object { - "marginRight": 4, + "marginEnd": 4, }, Object { - "marginRight": 8, + "marginEnd": 8, "padding": 0, }, ] @@ -674,14 +674,14 @@ exports[`renders chip with icon 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -694,8 +694,8 @@ exports[`renders chip with icon 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -771,8 +771,8 @@ exports[`renders chip with icon 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], @@ -885,14 +885,14 @@ exports[`renders chip with onPress 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -930,8 +930,8 @@ exports[`renders chip with onPress 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, undefined, ], @@ -1044,14 +1044,14 @@ exports[`renders outlined disabled chip 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -1089,8 +1089,8 @@ exports[`renders outlined disabled chip 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, undefined, ], @@ -1203,14 +1203,14 @@ exports[`renders selected chip 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -1223,8 +1223,8 @@ exports[`renders selected chip 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -1300,8 +1300,8 @@ exports[`renders selected chip 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index 1cec04437d..502bdeea8a 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -222,7 +222,7 @@ exports[`renders data table pagination 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -248,7 +248,7 @@ exports[`renders data table pagination 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -564,7 +564,7 @@ exports[`renders data table pagination with fast-forward buttons 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -590,7 +590,7 @@ exports[`renders data table pagination with fast-forward buttons 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1194,7 +1194,7 @@ exports[`renders data table pagination with label 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -1220,7 +1220,7 @@ exports[`renders data table pagination with label 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1538,7 +1538,7 @@ exports[`renders data table pagination with options select 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -1574,7 +1574,7 @@ exports[`renders data table pagination with options select 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1600,7 +1600,7 @@ exports[`renders data table pagination with options select 1`] = ` "flex": undefined, "height": undefined, "left": undefined, - "marginRight": 16, + "marginEnd": 16, "opacity": undefined, "position": undefined, "right": undefined, @@ -1692,12 +1692,12 @@ exports[`renders data table pagination with options select 1`] = ` style={ Array [ Object { - "marginLeft": -4, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -4, }, Object { - "marginLeft": -16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": -16, }, false, ] @@ -1815,7 +1815,7 @@ exports[`renders data table pagination with options select 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -2517,7 +2517,7 @@ exports[`renders data table title with press handler 1`] = ` }, Object {}, Object { - "marginLeft": 8, + "marginStart": 8, }, undefined, ], @@ -2637,7 +2637,7 @@ exports[`renders data table title with sort icon 1`] = ` }, Object {}, Object { - "marginLeft": 8, + "marginStart": 8, }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap index d0127c87a7..f6e5bdb6b3 100644 --- a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap @@ -40,8 +40,8 @@ exports[`renders DrawerItem with icon 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -58,8 +58,8 @@ exports[`renders DrawerItem with icon 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -131,7 +131,7 @@ exports[`renders DrawerItem with icon 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -140,7 +140,7 @@ exports[`renders DrawerItem with icon 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 12, + "marginStart": 12, }, ], ] @@ -194,8 +194,8 @@ exports[`renders active DrawerItem 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -212,8 +212,8 @@ exports[`renders active DrawerItem 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -285,7 +285,7 @@ exports[`renders active DrawerItem 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(29, 25, 43, 1)", @@ -294,7 +294,7 @@ exports[`renders active DrawerItem 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 12, + "marginStart": 12, }, ], ] @@ -348,8 +348,8 @@ exports[`renders basic DrawerItem 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -366,8 +366,8 @@ exports[`renders basic DrawerItem 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -403,7 +403,7 @@ exports[`renders basic DrawerItem 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -412,7 +412,7 @@ exports[`renders basic DrawerItem 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 0, + "marginStart": 0, }, ], ] diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap index 8d56391e04..7423f11474 100644 --- a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap @@ -172,7 +172,7 @@ exports[`renders expanded accordion 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -192,7 +192,7 @@ exports[`renders expanded accordion 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap index 3de447dbad..c198db276e 100644 --- a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap @@ -25,7 +25,7 @@ exports[`renders list item with custom description 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -45,7 +45,7 @@ exports[`renders list item with custom description 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -195,14 +195,14 @@ exports[`renders list item with custom description 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -215,8 +215,8 @@ exports[`renders list item with custom description 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -292,8 +292,8 @@ exports[`renders list item with custom description 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], @@ -338,7 +338,7 @@ exports[`renders list item with custom title and description styles 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -358,7 +358,7 @@ exports[`renders list item with custom title and description styles 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -464,7 +464,7 @@ exports[`renders list item with left and right items 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -487,7 +487,7 @@ exports[`renders list item with left and right items 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -570,8 +570,8 @@ exports[`renders list item with left and right items 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, }, ] } @@ -642,7 +642,7 @@ exports[`renders list item with left item 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -668,8 +668,8 @@ exports[`renders list item with left item 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -716,7 +716,7 @@ exports[`renders list item with left item 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -786,7 +786,7 @@ exports[`renders list item with right item 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -806,7 +806,7 @@ exports[`renders list item with right item 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -879,7 +879,7 @@ exports[`renders list item with title and description 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -899,7 +899,7 @@ exports[`renders list item with title and description 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1001,7 +1001,7 @@ exports[`renders with a description with typeof number 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1021,7 +1021,7 @@ exports[`renders with a description with typeof number 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap index a1b6776ad1..19754ae036 100644 --- a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap @@ -240,7 +240,7 @@ exports[`renders list section with custom title style 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -266,8 +266,8 @@ exports[`renders list section with custom title style 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -314,7 +314,7 @@ exports[`renders list section with custom title style 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -381,7 +381,7 @@ exports[`renders list section with custom title style 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -407,8 +407,8 @@ exports[`renders list section with custom title style 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -455,7 +455,7 @@ exports[`renders list section with custom title style 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -739,7 +739,7 @@ exports[`renders list section with subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -765,8 +765,8 @@ exports[`renders list section with subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -813,7 +813,7 @@ exports[`renders list section with subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -880,7 +880,7 @@ exports[`renders list section with subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -906,8 +906,8 @@ exports[`renders list section with subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -954,7 +954,7 @@ exports[`renders list section with subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1200,7 +1200,7 @@ exports[`renders list section without subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1226,8 +1226,8 @@ exports[`renders list section without subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -1274,7 +1274,7 @@ exports[`renders list section without subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1341,7 +1341,7 @@ exports[`renders list section without subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1367,8 +1367,8 @@ exports[`renders list section without subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -1415,7 +1415,7 @@ exports[`renders list section without subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index daa8f91b9c..121c17ab4a 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -352,7 +352,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -459,7 +459,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -1027,7 +1027,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -1134,7 +1134,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap index 261b8d6f3f..538ad4e4c3 100644 --- a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap @@ -110,7 +110,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -265,7 +265,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -420,7 +420,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -575,7 +575,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -682,7 +682,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap index 37c0404991..ee9e5b8f1e 100644 --- a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap @@ -208,8 +208,7 @@ exports[`activity indicator snapshot test 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -218,10 +217,11 @@ exports[`activity indicator snapshot test 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] @@ -640,8 +640,7 @@ exports[`renders with placeholder 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -650,10 +649,11 @@ exports[`renders with placeholder 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] @@ -667,7 +667,7 @@ exports[`renders with placeholder 1`] = ` style={ Array [ Object { - "marginLeft": 16, + "marginStart": 16, "position": "absolute", "right": 0, }, @@ -1032,8 +1032,7 @@ exports[`renders with text 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -1042,10 +1041,11 @@ exports[`renders with text 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap index 069ef978c8..7167c7de71 100644 --- a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap @@ -92,7 +92,7 @@ exports[`renders checked segmented button with selected check 1`] = ` collapsable={false} style={ Object { - "marginRight": 3, + "marginEnd": 3, "transform": Array [ Object { "scale": 0, diff --git a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap index d913e9979d..58f7d7c5a7 100644 --- a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap @@ -206,7 +206,7 @@ exports[`renders snackbar with View & Text as a child 1`] = ` "color": "#ffffff", "flexShrink": 1, "flexWrap": "wrap", - "marginLeft": 10, + "marginStart": 10, } } > @@ -338,7 +338,7 @@ exports[`renders snackbar with action button 1`] = ` "minHeight": 48, }, Object { - "marginLeft": -12, + "marginStart": -12, }, ] } @@ -355,8 +355,8 @@ exports[`renders snackbar with action button 1`] = ` "flex": undefined, "height": undefined, "left": undefined, - "marginLeft": 4, - "marginRight": 8, + "marginEnd": 8, + "marginStart": 4, "opacity": undefined, "position": undefined, "right": undefined, diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index d397e7558e..006a8d0be1 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -77,13 +77,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -122,13 +122,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -174,8 +174,8 @@ exports[`correctly applies a component as the text label 1`] = ` "margin": 0, }, Object { - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, }, Object { "height": 56, @@ -286,13 +286,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -323,13 +323,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -367,8 +367,8 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "margin": 0, }, Object { - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, }, Object { "height": 56, @@ -455,7 +455,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "top": 0, "transform": Array [ Object { - "translateX": 3, + "translateX": -3, }, ], "zIndex": 3, @@ -473,12 +473,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 8, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 1, "paddingHorizontal": 0, "position": "absolute", + "start": 8, "textAlign": "left", "top": 59, "transform": Array [ @@ -513,12 +513,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -549,12 +549,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -626,7 +626,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` `; -exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` +exports[`correctly applies paddingStart from contentStyleProp 1`] = ` = React.ComponentType< + Omit +>; + +const context = createContext( + I18nManager.getConstants().isRTL ? 'rtl' : 'ltr' +); + +const useLocaleDirection = (): Direction => { + return useContext(context); +}; + +const withLocaleDirection = >( + WrappedComponent: React.ComponentType +): LocaleDirectionComponent => { + const displayName = + WrappedComponent.displayName || WrappedComponent.name || 'Component'; + + const Component = (props: Props) => { + const direction = useLocaleDirection(); + + return ; + }; + + Component.displayName = `withLocaleDirection(${displayName})`; + + return Component as LocaleDirectionComponent; +}; + +export const { Provider: LocalizationProvider } = context; + +export { Direction, useLocaleDirection, withLocaleDirection }; diff --git a/src/core/Provider.tsx b/src/core/Provider.tsx index eebe58de09..3cf28ccc08 100644 --- a/src/core/Provider.tsx +++ b/src/core/Provider.tsx @@ -3,13 +3,18 @@ import { AccessibilityInfo, Appearance, ColorSchemeName, + I18nManager, NativeEventSubscription, + Platform, + StyleSheet, + View, } from 'react-native'; import MaterialCommunityIcon from '../components/MaterialCommunityIcon'; import PortalHost from '../components/Portal/PortalHost'; import type { ThemeProp } from '../types'; import { addEventListener } from '../utils/addEventListener'; +import { Direction, LocalizationProvider } from './Localization'; import SafeAreaProviderCompat from './SafeAreaProviderCompat'; import { Provider as SettingsProvider, Settings } from './settings'; import { defaultThemesByVersion, ThemeProvider } from './theming'; @@ -18,6 +23,7 @@ export type Props = { children: React.ReactNode; theme?: ThemeProp; settings?: Settings; + direction?: Direction; }; const Provider = (props: Props) => { @@ -76,6 +82,12 @@ const Provider = (props: Props) => { }; }, [props.theme, isOnlyVersionInTheme]); + React.useEffect(() => { + if (props.direction && Platform.OS !== 'web') { + I18nManager.forceRTL(props.direction === 'rtl'); + } + }, [props.direction]); + const getTheme = () => { const themeVersion = props.theme?.version || 3; const scheme = colorScheme || 'light'; @@ -97,18 +109,36 @@ const Provider = (props: Props) => { }; }; - const { children, settings } = props; + const { + children, + settings, + direction = I18nManager.getConstants().isRTL ? 'rtl' : 'ltr', + } = props; return ( - - {/* @ts-expect-error check @callstack/react-theme-provider's children prop */} - {children} - + + + {/* @ts-expect-error check @callstack/react-theme-provider's children prop */} + + { + + {children} + + } + + + ); }; +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + export default Provider; diff --git a/src/react-navigation/views/MaterialBottomTabView.tsx b/src/react-navigation/views/MaterialBottomTabView.tsx index 1b16c87fc6..bdac0a9daa 100644 --- a/src/react-navigation/views/MaterialBottomTabView.tsx +++ b/src/react-navigation/views/MaterialBottomTabView.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { I18nManager, Platform, StyleSheet } from 'react-native'; +import { Platform, StyleSheet } from 'react-native'; import { CommonActions, @@ -11,6 +11,7 @@ import { import BottomNavigation from '../../components/BottomNavigation/BottomNavigation'; import MaterialCommunityIcon from '../../components/MaterialCommunityIcon'; +import { useLocaleDirection } from '../../core/Localization'; import { useNavigationLink } from '../adapter'; import type { MaterialBottomTabDescriptorMap, @@ -45,6 +46,7 @@ export default function MaterialBottomTabView({ ...rest }: Props) { const buildLink = useNavigationLink(); + const direction = useLocaleDirection(); const eventHandlerCallback = ( type: keyof MaterialBottomTabNavigationEventMap, @@ -110,7 +112,7 @@ export default function MaterialBottomTabView({ if (typeof options.tabBarIcon === 'string') { return ( { backgroundColor: 'red', marginTop: 1, marginBottom: 2, - marginLeft: 3, + marginStart: 3, padding: 4, borderTopLeftRadius: 5, borderTopRightRadius: 6, From de8e22f30cf046fa2fa96280fb0e0a97400ae06b Mon Sep 17 00:00:00 2001 From: Tomasz Janiczek Date: Mon, 17 Apr 2023 10:09:29 +0200 Subject: [PATCH 2/5] fix: various components v1 --- docs/docs/guides/05-react-native-web.md | 17 +++++- example/src/DrawerItems.tsx | 15 +---- example/src/Examples/BadgeExample.tsx | 2 +- src/components/Checkbox/CheckboxItem.tsx | 9 ++- src/components/FAB/AnimatedFAB.tsx | 8 ++- src/components/Menu/Menu.tsx | 23 ++------ src/components/Menu/MenuItem.tsx | 20 +++---- .../RadioButton/RadioButtonItem.tsx | 9 ++- .../SegmentedButtons/SegmentedButtonItem.tsx | 3 + src/components/SegmentedButtons/utils.ts | 32 ++++++++-- .../ToggleButton/ToggleButtonRow.tsx | 37 ++++++++++-- src/components/Typography/AnimatedText.tsx | 4 +- src/components/Typography/Text.tsx | 3 +- src/components/__tests__/Menu.test.tsx | 4 +- .../__snapshots__/Menu.test.tsx.snap | 36 ++++++----- .../__snapshots__/MenuItem.test.tsx.snap | 48 +++++++++------ src/core/Localization.tsx | 59 +++++++++++-------- src/core/Provider.tsx | 41 +++++++------ 18 files changed, 226 insertions(+), 144 deletions(-) diff --git a/docs/docs/guides/05-react-native-web.md b/docs/docs/guides/05-react-native-web.md index 14b2f14a7a..154b479a11 100644 --- a/docs/docs/guides/05-react-native-web.md +++ b/docs/docs/guides/05-react-native-web.md @@ -1,8 +1,8 @@ --- -title: Using on the Web +title: Usage on the Web --- -# Using on the Web +# Usage on the Web ## Pre-requisites @@ -270,6 +270,19 @@ You can also load these fonts using [`css-loader`](https://github.com/webpack-co The default theme in React Native Paper uses the Roboto font. You can add them to your project following [the instructions on its Google Fonts page](https://fonts.google.com/specimen/Roboto?selection.family=Roboto:100,300,400,500). +## RTL support for Web +Since `react-native-web` does not support `I18nManager`, in order to support RTL layouts you have to define text direction manually: + +```jsx +export default function Main() { + return ( + + + + ); +} +``` + ## We're done! You can run `webpack-dev-server` to run the webpack server and open your project in the browser. You can add the following script in your `package.json` under the `"scripts"` section to make it easier: diff --git a/example/src/DrawerItems.tsx b/example/src/DrawerItems.tsx index 68f20cf4ce..c2b404ddc1 100644 --- a/example/src/DrawerItems.tsx +++ b/example/src/DrawerItems.tsx @@ -1,8 +1,7 @@ import * as React from 'react'; -import { I18nManager, StyleSheet, View } from 'react-native'; +import { StyleSheet, View } from 'react-native'; import { DrawerContentScrollView } from '@react-navigation/drawer'; -import * as Updates from 'expo-updates'; import { Badge, Drawer, @@ -13,8 +12,6 @@ import { TouchableRipple, } from 'react-native-paper'; -import { isWeb } from '../utils'; - import { PreferencesContext, useExampleTheme } from './'; type Props = { @@ -115,14 +112,6 @@ const DrawerItems = ({ const { isV3, colors } = useExampleTheme(); - const _handleToggleRTL = () => { - toggleRTL(); - if (!isWeb) { - I18nManager.forceRTL(!isRTL); - Updates.reloadAsync(); - } - }; - const coloredLabelTheme = { colors: isV3 ? { @@ -183,7 +172,7 @@ const DrawerItems = ({ - + RTL diff --git a/example/src/Examples/BadgeExample.tsx b/example/src/Examples/BadgeExample.tsx index 9a7dab2a4b..274d116751 100644 --- a/example/src/Examples/BadgeExample.tsx +++ b/example/src/Examples/BadgeExample.tsx @@ -87,7 +87,7 @@ const styles = StyleSheet.create({ badge: { position: 'absolute', top: 4, - right: 0, + end: 0, }, label: { flex: 1, diff --git a/src/components/Checkbox/CheckboxItem.tsx b/src/components/Checkbox/CheckboxItem.tsx index 291b01c101..a225f74a7c 100644 --- a/src/components/Checkbox/CheckboxItem.tsx +++ b/src/components/Checkbox/CheckboxItem.tsx @@ -8,6 +8,7 @@ import { ViewStyle, } from 'react-native'; +import { useRTLOverwrite } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp, MD3TypescaleKey } from '../../types'; import TouchableRipple from '../TouchableRipple/TouchableRipple'; @@ -126,6 +127,7 @@ const CheckboxItem = ({ const theme = useInternalTheme(themeOverrides); const checkboxProps = { ...props, status, theme, disabled }; const isLeading = position === 'leading'; + const overwriteRTL = useRTLOverwrite(); let checkbox; if (mode === 'android') { @@ -140,7 +142,12 @@ const CheckboxItem = ({ const disabledTextColor = theme.isV3 ? theme.colors.onSurfaceDisabled : theme.colors.disabled; - const textAlign = isLeading ? 'right' : 'left'; + + let textAlign = isLeading ? 'right' : 'left'; + + if (overwriteRTL) { + textAlign = isLeading ? 'left' : 'right'; + } const computedStyle = { color: disabled ? disabledTextColor : textColor, diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index 1881c7c82f..f3cf0e1626 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -19,7 +19,7 @@ import { import color from 'color'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocaleDirection, useRTLOverwrite } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { $RemoveChildren, ThemeProp } from '../../types'; import type { IconSource } from '../Icon'; @@ -211,7 +211,11 @@ const AnimatedFAB = ({ const direction = useLocaleDirection(); const uppercase: boolean = uppercaseProp ?? !theme.isV3; const isIOS = Platform.OS === 'ios'; - const isAnimatedFromRight = animateFrom === 'right'; + const overwriteRTL = useRTLOverwrite(); + const isAnimatedFromRight = overwriteRTL + ? animateFrom !== 'right' + : animateFrom === 'right'; + const isIconStatic = iconMode === 'static'; const { current: visibility } = React.useRef( new Animated.Value(visible ? 1 : 0) diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index ba97baa124..a318f76079 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -21,7 +21,6 @@ import { } from 'react-native'; import { APPROX_STATUSBAR_HEIGHT } from '../../constants'; -import { Direction, withLocaleDirection } from '../../core/Localization'; import { withInternalTheme } from '../../core/theming'; import type { $Omit, InternalTheme } from '../../types'; import { addEventListener } from '../../utils/addEventListener'; @@ -79,10 +78,6 @@ export type Props = { * testID to be used on tests. */ testID?: string; - /** - * Indicates the text direction - */ - direction: Direction; }; type Layout = $Omit<$Omit, 'y'>; @@ -397,8 +392,7 @@ class Menu extends React.Component { }; private keyboardDidShow = (e: RNKeyboardEvent) => { - const keyboardHeight = e.endCoordinates.height; - this.keyboardHeight = keyboardHeight; + this.keyboardHeight = e.endCoordinates.height; }; private keyboardDidHide = () => { @@ -419,7 +413,6 @@ class Menu extends React.Component { overlayAccessibilityLabel, keyboardShouldPersistTaps, testID, - direction, } = this.props; const { @@ -607,10 +600,10 @@ class Menu extends React.Component { ...(scrollableMenuHeight ? { height: scrollableMenuHeight } : {}), }; - const positionStyle = (isRTL: boolean) => ({ + const positionStyle = { top: this.isCoordinate(anchor) ? top : top + additionalVerticalValue, - ...(isRTL ? { right: left } : { left }), - }); + [Platform.OS === 'web' ? 'start' : 'end']: left, + }; return ( { }} collapsable={false} accessibilityViewIsModal={visible} - style={[ - styles.wrapper, - positionStyle(direction === 'rtl'), - style, - ]} + style={[styles.wrapper, positionStyle, style]} pointerEvents={visible ? 'box-none' : 'none'} onAccessibilityEscape={onDismiss} > @@ -684,7 +673,7 @@ const styles = StyleSheet.create({ }, }); -export default Object.assign(withInternalTheme(withLocaleDirection(Menu)), { +export default Object.assign(withInternalTheme(Menu), { // @component ./MenuItem.tsx Item: MenuItem, }); diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index db6228a2e1..2ecd827050 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { AccessibilityState, GestureResponderEvent, + Platform, StyleProp, StyleSheet, TextStyle, @@ -21,6 +22,9 @@ import { MIN_WIDTH, } from './utils'; +const iconMarginKey = + Platform.OS === 'web' ? 'marginInlineStart' : 'marginStart'; + export type Props = { /** * Title text for the `MenuItem`. @@ -150,6 +154,9 @@ const MenuItem = ({ }; const newAccessibilityState = { ...accessibilityState, disabled }; + const iconMargin = { + [iconMarginKey]: leadingIcon ? 22 : 4, + }; return ( - + {leadingIcon ? ( { const theme = useInternalTheme(themeOverrides); + const overwriteRTL = useRTLOverwrite(); const checkScale = React.useRef(new Animated.Value(0)).current; @@ -138,6 +140,7 @@ const SegmentedButtonItem = ({ const segmentBorderRadius = getSegmentedButtonBorderRadius({ theme, segment, + overwriteRTL, }); const rippleColor = color(textColor).alpha(0.12).rgb().string(); diff --git a/src/components/SegmentedButtons/utils.ts b/src/components/SegmentedButtons/utils.ts index 87d343c8a9..ca68f8af68 100644 --- a/src/components/SegmentedButtons/utils.ts +++ b/src/components/SegmentedButtons/utils.ts @@ -58,28 +58,48 @@ export const getDisabledSegmentedButtonStyle = ({ return {}; }; +const defaultCSSBorders = { + topEndRadius: 'borderTopRightRadius', + bottomEndRadius: 'borderBottomRightRadius', + endWidth: 'borderRightWidth', + topStartRadius: 'borderTopLeftRadius', + bottomStartRadius: 'borderBottomLeftRadius', +}; + +const rtlCSSBorders = { + topEndRadius: 'borderTopLeftRadius', + bottomEndRadius: 'borderBottomLeftRadius', + endWidth: 'borderLeftWidth', + topStartRadius: 'borderTopRightRadius', + bottomStartRadius: 'borderBottomRightRadius', +}; + export const getSegmentedButtonBorderRadius = ({ segment, theme, + overwriteRTL, }: { theme: InternalTheme; segment?: 'first' | 'last'; + overwriteRTL?: boolean; }): ViewStyle => { + const cssBorders = overwriteRTL ? rtlCSSBorders : defaultCSSBorders; + if (segment === 'first') { return { - borderTopRightRadius: 0, - borderBottomRightRadius: 0, - ...(theme.isV3 && { borderRightWidth: 0 }), + [cssBorders.topEndRadius]: 0, + [cssBorders.bottomEndRadius]: 0, + ...(theme.isV3 && { [cssBorders.endWidth]: 0 }), }; } else if (segment === 'last') { return { - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, + [cssBorders.topStartRadius]: 0, + [cssBorders.bottomStartRadius]: 0, }; } else { return { borderRadius: 0, - ...(theme.isV3 && { borderRightWidth: 0 }), + ...(theme.isV3 && { [cssBorders.endWidth]: 0 }), }; } }; diff --git a/src/components/ToggleButton/ToggleButtonRow.tsx b/src/components/ToggleButton/ToggleButtonRow.tsx index 3786c1fe97..c145fe0a27 100644 --- a/src/components/ToggleButton/ToggleButtonRow.tsx +++ b/src/components/ToggleButton/ToggleButtonRow.tsx @@ -1,9 +1,39 @@ import * as React from 'react'; import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'; +import { useRTLOverwrite } from '../../core/Localization'; import ToggleButton from './ToggleButton'; import ToggleButtonGroup from './ToggleButtonGroup'; +const useBorderPositions = () => { + const overwriteRTL = useRTLOverwrite(); + + return (index: number, count: number) => { + const first = index === 0; + const last = index === count - 1; + + if (overwriteRTL) { + if (first) { + return styles.last; + } + + if (last) { + return styles.first; + } + } + + if (first) { + return styles.first; + } + + if (last) { + return styles.last; + } + + return styles.middle; + }; +}; + export type Props = { /** * Function to execute on selection change. @@ -51,6 +81,7 @@ export type Props = { */ const ToggleButtonRow = ({ value, onValueChange, children, style }: Props) => { const count = React.Children.count(children); + const getBorderStyle = useBorderPositions(); return ( @@ -62,11 +93,7 @@ const ToggleButtonRow = ({ value, onValueChange, children, style }: Props) => { return React.cloneElement(child, { style: [ styles.button, - i === 0 - ? styles.first - : i === count - 1 - ? styles.last - : styles.middle, + getBorderStyle(i, count), // @ts-expect-error: We're sure that child is a React Element child.props.style, ], diff --git a/src/components/Typography/AnimatedText.tsx b/src/components/Typography/AnimatedText.tsx index c13453ade4..3bff613135 100644 --- a/src/components/Typography/AnimatedText.tsx +++ b/src/components/Typography/AnimatedText.tsx @@ -41,9 +41,7 @@ function AnimatedText({ ...rest }: Props) { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); - - const writingDirection = direction; + const writingDirection = useLocaleDirection(); if (theme.isV3 && variant) { const font = theme.fonts[variant]; diff --git a/src/components/Typography/Text.tsx b/src/components/Typography/Text.tsx index a8786c7504..fb84963ea5 100644 --- a/src/components/Typography/Text.tsx +++ b/src/components/Typography/Text.tsx @@ -90,8 +90,7 @@ const Text = ( const root = React.useRef(null); // FIXME: destructure it in TS 4.6+ const theme = useInternalTheme(initialTheme); - const direction = useLocaleDirection(); - const writingDirection = direction; + const writingDirection = useLocaleDirection(); const isWeb = Platform.OS === 'web'; React.useImperativeHandle(ref, () => ({ diff --git a/src/components/__tests__/Menu.test.tsx b/src/components/__tests__/Menu.test.tsx index 116a2386df..9c3f475a86 100644 --- a/src/components/__tests__/Menu.test.tsx +++ b/src/components/__tests__/Menu.test.tsx @@ -115,7 +115,7 @@ it('uses the default anchorPosition of top', async () => { position: 'absolute', }, { - left: 100, + end: 100, top: 100, }, undefined, @@ -161,7 +161,7 @@ it('respects anchorPosition bottom', async () => { position: 'absolute', }, { - left: 100, + end: 100, top: 132, }, undefined, diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index 121c17ab4a..4109a8b358 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -210,7 +210,7 @@ Array [ "position": "absolute", }, Object { - "left": 8, + "end": 8, "top": 8, }, undefined, @@ -334,9 +334,11 @@ Array [ > = React.ComponentType< - Omit ->; +// type LocaleDirectionComponent = React.ComponentType< +// Omit +// >; -const context = createContext( - I18nManager.getConstants().isRTL ? 'rtl' : 'ltr' -); +const defaultDirection: Direction = 'ltr'; +const context = createContext(defaultDirection); const useLocaleDirection = (): Direction => { return useContext(context); }; -const withLocaleDirection = >( - WrappedComponent: React.ComponentType -): LocaleDirectionComponent => { - const displayName = - WrappedComponent.displayName || WrappedComponent.name || 'Component'; - - const Component = (props: Props) => { - const direction = useLocaleDirection(); - - return ; - }; - - Component.displayName = `withLocaleDirection(${displayName})`; - - return Component as LocaleDirectionComponent; +// const withLocaleDirection = >( +// WrappedComponent: React.ComponentType +// ): LocaleDirectionComponent => { +// const displayName = +// WrappedComponent.displayName || WrappedComponent.name || 'Component'; +// +// const Component = (props: Props) => { +// const direction = useLocaleDirection(); +// +// return ; +// }; +// +// Component.displayName = `withLocaleDirection(${displayName})`; +// +// return Component as LocaleDirectionComponent; +// }; + +const isWeb = Platform.OS === 'web'; + +// Since I18nManager is mocked in react-native-web (https://github.com/necolas/react-native-web/releases/tag/0.18.0) +// we have to rely on default react-native-web positioning for RTL languages. +// Most of the time this works out of the box, but in few specific cases +// we need to overwrite right/left ourselves. + +const useRTLOverwrite = () => { + const direction = useLocaleDirection(); + return isWeb && direction === 'rtl'; }; export const { Provider: LocalizationProvider } = context; -export { Direction, useLocaleDirection, withLocaleDirection }; +export { Direction, useLocaleDirection, useRTLOverwrite }; diff --git a/src/core/Provider.tsx b/src/core/Provider.tsx index 3cf28ccc08..e339349a13 100644 --- a/src/core/Provider.tsx +++ b/src/core/Provider.tsx @@ -6,8 +6,6 @@ import { I18nManager, NativeEventSubscription, Platform, - StyleSheet, - View, } from 'react-native'; import MaterialCommunityIcon from '../components/MaterialCommunityIcon'; @@ -83,8 +81,21 @@ const Provider = (props: Props) => { }, [props.theme, isOnlyVersionInTheme]); React.useEffect(() => { - if (props.direction && Platform.OS !== 'web') { - I18nManager.forceRTL(props.direction === 'rtl'); + if (!props.direction || !['rtl', 'ltr'].includes(props.direction)) { + return; + } + + const isRTL = props.direction === 'rtl'; + + if (Platform.OS === 'web') { + const htmlDir = document.documentElement.getAttribute('dir'); + if (isRTL && htmlDir !== 'rtl') { + document.documentElement.setAttribute('dir', 'rtl'); + } + } else { + if (isRTL && !I18nManager.isRTL) { + I18nManager.forceRTL(isRTL); + } } }, [props.direction]); @@ -117,28 +128,16 @@ const Provider = (props: Props) => { return ( - - + + {/* @ts-expect-error check @callstack/react-theme-provider's children prop */} - - { - - {children} - - } - + {children} - - + + ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - }, -}); - export default Provider; From 42212471d5074229200623efccf1b09a5626ef8d Mon Sep 17 00:00:00 2001 From: Tomasz Janiczek Date: Tue, 18 Apr 2023 10:47:55 +0200 Subject: [PATCH 3/5] rtl-progress --- .../AnimatedFABExample/AnimatedFABExample.tsx | 3 ++ example/src/Examples/TeamDetails.tsx | 4 +- src/components/Appbar/AppbarBackIcon.tsx | 4 +- src/components/Appbar/AppbarContent.tsx | 3 ++ src/components/Badge.tsx | 3 ++ src/components/Button/Button.tsx | 3 ++ src/components/Checkbox/CheckboxItem.tsx | 4 +- src/components/Chip/Chip.tsx | 12 ++++- .../DataTable/DataTablePagination.tsx | 4 +- src/components/DataTable/DataTableTitle.tsx | 4 +- src/components/FAB/AnimatedFAB.tsx | 9 ++-- src/components/Icon.tsx | 4 +- src/components/List/ListAccordion.tsx | 4 +- src/components/List/ListItem.tsx | 5 +- src/components/List/ListSection.tsx | 4 +- src/components/Menu/MenuItem.tsx | 9 ++-- src/components/ProgressBar.tsx | 4 +- .../RadioButton/RadioButtonItem.tsx | 4 +- src/components/Searchbar.tsx | 5 +- .../SegmentedButtons/SegmentedButtonItem.tsx | 4 +- .../SegmentedButtons/SegmentedButtons.tsx | 4 +- src/components/SegmentedButtons/utils.ts | 4 +- src/components/Snackbar.tsx | 5 +- src/components/Switch/Switch.tsx | 3 ++ src/components/TextInput/TextInputFlat.tsx | 4 +- .../TextInput/TextInputOutlined.tsx | 4 +- .../ToggleButton/ToggleButtonRow.tsx | 4 +- src/components/Typography/AnimatedText.tsx | 4 +- src/components/Typography/Text.tsx | 4 +- src/components/Typography/v2/StyledText.tsx | 4 +- src/core/Localization.tsx | 51 ++++++------------- .../views/MaterialBottomTabView.tsx | 4 +- 32 files changed, 101 insertions(+), 90 deletions(-) diff --git a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx index a2b1d54da1..d424f3f480 100644 --- a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx +++ b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx @@ -12,6 +12,7 @@ import { import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import { useExampleTheme } from '../..'; +import { useLocale } from '../../../../src/core/Localization'; import { animatedFABExampleData } from '../../../utils'; import CustomFAB from './CustomFAB'; import CustomFABControls, { @@ -33,6 +34,7 @@ type Item = { const AnimatedFABExample = () => { const { colors, isV3 } = useExampleTheme(); + const { localeProps } = useLocale(); const isIOS = Platform.OS === 'ios'; @@ -155,6 +157,7 @@ const AnimatedFABExample = () => { ]} contentContainerStyle={styles.container} onScroll={onScroll} + {...localeProps} /> { const ThemeBasedOnSourceColor = ({ navigation, route }: Props) => { const insets = useSafeAreaInsets(); const [index, setIndex] = React.useState(0); + const { direction } = useLocale(); const { params } = route; const { sourceColor, headerTitle, darkMode } = params; @@ -217,7 +219,7 @@ const ThemeBasedOnSourceColor = ({ navigation, route }: Props) => { const colorScheme = darkMode ? 'dark' : systemColorScheme; return ( - + navigation.goBack()} /> diff --git a/src/components/Appbar/AppbarBackIcon.tsx b/src/components/Appbar/AppbarBackIcon.tsx index e8bca024ad..9e6fb45710 100644 --- a/src/components/Appbar/AppbarBackIcon.tsx +++ b/src/components/Appbar/AppbarBackIcon.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import { Platform, View, Image, StyleSheet } from 'react-native'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; const AppbarBackIcon = ({ size, color }: { size: number; color: string }) => { - const direction = useLocaleDirection(); + const { direction } = useLocale(); const iosIconSize = size - 3; return Platform.OS === 'ios' ? ( diff --git a/src/components/Appbar/AppbarContent.tsx b/src/components/Appbar/AppbarContent.tsx index 52b0b09b86..e36f7f5efd 100644 --- a/src/components/Appbar/AppbarContent.tsx +++ b/src/components/Appbar/AppbarContent.tsx @@ -18,6 +18,7 @@ import { white } from '../../styles/themes/v2/colors'; import type { $RemoveChildren, MD3TypescaleKey, ThemeProp } from '../../types'; import Text, { TextRef } from '../Typography/Text'; import { modeTextVariant } from './utils'; +import { useLocale } from '../../core/Localization'; type TitleString = { title: string; @@ -115,6 +116,7 @@ const AppbarContent = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const { isV3, colors } = theme; const titleTextColor = titleColor @@ -140,6 +142,7 @@ const AppbarContent = ({ style={[styles.container, isV3 && modeContainerStyles[mode], style]} testID={testID} {...rest} + {...localeProps} > {typeof title === 'string' ? ( { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const { current: opacity } = React.useRef( new Animated.Value(visible ? 1 : 0) ); @@ -130,6 +132,7 @@ const Badge = ({ styles.container, restStyle, ]} + {...localeProps} {...rest} > {children} diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index e4c9367c58..3e221ca22a 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -19,6 +19,7 @@ import Surface from '../Surface'; import TouchableRipple from '../TouchableRipple/TouchableRipple'; import Text from '../Typography/Text'; import { ButtonMode, getButtonColors } from './utils'; +import { useLocale } from '../../core/Localization'; export type Props = $Omit, 'mode'> & { /** @@ -188,6 +189,7 @@ const Button = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const isMode = React.useCallback( (modeToCompare: ButtonMode) => { return mode === modeToCompare; @@ -303,6 +305,7 @@ const Button = ({ ] as ViewStyle } {...(isV3 && { elevation: elevation })} + {...localeProps} > , 'mode'> & { /** @@ -171,6 +172,7 @@ const Chip = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { direction, localeProps } = useLocale(); const { isV3 } = theme; const { current: elevation } = React.useRef( @@ -260,6 +262,8 @@ const Chip = ({ {...rest} testID={`${testID}-container`} theme={theme} + // @ts-ignore + dir="rtl" > )} @@ -369,7 +374,7 @@ const Chip = ({ name={isV3 ? 'close' : 'close-circle'} size={iconSize} color={iconColor} - direction="ltr" + direction={direction} /> )} @@ -386,6 +391,9 @@ const styles = StyleSheet.create({ borderStyle: 'solid', flexDirection: Platform.select({ default: 'column', web: 'row' }), }, + containerRTL: { + flexDirection: 'row-reverse', + }, md3OutlineContainer: { borderWidth: 1, }, diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index 95721f75ae..8651384852 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -4,7 +4,7 @@ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import color from 'color'; import type { ThemeProp } from 'src/types'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import Button from '../Button/Button'; import IconButton from '../IconButton/IconButton'; @@ -88,7 +88,7 @@ const PaginationControls = ({ theme: themeOverrides, }: PaginationControlsProps) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction } = useLocale(); const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; diff --git a/src/components/DataTable/DataTableTitle.tsx b/src/components/DataTable/DataTableTitle.tsx index 9a45f5d7ea..c05fdc7ad6 100644 --- a/src/components/DataTable/DataTableTitle.tsx +++ b/src/components/DataTable/DataTableTitle.tsx @@ -12,7 +12,7 @@ import { import color from 'color'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -97,7 +97,7 @@ const DataTableTitle = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction } = useLocale(); const { current: spinAnim } = React.useRef( new Animated.Value(sortDirection === 'ascending' ? 0 : 1) ); diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index 560dcb538e..7b4025e42e 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -19,7 +19,7 @@ import { import color from 'color'; -import { useLocaleDirection, useRTLOverwrite } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { $Omit, $RemoveChildren, ThemeProp } from '../../types'; import type { IconSource } from '../Icon'; @@ -208,13 +208,10 @@ const AnimatedFAB = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction } = useLocale(); const uppercase: boolean = uppercaseProp ?? !theme.isV3; const isIOS = Platform.OS === 'ios'; - const overwriteRTL = useRTLOverwrite(); - const isAnimatedFromRight = overwriteRTL - ? animateFrom !== 'right' - : animateFrom === 'right'; + const isAnimatedFromRight = animateFrom === 'right'; const isIconStatic = iconMode === 'static'; const { current: visibility } = React.useRef( diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index b391e16941..53afb9ff52 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Image, ImageSourcePropType, Platform } from 'react-native'; -import { useLocaleDirection } from '../core/Localization'; +import { useLocale } from '../core/Localization'; import { Consumer as SettingsConsumer } from '../core/settings'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -71,7 +71,7 @@ const Icon = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const localeDirection = useLocaleDirection(); + const localeDirection = useLocale(); const direction = typeof source === 'object' && source.direction && source.source ? source.direction === 'auto' diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index e4d1a2a5ef..1b610972b5 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -9,7 +9,7 @@ import { ViewStyle, } from 'react-native'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -166,7 +166,7 @@ const ListAccordion = ({ pointerEvents = 'none', }: Props) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction } = useLocale(); const [expanded, setExpanded] = React.useState( expandedProp || false ); diff --git a/src/components/List/ListItem.tsx b/src/components/List/ListItem.tsx index b5b9b184fc..39d19e745b 100644 --- a/src/components/List/ListItem.tsx +++ b/src/components/List/ListItem.tsx @@ -18,6 +18,7 @@ import type { $RemoveChildren, EllipsizeProp, ThemeProp } from '../../types'; import TouchableRipple from '../TouchableRipple/TouchableRipple'; import Text from '../Typography/Text'; import { getLeftStyles, getRightStyles } from './utils'; +import { useLocale } from '../../core/Localization'; type Title = | React.ReactNode @@ -149,6 +150,7 @@ const ListItem = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const [alignToTop, setAlignToTop] = React.useState(false); const onDescriptionTextLayout = ( @@ -223,8 +225,9 @@ const ListItem = ({ style={[theme.isV3 ? styles.containerV3 : styles.container, style]} onPress={onPress} theme={theme} + {...localeProps} > - + {left ? left({ color: descriptionColor, diff --git a/src/components/List/ListSection.tsx b/src/components/List/ListSection.tsx index 67cc4862f0..01a4ffb93e 100644 --- a/src/components/List/ListSection.tsx +++ b/src/components/List/ListSection.tsx @@ -7,6 +7,7 @@ import { ViewStyle, } from 'react-native'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import ListSubheader from './ListSubheader'; @@ -66,10 +67,11 @@ const ListSection = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const viewProps = { ...rest, theme }; return ( - + {title ? ( {title} diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 2ecd827050..36d5b37ce3 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { AccessibilityState, GestureResponderEvent, - Platform, StyleProp, StyleSheet, TextStyle, @@ -10,6 +9,7 @@ import { ViewStyle, } from 'react-native'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import Icon, { IconSource } from '../Icon'; @@ -22,9 +22,6 @@ import { MIN_WIDTH, } from './utils'; -const iconMarginKey = - Platform.OS === 'web' ? 'marginInlineStart' : 'marginStart'; - export type Props = { /** * Title text for the `MenuItem`. @@ -129,6 +126,7 @@ const MenuItem = ({ titleMaxFontSizeMultiplier = 1.5, }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const { titleColor, iconColor, underlayColor } = getMenuItemColor({ theme, disabled, @@ -155,7 +153,7 @@ const MenuItem = ({ const newAccessibilityState = { ...accessibilityState, disabled }; const iconMargin = { - [iconMarginKey]: leadingIcon ? 22 : 4, + marginStart: leadingIcon ? 22 : 4, }; return ( @@ -192,6 +190,7 @@ const MenuItem = ({ contentStyle, ]} pointerEvents="none" + {...localeProps} > { - const direction = useLocaleDirection(); + const { direction } = useLocale(); const theme = useInternalTheme(themeOverrides); const { current: timer } = React.useRef( new Animated.Value(0) diff --git a/src/components/RadioButton/RadioButtonItem.tsx b/src/components/RadioButton/RadioButtonItem.tsx index 676e455f6e..11bb71c945 100644 --- a/src/components/RadioButton/RadioButtonItem.tsx +++ b/src/components/RadioButton/RadioButtonItem.tsx @@ -8,7 +8,7 @@ import { ViewStyle, } from 'react-native'; -import { useRTLOverwrite } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { InternalTheme, MD3TypescaleKey } from '../../types'; import TouchableRipple from '../TouchableRipple/TouchableRipple'; @@ -143,6 +143,7 @@ const RadioButtonItem = ({ labelVariant = 'bodyLarge', }: Props) => { const theme = useInternalTheme(themeOverrides); + const { overwriteRTL } = useLocale(); const radioButtonProps = { value, disabled, status, color, uncheckedColor }; const isLeading = position === 'leading'; let radioButton: any; @@ -160,7 +161,6 @@ const RadioButtonItem = ({ ? theme.colors.onSurfaceDisabled : theme.colors.disabled; - const overwriteRTL = useRTLOverwrite(); let textAlign = isLeading ? 'right' : 'left'; if (overwriteRTL) { diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 93c2cfabbe..bec8b4157a 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -14,7 +14,7 @@ import { import color from 'color'; -import { useLocaleDirection } from '../core/Localization'; +import { useLocale } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; import { forwardRef } from '../utils/forwardRef'; @@ -202,7 +202,7 @@ const Searchbar = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction, localeProps } = useLocale(); const root = React.useRef(null); React.useImperativeHandle(ref, () => { @@ -282,6 +282,7 @@ const Searchbar = forwardRef( testID={`${testID}-container`} {...(theme.isV3 && { elevation })} theme={theme} + {...localeProps} > { const theme = useInternalTheme(themeOverrides); - const overwriteRTL = useRTLOverwrite(); + const { overwriteRTL } = useLocale(); const checkScale = React.useRef(new Animated.Value(0)).current; diff --git a/src/components/SegmentedButtons/SegmentedButtons.tsx b/src/components/SegmentedButtons/SegmentedButtons.tsx index 16489a3530..4ed32b87c8 100644 --- a/src/components/SegmentedButtons/SegmentedButtons.tsx +++ b/src/components/SegmentedButtons/SegmentedButtons.tsx @@ -9,6 +9,7 @@ import { import type { ThemeProp } from 'src/types'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { IconSource } from '../Icon'; import SegmentedButtonItem from './SegmentedButtonItem'; @@ -138,9 +139,10 @@ const SegmentedButtons = ({ theme: themeOverrides, }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); return ( - + {buttons.map((item, i) => { const disabledChildStyle = getDisabledSegmentedButtonStyle({ theme, diff --git a/src/components/SegmentedButtons/utils.ts b/src/components/SegmentedButtons/utils.ts index ca68f8af68..a21bc176c2 100644 --- a/src/components/SegmentedButtons/utils.ts +++ b/src/components/SegmentedButtons/utils.ts @@ -58,7 +58,7 @@ export const getDisabledSegmentedButtonStyle = ({ return {}; }; -const defaultCSSBorders = { +const ltrCSSBorders = { topEndRadius: 'borderTopRightRadius', bottomEndRadius: 'borderBottomRightRadius', endWidth: 'borderRightWidth', @@ -83,7 +83,7 @@ export const getSegmentedButtonBorderRadius = ({ segment?: 'first' | 'last'; overwriteRTL?: boolean; }): ViewStyle => { - const cssBorders = overwriteRTL ? rtlCSSBorders : defaultCSSBorders; + const cssBorders = overwriteRTL ? rtlCSSBorders : ltrCSSBorders; if (segment === 'first') { return { diff --git a/src/components/Snackbar.tsx b/src/components/Snackbar.tsx index bb48455800..8ebc591a6f 100644 --- a/src/components/Snackbar.tsx +++ b/src/components/Snackbar.tsx @@ -11,7 +11,7 @@ import { import { useSafeAreaInsets } from 'react-native-safe-area-context'; import useLatestCallback from 'use-latest-callback'; -import { useLocaleDirection } from '../core/Localization'; +import { useLocale } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { $Omit, $RemoveChildren, ThemeProp } from '../types'; import Button from './Button/Button'; @@ -146,7 +146,7 @@ const Snackbar = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction, localeProps } = useLocale(); const { bottom, right, left } = useSafeAreaInsets(); const { current: opacity } = React.useRef( @@ -290,6 +290,7 @@ const Snackbar = ({ style, ]} {...(isV3 && { elevation })} + {...localeProps} {...rest} > {renderChildrenWithWrapper()} diff --git a/src/components/Switch/Switch.tsx b/src/components/Switch/Switch.tsx index 8ef3bf1404..ae1cf30deb 100644 --- a/src/components/Switch/Switch.tsx +++ b/src/components/Switch/Switch.tsx @@ -10,6 +10,7 @@ import { import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import { getSwitchColor } from './utils'; +import { useLocale } from '../../core/Localization'; const version = NativeModules.PlatformConstants ? NativeModules.PlatformConstants.reactNativeVersion @@ -86,6 +87,7 @@ const Switch = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const { localeProps } = useLocale(); const { checkedColor, onTintColor, thumbTintColor } = getSwitchColor({ theme, disabled, @@ -119,6 +121,7 @@ const Switch = ({ disabled={disabled} onValueChange={disabled ? undefined : onValueChange} {...props} + {...localeProps} {...rest} /> ); diff --git a/src/components/TextInput/TextInputFlat.tsx b/src/components/TextInput/TextInputFlat.tsx index 97ec1b825d..bb5e87b12f 100644 --- a/src/components/TextInput/TextInputFlat.tsx +++ b/src/components/TextInput/TextInputFlat.tsx @@ -12,7 +12,7 @@ import { import type { ThemeProp } from 'src/types'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import { AdornmentSide, AdornmentType, InputMode } from './Adornment/enums'; import TextInputAdornment, { @@ -77,7 +77,7 @@ const TextInputFlat = ({ contentStyle, ...rest }: ChildTextInputProps) => { - const direction = useLocaleDirection(); + const { direction } = useLocale(); const isAndroid = Platform.OS === 'android'; const { colors, isV3, roundness } = theme; const font = isV3 ? theme.fonts.bodyLarge : theme.fonts.regular; diff --git a/src/components/TextInput/TextInputOutlined.tsx b/src/components/TextInput/TextInputOutlined.tsx index 493759f0bc..0eb9fd25e7 100644 --- a/src/components/TextInput/TextInputOutlined.tsx +++ b/src/components/TextInput/TextInputOutlined.tsx @@ -10,7 +10,7 @@ import { ViewStyle, } from 'react-native'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { AdornmentType, AdornmentSide } from './Adornment/enums'; import TextInputAdornment, { getAdornmentConfig, @@ -73,7 +73,7 @@ const TextInputOutlined = ({ contentStyle, ...rest }: ChildTextInputProps) => { - const direction = useLocaleDirection(); + const { direction } = useLocale(); const adornmentConfig = getAdornmentConfig({ left, right }); diff --git a/src/components/ToggleButton/ToggleButtonRow.tsx b/src/components/ToggleButton/ToggleButtonRow.tsx index c145fe0a27..3501d5c89d 100644 --- a/src/components/ToggleButton/ToggleButtonRow.tsx +++ b/src/components/ToggleButton/ToggleButtonRow.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'; -import { useRTLOverwrite } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import ToggleButton from './ToggleButton'; import ToggleButtonGroup from './ToggleButtonGroup'; const useBorderPositions = () => { - const overwriteRTL = useRTLOverwrite(); + const { overwriteRTL } = useLocale(); return (index: number, count: number) => { const first = index === 0; diff --git a/src/components/Typography/AnimatedText.tsx b/src/components/Typography/AnimatedText.tsx index 3bff613135..548074d31d 100644 --- a/src/components/Typography/AnimatedText.tsx +++ b/src/components/Typography/AnimatedText.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Animated, StyleSheet, TextStyle } from 'react-native'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import type { VariantProp } from './types'; @@ -41,7 +41,7 @@ function AnimatedText({ ...rest }: Props) { const theme = useInternalTheme(themeOverrides); - const writingDirection = useLocaleDirection(); + const { direction: writingDirection } = useLocale(); if (theme.isV3 && variant) { const font = theme.fonts[variant]; diff --git a/src/components/Typography/Text.tsx b/src/components/Typography/Text.tsx index fb84963ea5..9d9b77bc65 100644 --- a/src/components/Typography/Text.tsx +++ b/src/components/Typography/Text.tsx @@ -7,7 +7,7 @@ import { TextStyle, } from 'react-native'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import { forwardRef } from '../../utils/forwardRef'; @@ -90,7 +90,7 @@ const Text = ( const root = React.useRef(null); // FIXME: destructure it in TS 4.6+ const theme = useInternalTheme(initialTheme); - const writingDirection = useLocaleDirection(); + const { direction: writingDirection } = useLocale(); const isWeb = Platform.OS === 'web'; React.useImperativeHandle(ref, () => ({ diff --git a/src/components/Typography/v2/StyledText.tsx b/src/components/Typography/v2/StyledText.tsx index e58b11cfbe..ff58978482 100644 --- a/src/components/Typography/v2/StyledText.tsx +++ b/src/components/Typography/v2/StyledText.tsx @@ -4,7 +4,7 @@ import { StyleProp, StyleSheet, TextStyle } from 'react-native'; import color from 'color'; import type { ThemeProp } from 'src/types'; -import { useLocaleDirection } from '../../../core/Localization'; +import { useLocale } from '../../../core/Localization'; import { useInternalTheme } from '../../../core/theming'; import Text from './Text'; @@ -23,7 +23,7 @@ const StyledText = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); - const direction = useLocaleDirection(); + const { direction } = useLocale(); const textColor = color( theme.isV3 ? theme.colors.onSurface : theme.colors?.text diff --git a/src/core/Localization.tsx b/src/core/Localization.tsx index 0e55da5154..ac8ce61101 100644 --- a/src/core/Localization.tsx +++ b/src/core/Localization.tsx @@ -3,46 +3,27 @@ import { Platform } from 'react-native'; type Direction = 'rtl' | 'ltr'; -// type LocaleDirectionComponent = React.ComponentType< -// Omit -// >; - const defaultDirection: Direction = 'ltr'; const context = createContext(defaultDirection); - -const useLocaleDirection = (): Direction => { - return useContext(context); -}; - -// const withLocaleDirection = >( -// WrappedComponent: React.ComponentType -// ): LocaleDirectionComponent => { -// const displayName = -// WrappedComponent.displayName || WrappedComponent.name || 'Component'; -// -// const Component = (props: Props) => { -// const direction = useLocaleDirection(); -// -// return ; -// }; -// -// Component.displayName = `withLocaleDirection(${displayName})`; -// -// return Component as LocaleDirectionComponent; -// }; - const isWeb = Platform.OS === 'web'; -// Since I18nManager is mocked in react-native-web (https://github.com/necolas/react-native-web/releases/tag/0.18.0) -// we have to rely on default react-native-web positioning for RTL languages. -// Most of the time this works out of the box, but in few specific cases -// we need to overwrite right/left ourselves. - -const useRTLOverwrite = () => { - const direction = useLocaleDirection(); - return isWeb && direction === 'rtl'; +const useLocale = () => { + const direction = useContext(context); + const localeProps = direction === 'rtl' ? { dir: 'rtl' } : {}; + + // Since I18nManager is mocked in react-native-web (https://github.com/necolas/react-native-web/releases/tag/0.18.0) + // we have to rely on default react-native-web positioning for RTL languages. + // Most of the time this works out of the box, but in few specific cases + // we need to overwrite right/left ourselves. + const overwriteRTL = isWeb && direction === 'rtl'; + + return { + direction, + localeProps, + overwriteRTL, + }; }; export const { Provider: LocalizationProvider } = context; -export { Direction, useLocaleDirection, useRTLOverwrite }; +export { Direction, useLocale }; diff --git a/src/react-navigation/views/MaterialBottomTabView.tsx b/src/react-navigation/views/MaterialBottomTabView.tsx index 34bb0c6ef5..b132e84e2b 100644 --- a/src/react-navigation/views/MaterialBottomTabView.tsx +++ b/src/react-navigation/views/MaterialBottomTabView.tsx @@ -11,7 +11,7 @@ import { import BottomNavigation from '../../components/BottomNavigation/BottomNavigation'; import MaterialCommunityIcon from '../../components/MaterialCommunityIcon'; -import { useLocaleDirection } from '../../core/Localization'; +import { useLocale } from '../../core/Localization'; import { useNavigationLink } from '../adapter'; import type { MaterialBottomTabDescriptorMap, @@ -32,7 +32,7 @@ export default function MaterialBottomTabView({ ...rest }: Props) { const buildLink = useNavigationLink(); - const direction = useLocaleDirection(); + const { direction } = useLocale(); return ( Date: Wed, 22 Mar 2023 20:09:46 +0000 Subject: [PATCH 4/5] fix: rtl not being detected correctly on web --- docs/src/components/GetStartedButtons.tsx | 4 +- example/src/DrawerItems.tsx | 4 +- example/src/ExampleList.tsx | 4 +- .../AnimatedFABExample/AnimatedFABExample.tsx | 6 +- .../AnimatedFABExample/CustomFABControls.tsx | 2 +- example/src/Examples/ChipExample.tsx | 4 +- .../Dialogs/DialogWithLoadingIndicator.tsx | 6 +- .../Examples/Dialogs/DialogWithRadioBtns.tsx | 2 +- example/src/Examples/TeamDetails.tsx | 6 +- example/src/Examples/TextInputExample.tsx | 2 +- example/src/ScreenWrapper.tsx | 4 +- example/src/index.tsx | 11 +- src/components/Appbar/Appbar.tsx | 4 +- src/components/Appbar/AppbarBackIcon.tsx | 8 +- src/components/Appbar/utils.ts | 4 +- .../BottomNavigation/BottomNavigationBar.tsx | 2 +- src/components/Button/Button.tsx | 40 +++---- src/components/Card/CardActions.tsx | 2 +- src/components/Card/CardTitle.tsx | 8 +- src/components/Chip/Chip.tsx | 30 ++--- .../DataTable/DataTablePagination.tsx | 24 ++-- src/components/DataTable/DataTableTitle.tsx | 9 +- src/components/Dialog/DialogActions.tsx | 2 +- src/components/Divider.tsx | 8 +- src/components/Drawer/DrawerCollapsedItem.tsx | 2 +- src/components/Drawer/DrawerItem.tsx | 12 +- src/components/Drawer/DrawerSection.tsx | 2 +- src/components/FAB/AnimatedFAB.tsx | 13 ++- src/components/FAB/FABGroup.tsx | 4 +- src/components/FAB/utils.ts | 8 +- src/components/Icon.tsx | 11 +- src/components/List/ListAccordion.tsx | 7 +- src/components/List/ListImage.tsx | 4 +- src/components/List/ListItem.tsx | 10 +- src/components/List/utils.ts | 22 ++-- src/components/Menu/Menu.tsx | 36 ++++-- src/components/Menu/MenuItem.tsx | 4 +- src/components/ProgressBar.tsx | 15 ++- src/components/Searchbar.tsx | 22 ++-- .../SegmentedButtons/SegmentedButtonItem.tsx | 2 +- src/components/Snackbar.tsx | 15 ++- src/components/TextInput/Adornment/types.tsx | 2 +- src/components/TextInput/Label/InputLabel.tsx | 6 +- .../TextInput/Label/LabelBackground.tsx | 4 +- src/components/TextInput/TextInput.tsx | 2 +- src/components/TextInput/TextInputFlat.tsx | 37 +++--- .../TextInput/TextInputOutlined.tsx | 12 +- src/components/TextInput/helpers.tsx | 12 +- src/components/TextInput/types.tsx | 4 +- src/components/Typography/AnimatedText.tsx | 7 +- src/components/Typography/Text.tsx | 11 +- src/components/Typography/v2/StyledText.tsx | 6 +- .../__tests__/Appbar/Appbar.test.tsx | 4 +- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 16 +-- src/components/__tests__/Button.test.tsx | 16 +-- src/components/__tests__/Dialog.test.tsx | 4 +- .../__snapshots__/DrawerSection.test.tsx.snap | 4 +- src/components/__tests__/FABGroup.test.tsx | 2 +- src/components/__tests__/ListImage.test.tsx | 2 +- src/components/__tests__/ListUtils.test.tsx | 14 +-- src/components/__tests__/Searchbar.test.tsx | 2 +- src/components/__tests__/Snackbar.test.tsx | 2 +- src/components/__tests__/Surface.test.tsx | 8 +- src/components/__tests__/TextInput.test.tsx | 55 +-------- .../BottomNavigation.test.tsx.snap | 80 ++++++------- .../__snapshots__/Button.test.tsx.snap | 36 +++--- .../__snapshots__/Chip.test.tsx.snap | 88 +++++++------- .../__snapshots__/DataTable.test.tsx.snap | 32 +++--- .../__snapshots__/DrawerItem.test.tsx.snap | 36 +++--- .../__snapshots__/ListAccordion.test.tsx.snap | 4 +- .../__snapshots__/ListItem.test.tsx.snap | 50 ++++---- .../__snapshots__/ListSection.test.tsx.snap | 48 ++++---- .../__snapshots__/Menu.test.tsx.snap | 8 +- .../__snapshots__/MenuItem.test.tsx.snap | 10 +- .../__snapshots__/Searchbar.test.tsx.snap | 20 ++-- .../SegmentedButton.test.tsx.snap | 2 +- .../__snapshots__/Snackbar.test.tsx.snap | 8 +- .../__snapshots__/TextInput.test.tsx.snap | 108 +++++++++--------- src/core/Localization.tsx | 37 ++++++ src/core/Provider.tsx | 40 ++++++- .../views/MaterialBottomTabView.tsx | 6 +- src/utils/__tests__/splitStyles.test.ts | 2 +- 82 files changed, 637 insertions(+), 595 deletions(-) create mode 100644 src/core/Localization.tsx diff --git a/docs/src/components/GetStartedButtons.tsx b/docs/src/components/GetStartedButtons.tsx index d86e2fee97..9cfb97cebc 100644 --- a/docs/src/components/GetStartedButtons.tsx +++ b/docs/src/components/GetStartedButtons.tsx @@ -21,7 +21,7 @@ const styles = StyleSheet.create({ paddingBottom: 16, }, button: { - marginRight: 16, + marginEnd: 16, }, }); @@ -70,7 +70,7 @@ const Shimmer = () => { { toggleRTL(); - I18nManager.forceRTL(!isRTL); - if (isWeb) { + if (!isWeb) { + I18nManager.forceRTL(!isRTL); Updates.reloadAsync(); } }; diff --git a/example/src/ExampleList.tsx b/example/src/ExampleList.tsx index 5c41d671a5..dd4a8f80bd 100644 --- a/example/src/ExampleList.tsx +++ b/example/src/ExampleList.tsx @@ -153,8 +153,8 @@ export default function ExampleList({ navigation }: Props) { contentContainerStyle={{ backgroundColor: colors.background, paddingBottom: safeArea.bottom, - paddingLeft: safeArea.left, - paddingRight: safeArea.right, + paddingStart: safeArea.left, + paddingEnd: safeArea.right, }} style={{ backgroundColor: colors.background, diff --git a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx index fd190c9953..a2b1d54da1 100644 --- a/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx +++ b/example/src/Examples/AnimatedFABExample/AnimatedFABExample.tsx @@ -177,7 +177,7 @@ const styles = StyleSheet.create({ paddingBottom: 60, }, avatar: { - marginRight: 16, + marginEnd: 16, marginTop: 8, }, flex: { @@ -204,7 +204,7 @@ const styles = StyleSheet.create({ fontWeight: 'bold', }, icon: { - marginLeft: 16, + marginStart: 16, alignSelf: 'flex-end', }, date: { @@ -212,7 +212,7 @@ const styles = StyleSheet.create({ }, header: { fontSize: 14, - marginRight: 8, + marginEnd: 8, flex: 1, }, }); diff --git a/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx b/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx index 9825be219e..57cdb51c26 100644 --- a/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx +++ b/example/src/Examples/AnimatedFABExample/CustomFABControls.tsx @@ -139,7 +139,7 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', }, controlItem: { - marginLeft: 16, + marginStart: 16, flexDirection: 'row', alignItems: 'center', }, diff --git a/example/src/Examples/ChipExample.tsx b/example/src/Examples/ChipExample.tsx index 3a60a6c41c..fd53492b1f 100644 --- a/example/src/Examples/ChipExample.tsx +++ b/example/src/Examples/ChipExample.tsx @@ -340,8 +340,8 @@ const styles = StyleSheet.create({ }, tiny: { marginVertical: 2, - marginRight: 2, - marginLeft: 2, + marginEnd: 2, + marginStart: 2, minHeight: 19, lineHeight: 19, }, diff --git a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx index 10ce6f010b..584d748415 100644 --- a/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx +++ b/example/src/Examples/Dialogs/DialogWithLoadingIndicator.tsx @@ -25,7 +25,7 @@ const DialogWithLoadingIndicator = ({ Loading..... @@ -40,8 +40,8 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', }, - marginRight: { - marginRight: 16, + marginEnd: { + marginEnd: 16, }, }); diff --git a/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx b/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx index 966422369e..8893cece09 100644 --- a/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx +++ b/example/src/Examples/Dialogs/DialogWithRadioBtns.tsx @@ -106,6 +106,6 @@ const styles = StyleSheet.create({ paddingVertical: 8, }, text: { - paddingLeft: 8, + paddingStart: 8, }, }); diff --git a/example/src/Examples/TeamDetails.tsx b/example/src/Examples/TeamDetails.tsx index 5e56b5ebf3..e4907e5583 100644 --- a/example/src/Examples/TeamDetails.tsx +++ b/example/src/Examples/TeamDetails.tsx @@ -264,7 +264,7 @@ const styles = StyleSheet.create({ flexDirection: 'row', }, score: { - marginRight: 16, + marginEnd: 16, }, fab: { position: 'absolute', @@ -282,10 +282,10 @@ const styles = StyleSheet.create({ flexDirection: 'row', }, chipsContent: { - paddingLeft: 8, + paddingStart: 8, paddingVertical: 8, }, chip: { - marginRight: 8, + marginEnd: 8, }, }); diff --git a/example/src/Examples/TextInputExample.tsx b/example/src/Examples/TextInputExample.tsx index 8e4ce574fd..5e668d1a85 100644 --- a/example/src/Examples/TextInputExample.tsx +++ b/example/src/Examples/TextInputExample.tsx @@ -660,7 +660,7 @@ const styles = StyleSheet.create({ margin: 8, }, inputContentStyle: { - paddingLeft: 50, + paddingStart: 50, fontWeight: 'bold', fontStyle: 'italic', }, diff --git a/example/src/ScreenWrapper.tsx b/example/src/ScreenWrapper.tsx index bb96250899..3291c81113 100644 --- a/example/src/ScreenWrapper.tsx +++ b/example/src/ScreenWrapper.tsx @@ -35,8 +35,8 @@ export default function ScreenWrapper({ { backgroundColor: theme.colors.background, paddingBottom: insets.bottom, - paddingLeft: insets.left, - paddingRight: insets.left, + paddingStart: insets.left, + paddingEnd: insets.left, }, ]; diff --git a/example/src/index.tsx b/example/src/index.tsx index 19cff80a1d..cc24dcf04e 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -147,11 +147,9 @@ export default function PaperExample() { // ignore error } - if (I18nManager.getConstants().isRTL !== rtl) { + if (!isWeb && I18nManager.getConstants().isRTL !== rtl) { I18nManager.forceRTL(rtl); - if (!isWeb) { - Updates.reloadAsync(); - } + Updates.reloadAsync(); } }; @@ -215,7 +213,10 @@ export default function PaperExample() { }; return ( - + { + const direction = useLocaleDirection(); const iosIconSize = size - 3; return Platform.OS === 'ios' ? ( @@ -13,7 +15,7 @@ const AppbarBackIcon = ({ size, color }: { size: number; color: string }) => { { width: size, height: size, - transform: [{ scaleX: I18nManager.getConstants().isRTL ? -1 : 1 }], + transform: [{ scaleX: direction === 'rtl' ? -1 : 1 }], }, ]} > @@ -31,7 +33,7 @@ const AppbarBackIcon = ({ size, color }: { size: number; color: string }) => { name="arrow-left" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> ); }; diff --git a/src/components/Appbar/utils.ts b/src/components/Appbar/utils.ts index 3c433cb798..a485b32b1a 100644 --- a/src/components/Appbar/utils.ts +++ b/src/components/Appbar/utils.ts @@ -160,9 +160,9 @@ const styles = StyleSheet.create({ alignItems: 'center', }, v2Spacing: { - marginLeft: 8, + marginStart: 8, }, v3Spacing: { - marginLeft: 12, + marginStart: 12, }, }); diff --git a/src/components/BottomNavigation/BottomNavigationBar.tsx b/src/components/BottomNavigation/BottomNavigationBar.tsx index a3d9f6e07f..b9b5c946a1 100644 --- a/src/components/BottomNavigation/BottomNavigationBar.tsx +++ b/src/components/BottomNavigation/BottomNavigationBar.tsx @@ -1011,7 +1011,7 @@ const styles = StyleSheet.create({ }, badgeContainer: { position: 'absolute', - left: 0, + start: 0, }, v3TouchableContainer: { paddingTop: 12, diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 94ff5d774b..e4c9367c58 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -389,45 +389,45 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, icon: { - marginLeft: 12, - marginRight: -4, + marginStart: 12, + marginEnd: -4, }, iconReverse: { - marginRight: 12, - marginLeft: -4, + marginEnd: 12, + marginStart: -4, }, /* eslint-disable react-native/no-unused-styles */ md3Icon: { - marginLeft: 16, - marginRight: -16, + marginStart: 16, + marginEnd: -16, }, md3IconCompact: { - marginLeft: 8, - marginRight: 0, + marginStart: 8, + marginEnd: 0, }, md3IconReverse: { - marginLeft: -16, - marginRight: 16, + marginStart: -16, + marginEnd: 16, }, md3IconReverseCompact: { - marginLeft: 0, - marginRight: 8, + marginStart: 0, + marginEnd: 8, }, md3IconTextMode: { - marginLeft: 12, - marginRight: -8, + marginStart: 12, + marginEnd: -8, }, md3IconTextModeCompact: { - marginLeft: 6, - marginRight: 0, + marginStart: 6, + marginEnd: 0, }, md3IconReverseTextMode: { - marginLeft: -8, - marginRight: 12, + marginStart: -8, + marginEnd: 12, }, md3IconReverseTextModeCompact: { - marginLeft: 0, - marginRight: 6, + marginStart: 0, + marginEnd: 6, }, /* eslint-enable react-native/no-unused-styles */ label: { diff --git a/src/components/Card/CardActions.tsx b/src/components/Card/CardActions.tsx index dfefad98b7..6c874f4cd3 100644 --- a/src/components/Card/CardActions.tsx +++ b/src/components/Card/CardActions.tsx @@ -73,7 +73,7 @@ const styles = StyleSheet.create({ padding: 8, }, button: { - marginLeft: 8, + marginStart: 8, }, }); diff --git a/src/components/Card/CardTitle.tsx b/src/components/Card/CardTitle.tsx index e84ff3691f..300f12b71d 100644 --- a/src/components/Card/CardTitle.tsx +++ b/src/components/Card/CardTitle.tsx @@ -194,12 +194,12 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - paddingLeft: 16, + paddingStart: 16, }, left: { justifyContent: 'center', - marginRight: 16, + marginEnd: 16, height: LEFT_SIZE, width: LEFT_SIZE, }, @@ -212,13 +212,13 @@ const styles = StyleSheet.create({ title: { minHeight: 30, - paddingRight: 16, + paddingEnd: 16, }, subtitle: { minHeight: 20, marginVertical: 0, - paddingRight: 16, + paddingEnd: 16, }, }); diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx index 6da7972ff7..9f4011a10f 100644 --- a/src/components/Chip/Chip.tsx +++ b/src/components/Chip/Chip.tsx @@ -230,11 +230,11 @@ const Chip = ({ const elevationStyle = isV3 || Platform.OS === 'android' ? elevation : 0; const multiplier = isV3 ? (compact ? 1.5 : 2) : 1; const labelSpacings = { - marginRight: onClose ? 0 : 8 * multiplier, - marginLeft: avatar || icon || selected ? 4 * multiplier : 8 * multiplier, + marginEnd: onClose ? 0 : 8 * multiplier, + marginStart: avatar || icon || selected ? 4 * multiplier : 8 * multiplier, }; const contentSpacings = { - paddingRight: isV3 ? (onClose ? 34 : 0) : onClose ? 32 : 4, + paddingEnd: isV3 ? (onClose ? 34 : 0) : onClose ? 32 : 4, }; const labelTextStyle = { color: textColor, @@ -395,26 +395,26 @@ const styles = StyleSheet.create({ content: { flexDirection: 'row', alignItems: 'center', - paddingLeft: 4, + paddingStart: 4, position: 'relative', flexGrow: 1, }, md3Content: { - paddingLeft: 0, + paddingStart: 0, }, icon: { padding: 4, alignSelf: 'center', }, md3Icon: { - paddingLeft: 8, - paddingRight: 0, + paddingStart: 8, + paddingEnd: 0, }, closeIcon: { - marginRight: 4, + marginEnd: 4, }, md3CloseIcon: { - marginRight: 8, + marginEnd: 8, padding: 0, }, labelText: { @@ -433,25 +433,25 @@ const styles = StyleSheet.create({ borderRadius: 12, }, avatarWrapper: { - marginRight: 4, + marginEnd: 4, }, md3AvatarWrapper: { - marginLeft: 4, - marginRight: 0, + marginStart: 4, + marginEnd: 0, }, md3SelectedIcon: { - paddingLeft: 4, + paddingStart: 4, }, // eslint-disable-next-line react-native/no-color-literals avatarSelected: { position: 'absolute', top: 4, - left: 4, + start: 4, backgroundColor: 'rgba(0, 0, 0, .29)', }, closeButtonStyle: { position: 'absolute', - right: 0, + end: 0, height: '100%', justifyContent: 'center', alignItems: 'center', diff --git a/src/components/DataTable/DataTablePagination.tsx b/src/components/DataTable/DataTablePagination.tsx index 767b9fa3e4..95721f75ae 100644 --- a/src/components/DataTable/DataTablePagination.tsx +++ b/src/components/DataTable/DataTablePagination.tsx @@ -1,15 +1,10 @@ import * as React from 'react'; -import { - I18nManager, - StyleProp, - StyleSheet, - View, - ViewStyle, -} from 'react-native'; +import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import color from 'color'; import type { ThemeProp } from 'src/types'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import Button from '../Button/Button'; import IconButton from '../IconButton/IconButton'; @@ -93,6 +88,7 @@ const PaginationControls = ({ theme: themeOverrides, }: PaginationControlsProps) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text; @@ -105,7 +101,7 @@ const PaginationControls = ({ name="page-first" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -121,7 +117,7 @@ const PaginationControls = ({ name="chevron-left" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -136,7 +132,7 @@ const PaginationControls = ({ name="chevron-right" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -152,7 +148,7 @@ const PaginationControls = ({ name="page-last" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} iconColor={textColor} @@ -358,7 +354,7 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', flexDirection: 'row', alignItems: 'center', - paddingLeft: 16, + paddingStart: 16, flexWrap: 'wrap', }, optionsContainer: { @@ -368,11 +364,11 @@ const styles = StyleSheet.create({ }, label: { fontSize: 12, - marginRight: 16, + marginEnd: 16, }, button: { textAlign: 'center', - marginRight: 16, + marginEnd: 16, }, iconsContainer: { flexDirection: 'row', diff --git a/src/components/DataTable/DataTableTitle.tsx b/src/components/DataTable/DataTableTitle.tsx index 0fbe3f26d3..9a45f5d7ea 100644 --- a/src/components/DataTable/DataTableTitle.tsx +++ b/src/components/DataTable/DataTableTitle.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, GestureResponderEvent, - I18nManager, StyleProp, StyleSheet, TextStyle, @@ -13,6 +12,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -97,6 +97,7 @@ const DataTableTitle = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const { current: spinAnim } = React.useRef( new Animated.Value(sortDirection === 'ascending' ? 0 : 1) ); @@ -124,7 +125,7 @@ const DataTableTitle = ({ name="arrow-up" size={16} color={textColor} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> ) : null; @@ -142,7 +143,7 @@ const DataTableTitle = ({ // if numberOfLines causes wrap, center is lost. Align directly, sensitive to numeric and RTL numberOfLines > 1 ? numeric - ? I18nManager.getConstants().isRTL + ? direction === 'rtl' ? styles.leftText : styles.rightText : styles.centerText @@ -193,7 +194,7 @@ const styles = StyleSheet.create({ }, sorted: { - marginLeft: 8, + marginStart: 8, }, icon: { diff --git a/src/components/Dialog/DialogActions.tsx b/src/components/Dialog/DialogActions.tsx index 8dd5f9fd87..972ceb84aa 100644 --- a/src/components/Dialog/DialogActions.tsx +++ b/src/components/Dialog/DialogActions.tsx @@ -67,7 +67,7 @@ const DialogActions = (props: Props) => { uppercase: !isV3, style: [ isV3 && { - marginRight: i + 1 === actionsLength ? 0 : 8, + marginEnd: i + 1 === actionsLength ? 0 : 8, }, child.props.style, ], diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx index f30c8f44e2..338283308b 100644 --- a/src/components/Divider.tsx +++ b/src/components/Divider.tsx @@ -91,14 +91,14 @@ const Divider = ({ const styles = StyleSheet.create({ leftInset: { - marginLeft: 72, + marginStart: 72, }, v3LeftInset: { - marginLeft: 16, + marginStart: 16, }, horizontalInset: { - marginLeft: 16, - marginRight: 16, + marginStart: 16, + marginEnd: 16, }, bold: { height: 1, diff --git a/src/components/Drawer/DrawerCollapsedItem.tsx b/src/components/Drawer/DrawerCollapsedItem.tsx index ed77eeded3..82255dead7 100644 --- a/src/components/Drawer/DrawerCollapsedItem.tsx +++ b/src/components/Drawer/DrawerCollapsedItem.tsx @@ -267,7 +267,7 @@ const styles = StyleSheet.create({ }, badgeContainer: { position: 'absolute', - left: 20, + start: 20, bottom: 20, zIndex: 2, }, diff --git a/src/components/Drawer/DrawerItem.tsx b/src/components/Drawer/DrawerItem.tsx index df073778c8..92beacdcc3 100644 --- a/src/components/Drawer/DrawerItem.tsx +++ b/src/components/Drawer/DrawerItem.tsx @@ -139,7 +139,7 @@ const DrawerItem = ({ styles.label, { color: contentColor, - marginLeft: labelMargin, + marginStart: labelMargin, ...font, }, ]} @@ -165,8 +165,8 @@ const styles = StyleSheet.create({ v3Container: { justifyContent: 'center', height: 56, - marginLeft: 12, - marginRight: 12, + marginStart: 12, + marginEnd: 12, marginVertical: 0, }, wrapper: { @@ -175,8 +175,8 @@ const styles = StyleSheet.create({ padding: 8, }, v3Wrapper: { - marginLeft: 16, - marginRight: 24, + marginStart: 16, + marginEnd: 24, padding: 0, }, content: { @@ -185,7 +185,7 @@ const styles = StyleSheet.create({ alignItems: 'center', }, label: { - marginRight: 32, + marginEnd: 32, }, }); diff --git a/src/components/Drawer/DrawerSection.tsx b/src/components/Drawer/DrawerSection.tsx index 27759c9e71..9a4d38a4c6 100644 --- a/src/components/Drawer/DrawerSection.tsx +++ b/src/components/Drawer/DrawerSection.tsx @@ -92,7 +92,7 @@ const DrawerSection = ({ style={[ { color: titleColor, - marginLeft: titleMargin, + marginStart: titleMargin, ...font, }, ]} diff --git a/src/components/FAB/AnimatedFAB.tsx b/src/components/FAB/AnimatedFAB.tsx index 84ea8c6321..a078efa4a7 100644 --- a/src/components/FAB/AnimatedFAB.tsx +++ b/src/components/FAB/AnimatedFAB.tsx @@ -8,7 +8,6 @@ import { Animated, Easing, GestureResponderEvent, - I18nManager, Platform, ScrollView, StyleProp, @@ -20,6 +19,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { $Omit, $RemoveChildren, ThemeProp } from '../../types'; import type { IconSource } from '../Icon'; @@ -126,7 +126,6 @@ const SCALE = 0.9; * ScrollView, * Text, * SafeAreaView, - * I18nManager, * } from 'react-native'; * import { AnimatedFAB } from 'react-native-paper'; * @@ -209,11 +208,11 @@ const AnimatedFAB = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const uppercase: boolean = uppercaseProp ?? !theme.isV3; const isIOS = Platform.OS === 'ios'; const isAnimatedFromRight = animateFrom === 'right'; const isIconStatic = iconMode === 'static'; - const { isRTL } = I18nManager; const { current: visibility } = React.useRef( new Animated.Value(visible ? 1 : 0) ); @@ -302,6 +301,7 @@ const AnimatedFAB = ({ isIconStatic, distance, animFAB, + direction, }); const font = isV3 ? theme.fonts.labelLarge : theme.fonts.medium; @@ -452,9 +452,10 @@ const AnimatedFAB = ({ ellipsizeMode={'tail'} style={[ { - [isAnimatedFromRight || isRTL ? 'right' : 'left']: isIconStatic - ? textWidth - SIZE + borderRadius / (isV3 ? 1 : 2) - : borderRadius, + [isAnimatedFromRight || direction === 'rtl' ? 'right' : 'left']: + isIconStatic + ? textWidth - SIZE + borderRadius / (isV3 ? 1 : 2) + : borderRadius, }, { minWidth: textWidth, diff --git a/src/components/FAB/FABGroup.tsx b/src/components/FAB/FABGroup.tsx index e3ff9d159c..d88b712eb4 100644 --- a/src/components/FAB/FABGroup.tsx +++ b/src/components/FAB/FABGroup.tsx @@ -298,8 +298,8 @@ const FABGroup = ({ const { top, bottom, right, left } = useSafeAreaInsets(); const containerPaddings = { paddingBottom: bottom, - paddingRight: right, - paddingLeft: left, + paddingEnd: right, + paddingStart: left, paddingTop: top, }; diff --git a/src/components/FAB/utils.ts b/src/components/FAB/utils.ts index 1ac53884d1..f7fe42038a 100644 --- a/src/components/FAB/utils.ts +++ b/src/components/FAB/utils.ts @@ -1,7 +1,8 @@ -import { Animated, ColorValue, I18nManager, ViewStyle } from 'react-native'; +import type { Animated, ColorValue, ViewStyle } from 'react-native'; import color from 'color'; +import type { Direction } from '../../core/Localization'; import { black, white } from '../../styles/themes/v2/colors'; import type { InternalTheme } from '../../types'; import getContrastingColor from '../../utils/getContrastingColor'; @@ -11,6 +12,7 @@ type GetCombinedStylesProps = { isIconStatic: boolean; distance: number; animFAB: Animated.Value; + direction: Direction; }; type CombinedStyles = { @@ -32,9 +34,9 @@ export const getCombinedStyles = ({ isIconStatic, distance, animFAB, + direction, }: GetCombinedStylesProps): CombinedStyles => { - const { isRTL } = I18nManager; - + const isRTL = direction === 'rtl'; const defaultPositionStyles = { left: -distance, right: undefined }; const combinedStyles: CombinedStyles = { diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 4d0a600f41..b391e16941 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,11 +1,7 @@ import * as React from 'react'; -import { - I18nManager, - Image, - ImageSourcePropType, - Platform, -} from 'react-native'; +import { Image, ImageSourcePropType, Platform } from 'react-native'; +import { useLocaleDirection } from '../core/Localization'; import { Consumer as SettingsConsumer } from '../core/settings'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -75,10 +71,11 @@ const Icon = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const localeDirection = useLocaleDirection(); const direction = typeof source === 'object' && source.direction && source.source ? source.direction === 'auto' - ? I18nManager.getConstants().isRTL + ? localeDirection ? 'rtl' : 'ltr' : source.direction diff --git a/src/components/List/ListAccordion.tsx b/src/components/List/ListAccordion.tsx index ab54276117..e4d1a2a5ef 100644 --- a/src/components/List/ListAccordion.tsx +++ b/src/components/List/ListAccordion.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { GestureResponderEvent, - I18nManager, StyleProp, StyleSheet, TextStyle, @@ -10,6 +9,7 @@ import { ViewStyle, } from 'react-native'; +import { useLocaleDirection } from '../../core/Localization'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; @@ -166,6 +166,7 @@ const ListAccordion = ({ pointerEvents = 'none', }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const [expanded, setExpanded] = React.useState( expandedProp || false ); @@ -266,7 +267,7 @@ const ListAccordion = ({ name={isExpanded ? 'chevron-up' : 'chevron-down'} color={theme.isV3 ? descriptionColor : titleColor} size={24} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )} @@ -320,7 +321,7 @@ const styles = StyleSheet.create({ margin: 8, }, child: { - paddingLeft: 64, + paddingStart: 64, }, content: { flex: 1, diff --git a/src/components/List/ListImage.tsx b/src/components/List/ListImage.tsx index 92cc7b5cc8..a0ae707901 100644 --- a/src/components/List/ListImage.tsx +++ b/src/components/List/ListImage.tsx @@ -81,12 +81,12 @@ const styles = StyleSheet.create({ video: { width: 100, height: 64, - marginLeft: 0, + marginStart: 0, }, videoV3: { width: 114, height: 64, - marginLeft: 0, + marginStart: 0, }, }); diff --git a/src/components/List/ListItem.tsx b/src/components/List/ListItem.tsx index b0b4516c69..b5b9b184fc 100644 --- a/src/components/List/ListItem.tsx +++ b/src/components/List/ListItem.tsx @@ -38,8 +38,8 @@ type Description = }) => React.ReactNode); interface Style { - marginLeft?: number; - marginRight?: number; + marginStart?: number; + marginEnd?: number; marginVertical?: number; alignSelf?: FlexAlignType; } @@ -259,7 +259,7 @@ const styles = StyleSheet.create({ }, containerV3: { paddingVertical: 8, - paddingRight: 24, + paddingEnd: 24, }, row: { flexDirection: 'row', @@ -276,10 +276,10 @@ const styles = StyleSheet.create({ }, item: { marginVertical: 6, - paddingLeft: 8, + paddingStart: 8, }, itemV3: { - paddingLeft: 16, + paddingStart: 16, }, content: { flex: 1, diff --git a/src/components/List/utils.ts b/src/components/List/utils.ts index 00c6cee1b2..51c713e2c3 100644 --- a/src/components/List/utils.ts +++ b/src/components/List/utils.ts @@ -18,25 +18,25 @@ export const getLeftStyles = ( isV3: boolean ) => { const stylesV3 = { - marginRight: 0, - marginLeft: 16, + marginEnd: 0, + marginStart: 16, alignSelf: alignToTop ? 'flex-start' : 'center', }; if (!description) { return { - ...styles.iconMarginLeft, + ...styles.iconmarginStart, ...styles.marginVerticalNone, ...(isV3 && { ...stylesV3 }), }; } if (!isV3) { - return styles.iconMarginLeft; + return styles.iconmarginStart; } return { - ...styles.iconMarginLeft, + ...styles.iconmarginStart, ...stylesV3, }; }; @@ -47,32 +47,32 @@ export const getRightStyles = ( isV3: boolean ) => { const stylesV3 = { - marginLeft: 16, + marginStart: 16, alignSelf: alignToTop ? 'flex-start' : 'center', }; if (!description) { return { - ...styles.iconMarginRight, + ...styles.iconmarginEnd, ...styles.marginVerticalNone, ...(isV3 && { ...stylesV3 }), }; } if (!isV3) { - return styles.iconMarginRight; + return styles.iconmarginEnd; } return { - ...styles.iconMarginRight, + ...styles.iconmarginEnd, ...stylesV3, }; }; const styles = StyleSheet.create({ marginVerticalNone: { marginVertical: 0 }, - iconMarginLeft: { marginLeft: 0, marginRight: 16 }, - iconMarginRight: { marginRight: 0 }, + iconmarginStart: { marginStart: 0, marginEnd: 16 }, + iconmarginEnd: { marginEnd: 0 }, }); export const getAccordionColors = ({ diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index a019c0fb04..ae40dafaa4 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -6,7 +6,6 @@ import { Easing, EmitterSubscription, findNodeHandle, - I18nManager, Keyboard, KeyboardEvent as RNKeyboardEvent, LayoutRectangle, @@ -22,6 +21,7 @@ import { } from 'react-native'; import { APPROX_STATUSBAR_HEIGHT } from '../../constants'; +import { Direction, withLocaleDirection } from '../../core/Localization'; import { withInternalTheme } from '../../core/theming'; import type { $Omit, InternalTheme } from '../../types'; import { addEventListener } from '../../utils/addEventListener'; @@ -79,6 +79,10 @@ export type Props = { * testID to be used on tests. */ testID?: string; + /** + * Indicates the text direction + */ + direction: Direction; }; type Layout = $Omit<$Omit, 'y'>; @@ -155,9 +159,6 @@ const WINDOW_LAYOUT = Dimensions.get('window'); * wrapping is not necessary if you use Paper's `Modal` instead. */ class Menu extends React.Component { - // @component ./MenuItem.tsx - static Item = MenuItem; - static defaultProps = { statusBarHeight: APPROX_STATUSBAR_HEIGHT, overlayAccessibilityLabel: 'Close menu', @@ -418,6 +419,7 @@ class Menu extends React.Component { overlayAccessibilityLabel, keyboardShouldPersistTaps, testID, + direction, } = this.props; const { @@ -457,7 +459,14 @@ class Menu extends React.Component { ]; // We need to translate menu while animating scale to imitate transform origin for scale animation - const positionTransforms = []; + const positionTransforms: ( + | { + translateX: Animated.AnimatedInterpolation; + } + | { + translateY: Animated.AnimatedInterpolation; + } + )[] = []; // Check if menu fits horizontally and if not align it to right. if (left <= windowLayout.width - menuLayout.width - SCREEN_INDENT) { @@ -598,10 +607,10 @@ class Menu extends React.Component { ...(scrollableMenuHeight ? { height: scrollableMenuHeight } : {}), }; - const positionStyle = { + const positionStyle = (isRTL: boolean) => ({ top: this.isCoordinate(anchor) ? top : top + additionalVerticalValue, - ...(I18nManager.getConstants().isRTL ? { right: left } : { left }), - }; + ...(isRTL ? { right: left } : { left }), + }); return ( { }} collapsable={false} accessibilityViewIsModal={visible} - style={[styles.wrapper, positionStyle, style]} + style={[ + styles.wrapper, + positionStyle(direction === 'rtl'), + style, + ]} pointerEvents={visible ? 'box-none' : 'none'} onAccessibilityEscape={onDismiss} testID={`${testID}-view`} @@ -672,4 +685,7 @@ const styles = StyleSheet.create({ }, }); -export default withInternalTheme(Menu); +export default Object.assign(withInternalTheme(withLocaleDirection(Menu)), { + // @component ./MenuItem.tsx + Item: MenuItem, +}); diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index e7ec4691e8..db6228a2e1 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -238,10 +238,10 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, md3LeadingIcon: { - marginLeft: 12, + marginStart: 12, }, md3WithoutLeadingIcon: { - marginLeft: 4, + marginStart: 4, }, }); diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index b5538fdff5..37e3e20f4d 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { Animated, - I18nManager, LayoutChangeEvent, Platform, StyleProp, @@ -12,6 +11,7 @@ import { import setColor from 'color'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; @@ -47,7 +47,6 @@ export type Props = React.ComponentPropsWithRef & { const INDETERMINATE_DURATION = 2000; const INDETERMINATE_MAX_WIDTH = 0.6; -const { isRTL } = I18nManager; /** * Progress bar is an indicator used to present progress of some activity in the app. @@ -78,6 +77,7 @@ const ProgressBar = ({ animatedValue, ...rest }: Props) => { + const direction = useLocaleDirection(); const theme = useInternalTheme(themeOverrides); const { current: timer } = React.useRef( new Animated.Value(0) @@ -220,17 +220,20 @@ const ProgressBar = ({ ? { inputRange: [0, 0.5, 1], outputRange: [ - (isRTL ? 1 : -1) * 0.5 * width, - (isRTL ? 1 : -1) * + (direction === 'rtl' ? 1 : -1) * 0.5 * width, + (direction === 'rtl' ? 1 : -1) * 0.5 * INDETERMINATE_MAX_WIDTH * width, - (isRTL ? -1 : 1) * 0.7 * width, + (direction === 'rtl' ? -1 : 1) * 0.7 * width, ], } : { inputRange: [0, 1], - outputRange: [(isRTL ? 1 : -1) * 0.5 * width, 0], + outputRange: [ + (direction === 'rtl' ? 1 : -1) * 0.5 * width, + 0, + ], } ), }, diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 62c77a4a1b..93c2cfabbe 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, GestureResponderEvent, - I18nManager, Platform, StyleProp, StyleSheet, @@ -15,6 +14,7 @@ import { import color from 'color'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { ThemeProp } from '../types'; import { forwardRef } from '../utils/forwardRef'; @@ -26,7 +26,7 @@ import MaterialCommunityIcon from './MaterialCommunityIcon'; import Surface from './Surface'; interface Style { - marginRight: number; + marginEnd: number; } export type Props = React.ComponentPropsWithRef & { @@ -202,6 +202,7 @@ const Searchbar = forwardRef( ref ) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const root = React.useRef(null); React.useImperativeHandle(ref, () => { @@ -295,7 +296,7 @@ const Searchbar = forwardRef( name="magnify" color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )) } @@ -305,7 +306,9 @@ const Searchbar = forwardRef( ( name={isV3 ? 'close' : 'close-circle-outline'} color={color} size={size} - direction={I18nManager.getConstants().isRTL ? 'rtl' : 'ltr'} + direction={direction} /> )) } @@ -403,17 +406,16 @@ const styles = StyleSheet.create({ input: { flex: 1, fontSize: 18, - paddingLeft: 8, + paddingStart: 8, alignSelf: 'stretch', - textAlign: I18nManager.getConstants().isRTL ? 'right' : 'left', minWidth: 0, }, barModeInput: { - paddingLeft: 0, + paddingStart: 0, minHeight: 56, }, viewModeInput: { - paddingLeft: 0, + paddingStart: 0, minHeight: 72, }, elevation: { @@ -426,12 +428,12 @@ const styles = StyleSheet.create({ marginHorizontal: 16, }, rightStyle: { - marginRight: 16, + marginEnd: 16, }, v3ClearIcon: { position: 'absolute', right: 0, - marginLeft: 16, + marginStart: 16, }, v3ClearIconHidden: { display: 'none', diff --git a/src/components/SegmentedButtons/SegmentedButtonItem.tsx b/src/components/SegmentedButtons/SegmentedButtonItem.tsx index ad33861651..6457f5c2aa 100644 --- a/src/components/SegmentedButtons/SegmentedButtonItem.tsx +++ b/src/components/SegmentedButtons/SegmentedButtonItem.tsx @@ -146,7 +146,7 @@ const SegmentedButtonItem = ({ const iconSize = isV3 ? 18 : 16; const iconStyle = { - marginRight: label ? 5 : showCheckedIcon ? 3 : 0, + marginEnd: label ? 5 : showCheckedIcon ? 3 : 0, ...(label && { transform: [ { diff --git a/src/components/Snackbar.tsx b/src/components/Snackbar.tsx index 137d617867..bb48455800 100644 --- a/src/components/Snackbar.tsx +++ b/src/components/Snackbar.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { Animated, Easing, - I18nManager, StyleProp, StyleSheet, View, @@ -12,6 +11,7 @@ import { import { useSafeAreaInsets } from 'react-native-safe-area-context'; import useLatestCallback from 'use-latest-callback'; +import { useLocaleDirection } from '../core/Localization'; import { useInternalTheme } from '../core/theming'; import type { $Omit, $RemoveChildren, ThemeProp } from '../types'; import Button from './Button/Button'; @@ -146,6 +146,7 @@ const Snackbar = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const direction = useLocaleDirection(); const { bottom, right, left } = useSafeAreaInsets(); const { current: opacity } = React.useRef( @@ -232,7 +233,7 @@ const Snackbar = ({ const isIconButton = isV3 && onIconPress; - const marginLeft = action ? -12 : -16; + const marginStart = action ? -12 : -16; const wrapperPaddings = { paddingBottom: bottom, @@ -293,7 +294,7 @@ const Snackbar = ({ > {renderChildrenWithWrapper()} {(action || isIconButton) && ( - + {action ? ( ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 6, - marginRight: 0, + marginStart: 6, + marginEnd: 0, }); }); @@ -187,8 +187,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 8, - marginRight: 0, + marginStart: 8, + marginEnd: 0, }); }) ); @@ -200,8 +200,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 12, - marginRight: -8, + marginStart: 12, + marginEnd: -8, }); }); @@ -214,8 +214,8 @@ describe('button icon styles', () => { ); expect(getByTestId('compact-button-icon-container')).toHaveStyle({ - marginLeft: 16, - marginRight: -16, + marginStart: 16, + marginEnd: -16, }); }) ); diff --git a/src/components/__tests__/Dialog.test.tsx b/src/components/__tests__/Dialog.test.tsx index 7d049caa01..50ffa1d091 100644 --- a/src/components/__tests__/Dialog.test.tsx +++ b/src/components/__tests__/Dialog.test.tsx @@ -80,8 +80,8 @@ describe('DialogActions', () => { paddingBottom: 24, paddingHorizontal: 24, }); - expect(dialogActionButtons[0]).toHaveStyle({ marginRight: 8 }); - expect(dialogActionButtons[1]).toHaveStyle({ marginRight: 0 }); + expect(dialogActionButtons[0]).toHaveStyle({ marginEnd: 8 }); + expect(dialogActionButtons[1]).toHaveStyle({ marginEnd: 0 }); }); it('should apply custom styles', () => { diff --git a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap index 6be4cc0dcd..134219c377 100644 --- a/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap +++ b/src/components/__tests__/Drawer/__snapshots__/DrawerSection.test.tsx.snap @@ -21,8 +21,8 @@ exports[`DrawerSection renders properly 1`] = ` }, undefined, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, Object { "height": 1, diff --git a/src/components/__tests__/FABGroup.test.tsx b/src/components/__tests__/FABGroup.test.tsx index b735cf5166..23714af440 100644 --- a/src/components/__tests__/FABGroup.test.tsx +++ b/src/components/__tests__/FABGroup.test.tsx @@ -147,7 +147,7 @@ describe('FABActions - labelStyle - containerStyle', () => { containerStyle: { padding: 16, backgroundColor: '#687456', - marginLeft: 16, + marginStart: 16, }, onPress() {}, icon: '', diff --git a/src/components/__tests__/ListImage.test.tsx b/src/components/__tests__/ListImage.test.tsx index 5248019277..283cc6afa5 100644 --- a/src/components/__tests__/ListImage.test.tsx +++ b/src/components/__tests__/ListImage.test.tsx @@ -13,7 +13,7 @@ const styles = StyleSheet.create({ video: { width: 114, height: 64, - marginLeft: 0, + marginStart: 0, }, container: { width: 30, diff --git a/src/components/__tests__/ListUtils.test.tsx b/src/components/__tests__/ListUtils.test.tsx index 4aeefb6ca9..98fa2b0141 100644 --- a/src/components/__tests__/ListUtils.test.tsx +++ b/src/components/__tests__/ListUtils.test.tsx @@ -6,20 +6,20 @@ import Text from '../Typography/Text'; const styles = StyleSheet.create({ leftItem: { - marginLeft: 0, - marginRight: 16, + marginStart: 0, + marginEnd: 16, }, leftItemV3: { - marginLeft: 16, - marginRight: 0, + marginStart: 16, + marginEnd: 0, alignSelf: 'center', }, rightItem: { - marginRight: 0, + marginEnd: 0, }, rightItemV3: { - marginLeft: 16, - marginRight: 0, + marginStart: 16, + marginEnd: 0, alignSelf: 'center', }, }); diff --git a/src/components/__tests__/Searchbar.test.tsx b/src/components/__tests__/Searchbar.test.tsx index a9bf8ce6e1..7d9927b526 100644 --- a/src/components/__tests__/Searchbar.test.tsx +++ b/src/components/__tests__/Searchbar.test.tsx @@ -115,7 +115,7 @@ it('renders clear icon wrapper, with appropriate style for v3', () => { expect(getByTestId('search-bar-icon-wrapper')).toHaveStyle({ position: 'absolute', right: 0, - marginLeft: 16, + marginStart: 16, }); update( diff --git a/src/components/__tests__/Snackbar.test.tsx b/src/components/__tests__/Snackbar.test.tsx index b9fcb31da4..0dddc85a57 100644 --- a/src/components/__tests__/Snackbar.test.tsx +++ b/src/components/__tests__/Snackbar.test.tsx @@ -15,7 +15,7 @@ const styles = StyleSheet.create({ backgroundColor: red200, padding: 15, }, - text: { color: white, marginLeft: 10, flexWrap: 'wrap', flexShrink: 1 }, + text: { color: white, marginStart: 10, flexWrap: 'wrap', flexShrink: 1 }, }); // Make sure any animation finishes before checking the snapshot results diff --git a/src/components/__tests__/Surface.test.tsx b/src/components/__tests__/Surface.test.tsx index 8d8e639779..9034b9869b 100644 --- a/src/components/__tests__/Surface.test.tsx +++ b/src/components/__tests__/Surface.test.tsx @@ -76,8 +76,8 @@ describe('Surface', () => { ${'width'} | ${'42%'} ${'height'} | ${'32.5%'} ${'margin'} | ${13} - ${'marginLeft'} | ${13.1} - ${'marginRight'} | ${13.2} + ${'marginStart'} | ${13.1} + ${'marginEnd'} | ${13.2} ${'marginTop'} | ${13.3} ${'marginBottom'} | ${13.4} ${'marginHorizontal'} | ${13.5} @@ -107,8 +107,8 @@ describe('Surface', () => { it.each` property | value ${'padding'} | ${12} - ${'paddingLeft'} | ${12.1} - ${'paddingRight'} | ${12.2} + ${'paddingStart'} | ${12.1} + ${'paddingEnd'} | ${12.2} ${'paddingTop'} | ${12.3} ${'paddingBottom'} | ${12.4} ${'paddingHorizontal'} | ${12.5} diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index 0c228f02e2..8297c9ee72 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ import * as React from 'react'; -import { StyleSheet, Text, Platform, I18nManager } from 'react-native'; +import { StyleSheet, Text, Platform } from 'react-native'; import { fireEvent, render } from '@testing-library/react-native'; import color from 'color'; @@ -27,7 +27,7 @@ const style = StyleSheet.create({ lineHeight: 22, }, contentStyle: { - paddingLeft: 20, + paddingStart: 20, }, }); @@ -181,7 +181,7 @@ it('correctly applies a component as the text label', () => { expect(toJSON()).toMatchSnapshot(); }); -it('correctly applies paddingLeft from contentStyleProp', () => { +it('correctly applies paddingStart from contentStyleProp', () => { const { toJSON } = render( { expect(getByTestId('text-input').props.placeholder).toBe(' '); }); -it('correctly applies padding offset to input label on Android when RTL', () => { - Platform.OS = 'android'; - I18nManager.isRTL = true; - - const { getByTestId } = render( - - } - right={ - - } - /> - ); - - expect(getByTestId('text-input-flat-label-active')).toHaveStyle({ - paddingLeft: 56, - paddingRight: 16, - }); - - I18nManager.isRTL = false; -}); - -it('correctly applies padding offset to input label on Android when LTR', () => { - Platform.OS = 'android'; - - const { getByTestId } = render( - - } - right={ - - } - /> - ); - - expect(getByTestId('text-input-flat-label-active')).toHaveStyle({ - paddingLeft: 16, - paddingRight: 56, - }); -}); - it('calls onLayout on right-side affix adornment', () => { const onLayoutMock = jest.fn(); const nativeEventMock = { diff --git a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap index 8078033e8f..9b132de57b 100644 --- a/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/BottomNavigation.test.tsx.snap @@ -245,8 +245,8 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -479,8 +479,8 @@ exports[`allows customizing Route's type via generics 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -957,8 +957,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1150,8 +1150,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1343,8 +1343,8 @@ exports[`hides labels in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1705,8 +1705,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -1898,8 +1898,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2091,8 +2091,8 @@ exports[`hides labels in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2584,8 +2584,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -2892,8 +2892,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3200,8 +3200,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3508,8 +3508,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -3816,8 +3816,8 @@ exports[`renders bottom navigation with getLazy 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4298,8 +4298,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4558,8 +4558,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -4818,8 +4818,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5078,8 +5078,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5338,8 +5338,8 @@ exports[`renders bottom navigation with scene animation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5696,8 +5696,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -5869,8 +5869,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6042,8 +6042,8 @@ exports[`renders custom icon and label in non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6389,8 +6389,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6549,8 +6549,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6709,8 +6709,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -6869,8 +6869,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7029,8 +7029,8 @@ exports[`renders custom icon and label in shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7419,8 +7419,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -7727,8 +7727,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8035,8 +8035,8 @@ exports[`renders custom icon and label with custom colors in non-shifting bottom style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8517,8 +8517,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -8777,8 +8777,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9037,8 +9037,8 @@ exports[`renders custom icon and label with custom colors in shifting bottom nav style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9461,8 +9461,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -9769,8 +9769,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10077,8 +10077,8 @@ exports[`renders non-shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10559,8 +10559,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -10819,8 +10819,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11079,8 +11079,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11339,8 +11339,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, @@ -11599,8 +11599,8 @@ exports[`renders shifting bottom navigation 1`] = ` style={ Array [ Object { - "left": 0, "position": "absolute", + "start": 0, }, Object { "right": 0, diff --git a/src/components/__tests__/__snapshots__/Button.test.tsx.snap b/src/components/__tests__/__snapshots__/Button.test.tsx.snap index 8b7bb4d2b8..0f15771937 100644 --- a/src/components/__tests__/__snapshots__/Button.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Button.test.tsx.snap @@ -853,16 +853,16 @@ exports[`renders button with icon 1`] = ` style={ Array [ Object { - "marginLeft": 12, - "marginRight": -4, + "marginEnd": -4, + "marginStart": 12, }, Object { - "marginLeft": 16, - "marginRight": -16, + "marginEnd": -16, + "marginStart": 16, }, Object { - "marginLeft": 12, - "marginRight": -8, + "marginEnd": -8, + "marginStart": 12, }, ] } @@ -1061,16 +1061,16 @@ exports[`renders button with icon in reverse order 1`] = ` style={ Array [ Object { - "marginLeft": -4, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -4, }, Object { - "marginLeft": -16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": -16, }, Object { - "marginLeft": -8, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -8, }, ] } @@ -1580,16 +1580,16 @@ exports[`renders loading button 1`] = ` }, Array [ Object { - "marginLeft": 12, - "marginRight": -4, + "marginEnd": -4, + "marginStart": 12, }, Object { - "marginLeft": 16, - "marginRight": -16, + "marginEnd": -16, + "marginStart": 16, }, Object { - "marginLeft": 12, - "marginRight": -8, + "marginEnd": -8, + "marginStart": 12, }, ], ] diff --git a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap index 7706df508a..e2dcbc1067 100644 --- a/src/components/__tests__/__snapshots__/Chip.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Chip.test.tsx.snap @@ -98,14 +98,14 @@ exports[`renders chip with close button 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 34, + "paddingEnd": 34, }, ] } @@ -118,8 +118,8 @@ exports[`renders chip with close button 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -195,8 +195,8 @@ exports[`renders chip with close button 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 8, }, undefined, ], @@ -211,10 +211,10 @@ exports[`renders chip with close button 1`] = ` style={ Object { "alignItems": "center", + "end": 0, "height": "100%", "justifyContent": "center", "position": "absolute", - "right": 0, } } > @@ -237,10 +237,10 @@ exports[`renders chip with close button 1`] = ` "padding": 4, }, Object { - "marginRight": 4, + "marginEnd": 4, }, Object { - "marginRight": 8, + "marginEnd": 8, "padding": 0, }, ] @@ -386,14 +386,14 @@ exports[`renders chip with custom close button 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 34, + "paddingEnd": 34, }, ] } @@ -406,8 +406,8 @@ exports[`renders chip with custom close button 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -483,8 +483,8 @@ exports[`renders chip with custom close button 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 8, }, undefined, ], @@ -499,10 +499,10 @@ exports[`renders chip with custom close button 1`] = ` style={ Object { "alignItems": "center", + "end": 0, "height": "100%", "justifyContent": "center", "position": "absolute", - "right": 0, } } > @@ -525,10 +525,10 @@ exports[`renders chip with custom close button 1`] = ` "padding": 4, }, Object { - "marginRight": 4, + "marginEnd": 4, }, Object { - "marginRight": 8, + "marginEnd": 8, "padding": 0, }, ] @@ -674,14 +674,14 @@ exports[`renders chip with icon 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -694,8 +694,8 @@ exports[`renders chip with icon 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -771,8 +771,8 @@ exports[`renders chip with icon 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], @@ -885,14 +885,14 @@ exports[`renders chip with onPress 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -930,8 +930,8 @@ exports[`renders chip with onPress 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, undefined, ], @@ -1044,14 +1044,14 @@ exports[`renders outlined disabled chip 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -1089,8 +1089,8 @@ exports[`renders outlined disabled chip 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 16, }, undefined, ], @@ -1203,14 +1203,14 @@ exports[`renders selected chip 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -1223,8 +1223,8 @@ exports[`renders selected chip 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -1300,8 +1300,8 @@ exports[`renders selected chip 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index ea65a6bea9..dd867d66f7 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -221,7 +221,7 @@ exports[`renders data table pagination 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -247,7 +247,7 @@ exports[`renders data table pagination 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -563,7 +563,7 @@ exports[`renders data table pagination with fast-forward buttons 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -589,7 +589,7 @@ exports[`renders data table pagination with fast-forward buttons 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1193,7 +1193,7 @@ exports[`renders data table pagination with label 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -1219,7 +1219,7 @@ exports[`renders data table pagination with label 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1537,7 +1537,7 @@ exports[`renders data table pagination with options select 1`] = ` "flexDirection": "row", "flexWrap": "wrap", "justifyContent": "flex-end", - "paddingLeft": 16, + "paddingStart": 16, }, undefined, ] @@ -1573,7 +1573,7 @@ exports[`renders data table pagination with options select 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -1599,7 +1599,7 @@ exports[`renders data table pagination with options select 1`] = ` "flex": undefined, "height": undefined, "left": undefined, - "marginRight": 16, + "marginEnd": 16, "opacity": undefined, "position": undefined, "right": undefined, @@ -1691,12 +1691,12 @@ exports[`renders data table pagination with options select 1`] = ` style={ Array [ Object { - "marginLeft": -4, - "marginRight": 12, + "marginEnd": 12, + "marginStart": -4, }, Object { - "marginLeft": -16, - "marginRight": 16, + "marginEnd": 16, + "marginStart": -16, }, false, ] @@ -1814,7 +1814,7 @@ exports[`renders data table pagination with options select 1`] = ` Array [ Object { "fontSize": 12, - "marginRight": 16, + "marginEnd": 16, }, Object { "color": "rgba(28, 27, 31, 0.6)", @@ -2516,7 +2516,7 @@ exports[`renders data table title with press handler 1`] = ` }, Object {}, Object { - "marginLeft": 8, + "marginStart": 8, }, undefined, ], @@ -2636,7 +2636,7 @@ exports[`renders data table title with sort icon 1`] = ` }, Object {}, Object { - "marginLeft": 8, + "marginStart": 8, }, undefined, ], diff --git a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap index d0127c87a7..f6e5bdb6b3 100644 --- a/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DrawerItem.test.tsx.snap @@ -40,8 +40,8 @@ exports[`renders DrawerItem with icon 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -58,8 +58,8 @@ exports[`renders DrawerItem with icon 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -131,7 +131,7 @@ exports[`renders DrawerItem with icon 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -140,7 +140,7 @@ exports[`renders DrawerItem with icon 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 12, + "marginStart": 12, }, ], ] @@ -194,8 +194,8 @@ exports[`renders active DrawerItem 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -212,8 +212,8 @@ exports[`renders active DrawerItem 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -285,7 +285,7 @@ exports[`renders active DrawerItem 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(29, 25, 43, 1)", @@ -294,7 +294,7 @@ exports[`renders active DrawerItem 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 12, + "marginStart": 12, }, ], ] @@ -348,8 +348,8 @@ exports[`renders basic DrawerItem 1`] = ` Object { "height": 56, "justifyContent": "center", - "marginLeft": 12, - "marginRight": 12, + "marginEnd": 12, + "marginStart": 12, "marginVertical": 0, }, undefined, @@ -366,8 +366,8 @@ exports[`renders basic DrawerItem 1`] = ` "padding": 8, }, Object { - "marginLeft": 16, - "marginRight": 24, + "marginEnd": 24, + "marginStart": 16, "padding": 0, }, ] @@ -403,7 +403,7 @@ exports[`renders basic DrawerItem 1`] = ` }, Array [ Object { - "marginRight": 32, + "marginEnd": 32, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -412,7 +412,7 @@ exports[`renders basic DrawerItem 1`] = ` "fontWeight": "500", "letterSpacing": 0.1, "lineHeight": 20, - "marginLeft": 0, + "marginStart": 0, }, ], ] diff --git a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap index 8d56391e04..7423f11474 100644 --- a/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListAccordion.test.tsx.snap @@ -172,7 +172,7 @@ exports[`renders expanded accordion 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -192,7 +192,7 @@ exports[`renders expanded accordion 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap index 3de447dbad..c198db276e 100644 --- a/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListItem.test.tsx.snap @@ -25,7 +25,7 @@ exports[`renders list item with custom description 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -45,7 +45,7 @@ exports[`renders list item with custom description 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -195,14 +195,14 @@ exports[`renders list item with custom description 1`] = ` "alignItems": "center", "flexDirection": "row", "flexGrow": 1, - "paddingLeft": 4, + "paddingStart": 4, "position": "relative", }, Object { - "paddingLeft": 0, + "paddingStart": 0, }, Object { - "paddingRight": 0, + "paddingEnd": 0, }, ] } @@ -215,8 +215,8 @@ exports[`renders list item with custom description 1`] = ` "padding": 4, }, Object { - "paddingLeft": 8, - "paddingRight": 0, + "paddingEnd": 0, + "paddingStart": 8, }, null, ] @@ -292,8 +292,8 @@ exports[`renders list item with custom description 1`] = ` "lineHeight": 20, }, Object { - "marginLeft": 8, - "marginRight": 16, + "marginEnd": 16, + "marginStart": 8, }, undefined, ], @@ -338,7 +338,7 @@ exports[`renders list item with custom title and description styles 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -358,7 +358,7 @@ exports[`renders list item with custom title and description styles 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -464,7 +464,7 @@ exports[`renders list item with left and right items 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -487,7 +487,7 @@ exports[`renders list item with left and right items 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -570,8 +570,8 @@ exports[`renders list item with left and right items 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, }, ] } @@ -642,7 +642,7 @@ exports[`renders list item with left item 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -668,8 +668,8 @@ exports[`renders list item with left item 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -716,7 +716,7 @@ exports[`renders list item with left item 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -786,7 +786,7 @@ exports[`renders list item with right item 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -806,7 +806,7 @@ exports[`renders list item with right item 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -879,7 +879,7 @@ exports[`renders list item with title and description 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -899,7 +899,7 @@ exports[`renders list item with title and description 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1001,7 +1001,7 @@ exports[`renders with a description with typeof number 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1021,7 +1021,7 @@ exports[`renders with a description with typeof number 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap index a1b6776ad1..19754ae036 100644 --- a/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/ListSection.test.tsx.snap @@ -240,7 +240,7 @@ exports[`renders list section with custom title style 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -266,8 +266,8 @@ exports[`renders list section with custom title style 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -314,7 +314,7 @@ exports[`renders list section with custom title style 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -381,7 +381,7 @@ exports[`renders list section with custom title style 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -407,8 +407,8 @@ exports[`renders list section with custom title style 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -455,7 +455,7 @@ exports[`renders list section with custom title style 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -739,7 +739,7 @@ exports[`renders list section with subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -765,8 +765,8 @@ exports[`renders list section with subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -813,7 +813,7 @@ exports[`renders list section with subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -880,7 +880,7 @@ exports[`renders list section with subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -906,8 +906,8 @@ exports[`renders list section with subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -954,7 +954,7 @@ exports[`renders list section with subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1200,7 +1200,7 @@ exports[`renders list section without subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1226,8 +1226,8 @@ exports[`renders list section without subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -1274,7 +1274,7 @@ exports[`renders list section without subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, @@ -1341,7 +1341,7 @@ exports[`renders list section without subheader 1`] = ` false, Array [ Object { - "paddingRight": 24, + "paddingEnd": 24, "paddingVertical": 8, }, undefined, @@ -1367,8 +1367,8 @@ exports[`renders list section without subheader 1`] = ` }, Object { "alignSelf": "center", - "marginLeft": 16, - "marginRight": 0, + "marginEnd": 0, + "marginStart": 16, "marginVertical": 0, }, ] @@ -1415,7 +1415,7 @@ exports[`renders list section without subheader 1`] = ` style={ Array [ Object { - "paddingLeft": 16, + "paddingStart": 16, }, Object { "flex": 1, diff --git a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap index dc24bab891..6c6be23c31 100644 --- a/src/components/__tests__/__snapshots__/Menu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Menu.test.tsx.snap @@ -353,7 +353,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -460,7 +460,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -1029,7 +1029,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] @@ -1136,7 +1136,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap index 261b8d6f3f..538ad4e4c3 100644 --- a/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/MenuItem.test.tsx.snap @@ -110,7 +110,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -265,7 +265,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -420,7 +420,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -575,7 +575,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 12, + "marginStart": 12, }, undefined, ] @@ -682,7 +682,7 @@ Array [ "minWidth": 100, }, Object { - "marginLeft": 4, + "marginStart": 4, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap index 37c0404991..ee9e5b8f1e 100644 --- a/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Searchbar.test.tsx.snap @@ -208,8 +208,7 @@ exports[`activity indicator snapshot test 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -218,10 +217,11 @@ exports[`activity indicator snapshot test 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] @@ -640,8 +640,7 @@ exports[`renders with placeholder 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -650,10 +649,11 @@ exports[`renders with placeholder 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] @@ -667,7 +667,7 @@ exports[`renders with placeholder 1`] = ` style={ Array [ Object { - "marginLeft": 16, + "marginStart": 16, "position": "absolute", "right": 0, }, @@ -1032,8 +1032,7 @@ exports[`renders with text 1`] = ` "flex": 1, "fontSize": 18, "minWidth": 0, - "paddingLeft": 8, - "textAlign": "left", + "paddingStart": 8, }, Object { "color": "rgba(73, 69, 79, 1)", @@ -1042,10 +1041,11 @@ exports[`renders with text 1`] = ` "fontWeight": "400", "letterSpacing": 0.15, "lineHeight": 0, + "textAlign": "left", }, Object { "minHeight": 56, - "paddingLeft": 0, + "paddingStart": 0, }, undefined, ] diff --git a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap index 069ef978c8..7167c7de71 100644 --- a/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/SegmentedButton.test.tsx.snap @@ -92,7 +92,7 @@ exports[`renders checked segmented button with selected check 1`] = ` collapsable={false} style={ Object { - "marginRight": 3, + "marginEnd": 3, "transform": Array [ Object { "scale": 0, diff --git a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap index d913e9979d..58f7d7c5a7 100644 --- a/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Snackbar.test.tsx.snap @@ -206,7 +206,7 @@ exports[`renders snackbar with View & Text as a child 1`] = ` "color": "#ffffff", "flexShrink": 1, "flexWrap": "wrap", - "marginLeft": 10, + "marginStart": 10, } } > @@ -338,7 +338,7 @@ exports[`renders snackbar with action button 1`] = ` "minHeight": 48, }, Object { - "marginLeft": -12, + "marginStart": -12, }, ] } @@ -355,8 +355,8 @@ exports[`renders snackbar with action button 1`] = ` "flex": undefined, "height": undefined, "left": undefined, - "marginLeft": 4, - "marginRight": 8, + "marginEnd": 8, + "marginStart": 4, "opacity": undefined, "position": undefined, "right": undefined, diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index d397e7558e..006a8d0be1 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -77,13 +77,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -122,13 +122,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -174,8 +174,8 @@ exports[`correctly applies a component as the text label 1`] = ` "margin": 0, }, Object { - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, }, Object { "height": 56, @@ -286,13 +286,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -323,13 +323,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -367,8 +367,8 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "margin": 0, }, Object { - "paddingLeft": 16, - "paddingRight": 16, + "paddingEnd": 16, + "paddingStart": 16, }, Object { "height": 56, @@ -455,7 +455,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "top": 0, "transform": Array [ Object { - "translateX": 3, + "translateX": -3, }, ], "zIndex": 3, @@ -473,12 +473,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 8, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 1, "paddingHorizontal": 0, "position": "absolute", + "start": 8, "textAlign": "left", "top": 59, "transform": Array [ @@ -513,12 +513,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -549,12 +549,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, - "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", + "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -626,7 +626,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` `; -exports[`correctly applies paddingLeft from contentStyleProp 1`] = ` +exports[`correctly applies paddingStart from contentStyleProp 1`] = ` = React.ComponentType< + Omit +>; + +const context = createContext( + I18nManager.getConstants().isRTL ? 'rtl' : 'ltr' +); + +const useLocaleDirection = (): Direction => { + return useContext(context); +}; + +const withLocaleDirection = >( + WrappedComponent: React.ComponentType +): LocaleDirectionComponent => { + const displayName = + WrappedComponent.displayName || WrappedComponent.name || 'Component'; + + const Component = (props: Props) => { + const direction = useLocaleDirection(); + + return ; + }; + + Component.displayName = `withLocaleDirection(${displayName})`; + + return Component as LocaleDirectionComponent; +}; + +export const { Provider: LocalizationProvider } = context; + +export { Direction, useLocaleDirection, withLocaleDirection }; diff --git a/src/core/Provider.tsx b/src/core/Provider.tsx index eebe58de09..3cf28ccc08 100644 --- a/src/core/Provider.tsx +++ b/src/core/Provider.tsx @@ -3,13 +3,18 @@ import { AccessibilityInfo, Appearance, ColorSchemeName, + I18nManager, NativeEventSubscription, + Platform, + StyleSheet, + View, } from 'react-native'; import MaterialCommunityIcon from '../components/MaterialCommunityIcon'; import PortalHost from '../components/Portal/PortalHost'; import type { ThemeProp } from '../types'; import { addEventListener } from '../utils/addEventListener'; +import { Direction, LocalizationProvider } from './Localization'; import SafeAreaProviderCompat from './SafeAreaProviderCompat'; import { Provider as SettingsProvider, Settings } from './settings'; import { defaultThemesByVersion, ThemeProvider } from './theming'; @@ -18,6 +23,7 @@ export type Props = { children: React.ReactNode; theme?: ThemeProp; settings?: Settings; + direction?: Direction; }; const Provider = (props: Props) => { @@ -76,6 +82,12 @@ const Provider = (props: Props) => { }; }, [props.theme, isOnlyVersionInTheme]); + React.useEffect(() => { + if (props.direction && Platform.OS !== 'web') { + I18nManager.forceRTL(props.direction === 'rtl'); + } + }, [props.direction]); + const getTheme = () => { const themeVersion = props.theme?.version || 3; const scheme = colorScheme || 'light'; @@ -97,18 +109,36 @@ const Provider = (props: Props) => { }; }; - const { children, settings } = props; + const { + children, + settings, + direction = I18nManager.getConstants().isRTL ? 'rtl' : 'ltr', + } = props; return ( - - {/* @ts-expect-error check @callstack/react-theme-provider's children prop */} - {children} - + + + {/* @ts-expect-error check @callstack/react-theme-provider's children prop */} + + { + + {children} + + } + + + ); }; +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + export default Provider; diff --git a/src/react-navigation/views/MaterialBottomTabView.tsx b/src/react-navigation/views/MaterialBottomTabView.tsx index a582c2dfbc..34bb0c6ef5 100644 --- a/src/react-navigation/views/MaterialBottomTabView.tsx +++ b/src/react-navigation/views/MaterialBottomTabView.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { I18nManager, Platform, StyleSheet } from 'react-native'; +import { Platform, StyleSheet } from 'react-native'; import { CommonActions, @@ -11,6 +11,7 @@ import { import BottomNavigation from '../../components/BottomNavigation/BottomNavigation'; import MaterialCommunityIcon from '../../components/MaterialCommunityIcon'; +import { useLocaleDirection } from '../../core/Localization'; import { useNavigationLink } from '../adapter'; import type { MaterialBottomTabDescriptorMap, @@ -31,6 +32,7 @@ export default function MaterialBottomTabView({ ...rest }: Props) { const buildLink = useNavigationLink(); + const direction = useLocaleDirection(); return ( { backgroundColor: 'red', marginTop: 1, marginBottom: 2, - marginLeft: 3, + marginStart: 3, padding: 4, borderTopLeftRadius: 5, borderTopRightRadius: 6, From 1dbd6bf597a0ebb3c1411466029bdb00de53b085 Mon Sep 17 00:00:00 2001 From: Tomasz Janiczek Date: Mon, 31 Jul 2023 16:54:25 +0200 Subject: [PATCH 5/5] Fix issues --- example/src/DrawerItems.tsx | 14 +- example/src/Examples/CardExample.tsx | 7 +- example/src/Examples/SnackbarExample.tsx | 7 +- example/src/PreferencesContext.ts | 31 +++++ example/src/index.native.tsx | 35 ++--- example/src/index.tsx | 32 ++--- src/components/TextInput/Label/InputLabel.tsx | 6 +- .../TextInput/Label/LabelBackground.tsx | 4 +- src/components/TextInput/TextInput.tsx | 2 +- src/components/TextInput/TextInputFlat.tsx | 36 +++--- .../TextInput/TextInputOutlined.tsx | 14 +- src/components/TextInput/helpers.tsx | 12 +- src/components/TextInput/types.tsx | 4 +- .../__snapshots__/TextInput.test.tsx.snap | 120 +++++++++--------- 14 files changed, 173 insertions(+), 151 deletions(-) create mode 100644 example/src/PreferencesContext.ts diff --git a/example/src/DrawerItems.tsx b/example/src/DrawerItems.tsx index f8cfddd5f1..a8ceff2a8d 100644 --- a/example/src/DrawerItems.tsx +++ b/example/src/DrawerItems.tsx @@ -12,8 +12,10 @@ import { TouchableRipple, } from 'react-native-paper'; -import { deviceColorsSupported, isWeb } from '../utils'; -import { PreferencesContext, useExampleTheme } from './'; +import { deviceColorsSupported } from '../utils'; +import { usePreferences } from './PreferencesContext'; + +import { useExampleTheme } from './'; const DrawerItemsData = [ { @@ -85,27 +87,25 @@ const DrawerCollapsedItemsData = [ function DrawerItems() { const [drawerItemIndex, setDrawerItemIndex] = React.useState(0); - const preferences = React.useContext(PreferencesContext); + const preferences = usePreferences(); const _setDrawerItem = (index: number) => setDrawerItemIndex(index); const { isV3, colors } = useExampleTheme(); const isIOS = Platform.OS === 'ios'; - if (!preferences) throw new Error('PreferencesContext not provided'); - const { toggleShouldUseDeviceColors, toggleTheme, - toggleRtl: toggleRTL, toggleThemeVersion, toggleCollapsed, toggleCustomFont, toggleRippleEffect, + toggleRTL, customFontLoaded, rippleEffectEnabled, collapsed, - rtl: isRTL, + isRTL, theme: { dark: isDarkTheme }, shouldUseDeviceColors, } = preferences; diff --git a/example/src/Examples/CardExample.tsx b/example/src/Examples/CardExample.tsx index 9d4d5fe56d..9b40faa6d8 100644 --- a/example/src/Examples/CardExample.tsx +++ b/example/src/Examples/CardExample.tsx @@ -11,8 +11,9 @@ import { Text, } from 'react-native-paper'; -import { PreferencesContext, useExampleTheme } from '..'; +import { useExampleTheme } from '..'; import { isWeb } from '../../utils'; +import { usePreferences } from '../PreferencesContext'; import ScreenWrapper from '../ScreenWrapper'; type Mode = 'elevated' | 'outlined' | 'contained'; @@ -21,7 +22,7 @@ const CardExample = () => { const { colors, isV3 } = useExampleTheme(); const [selectedMode, setSelectedMode] = React.useState('elevated' as Mode); const [isSelected, setIsSelected] = React.useState(false); - const preferences = React.useContext(PreferencesContext); + const preferences = usePreferences(); const modes = isV3 ? ['elevated', 'outlined', 'contained'] @@ -175,7 +176,7 @@ const CardExample = () => { { - preferences?.toggleTheme(); + preferences.toggleTheme(); }} mode={selectedMode} > diff --git a/example/src/Examples/SnackbarExample.tsx b/example/src/Examples/SnackbarExample.tsx index 4a6511a9b9..d220043a05 100644 --- a/example/src/Examples/SnackbarExample.tsx +++ b/example/src/Examples/SnackbarExample.tsx @@ -3,7 +3,8 @@ import { StyleSheet, View } from 'react-native'; import { Snackbar, Button, List, Text, Switch } from 'react-native-paper'; -import { PreferencesContext, useExampleTheme } from '..'; +import { useExampleTheme } from '..'; +import { usePreferences } from '../PreferencesContext'; import ScreenWrapper from '../ScreenWrapper'; const SHORT_MESSAGE = 'Single-line snackbar'; @@ -11,7 +12,7 @@ const LONG_MESSAGE = 'Snackbar with longer message which does not fit in one line'; const SnackbarExample = () => { - const preferences = React.useContext(PreferencesContext); + const preferences = usePreferences(); const theme = useExampleTheme(); const [options, setOptions] = React.useState({ @@ -33,7 +34,7 @@ const SnackbarExample = () => { const action = { label: showLongerAction ? 'Toggle Theme' : 'Action', onPress: () => { - preferences?.toggleTheme(); + preferences.toggleTheme(); }, }; diff --git a/example/src/PreferencesContext.ts b/example/src/PreferencesContext.ts new file mode 100644 index 0000000000..c85c163d9e --- /dev/null +++ b/example/src/PreferencesContext.ts @@ -0,0 +1,31 @@ +import * as React from 'react'; + +import type { MD2Theme, MD3Theme } from 'react-native-paper'; + +const PreferencesContext = React.createContext<{ + toggleShouldUseDeviceColors?: () => void; + toggleTheme: () => void; + toggleRTL: () => void; + toggleThemeVersion: () => void; + toggleCollapsed: () => void; + toggleCustomFont: () => void; + toggleRippleEffect: () => void; + customFontLoaded: boolean; + rippleEffectEnabled: boolean; + collapsed: boolean; + isRTL: boolean; + theme: MD2Theme | MD3Theme; + shouldUseDeviceColors?: boolean; +} | null>(null); + +export const usePreferences = () => { + const context = React.useContext(PreferencesContext); + + if (!context) { + throw new Error('Context required'); + } + + return context; +}; + +export default PreferencesContext; diff --git a/example/src/index.native.tsx b/example/src/index.native.tsx index 78698bdbfc..6cb2a1656f 100644 --- a/example/src/index.native.tsx +++ b/example/src/index.native.tsx @@ -30,27 +30,12 @@ import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import { deviceColorsSupported } from '../utils'; import DrawerItems from './DrawerItems'; +import PreferencesContext from './PreferencesContext'; import App from './RootNavigator'; const PERSISTENCE_KEY = 'NAVIGATION_STATE'; const PREFERENCES_KEY = 'APP_PREFERENCES'; -export const PreferencesContext = React.createContext<{ - toggleShouldUseDeviceColors?: () => void; - toggleTheme: () => void; - toggleRtl: () => void; - toggleThemeVersion: () => void; - toggleCollapsed: () => void; - toggleCustomFont: () => void; - toggleRippleEffect: () => void; - customFontLoaded: boolean; - rippleEffectEnabled: boolean; - collapsed: boolean; - rtl: boolean; - theme: MD2Theme | MD3Theme; - shouldUseDeviceColors?: boolean; -} | null>(null); - export const useExampleTheme = () => useTheme(); const Drawer = createDrawerNavigator<{ Home: undefined }>(); @@ -71,7 +56,7 @@ export default function PaperExample() { React.useState(true); const [isDarkMode, setIsDarkMode] = React.useState(false); const [themeVersion, setThemeVersion] = React.useState<2 | 3>(3); - const [rtl, setRtl] = React.useState( + const [isRTL, setIsRTL] = React.useState( I18nManager.getConstants().isRTL ); const [collapsed, setCollapsed] = React.useState(false); @@ -122,7 +107,7 @@ export default function PaperExample() { setIsDarkMode(preferences.theme === 'dark'); if (typeof preferences.rtl === 'boolean') { - setRtl(preferences.rtl); + setIsRTL(preferences.rtl); } } } catch (e) { @@ -140,28 +125,28 @@ export default function PaperExample() { PREFERENCES_KEY, JSON.stringify({ theme: isDarkMode ? 'dark' : 'light', - rtl, + rtl: isRTL, }) ); } catch (e) { // ignore error } - if (I18nManager.getConstants().isRTL !== rtl) { - I18nManager.forceRTL(rtl); + if (I18nManager.getConstants().isRTL !== isRTL) { + I18nManager.forceRTL(isRTL); Updates.reloadAsync(); } }; savePrefs(); - }, [rtl, isDarkMode]); + }, [isRTL, isDarkMode]); const preferences = React.useMemo( () => ({ toggleShouldUseDeviceColors: () => setShouldUseDeviceColors((oldValue) => !oldValue), toggleTheme: () => setIsDarkMode((oldValue) => !oldValue), - toggleRtl: () => setRtl((rtl) => !rtl), + toggleRTL: () => setIsRTL((rtl) => !rtl), toggleCollapsed: () => setCollapsed(!collapsed), toggleCustomFont: () => setCustomFont(!customFontLoaded), toggleRippleEffect: () => setRippleEffectEnabled(!rippleEffectEnabled), @@ -174,12 +159,12 @@ export default function PaperExample() { customFontLoaded, rippleEffectEnabled, collapsed, - rtl, + isRTL, theme, shouldUseDeviceColors, }), [ - rtl, + isRTL, theme, collapsed, customFontLoaded, diff --git a/example/src/index.tsx b/example/src/index.tsx index b2f0dfdee3..f8db09c265 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { I18nManager } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { createDrawerNavigator } from '@react-navigation/drawer'; @@ -25,23 +26,12 @@ import { import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; import DrawerItems from './DrawerItems'; +import PreferencesContext from './PreferencesContext'; import App from './RootNavigator'; const PERSISTENCE_KEY = 'NAVIGATION_STATE'; const PREFERENCES_KEY = 'APP_PREFERENCES'; -export const PreferencesContext = React.createContext<{ - toggleTheme: () => void; - toggleThemeVersion: () => void; - toggleCollapsed: () => void; - toggleCustomFont: () => void; - toggleRippleEffect: () => void; - customFontLoaded: boolean; - rippleEffectEnabled: boolean; - collapsed: boolean; - theme: MD2Theme | MD3Theme; -} | null>(null); - export const useExampleTheme = () => useTheme(); const Drawer = createDrawerNavigator<{ Home: undefined }>(); @@ -63,6 +53,7 @@ export default function PaperExample() { const [collapsed, setCollapsed] = React.useState(false); const [customFontLoaded, setCustomFont] = React.useState(false); const [rippleEffectEnabled, setRippleEffectEnabled] = React.useState(true); + const [isRTL, setIsRTL] = React.useState(false); const theme = React.useMemo(() => { if (themeVersion === 2) { @@ -99,6 +90,10 @@ export default function PaperExample() { if (preferences) { setIsDarkMode(preferences.theme === 'dark'); + + if (typeof preferences.rtl === 'boolean') { + setIsRTL(preferences.rtl); + } } } catch (e) { // ignore error @@ -115,15 +110,19 @@ export default function PaperExample() { PREFERENCES_KEY, JSON.stringify({ theme: isDarkMode ? 'dark' : 'light', + rtl: isRTL, }) ); } catch (e) { // ignore error } + + document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr'); + I18nManager.forceRTL(isRTL); }; savePrefs(); - }, [isDarkMode]); + }, [isDarkMode, isRTL]); const preferences = React.useMemo( () => ({ @@ -131,6 +130,7 @@ export default function PaperExample() { toggleCollapsed: () => setCollapsed(!collapsed), toggleCustomFont: () => setCustomFont(!customFontLoaded), toggleRippleEffect: () => setRippleEffectEnabled(!rippleEffectEnabled), + toggleRTL: () => setIsRTL((rtl) => !rtl), toggleThemeVersion: () => { setCustomFont(false); setCollapsed(false); @@ -140,9 +140,10 @@ export default function PaperExample() { customFontLoaded, rippleEffectEnabled, collapsed, + isRTL, theme, }), - [theme, collapsed, customFontLoaded, rippleEffectEnabled] + [customFontLoaded, rippleEffectEnabled, collapsed, isRTL, theme] ); if (!isReady && !fontsLoaded) { @@ -186,7 +187,7 @@ export default function PaperExample() { @@ -207,6 +208,7 @@ export default function PaperExample() { drawerStyle: collapsed && { width: collapsedDrawerWidth, }, + // drawerPosition: isRTL ? 'right' : 'left', }} drawerContent={() => } > diff --git a/src/components/TextInput/Label/InputLabel.tsx b/src/components/TextInput/Label/InputLabel.tsx index 2ad987cbd8..0289bdc76c 100644 --- a/src/components/TextInput/Label/InputLabel.tsx +++ b/src/components/TextInput/Label/InputLabel.tsx @@ -29,8 +29,8 @@ const InputLabel = (props: InputLabelProps) => { wiggleOffsetX, labelScale, topPosition, - paddingStart, - paddingEnd, + paddingLeft, + paddingRight, backgroundColor, roundness, placeholderColor, @@ -41,7 +41,7 @@ const InputLabel = (props: InputLabelProps) => { } = props; const paddingOffset = - paddingStart && paddingEnd ? { paddingStart, paddingEnd } : {}; + paddingLeft && paddingRight ? { paddingLeft, paddingRight } : {}; const labelTranslationX = { transform: [ diff --git a/src/components/TextInput/Label/LabelBackground.tsx b/src/components/TextInput/Label/LabelBackground.tsx index 2c02b749e8..20e775304c 100644 --- a/src/components/TextInput/Label/LabelBackground.tsx +++ b/src/components/TextInput/Label/LabelBackground.tsx @@ -86,13 +86,13 @@ const styles = StyleSheet.create({ view: { position: 'absolute', top: 6, - start: 10, + left: 10, width: 12, }, // eslint-disable-next-line react-native/no-color-literals outlinedLabel: { position: 'absolute', - start: 8, + left: 8, paddingHorizontal: 0, color: 'transparent', }, diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index 6deff8008e..58c98f1e1f 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -155,7 +155,7 @@ export type Props = React.ComponentPropsWithRef & { /** * Pass custom style directly to the input itself. * Overrides input style - * Example: `paddingStart`, `backgroundColor` + * Example: `paddingLeft`, `backgroundColor` */ contentStyle?: StyleProp; /** diff --git a/src/components/TextInput/TextInputFlat.tsx b/src/components/TextInput/TextInputFlat.tsx index 1a8e4db52b..8a463aec19 100644 --- a/src/components/TextInput/TextInputFlat.tsx +++ b/src/components/TextInput/TextInputFlat.tsx @@ -78,7 +78,8 @@ const TextInputFlat = ({ contentStyle, ...rest }: ChildTextInputProps) => { - const { direction } = useLocale(); + const { direction, overwriteRTL } = useLocale(); + const isRTL = direction === 'rtl'; const isAndroid = Platform.OS === 'android'; const { colors, isV3, roundness } = theme; const font = isV3 ? theme.fonts.bodyLarge : theme.fonts.regular; @@ -106,14 +107,14 @@ const TextInputFlat = ({ right, }); - let { paddingStart, paddingEnd } = calculateFlatInputHorizontalPadding({ + let { paddingLeft, paddingRight } = calculateFlatInputHorizontalPadding({ adornmentConfig, isV3, }); if (isPaddingHorizontalPassed) { - paddingStart = paddingHorizontal as number; - paddingEnd = paddingHorizontal as number; + paddingLeft = paddingHorizontal as number; + paddingRight = paddingHorizontal as number; } const { leftLayout, rightLayout } = parentState; @@ -168,9 +169,8 @@ const TextInputFlat = ({ const labelHalfHeight = labelHeight / 2; const baseLabelTranslateX = - (direction === 'rtl' ? 1 : -1) * - (labelHalfWidth - (labelScale * labelWidth) / 2) + - (1 - labelScale) * (direction === 'rtl' ? -1 : 1) * paddingStart; + (isRTL ? 1 : -1) * (labelHalfWidth - (labelScale * labelWidth) / 2) + + (1 - labelScale) * (isRTL ? -1 : 1) * paddingLeft; const minInputHeight = dense ? (label ? MIN_DENSE_HEIGHT_WL : MIN_DENSE_HEIGHT) - LABEL_PADDING_TOP_DENSE @@ -263,8 +263,12 @@ const TextInputFlat = ({ labelScale, wiggleOffsetX: LABEL_WIGGLE_X_OFFSET, topPosition, - paddingStart, - paddingEnd, + paddingLeft: isAndroid ? (isRTL ? paddingRight : paddingLeft) : paddingLeft, + paddingRight: isAndroid + ? isRTL + ? paddingLeft + : paddingRight + : paddingRight, hasActiveOutline, activeColor, placeholderColor, @@ -345,8 +349,8 @@ const TextInputFlat = ({ { backgroundColor: viewStyle.backgroundColor || containerStyle.backgroundColor, - start: paddingStart, - end: paddingEnd, + left: paddingLeft, + right: paddingRight, }, ]} /> @@ -382,7 +386,7 @@ const TextInputFlat = ({ multiline, style: [ styles.input, - { paddingStart: paddingStart, paddingEnd: paddingEnd }, + { paddingLeft, paddingRight }, !multiline || (multiline && height) ? { height: flatHeight } : {}, paddingFlat, { @@ -392,9 +396,11 @@ const TextInputFlat = ({ fontWeight, color: inputTextColor, textAlignVertical: multiline ? 'top' : 'center', - textAlign: textAlign + textAlign: overwriteRTL + ? 'right' + : textAlign ? textAlign - : direction === 'rtl' + : isRTL ? 'right' : 'left', }, @@ -472,7 +478,7 @@ const Underline = ({ const styles = StyleSheet.create({ placeholder: { position: 'absolute', - start: 0, + left: 0, }, underline: { position: 'absolute', diff --git a/src/components/TextInput/TextInputOutlined.tsx b/src/components/TextInput/TextInputOutlined.tsx index 0240062374..4726bab4c6 100644 --- a/src/components/TextInput/TextInputOutlined.tsx +++ b/src/components/TextInput/TextInputOutlined.tsx @@ -75,6 +75,7 @@ const TextInputOutlined = ({ ...rest }: ChildTextInputProps) => { const { direction } = useLocale(); + const isRTL = direction === 'rtl'; const adornmentConfig = getAdornmentConfig({ left, right }); @@ -120,7 +121,7 @@ const TextInputOutlined = ({ const labelHalfHeight = labelHeight / 2; const baseLabelTranslateX = - (direction === 'rtl' ? -1 : 1) * + (isRTL ? 1 : -1) * (labelHalfWidth - (labelScale * labelWidth) / 2 - (fontSize - MINIMIZED_LABEL_FONT_SIZE) * labelScale); @@ -132,8 +133,7 @@ const TextInputOutlined = ({ ); if (isAdornmentLeftIcon) { labelTranslationXOffset = - (direction === 'rtl' ? -1 : 1) * - (ADORNMENT_SIZE + ADORNMENT_OFFSET - (isV3 ? 0 : 8)); + (isRTL ? -1 : 1) * (ADORNMENT_SIZE + ADORNMENT_OFFSET - (isV3 ? 0 : 8)); } const minInputHeight = @@ -184,7 +184,7 @@ const TextInputOutlined = ({ const placeholderStyle = { position: 'absolute', - start: 0, + left: 0, paddingHorizontal: INPUT_PADDING_HORIZONTAL, }; @@ -365,11 +365,7 @@ const TextInputOutlined = ({ fontWeight, color: inputTextColor, textAlignVertical: multiline ? 'top' : 'center', - textAlign: textAlign - ? textAlign - : direction === 'rtl' - ? 'right' - : 'left', + textAlign: textAlign ? textAlign : isRTL ? 'right' : 'left', paddingHorizontal: INPUT_PADDING_HORIZONTAL, }, Platform.OS === 'web' && { outline: 'none' }, diff --git a/src/components/TextInput/helpers.tsx b/src/components/TextInput/helpers.tsx index 3b36c01d0a..291e1e40d7 100644 --- a/src/components/TextInput/helpers.tsx +++ b/src/components/TextInput/helpers.tsx @@ -283,22 +283,22 @@ export const calculateFlatInputHorizontalPadding = ({ const { LABEL_PADDING_HORIZONTAL, ADORNMENT_OFFSET, FLAT_INPUT_OFFSET } = getConstants(isV3); - let paddingStart = LABEL_PADDING_HORIZONTAL; - let paddingEnd = LABEL_PADDING_HORIZONTAL; + let paddingLeft = LABEL_PADDING_HORIZONTAL; + let paddingRight = LABEL_PADDING_HORIZONTAL; adornmentConfig.forEach(({ type, side }) => { if (type === AdornmentType.Icon && side === AdornmentSide.Left) { - paddingStart = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; + paddingLeft = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; } else if (side === AdornmentSide.Right) { if (type === AdornmentType.Affix) { - paddingEnd = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; + paddingRight = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; } else if (type === AdornmentType.Icon) { - paddingEnd = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; + paddingRight = ADORNMENT_SIZE + ADORNMENT_OFFSET + FLAT_INPUT_OFFSET; } } }); - return { paddingStart, paddingEnd }; + return { paddingLeft, paddingRight }; }; type BaseProps = { diff --git a/src/components/TextInput/types.tsx b/src/components/TextInput/types.tsx index 924fd8a349..6407ed79e5 100644 --- a/src/components/TextInput/types.tsx +++ b/src/components/TextInput/types.tsx @@ -71,8 +71,8 @@ export type LabelProps = { fontWeight: TextStyle['fontWeight']; font: any; topPosition: number; - paddingStart?: number; - paddingEnd?: number; + paddingLeft?: number; + paddingRight?: number; labelTranslationXOffset?: number; placeholderColor: string | null; backgroundColor?: ColorValue; diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 424aa7e2df..0a3e56618a 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -77,13 +77,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -122,13 +122,13 @@ exports[`correctly applies a component as the text label 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -175,8 +175,8 @@ exports[`correctly applies a component as the text label 1`] = ` "margin": 0, }, Object { - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, }, Object { "height": 56, @@ -287,13 +287,13 @@ exports[`correctly applies cursorColor prop 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -324,13 +324,13 @@ exports[`correctly applies cursorColor prop 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -369,8 +369,8 @@ exports[`correctly applies cursorColor prop 1`] = ` "margin": 0, }, Object { - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, }, Object { "height": 56, @@ -481,13 +481,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -518,13 +518,13 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -563,8 +563,8 @@ exports[`correctly applies default textAlign based on default RTL 1`] = ` "margin": 0, }, Object { - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, }, Object { "height": 56, @@ -651,7 +651,7 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "top": 0, "transform": Array [ Object { - "translateX": -3, + "translateX": 3, }, ], "zIndex": 3, @@ -669,12 +669,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 8, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 1, "paddingHorizontal": 0, "position": "absolute", - "start": 8, "textAlign": "left", "top": 59, "transform": Array [ @@ -709,12 +709,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -745,12 +745,12 @@ exports[`correctly applies height to multiline Outline TextInput 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, "paddingHorizontal": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 58, "transform": Array [ @@ -900,13 +900,13 @@ exports[`correctly applies paddingStart from contentStyleProp 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -937,13 +937,13 @@ exports[`correctly applies paddingStart from contentStyleProp 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -982,8 +982,8 @@ exports[`correctly applies paddingStart from contentStyleProp 1`] = ` "margin": 0, }, Object { - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, }, Object { "height": 56, @@ -1096,13 +1096,13 @@ exports[`correctly applies textAlign center 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1133,13 +1133,13 @@ exports[`correctly applies textAlign center 1`] = ` "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1178,8 +1178,8 @@ exports[`correctly applies textAlign center 1`] = ` "margin": 0, }, Object { - "paddingEnd": 16, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 16, }, Object { "height": 56, @@ -1290,13 +1290,13 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 56, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 56, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1327,13 +1327,13 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 56, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 56, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1372,8 +1372,8 @@ exports[`correctly renders left-side affix adornment, and right-side icon adornm "margin": 0, }, Object { - "paddingEnd": 56, - "paddingStart": 16, + "paddingLeft": 16, + "paddingRight": 56, }, Object { "height": 56, @@ -1674,13 +1674,13 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 56, - "paddingStart": 56, + "paddingLeft": 56, + "paddingRight": 56, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1711,13 +1711,13 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "fontFamily": "System", "fontSize": 16, "fontWeight": undefined, + "left": 0, "letterSpacing": 0.15, "lineHeight": undefined, "opacity": 0, - "paddingEnd": 56, - "paddingStart": 56, + "paddingLeft": 56, + "paddingRight": 56, "position": "absolute", - "start": 0, "textAlign": "left", "top": 30, "transform": Array [ @@ -1756,8 +1756,8 @@ exports[`correctly renders left-side icon adornment, and right-side affix adornm "margin": 0, }, Object { - "paddingEnd": 56, - "paddingStart": 56, + "paddingLeft": 56, + "paddingRight": 56, }, Object { "height": 56,