UNPKG

@herberthtk/react-native-animated-reactions

Version:
128 lines (121 loc) 3.18 kB
"use strict"; import { useImperativeHandle, forwardRef, useCallback, useMemo } from 'react'; import { StyleSheet, TouchableOpacity } from 'react-native'; import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, useAnimatedReaction, runOnJS } from 'react-native-reanimated'; import { iconUrls } from "./constants.js"; import { jsx as _jsx } from "react/jsx-runtime"; const ReactionBar = /*#__PURE__*/forwardRef(({ onDismiss, onReactionSelect }, ref) => { // Reanimated shared values for animations const scale = useSharedValue(0); const bounce = useSharedValue(1); const reactions = useMemo(() => [{ id: 'like', iconUrl: iconUrls[0] }, { id: 'love', iconUrl: iconUrls[1] }, { id: 'haha', iconUrl: iconUrls[2] }, { id: 'wow', iconUrl: iconUrls[3] }, { id: 'sad', iconUrl: iconUrls[4] }, { id: 'angry', iconUrl: iconUrls[5] }], []); // Animated styles const reactionBarStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], opacity: scale.value })); const bounceStyle = useAnimatedStyle(() => ({ transform: [{ scale: bounce.value }] })); // Show reactions const showReactions = useCallback(() => { scale.value = withSpring(1, { damping: 10, stiffness: 100 }); }, [scale]); // Dismiss reactions const dismissReactions = useCallback(() => { scale.value = withTiming(0, { duration: 200 }); }, [scale]); // Handle reaction selection const handleReactionSelect = useCallback(id => { const selectedReaction = reactions.find(reaction => reaction.id === id); if (selectedReaction) { onReactionSelect(selectedReaction); } // Trigger bounce effect bounce.value = 1.5; bounce.value = withSpring(1, { damping: 5, stiffness: 150 }); dismissReactions(); }, [bounce, dismissReactions, onReactionSelect, reactions]); useAnimatedReaction(() => scale.value === 0, isDismissed => { if (isDismissed) { runOnJS(onDismiss)(); } }); // Expose methods to parent component useImperativeHandle(ref, () => ({ showReactions, dismissReactions })); return /*#__PURE__*/_jsx(Animated.View, { style: [styles.reactionBar, reactionBarStyle], children: reactions.map(reaction => /*#__PURE__*/_jsx(TouchableOpacity, { onPress: () => handleReactionSelect(reaction.id), style: styles.reactionIconWrapper, children: /*#__PURE__*/_jsx(Animated.Image, { source: { uri: reaction.iconUrl }, style: [styles.reactionIcon, bounceStyle] }) }, reaction.id)) }); }); const styles = StyleSheet.create({ reactionBar: { flexDirection: 'row', backgroundColor: '#FFFFFF', borderRadius: 30, padding: 10, alignSelf: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 3 }, shadowOpacity: 0.2, shadowRadius: 4, elevation: 5 }, reactionIconWrapper: { marginHorizontal: 9 }, reactionIcon: { width: 32, height: 32 } }); export default ReactionBar; //# sourceMappingURL=index.js.map