import { I18nManager } from 'react-native'; import Animated from 'react-native-reanimated'; import { CardInterpolationProps, CardInterpolatedStyle } from '../types'; import { getStatusBarHeight } from 'react-native-safe-area-view'; const { cond, add, multiply, interpolate } = Animated; /** * Standard iOS-style slide in from the right. */ export function forHorizontalIOS({ current, next, layouts: { screen }, }: CardInterpolationProps): CardInterpolatedStyle { const translateFocused = interpolate(current.progress, { inputRange: [0, 1], outputRange: [I18nManager.isRTL ? -screen.width : screen.width, 0], }); const translateUnfocused = next ? interpolate(next.progress, { inputRange: [0, 1], outputRange: [ 0, multiply(I18nManager.isRTL ? -screen.width : screen.width, -0.3), ], }) : 0; const overlayOpacity = interpolate(current.progress, { inputRange: [0, 1], outputRange: [0, 0.07], }); const shadowOpacity = interpolate(current.progress, { inputRange: [0, 1], outputRange: [0, 0.3], }); return { cardStyle: { transform: [ // Translation for the animation of the current card { translateX: translateFocused }, // Translation for the animation of the card on top of this { translateX: translateUnfocused }, ], }, overlayStyle: { opacity: overlayOpacity }, shadowStyle: { shadowOpacity }, }; } /** * Standard iOS-style slide in from the bottom (used for modals). */ export function forVerticalIOS({ current, layouts: { screen }, }: CardInterpolationProps): CardInterpolatedStyle { const translateY = interpolate(current.progress, { inputRange: [0, 1], outputRange: [screen.height, 0], }); return { cardStyle: { transform: [ // Translation for the animation of the current card { translateY }, ], }, }; } /** * Standard iOS-style modal animation in iOS 13. */ export function forModalPresentationIOS({ index, current, next, layouts: { screen }, }: CardInterpolationProps): CardInterpolatedStyle { const topOffset = 10; const statusBarHeight = getStatusBarHeight(screen.width > screen.height); const aspectRatio = screen.height / screen.width; const progress = add(current.progress, next ? next.progress : 0); const translateY = interpolate(progress, { inputRange: [0, 1, 2], outputRange: [ screen.height, index === 0 ? 0 : topOffset, (index === 0 ? statusBarHeight : 0) - topOffset * aspectRatio, ], }); const overlayOpacity = interpolate(progress, { inputRange: [0, 1, 2], outputRange: [0, 0.3, 1], }); const scale = interpolate(progress, { inputRange: [0, 1, 2], outputRange: [1, 1, screen.width ? 1 - (topOffset * 2) / screen.width : 1], }); const borderRadius = index === 0 ? interpolate(progress, { inputRange: [0, 1, 2], outputRange: [0, 0, 10], }) : 10; return { cardStyle: { overflow: 'hidden', borderTopLeftRadius: borderRadius, borderTopRightRadius: borderRadius, marginTop: index === 0 ? 0 : statusBarHeight, transform: [{ translateY }, { scale }], }, overlayStyle: { opacity: overlayOpacity }, }; } /** * Standard Android-style fade in from the bottom for Android Oreo. */ export function forFadeFromBottomAndroid({ current, layouts: { screen }, closing, }: CardInterpolationProps): CardInterpolatedStyle { const translateY = interpolate(current.progress, { inputRange: [0, 1], outputRange: [multiply(screen.height, 0.08), 0], }); const opacity = cond( closing, current.progress, interpolate(current.progress, { inputRange: [0, 0.5, 0.9, 1], outputRange: [0, 0.25, 0.7, 1], }) ); return { cardStyle: { opacity, transform: [{ translateY }], }, }; } /** * Standard Android-style reveal from the bottom for Android Pie. */ export function forRevealFromBottomAndroid({ current, next, layouts: { screen }, }: CardInterpolationProps): CardInterpolatedStyle { const containerTranslateY = interpolate(current.progress, { inputRange: [0, 1], outputRange: [screen.height, 0], }); const cardTranslateYFocused = interpolate(current.progress, { inputRange: [0, 1], outputRange: [multiply(screen.height, 95.9 / 100, -1), 0], }); const cardTranslateYUnfocused = next ? interpolate(next.progress, { inputRange: [0, 1], outputRange: [0, multiply(screen.height, 2 / 100, -1)], }) : 0; const overlayOpacity = interpolate(current.progress, { inputRange: [0, 0.36, 1], outputRange: [0, 0.1, 0.1], }); return { containerStyle: { overflow: 'hidden', transform: [{ translateY: containerTranslateY }], }, cardStyle: { transform: [ { translateY: cardTranslateYFocused }, { translateY: cardTranslateYUnfocused }, ], }, overlayStyle: { opacity: overlayOpacity }, }; }