// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {useCallback, useEffect, useState} from 'react'; import {Pressable, StyleSheet, Text, View} from 'react-native'; import Animated, {Easing, interpolate, interpolateColor, runOnJS, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import CompassIcon from '@components/compass_icon'; import {useTheme} from '@context/theme'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {typography} from '@utils/typography'; import {OPTIONS_HEIGHT} from '.'; type OptionBoxProps = { animatedBackgroundColor: string; animatedColor: string; animatedIconName: string; animatedText: string; iconName: string; onAnimationEnd?: () => void; onPress: () => void; testID?: string; text: string; } const AnimatedPressable = Animated.createAnimatedComponent(Pressable); const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ container: { borderRadius: 4, flex: 1, maxHeight: OPTIONS_HEIGHT, minWidth: 60, }, background: { backgroundColor: changeOpacity(theme.centerChannelColor, 0.04), }, center: { alignItems: 'center', justifyContent: 'center', }, text: { color: changeOpacity(theme.centerChannelColor, 0.56), paddingHorizontal: 5, textTransform: 'capitalize', ...typography('Body', 50, 'SemiBold'), }, })); const AnimatedOptionBox = ({ animatedBackgroundColor, animatedColor, animatedIconName, animatedText, iconName, onAnimationEnd, onPress, testID, text, }: OptionBoxProps) => { const theme = useTheme(); const styles = getStyleSheet(theme); const [activated, setActivated] = useState(false); const animate = useSharedValue(0); const handleOnPress = useCallback(() => { animate.value = withTiming(1, {duration: 150, easing: Easing.out(Easing.linear)}); setActivated(true); onPress(); }, [animate, onPress]); const backgroundStyle = useAnimatedStyle(() => ({ backgroundColor: interpolateColor( animate.value, [0, 1], ['transparent', animatedBackgroundColor], ), })); const optionStyle = useAnimatedStyle(() => ({ opacity: interpolate( animate.value, [0, 1], [1, 0], ), })); const scaleStyle = useAnimatedStyle(() => ({ transform: [{ scale: interpolate( animate.value, [0, 1], [0.25, 1], ), }], opacity: animate.value, }), [activated]); useEffect(() => { let t: NodeJS.Timeout|undefined; const callback = () => { 'worklet'; if (onAnimationEnd) { runOnJS(onAnimationEnd)(); } }; if (activated) { t = setTimeout(() => { setActivated(false); animate.value = withTiming(0, {duration: 150, easing: Easing.out(Easing.linear)}, callback); }, 1200); } return () => { if (t) { clearTimeout(t); } }; }, [activated, animate, onAnimationEnd]); return ( {({pressed}) => ( {text} {animatedText} )} ); }; export default AnimatedOptionBox;