import React from 'react' import { Animated, I18nManager, StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle, } from 'react-native' import { PanGestureHandlerProps, RectButton, } from 'react-native-gesture-handler' import Swipeable from 'react-native-gesture-handler/Swipeable' declare type SwipeableExcludes = Exclude< keyof PanGestureHandlerProps, 'onGestureEvent' | 'onHandlerStateChange' > interface SwipeableProps extends Pick { enableTrackpadTwoFingerGesture?: boolean friction?: number leftThreshold?: number rightThreshold?: number overshootLeft?: boolean overshootRight?: boolean overshootFriction?: number onSwipeableLeftOpen?: () => void onSwipeableRightOpen?: () => void onSwipeableOpen?: () => void onSwipeableClose?: () => void onSwipeableLeftWillOpen?: () => void onSwipeableRightWillOpen?: () => void onSwipeableWillOpen?: () => void onSwipeableWillClose?: () => void /** * * This map describes the values to use as inputRange for extra interpolation: * AnimatedValue: [startValue, endValue] * * progressAnimatedValue: [0, 1] * dragAnimatedValue: [0, +] * * To support `rtl` flexbox layouts use `flexDirection` styling. * */ renderLeftActions?: ( progressAnimatedValue: Animated.AnimatedInterpolation, dragAnimatedValue: Animated.AnimatedInterpolation, ) => React.ReactNode /** * * This map describes the values to use as inputRange for extra interpolation: * AnimatedValue: [startValue, endValue] * * progressAnimatedValue: [0, 1] * dragAnimatedValue: [0, -] * * To support `rtl` flexbox layouts use `flexDirection` styling. * */ renderRightActions?: ( progressAnimatedValue: Animated.AnimatedInterpolation, dragAnimatedValue: Animated.AnimatedInterpolation, ) => React.ReactNode useNativeAnimations?: boolean animationOptions?: Record containerStyle?: StyleProp childrenContainerStyle?: StyleProp } export interface SwipeActionProps extends SwipeableProps { left?: SwipeoutButtonProps[] options?: SwipeActionOption[] onClick?: (button: any, index: number) => void buttonWidth?: number autoClose?: boolean children?: React.ReactNode } export interface SwipeoutButtonProps { style?: StyleProp // backgroundColor?: string // color?: string text?: React.ReactNode // disabled?: boolean // onPress?(): void } class SwipeAction extends React.Component { swipeableRow?: Swipeable render() { const { left, options, children, ...restProps } = this.props return ( this.renderActions(v, d, true)} renderRightActions={(v, d) => this.renderActions(v, d, false)} {...restProps}> {children} ) } updateRef = (ref: Swipeable) => { this.swipeableRow = ref } close = () => { this.swipeableRow?.close() } renderActions = ( progress: Animated.AnimatedInterpolation, _dragAnimatedValue: Animated.AnimatedInterpolation, isLeft = false, ) => { const { options, left, buttonWidth = 60 } = this.props const buttons = isLeft ? left : options if (!buttons) { return null } const len = buttons.length const width = buttonWidth * len return ( {buttons.map((button, i) => { const x = isLeft ? -i * buttonWidth : (len - i) * buttonWidth const trans = progress.interpolate({ inputRange: [0, 1], outputRange: [x, 0], extrapolate: 'clamp', }) const pressHandler = () => { if (button.disabled) { return } if (this.props.autoClose) this.close() this.props.onClick?.(button, i) } return ( {React.isValidElement(button.text) ? ( button.text ) : ( {button.text} )} ) })} ) } } export default SwipeAction const styles = StyleSheet.create({ actionText: { color: 'white', fontSize: 16, backgroundColor: 'transparent', padding: 10, }, rightAction: { alignItems: 'center', flex: 1, justifyContent: 'center', }, })