import React, {useRef} from 'react'; import { Animated, StyleSheet, View, I18nManager, TouchableOpacity, } from 'react-native'; import {Swipeable} from 'react-native-gesture-handler'; interface SwipeAction { comp: React.ReactNode; color?: string; width?: number; onPress?: () => void; } interface SwipeableComponentProps { children: React.ReactNode; leftSwipeEnabled?: boolean; rightSwipeEnabled?: boolean; leftActions?: SwipeAction[]; rightActions?: SwipeAction[]; } const SwipeableComponent: React.FC = ({ children, leftSwipeEnabled = true, rightSwipeEnabled = true, leftActions = [], rightActions = [], }) => { const swipeableRow = useRef(null); const close = () => { // Add a small delay for better UX, like WhatsApp setTimeout(() => { swipeableRow.current?.close(); }, 150); }; const renderLeftActions = ( progress: Animated.AnimatedInterpolation, ) => { if (!leftSwipeEnabled || !leftActions?.length) return null; return ( {leftActions.map((action, i) => { const baseWidth = action.width || 80; const offset = baseWidth * leftActions.length; const trans = progress.interpolate({ inputRange: [0, 1], outputRange: [-offset, 0], extrapolate: 'clamp', }); const scale = progress.interpolate({ inputRange: [0, 0.5, 1], outputRange: [1, 1, 1], extrapolate: 'clamp', }); const opacity = progress.interpolate({ inputRange: [0, 0.3, 1], outputRange: [0, 0.75, 1], extrapolate: 'clamp', }); return ( { action.onPress?.(); close(); }}> {action.comp} ); })} ); }; const renderRightActions = ( progress: Animated.AnimatedInterpolation, ) => { if (!rightSwipeEnabled || !rightActions?.length) return null; return ( {rightActions.map((action, i) => { // make further actions translate more so they appear to come from farther right const baseWidth = action.width || 80; const offset = baseWidth * rightActions.length; const trans = progress.interpolate({ inputRange: [0, 1], outputRange: [offset, 0], extrapolate: 'clamp', }); // Slight scale easing for a nicer pop-in feel. const scale = progress.interpolate({ inputRange: [0, 0.5, 1], outputRange: [1, 1, 1], extrapolate: 'clamp', }); const opacity = progress.interpolate({ inputRange: [0, 0.3, 1], outputRange: [0, 0.75, 1], extrapolate: 'clamp', }); return ( { action.onPress?.(); close(); }}> {action.comp} ); })} ); }; return ( {children} ); }; const styles = StyleSheet.create({ action: { justifyContent: 'center', alignItems: 'center', paddingHorizontal: 12, paddingVertical: 0, shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.1, shadowRadius: 3, elevation: 3, }, }); export default SwipeableComponent;