diff --git a/docs/6.x/docs/guides/migration.md b/docs/6.x/docs/guides/migration.md index e488b101ef..a4d7123a09 100644 --- a/docs/6.x/docs/guides/migration.md +++ b/docs/6.x/docs/guides/migration.md @@ -2,13 +2,11 @@ title: Migration from Paper 5.x to 6.x --- -TBC - ## General changes ### Animations -React Native Paper 6 uses [Reanimated](https://docs.swmansion.com/react-native-reanimated/) for animations as opposed to the built-in React Native `Animated` API. +React Native Paper 6 uses [Reanimated](https://docs.swmansion.com/react-native-reanimated/) for most animations instead of the built-in React Native `Animated` API. So make sure to install `react-native-reanimated` 4.3.0 or later and `react-native-worklets` 0.8.1 or later, then complete the Reanimated setup. See the [getting started guide](./getting-started) for Expo and Community CLI instructions. The following props now accept animated styles returned from `useAnimatedStyle`. They no longer accept `Animated.Value` or `Animated.AnimatedInterpolation` where these were previously supported: @@ -19,6 +17,7 @@ The following props now accept animated styles returned from `useAnimatedStyle`. - `Card`: `style` - `Chip`: `style` - `Dialog`: `style` +- `Drawer.CollapsedItem`: `style` - `FAB` and `FAB.Extended`: `style` - `IconButton`: `style` - `Menu`: `contentStyle` diff --git a/eslint.config.mjs b/eslint.config.mjs index b0415543d2..7c2aeb73a3 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -111,6 +111,20 @@ export default defineConfig( }, ], + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'react-native', + importNames: ['Animated', 'PanResponder'], + message: + 'Use react-native-reanimated for animations and react-native-gesture-handler for gestures.', + }, + ], + }, + ], + '@react-native/platform-colors': 'error', 'promise/no-callback-in-promise': 'error', diff --git a/example/src/Examples/ProgressBarExample.tsx b/example/src/Examples/ProgressBarExample.tsx index a42474b99d..e6ef656cb7 100644 --- a/example/src/Examples/ProgressBarExample.tsx +++ b/example/src/Examples/ProgressBarExample.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: remove after ProgressBar migrates to Reanimated. import { View, StyleSheet, Animated } from 'react-native'; import { diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx index 58ef633c9b..7ab61dfaa9 100644 --- a/src/components/ActivityIndicator.tsx +++ b/src/components/ActivityIndicator.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate ActivityIndicator to Reanimated. import { Animated, Easing, Platform, StyleSheet, View } from 'react-native'; import type { ColorValue, StyleProp, ViewProps, ViewStyle } from 'react-native'; diff --git a/src/components/Badge.tsx b/src/components/Badge.tsx index 4567055f6b..23a8cd973e 100644 --- a/src/components/Badge.tsx +++ b/src/components/Badge.tsx @@ -12,7 +12,7 @@ const LARGE_SIZE = 16; const MAX_LARGE_WIDTH = 36; const LARGE_PADDING = 4; -export type Props = TextProps & { +export type Props = Omit & { /** * Whether the badge is visible */ diff --git a/src/components/BottomNavigation/BottomNavigation.tsx b/src/components/BottomNavigation/BottomNavigation.tsx index df7e28cc76..7b0cd12111 100644 --- a/src/components/BottomNavigation/BottomNavigation.tsx +++ b/src/components/BottomNavigation/BottomNavigation.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate BottomNavigation to Reanimated. import { Animated, Platform, StyleSheet, View } from 'react-native'; import type { ColorValue, diff --git a/src/components/BottomNavigation/BottomNavigationBar.tsx b/src/components/BottomNavigation/BottomNavigationBar.tsx index 6305faa227..b5cd6da15a 100644 --- a/src/components/BottomNavigation/BottomNavigationBar.tsx +++ b/src/components/BottomNavigation/BottomNavigationBar.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate BottomNavigation to Reanimated. import { Animated, Platform, StyleSheet, Pressable, View } from 'react-native'; import type { ColorValue, diff --git a/src/components/BottomNavigation/BottomNavigationRouteScreen.tsx b/src/components/BottomNavigation/BottomNavigationRouteScreen.tsx index 5773e2e1fd..affffc6793 100644 --- a/src/components/BottomNavigation/BottomNavigationRouteScreen.tsx +++ b/src/components/BottomNavigation/BottomNavigationRouteScreen.tsx @@ -1,5 +1,6 @@ import React from 'react'; import type { ReactNode } from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate BottomNavigation to Reanimated. import { Animated, Platform, View } from 'react-native'; import type { ViewProps } from 'react-native'; diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx index f2527383d7..02df81b0b4 100644 --- a/src/components/Checkbox/Checkbox.tsx +++ b/src/components/Checkbox/Checkbox.tsx @@ -9,13 +9,7 @@ import type { ViewStyle, } from 'react-native'; -import Animated, { - Easing, - ReduceMotion, - useAnimatedStyle, - useSharedValue, - withTiming, -} from 'react-native-reanimated'; +import Animated, { cubicBezier, type CSSStyle } from 'react-native-reanimated'; import { CheckboxTokens } from './tokens'; import { getSelectionVisualState } from './utils'; @@ -123,7 +117,9 @@ const Checkbox = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const reduceMotion = useReduceMotion(); + const { direction } = useLocale(); // Web (react-native-web) doesn't auto-mirror layout, so flip the mask // anchor manually for RTL. Native handles it via `I18nManager`. @@ -132,56 +128,6 @@ const Checkbox = ({ const selected = status === 'checked' || status === 'indeterminate'; - const reanimatedReduceMotion = reduceMotion - ? ReduceMotion.Always - : ReduceMotion.Never; - - const fillTimingConfig = React.useMemo( - () => ({ - duration: theme.motion.duration.short2, - easing: Easing.bezier(...theme.motion.easing.standard), - reduceMotion: reanimatedReduceMotion, - }), - [ - theme.motion.duration.short2, - theme.motion.easing.standard, - reanimatedReduceMotion, - ] - ); - const checkTimingConfig = React.useMemo( - () => ({ - duration: theme.motion.duration.short3, - easing: Easing.bezier(...theme.motion.easing.standard), - reduceMotion: reanimatedReduceMotion, - }), - [ - theme.motion.duration.short3, - theme.motion.easing.standard, - reanimatedReduceMotion, - ] - ); - - // 0 = unselected (outline only), 1 = selected (filled + drawn icon). - const fillProgress = useSharedValue(selected ? 1 : 0); - const checkProgress = useSharedValue(selected ? 1 : 0); - const firstRender = React.useRef(true); - - React.useEffect(() => { - if (firstRender.current) { - firstRender.current = false; - return; - } - const target = selected ? 1 : 0; - fillProgress.value = withTiming(target, fillTimingConfig); - checkProgress.value = withTiming(target, checkTimingConfig); - }, [ - selected, - fillProgress, - checkProgress, - fillTimingConfig, - checkTimingConfig, - ]); - // Visual state (colors + opacity) for the static layers. `hovered` / // `pressed` aren't tracked here — `TouchableRipple` owns the press ripple // and hover overlay. @@ -194,19 +140,45 @@ const Checkbox = ({ customUncheckedColor: uncheckedColor, }); - // Outline fades out as fill fades in (and vice versa). - const outlineAnimatedStyle = useAnimatedStyle(() => ({ - opacity: 1 - fillProgress.value, - })); + const fillTransitionTimingFunction = cubicBezier( + ...theme.motion.easing.standard + ); + + const fillTransitionDuration = reduceMotion + ? 0 + : theme.motion.duration.short2; + + const checkTransitionDuration = reduceMotion + ? 0 + : theme.motion.duration.short3; + + const checkTransitionTimingFunction = cubicBezier( + ...theme.motion.easing.standard + ); - const fillAnimatedStyle = useAnimatedStyle(() => ({ - opacity: fillProgress.value, - })); + const outlineStyle: CSSStyle = { + borderColor: visual.outlineColor, + opacity: selected ? 0 : 1, + transitionDuration: fillTransitionDuration, + transitionProperty: ['opacity'], + transitionTimingFunction: fillTransitionTimingFunction, + }; - const maskAnimatedStyle = useAnimatedStyle(() => ({ - width: checkProgress.value * CONTAINER_SIZE, - opacity: checkProgress.value, - })); + const fillStyle: CSSStyle = { + backgroundColor: visual.containerColor, + opacity: selected ? 1 : 0, + transitionDuration: fillTransitionDuration, + transitionProperty: ['opacity'], + transitionTimingFunction: fillTransitionTimingFunction, + }; + + const maskStyle: CSSStyle = { + width: selected ? CONTAINER_SIZE : 0, + opacity: selected ? 1 : 0, + transitionDuration: checkTransitionDuration, + transitionProperty: ['width', 'opacity'], + transitionTimingFunction: checkTransitionTimingFunction, + }; // Remember the last drawn glyph so the reveal-mask can finish collapsing // when `selected` flips back to false. Computed via the "derive state @@ -283,92 +255,48 @@ const Checkbox = ({ + - {showIndeterminate ? ( - + > + {showIndeterminate ? ( - - ) : ( - - )} + ) : ( + + + + )} + ); }; -/** - * Reveal-mask checkmark: an L-shape (borderLeftWidth + borderBottomWidth - * rotated -45deg) inside a directional-anchored View whose width animates - * 0 → CONTAINER_SIZE so the stroke "draws in" along the writing direction. - */ -const Checkmark = ({ - color, - maskAnimatedStyle, - flipMaskForWebRTL, - isRTL, - autoSwapsBorders, -}: { - color: ColorValue; - maskAnimatedStyle: ReturnType; - flipMaskForWebRTL: boolean; - isRTL: boolean; - // True on platforms whose layout engine auto-swaps `borderLeftWidth` - // ↔ `borderRightWidth` in RTL (Android, iOS); false on web (RNW). - autoSwapsBorders: boolean; -}) => { - return ( - - - - - - ); -}; - // Web-only style; not in StyleSheet because `outline` is outside ViewStyle. // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion const webNoOutline = { outline: 'none' } as unknown as ViewStyle; diff --git a/src/components/Checkbox/utils.ts b/src/components/Checkbox/utils.ts index acd3c61126..75b7398a77 100644 --- a/src/components/Checkbox/utils.ts +++ b/src/components/Checkbox/utils.ts @@ -62,13 +62,9 @@ const getOutlineColor = ({ const getIconColor = ({ theme, - selected, disabled, error, }: SelectionState): ColorValue => { - if (!selected) { - return 'transparent'; - } if (disabled) { return theme.colors[CheckboxTokens.disabledIconColor]; } diff --git a/src/components/CrossFadeIcon.tsx b/src/components/CrossFadeIcon.tsx index db1fd244d8..686109a501 100644 --- a/src/components/CrossFadeIcon.tsx +++ b/src/components/CrossFadeIcon.tsx @@ -1,7 +1,16 @@ import * as React from 'react'; -import { Animated, StyleSheet, View } from 'react-native'; +import { StyleSheet, View } from 'react-native'; import type { ColorValue } from 'react-native'; +import Animated, { + Easing, + interpolate, + ReduceMotion, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated'; + import Icon, { isEqualIcon, isValidIcon } from './Icon'; import type { IconSource } from './Icon'; import { useInternalTheme } from '../core/theming'; @@ -38,15 +47,15 @@ const CrossFadeIcon = ({ testID = 'cross-fade-icon', }: Props) => { const theme = useInternalTheme(themeOverrides); + const [currentIcon, setCurrentIcon] = React.useState( () => source ); const [previousIcon, setPreviousIcon] = React.useState( null ); - const { current: fade } = React.useRef(new Animated.Value(1)); - const { scale } = theme.animation; + const fade = useSharedValue(1); if (currentIcon !== source) { setPreviousIcon(() => currentIcon); @@ -55,35 +64,37 @@ const CrossFadeIcon = ({ React.useEffect(() => { if (isValidIcon(previousIcon) && !isEqualIcon(previousIcon, currentIcon)) { - fade.setValue(1); + fade.value = 1; - Animated.timing(fade, { - duration: scale * 200, - toValue: 0, - useNativeDriver: true, - }).start(); + fade.value = withTiming(0, { + duration: theme.animation.scale * 200, + easing: Easing.inOut(Easing.ease), + reduceMotion: ReduceMotion.Never, + }); } - }, [currentIcon, previousIcon, fade, scale]); + }, [currentIcon, fade, previousIcon, theme.animation.scale]); - const opacityPrev = fade; - const opacityNext = previousIcon - ? fade.interpolate({ - inputRange: [0, 1], - outputRange: [1, 0], - }) - : 1; + const hasPreviousIcon = Boolean(previousIcon); - const rotatePrev = fade.interpolate({ - inputRange: [0, 1], - outputRange: ['-90deg', '0deg'], - }); + const previousIconStyle = useAnimatedStyle(() => ({ + opacity: fade.value, + transform: [ + { + rotate: `${interpolate(fade.value, [0, 1], [-90, 0])}deg`, + }, + ], + })); - const rotateNext = previousIcon - ? fade.interpolate({ - inputRange: [0, 1], - outputRange: ['0deg', '-180deg'], - }) - : '0deg'; + const currentIconStyle = useAnimatedStyle(() => ({ + opacity: hasPreviousIcon ? 1 - fade.value : 1, + transform: [ + { + rotate: hasPreviousIcon + ? `${interpolate(fade.value, [0, 1], [0, -180])}deg` + : '0deg', + }, + ], + })); return ( - {previousIcon ? ( + {hasPreviousIcon ? ( ) : null} diff --git a/src/components/DataTable/DataTableTitle.tsx b/src/components/DataTable/DataTableTitle.tsx index 4a972341e6..0015c8753f 100644 --- a/src/components/DataTable/DataTableTitle.tsx +++ b/src/components/DataTable/DataTableTitle.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Animated, PixelRatio, Pressable, StyleSheet } from 'react-native'; +import { PixelRatio, Pressable, StyleSheet } from 'react-native'; import type { GestureResponderEvent, PressableProps, @@ -8,8 +8,17 @@ import type { ViewStyle, } from 'react-native'; +import Animated, { + Easing, + ReduceMotion, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated'; + import { useLocale } from '../../core/locale'; import { useInternalTheme } from '../../core/theming'; +import { useReduceMotion } from '../../theme/accessibility/ReduceMotionContext'; import type { ThemeProp } from '../../types'; import MaterialCommunityIcon from '../MaterialCommunityIcon'; import Text from '../Typography/Text'; @@ -89,30 +98,30 @@ const DataTableTitle = ({ ...rest }: Props) => { const theme = useInternalTheme(themeOverrides); + const reduceMotion = useReduceMotion(); + const { direction } = useLocale(); - const { current: spinAnim } = React.useRef( - new Animated.Value(sortDirection === 'ascending' ? 0 : 1) - ); + + const spin = useSharedValue(sortDirection === 'ascending' ? 0 : 180); React.useEffect(() => { - Animated.timing(spinAnim, { - toValue: sortDirection === 'ascending' ? 0 : 1, + spin.value = withTiming(sortDirection === 'ascending' ? 0 : 180, { duration: 150, - useNativeDriver: true, - }).start(); - }, [sortDirection, spinAnim]); + easing: Easing.inOut(Easing.ease), + reduceMotion: reduceMotion ? ReduceMotion.Always : ReduceMotion.Never, + }); + }, [reduceMotion, sortDirection, spin]); + + const animatedStyle = useAnimatedStyle(() => ({ + transform: [{ rotate: `${spin.value}deg` }], + })); const textColor = theme.colors.onSurface; const alphaTextColor = theme.colors.onSurfaceVariant; - const spin = spinAnim.interpolate({ - inputRange: [0, 1], - outputRange: ['0deg', '180deg'], - }); - const icon = sortDirection ? ( - + ( - new Animated.Value(active ? 1 : 0.5) - ); + const outlineScale = useSharedValue(active ? 1 : 0.5); React.useEffect(() => { if (!active) { - animScale.setValue(0.5); + outlineScale.value = 0.5; } - }, [animScale, active]); + }, [active, outlineScale]); const handlePressOut = () => { - Animated.timing(animScale, { - toValue: 1, + outlineScale.value = withTiming(1, { duration: 150 * scale, - useNativeDriver: true, - }).start(); + easing: Easing.inOut(Easing.ease), + reduceMotion: ReduceMotion.Never, + }); }; const iconPadding = ((!label ? itemSize : outlineHeight) - iconSize) / 2; @@ -135,9 +141,11 @@ const DrawerCollapsedItem = ({ const backgroundColor = active ? theme.colors.secondaryContainer : 'transparent'; + const labelColor = active ? theme.colors.onSurface : theme.colors.onSurfaceVariant; + const iconColor = active ? theme.colors.onSecondaryContainer : theme.colors.onSurfaceVariant; @@ -161,6 +169,12 @@ const DrawerCollapsedItem = ({ const icon = !active && unfocusedIcon !== undefined ? unfocusedIcon : focusedIcon; + const animatedOutlineStyle = useAnimatedStyle(() => ({ + transform: [ + label ? { scaleX: outlineScale.value } : { scale: outlineScale.value }, + ], + })); + return ( diff --git a/src/components/FAB/Content.tsx b/src/components/FAB/Content.tsx index 0e5728c2e3..6114bcd62c 100644 --- a/src/components/FAB/Content.tsx +++ b/src/components/FAB/Content.tsx @@ -1,7 +1,7 @@ import { StyleSheet, View } from 'react-native'; import type { ColorValue, StyleProp, ViewStyle } from 'react-native'; -import Reanimated from 'react-native-reanimated'; +import Animated from 'react-native-reanimated'; import type { AnimatedStyle } from 'react-native-reanimated'; import type { TypescaleKey } from '../../theme/types'; @@ -72,7 +72,7 @@ const Content = ({ ) : null} {hasLabel ? ( - {label} - + ) : null} diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index c3a120b1fd..34b69bba3d 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate ProgressBar to Reanimated. import { Animated, Platform, StyleSheet, View } from 'react-native'; import type { LayoutChangeEvent, diff --git a/src/components/RadioButton/RadioButtonAndroid.tsx b/src/components/RadioButton/RadioButtonAndroid.tsx index 86740cafa8..b82d793a1e 100644 --- a/src/components/RadioButton/RadioButtonAndroid.tsx +++ b/src/components/RadioButton/RadioButtonAndroid.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: migrate RadioButtonAndroid to Reanimated. import { Animated, StyleSheet, View } from 'react-native'; import { RadioButtonContext } from './RadioButtonGroup'; diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index 8d7e038c31..cae3ae4334 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -24,7 +24,7 @@ interface Style { marginRight: number; } -export type Props = TextInputProps & { +export type Props = Omit & { /** * Hint text shown when the input is empty. */ diff --git a/src/components/SegmentedButtons/SegmentedButtonItem.tsx b/src/components/SegmentedButtons/SegmentedButtonItem.tsx index 4f701f0b48..15e34dd170 100644 --- a/src/components/SegmentedButtons/SegmentedButtonItem.tsx +++ b/src/components/SegmentedButtons/SegmentedButtonItem.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Animated, StyleSheet, View } from 'react-native'; +import { StyleSheet, View } from 'react-native'; import type { GestureResponderEvent, PressableAndroidRippleConfig, @@ -8,12 +8,20 @@ import type { ViewStyle, } from 'react-native'; +import Animated, { + ReduceMotion, + useAnimatedStyle, + useSharedValue, + withSpring, +} from 'react-native-reanimated'; + import { getSegmentedButtonBorderRadius, getSegmentedButtonColors, getSegmentedButtonDensityPadding, } from './utils'; import { useInternalTheme } from '../../core/theming'; +import { useReduceMotion } from '../../theme/accessibility/ReduceMotionContext'; import type { ThemeProp } from '../../types'; import type { IconSource } from '../Icon'; import Icon from '../Icon'; @@ -21,6 +29,12 @@ import TouchableRipple from '../TouchableRipple/TouchableRipple'; import type { Props as TouchableRippleProps } from '../TouchableRipple/TouchableRipple'; import Text from '../Typography/Text'; +const CHECK_SPRING_CONFIG = { + stiffness: 230.2, + damping: 22, + mass: 1, +}; + export type Props = { /** * Whether the segmented button is checked @@ -121,25 +135,28 @@ const SegmentedButtonItem = ({ hitSlop, }: Props) => { const theme = useInternalTheme(themeOverrides); + const reduceMotion = useReduceMotion(); - const checkScale = React.useRef(new Animated.Value(0)).current; + const checkScale = useSharedValue(0); React.useEffect(() => { if (!showSelectedCheck) { return; } - if (checked) { - Animated.spring(checkScale, { - toValue: 1, - useNativeDriver: true, - }).start(); - } else { - Animated.spring(checkScale, { - toValue: 0, - useNativeDriver: true, - }).start(); - } - }, [checked, checkScale, showSelectedCheck]); + + checkScale.value = withSpring(checked ? 1 : 0, { + ...CHECK_SPRING_CONFIG, + reduceMotion: reduceMotion ? ReduceMotion.Always : ReduceMotion.Never, + }); + }, [checked, checkScale, reduceMotion, showSelectedCheck]); + + const checkAnimatedStyle = useAnimatedStyle(() => ({ + transform: [{ scale: checkScale.value }], + })); + + const iconAnimatedStyle = useAnimatedStyle(() => ({ + transform: [{ scale: label ? 1 - checkScale.value : 1 }], + })); const { borderColor, textColor, textOpacity, borderWidth, backgroundColor } = getSegmentedButtonColors({ @@ -151,26 +168,19 @@ const SegmentedButtonItem = ({ }); const borderRadius = theme.shapes.corner.largeIncreased; + const segmentBorderRadius = getSegmentedButtonBorderRadius({ theme, segment, }); + const showIcon = !icon ? false : label && checked ? !showSelectedCheck : true; const showCheckedIcon = checked && showSelectedCheck; const iconSize = 18; + const iconStyle = { marginRight: label ? 5 : showCheckedIcon ? 3 : 0, - ...(label && { - transform: [ - { - scale: checkScale.interpolate({ - inputRange: [0, 1], - outputRange: [1, 0], - }), - }, - ], - }), }; const buttonStyle: ViewStyle = { @@ -180,11 +190,14 @@ const SegmentedButtonItem = ({ borderRadius, ...segmentBorderRadius, }; + const paddingVertical = getSegmentedButtonDensityPadding({ density }); + const rippleStyle: ViewStyle = { borderRadius, ...segmentBorderRadius, }; + const labelTextStyle: TextStyle = { ...theme.fonts.labelLarge, color: textColor, @@ -212,13 +225,16 @@ const SegmentedButtonItem = ({ {showCheckedIcon ? ( ) : null} {showIcon ? ( - + ) : null} diff --git a/src/components/TouchableRipple/Pressable.tsx b/src/components/TouchableRipple/Pressable.tsx index ebeb45cf9c..1798a634ba 100644 --- a/src/components/TouchableRipple/Pressable.tsx +++ b/src/components/TouchableRipple/Pressable.tsx @@ -1,6 +1,5 @@ import type * as React from 'react'; import type { - Animated, PressableProps as PressableNativeProps, StyleProp, View, @@ -27,12 +26,7 @@ export type PressableProps = Omit< | undefined; style?: | StyleProp - | Animated.WithAnimatedValue> - | (( - state: PressableStateCallbackType - ) => - | StyleProp - | Animated.WithAnimatedValue>) + | ((state: PressableStateCallbackType) => StyleProp) | undefined; }; diff --git a/src/components/Typography/AnimatedText.tsx b/src/components/Typography/AnimatedText.tsx index 497566b9f1..2892d8d495 100644 --- a/src/components/Typography/AnimatedText.tsx +++ b/src/components/Typography/AnimatedText.tsx @@ -1,14 +1,17 @@ import * as React from 'react'; import type { ReactNode } from 'react'; -import { Animated, StyleSheet, Text } from 'react-native'; -import type { StyleProp, TextProps, TextStyle } from 'react-native'; +import { StyleSheet } from 'react-native'; + +import Animated from 'react-native-reanimated'; import type { VariantProp } from './types'; import { useLocale } from '../../core/locale'; import { useInternalTheme } from '../../core/theming'; import type { ThemeProp } from '../../types'; -type Props = Animated.AnimatedProps & { +type AnimatedTextProps = React.ComponentProps; + +type Props = AnimatedTextProps & { /** * Variant defines appropriate text styles for type role and its size. * Available variants: @@ -24,8 +27,6 @@ type Props = Animated.AnimatedProps & { * Body: `bodyLarge`, `bodyMedium`, `bodySmall` */ variant?: VariantProp; - style?: StyleProp; - ref?: React.Ref; /** * @optional */ @@ -45,6 +46,7 @@ function AnimatedText({ ...rest }: Props) { const theme = useInternalTheme(themeOverrides); + const { direction: writingDirection } = useLocale(); if (variant) { diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 30aaf4e66d..882652f92d 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -688,19 +688,23 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A @@ -911,19 +915,23 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A diff --git a/src/components/__tests__/BottomNavigation.test.tsx b/src/components/__tests__/BottomNavigation.test.tsx index e4a275921f..cd05ff0956 100644 --- a/src/components/__tests__/BottomNavigation.test.tsx +++ b/src/components/__tests__/BottomNavigation.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-imports -- TODO: remove after BottomNavigation migrates to Reanimated. */ import { Animated, Easing, @@ -6,6 +7,7 @@ import { StyleSheet, Text, } from 'react-native'; +/* eslint-enable no-restricted-imports */ import type { KeyboardEvent } from 'react-native'; import { describe, expect, it, jest } from '@jest/globals'; diff --git a/src/components/__tests__/Checkbox/__snapshots__/Checkbox.test.tsx.snap b/src/components/__tests__/Checkbox/__snapshots__/Checkbox.test.tsx.snap index 714b65414e..202a95467a 100644 --- a/src/components/__tests__/Checkbox/__snapshots__/Checkbox.test.tsx.snap +++ b/src/components/__tests__/Checkbox/__snapshots__/Checkbox.test.tsx.snap @@ -98,8 +98,6 @@ exports[`renders Checkbox with custom testID 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -120,8 +118,6 @@ exports[`renders Checkbox with custom testID 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 1, }, ] @@ -286,8 +282,6 @@ exports[`renders checked Checkbox with color 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -308,8 +302,6 @@ exports[`renders checked Checkbox with color 1`] = ` }, { "backgroundColor": "red", - }, - { "opacity": 1, }, ] @@ -474,8 +466,6 @@ exports[`renders checked Checkbox with onPress 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -496,8 +486,6 @@ exports[`renders checked Checkbox with onPress 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 1, }, ] @@ -662,8 +650,6 @@ exports[`renders indeterminate Checkbox 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -684,8 +670,6 @@ exports[`renders indeterminate Checkbox 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 1, }, ] @@ -837,8 +821,6 @@ exports[`renders indeterminate Checkbox with color 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -859,8 +841,6 @@ exports[`renders indeterminate Checkbox with color 1`] = ` }, { "backgroundColor": "red", - }, - { "opacity": 1, }, ] @@ -1012,8 +992,6 @@ exports[`renders unchecked Checkbox with color 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 0, }, ] @@ -1034,8 +1012,6 @@ exports[`renders unchecked Checkbox with color 1`] = ` }, { "backgroundColor": "red", - }, - { "opacity": 1, }, ] @@ -1200,8 +1176,6 @@ exports[`renders unchecked Checkbox with onPress 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 1, }, ] @@ -1222,8 +1196,6 @@ exports[`renders unchecked Checkbox with onPress 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 0, }, ] @@ -1278,7 +1250,7 @@ exports[`renders unchecked Checkbox with onPress 1`] = ` "width": 11, }, { - "borderColor": "transparent", + "borderColor": "rgba(255, 255, 255, 1)", }, null, ] diff --git a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap index bba3d6f506..9617ebefbd 100644 --- a/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap +++ b/src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap @@ -150,8 +150,6 @@ exports[`can render leading checkbox control 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 1, }, ] @@ -172,8 +170,6 @@ exports[`can render leading checkbox control 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 0, }, ] @@ -228,7 +224,7 @@ exports[`can render leading checkbox control 1`] = ` "width": 11, }, { - "borderColor": "transparent", + "borderColor": "rgba(255, 255, 255, 1)", }, null, ] @@ -469,8 +465,6 @@ exports[`renders unchecked 1`] = ` }, { "borderColor": "rgba(73, 69, 79, 1)", - }, - { "opacity": 1, }, ] @@ -491,8 +485,6 @@ exports[`renders unchecked 1`] = ` }, { "backgroundColor": "rgba(103, 80, 164, 1)", - }, - { "opacity": 0, }, ] @@ -547,7 +539,7 @@ exports[`renders unchecked 1`] = ` "width": 11, }, { - "borderColor": "transparent", + "borderColor": "rgba(255, 255, 255, 1)", }, null, ] diff --git a/src/components/__tests__/Checkbox/utils.test.tsx b/src/components/__tests__/Checkbox/utils.test.tsx index 3e340bc961..ee0b09f159 100644 --- a/src/components/__tests__/Checkbox/utils.test.tsx +++ b/src/components/__tests__/Checkbox/utils.test.tsx @@ -82,9 +82,9 @@ describe('getSelectionVisualState', () => { }); describe('iconColor (checkmark / dash glyph)', () => { - it('is transparent when unselected (no glyph drawn)', () => { + it('keeps its color when unselected while the mask hides it', () => { expect(getSelectionVisualState({ theme, selected: false })).toMatchObject( - { iconColor: 'transparent' } + { iconColor: theme.colors.onPrimary } ); }); diff --git a/src/components/__tests__/ProgressBar.test.tsx b/src/components/__tests__/ProgressBar.test.tsx index 4939f25c4c..bed20ed08d 100644 --- a/src/components/__tests__/ProgressBar.test.tsx +++ b/src/components/__tests__/ProgressBar.test.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: remove after ProgressBar migrates to Reanimated. import { Animated, Platform, StyleSheet } from 'react-native'; import { afterEach, expect, it } from '@jest/globals'; diff --git a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap index 349fa1d224..b1b80b7341 100644 --- a/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DataTable.test.tsx.snap @@ -2348,15 +2348,19 @@ exports[`DataTable.Title renders data table title with press handler 1`] = ` @@ -295,16 +304,23 @@ exports[`renders extended FAB collapsed 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message @@ -545,16 +561,25 @@ exports[`renders extended FAB expanded 1`] = ` numberOfLines={1} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="extended-floating-action-button-text" > @@ -608,16 +633,23 @@ exports[`renders extended FAB expanded 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message @@ -858,16 +890,25 @@ exports[`renders extended FAB large size 1`] = ` numberOfLines={1} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 24, - "fontWeight": "400", - "letterSpacing": 0, - "lineHeight": 32, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 24, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 32, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="extended-floating-action-button-text" > @@ -921,16 +962,23 @@ exports[`renders extended FAB large size 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 24, - "fontWeight": "400", - "letterSpacing": 0, - "lineHeight": 32, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 24, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 32, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message @@ -1171,16 +1219,25 @@ exports[`renders extended FAB medium size 1`] = ` numberOfLines={1} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 22, - "fontWeight": "400", - "letterSpacing": 0, - "lineHeight": 28, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 22, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 28, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="extended-floating-action-button-text" > @@ -1234,16 +1291,23 @@ exports[`renders extended FAB medium size 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 22, - "fontWeight": "400", - "letterSpacing": 0, - "lineHeight": 28, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 22, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 28, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message @@ -1484,16 +1548,25 @@ exports[`renders extended FAB not visible 1`] = ` numberOfLines={1} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="extended-floating-action-button-text" > @@ -1547,16 +1620,23 @@ exports[`renders extended FAB not visible 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message @@ -1797,16 +1877,25 @@ exports[`renders extended FAB transitioning to collapsed 1`] = ` numberOfLines={1} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="extended-floating-action-button-text" > @@ -1860,16 +1949,23 @@ exports[`renders extended FAB transitioning to collapsed 1`] = ` collapsable={false} numberOfLines={1} style={ - { - "color": "rgba(29, 27, 32, 1)", - "fontFamily": "System", - "fontSize": 16, - "fontWeight": "500", - "letterSpacing": 0.15, - "lineHeight": 24, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "500", + "letterSpacing": 0.15, + "lineHeight": 24, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + undefined, + ] } > New message diff --git a/src/components/__tests__/__snapshots__/FABMenu.test.tsx.snap b/src/components/__tests__/__snapshots__/FABMenu.test.tsx.snap index dcbdf08ee2..059c17b9f4 100644 --- a/src/components/__tests__/__snapshots__/FABMenu.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/FABMenu.test.tsx.snap @@ -178,16 +178,25 @@ exports[`renders FAB.Menu closed 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -346,16 +355,25 @@ exports[`renders FAB.Menu closed 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > @@ -942,16 +960,25 @@ exports[`renders FAB.Menu not expanded when trigger is not visible 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -1110,16 +1137,25 @@ exports[`renders FAB.Menu not expanded when trigger is not visible 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > @@ -1706,16 +1742,25 @@ exports[`renders FAB.Menu open 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -1874,16 +1919,25 @@ exports[`renders FAB.Menu open 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > @@ -2470,16 +2524,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -2638,16 +2701,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > @@ -2806,16 +2878,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-2-text" > @@ -2974,16 +3055,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-3-text" > @@ -3142,16 +3232,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-4-text" > @@ -3310,16 +3409,25 @@ exports[`renders FAB.Menu with 6 items 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-5-text" > @@ -3907,16 +4015,25 @@ exports[`renders FAB.Menu with center alignment 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -4075,16 +4192,25 @@ exports[`renders FAB.Menu with center alignment 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > @@ -4701,16 +4827,25 @@ exports[`renders FAB.Menu with items having icons 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } > Send email @@ -4898,16 +5033,25 @@ exports[`renders FAB.Menu with items having icons 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } > Set reminder @@ -5493,16 +5637,25 @@ exports[`renders FAB.Menu with start alignment 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-0-text" > @@ -5661,16 +5814,25 @@ exports[`renders FAB.Menu with start alignment 1`] = ` collapsable={false} selectable={false} style={ - { - "color": "rgba(33, 0, 93, 1)", - "fontFamily": "System", - "fontSize": 14, - "fontWeight": "500", - "letterSpacing": 0.1, - "lineHeight": 20, - "textAlign": "left", - "writingDirection": "ltr", - } + [ + { + "fontFamily": "System", + "fontSize": 14, + "fontWeight": "500", + "letterSpacing": 0.1, + "lineHeight": 20, + }, + { + "textAlign": "left", + }, + { + "color": "rgba(29, 27, 32, 1)", + "writingDirection": "ltr", + }, + { + "color": "rgba(33, 0, 93, 1)", + }, + ] } testID="item-1-text" > diff --git a/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap b/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap index e383e7d05b..a5564668f6 100644 --- a/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/IconButton.test.tsx.snap @@ -593,19 +593,23 @@ exports[`renders icon change animated 1`] = ` diff --git a/src/utils/useAnimatedValue.tsx b/src/utils/useAnimatedValue.tsx index 5b61f9f4d7..565a177e0a 100644 --- a/src/utils/useAnimatedValue.tsx +++ b/src/utils/useAnimatedValue.tsx @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- TODO: remove after BottomNavigation migrates to Reanimated. import { Animated } from 'react-native'; import useLazyRef from './useLazyRef'; diff --git a/src/utils/useAnimatedValueArray.tsx b/src/utils/useAnimatedValueArray.tsx index 67fbfa0b51..b26ed88793 100644 --- a/src/utils/useAnimatedValueArray.tsx +++ b/src/utils/useAnimatedValueArray.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +// eslint-disable-next-line no-restricted-imports -- TODO: remove after BottomNavigation migrates to Reanimated. import { Animated } from 'react-native'; export default function useAnimatedValueArray(initialValues: number[]) {