Skip to content

Commit

Permalink
Merge pull request #27 from Skipperlla/feature/re-add-swipe-bottom
Browse files Browse the repository at this point in the history
feat: re add swipe bottom
  • Loading branch information
Skipperlla authored Jun 24, 2024
2 parents 6a03915 + 2bbbe8d commit d6c9866
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 19 deletions.
42 changes: 34 additions & 8 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const IMAGES: ImageSourcePropType[] = [
require('../assets/images/6.jpg'),
];

const ICON_SIZE = 24;

const App = () => {
const ref = useRef<SwiperCardRefType>();

Expand Down Expand Up @@ -71,6 +73,18 @@ const App = () => {
/>
);
}, []);
const OverlayLabelBottom = useCallback(() => {
return (
<View
style={[
styles.overlayLabelContainer,
{
backgroundColor: 'orange',
},
]}
/>
);
}, []);

return (
<GestureHandlerRootView style={styles.container}>
Expand All @@ -92,9 +106,13 @@ const App = () => {
onSwipeTop={(cardIndex) => {
console.log('onSwipeTop', cardIndex);
}}
onSwipeBottom={(cardIndex) => {
console.log('onSwipeBottom', cardIndex);
}}
OverlayLabelRight={OverlayLabelRight}
OverlayLabelLeft={OverlayLabelLeft}
OverlayLabelTop={OverlayLabelTop}
OverlayLabelBottom={OverlayLabelBottom}
onSwipeActive={() => {
console.log('onSwipeActive');
}}
Expand All @@ -108,37 +126,45 @@ const App = () => {
</View>

<View style={styles.buttonsContainer}>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeBack();
}}
>
<AntDesign name="reload1" size={ICON_SIZE} color="white" />
</ActionButton>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeLeft();
}}
>
<AntDesign name="close" size={32} color="white" />
<AntDesign name="close" size={ICON_SIZE} color="white" />
</ActionButton>
<ActionButton
style={[styles.button, { height: 60, marginHorizontal: 10 }]}
style={styles.button}
onTap={() => {
ref.current?.swipeBack();
ref.current?.swipeBottom();
}}
>
<AntDesign name="reload1" size={24} color="white" />
<AntDesign name="arrowdown" size={ICON_SIZE} color="white" />
</ActionButton>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeTop();
}}
>
<AntDesign name="arrowup" size={32} color="white" />
<AntDesign name="arrowup" size={ICON_SIZE} color="white" />
</ActionButton>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeRight();
}}
>
<AntDesign name="heart" size={32} color="white" />
<AntDesign name="heart" size={ICON_SIZE} color="white" />
</ActionButton>
</View>
</GestureHandlerRootView>
Expand All @@ -158,11 +184,11 @@ const styles = StyleSheet.create({
bottom: 34,
alignItems: 'center',
justifyContent: 'center',
gap: 24,
},
button: {
height: 80,
height: 50,
borderRadius: 40,
marginHorizontal: 20,
aspectRatio: 1,
backgroundColor: '#3A3D45',
elevation: 4,
Expand Down
30 changes: 27 additions & 3 deletions src/Swiper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ const Swiper = <T,>(
onSwipeLeft,
onSwipedAll,
onSwipeTop,
onSwipeBottom,
cardStyle,
disableRightSwipe,
disableLeftSwipe,
disableTopSwipe,
disableBottomSwipe,
translateXRange = [-windowWidth / 3, 0, windowWidth / 3],
translateYRange = [-windowHeight / 3, 0, windowHeight / 3],
rotateInputRange = [-windowWidth / 3, 0, windowWidth / 3],
Expand All @@ -30,17 +32,27 @@ const Swiper = <T,>(
outputOverlayLabelLeftOpacityRange = [0, 1],
inputOverlayLabelTopOpacityRange = [0, -(windowHeight / 3)],
outputOverlayLabelTopOpacityRange = [0, 1],
inputOverlayLabelBottomOpacityRange = [0, windowHeight / 3],
outputOverlayLabelBottomOpacityRange = [0, 1],
OverlayLabelRight,
OverlayLabelLeft,
OverlayLabelTop,
OverlayLabelBottom,
onSwipeStart,
onSwipeActive,
onSwipeEnd,
}: SwiperOptions<T>,
ref: ForwardedRef<SwiperCardRefType>
) => {
const { activeIndex, refs, swipeRight, swipeLeft, swipeBack, swipeTop } =
useSwipeControls(data);
const {
activeIndex,
refs,
swipeRight,
swipeLeft,
swipeBack,
swipeTop,
swipeBottom,
} = useSwipeControls(data);

useImperativeHandle(
ref,
Expand All @@ -50,9 +62,10 @@ const Swiper = <T,>(
swipeRight,
swipeBack,
swipeTop,
swipeBottom,
};
},
[swipeLeft, swipeRight, swipeBack, swipeTop]
[swipeLeft, swipeRight, swipeBack, swipeTop, swipeBottom]
);

useAnimatedReaction(
Expand All @@ -76,6 +89,7 @@ const Swiper = <T,>(
disableRightSwipe={disableRightSwipe}
disableLeftSwipe={disableLeftSwipe}
disableTopSwipe={disableTopSwipe}
disableBottomSwipe={disableBottomSwipe}
translateXRange={translateXRange}
translateYRange={translateYRange}
rotateOutputRange={rotateOutputRange}
Expand All @@ -88,10 +102,17 @@ const Swiper = <T,>(
outputOverlayLabelLeftOpacityRange={outputOverlayLabelLeftOpacityRange}
inputOverlayLabelTopOpacityRange={inputOverlayLabelTopOpacityRange}
outputOverlayLabelTopOpacityRange={outputOverlayLabelTopOpacityRange}
inputOverlayLabelBottomOpacityRange={
inputOverlayLabelBottomOpacityRange
}
outputOverlayLabelBottomOpacityRange={
outputOverlayLabelBottomOpacityRange
}
activeIndex={activeIndex}
OverlayLabelRight={OverlayLabelRight}
OverlayLabelLeft={OverlayLabelLeft}
OverlayLabelTop={OverlayLabelTop}
OverlayLabelBottom={OverlayLabelBottom}
ref={refs[index]}
onSwipeRight={(cardIndex) => {
onSwipeRight?.(cardIndex);
Expand All @@ -102,6 +123,9 @@ const Swiper = <T,>(
onSwipeTop={(cardIndex) => {
onSwipeTop?.(cardIndex);
}}
onSwipeBottom={(cardIndex) => {
onSwipeBottom?.(cardIndex);
}}
onSwipeStart={onSwipeStart}
onSwipeActive={onSwipeActive}
onSwipeEnd={onSwipeEnd}
Expand Down
53 changes: 45 additions & 8 deletions src/SwiperCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ import type { SwiperCardOptions, SwiperCardRefType } from 'rn-swiper-list';

import OverlayLabel from './OverlayLabel';

const SwipeBackUserConfig = {
damping: 15,
stiffness: 120,
mass: 0.5,
overshootClamping: false,
restDisplacementThreshold: 0.001,
restSpeedThreshold: 0.001,
};

const SwipeableCard = forwardRef<
SwiperCardRefType,
PropsWithChildren<SwiperCardOptions>
Expand All @@ -32,11 +41,13 @@ const SwipeableCard = forwardRef<
onSwipeLeft,
onSwipeRight,
onSwipeTop,
onSwipeBottom,
cardStyle,
children,
disableRightSwipe,
disableLeftSwipe,
disableTopSwipe,
disableBottomSwipe,
translateXRange,
translateYRange,
rotateInputRange,
Expand All @@ -47,9 +58,12 @@ const SwipeableCard = forwardRef<
outputOverlayLabelLeftOpacityRange,
inputOverlayLabelTopOpacityRange,
outputOverlayLabelTopOpacityRange,
inputOverlayLabelBottomOpacityRange,
outputOverlayLabelBottomOpacityRange,
OverlayLabelRight,
OverlayLabelLeft,
OverlayLabelTop,
OverlayLabelBottom,
onSwipeStart,
onSwipeActive,
onSwipeEnd,
Expand Down Expand Up @@ -83,11 +97,17 @@ const SwipeableCard = forwardRef<
activeIndex.value++;
}, [index, activeIndex, maxCardTranslationY, onSwipeTop, translateY]);

const swipeBottom = useCallback(() => {
onSwipeBottom?.(index);
translateY.value = withSpring(maxCardTranslationY);
activeIndex.value++;
}, [index, activeIndex, maxCardTranslationY, onSwipeBottom, translateY]);

const swipeBack = useCallback(() => {
cancelAnimation(translateX);
cancelAnimation(translateY);
translateX.value = withSpring(0);
translateY.value = withSpring(0);
translateX.value = withSpring(0, SwipeBackUserConfig);
translateY.value = withSpring(0, SwipeBackUserConfig);
}, [translateX, translateY]);

useImperativeHandle(
Expand All @@ -98,9 +118,10 @@ const SwipeableCard = forwardRef<
swipeRight,
swipeBack,
swipeTop,
swipeBottom,
};
},
[swipeLeft, swipeRight, swipeBack, swipeTop]
[swipeLeft, swipeRight, swipeBack, swipeTop, swipeBottom]
);

const inputRangeX = React.useMemo(() => {
Expand Down Expand Up @@ -129,6 +150,7 @@ const SwipeableCard = forwardRef<

translateX.value = event.translationX;
translateY.value = event.translationY;

if (height / 3 < Math.abs(event.translationY)) {
nextActiveIndex.value = interpolate(
translateY.value,
Expand Down Expand Up @@ -159,6 +181,7 @@ const SwipeableCard = forwardRef<
if (onSwipeEnd) runOnJS(onSwipeEnd)();
if (nextActiveIndex.value === activeIndex.value + 1) {
const sign = Math.sign(event.translationX);
const signY = Math.sign(event.translationY);
const signPositionY = Number.isInteger(
interpolate(
translateY.value,
Expand All @@ -172,9 +195,15 @@ const SwipeableCard = forwardRef<
)
);

if (signPositionY && !disableTopSwipe) {
runOnJS(swipeTop)();
return;
if (signPositionY) {
if (signY === -1 && !disableTopSwipe) {
runOnJS(swipeTop)();
return;
}
if (signY === 1 && !disableBottomSwipe) {
runOnJS(swipeBottom)();
return;
}
}

if (!signPositionY) {
Expand All @@ -188,8 +217,8 @@ const SwipeableCard = forwardRef<
}
}
}
translateX.value = withSpring(0);
translateY.value = withSpring(0);
translateX.value = withSpring(0, SwipeBackUserConfig);
translateY.value = withSpring(0, SwipeBackUserConfig);
});

const rCardStyle = useAnimatedStyle(() => {
Expand Down Expand Up @@ -240,6 +269,14 @@ const SwipeableCard = forwardRef<
opacityValue={translateY}
/>
)}
{OverlayLabelBottom && (
<OverlayLabel
inputRange={inputOverlayLabelBottomOpacityRange}
outputRange={outputOverlayLabelBottomOpacityRange}
Component={OverlayLabelBottom}
opacityValue={translateY}
/>
)}

{children}
</Animated.View>
Expand Down
7 changes: 7 additions & 0 deletions src/hooks/useSwipeControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const useSwipeControls = <T>(data: T[]) => {
}
refs[activeIndex.value]?.current?.swipeLeft();
}, [activeIndex.value, refs]);
const swipeBottom = useCallback(() => {
if (!refs[activeIndex.value]) {
return;
}
refs[activeIndex.value]?.current?.swipeBottom();
}, [activeIndex.value, refs]);

const swipeBack = useCallback(() => {
if (!refs[activeIndex.value - 1]) {
Expand All @@ -49,6 +55,7 @@ const useSwipeControls = <T>(data: T[]) => {
swipeLeft,
swipeBack,
swipeTop,
swipeBottom,
};
};

Expand Down
Loading

0 comments on commit d6c9866

Please sign in to comment.