From ac0afde8f8a2a90d890c81cb752ec52d30882ed0 Mon Sep 17 00:00:00 2001 From: Furkan Date: Mon, 14 Aug 2023 17:30:44 +0300 Subject: [PATCH] refactor: make module monolothic and extend swipe --- example/src/App.tsx | 42 +++++++++++------ src/Card.tsx | 92 ------------------------------------- src/Deck.tsx | 108 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 112 insertions(+), 130 deletions(-) delete mode 100644 src/Card.tsx diff --git a/example/src/App.tsx b/example/src/App.tsx index c98d00d..38f9eb6 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -2,29 +2,41 @@ import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; import { SwipeableDeck } from '@frknltrk/react-native-swipeable-cards'; -const data = [ - Card 1 Content, - Card 2, - - Custom View - More Custom Content - , - // Add more custom content as needed -]; - const App: React.FC = () => { - return ( - - - - ); + const data = [ + + Card 1 Content + , + + Card 2 Content + , + + Card 3 Content + , + // Add more custom content as needed + ]; + + return ; }; const styles = StyleSheet.create({ container: { flex: 1, + justifyContent: 'center', + alignItems: 'center', backgroundColor: '#fff', }, + card: { + width: 300, + height: 200, + backgroundColor: 'lightgray', + justifyContent: 'center', + alignItems: 'center', + borderRadius: 10, + borderWidth: 1, + borderColor: 'gray', + marginVertical: 10, + }, }); export default App; diff --git a/src/Card.tsx b/src/Card.tsx deleted file mode 100644 index 7b478a3..0000000 --- a/src/Card.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React from 'react'; -import { Animated, PanResponder, Dimensions, StyleSheet } from 'react-native'; - -const SCREEN_WIDTH = Dimensions.get('window').width; -const SWIPE_THRESHOLD = 0.25 * SCREEN_WIDTH; -const SWIPE_OUT_DURATION = 250; - -interface CardProps { - children: React.ReactNode; - onSwipeLeft: () => void; - onSwipeRight: () => void; -} - -const CardView: React.FC = ({ - children, - onSwipeLeft, - onSwipeRight, -}) => { - const position = new Animated.ValueXY(); - - const panResponder = PanResponder.create({ - onStartShouldSetPanResponder: () => true, - onPanResponderMove: (_, gesture) => { - position.setValue({ x: gesture.dx, y: gesture.dy }); - }, - onPanResponderRelease: (_, gesture) => { - if (gesture.dx > SWIPE_THRESHOLD) { - forceSwipe('right'); - } else if (gesture.dx < -SWIPE_THRESHOLD) { - forceSwipe('left'); - } else { - resetPosition(); - } - }, - }); - - const forceSwipe = (direction: 'right' | 'left') => { - const x = direction === 'right' ? SCREEN_WIDTH : -SCREEN_WIDTH; - Animated.timing(position, { - toValue: { x, y: 0 }, - duration: SWIPE_OUT_DURATION, - useNativeDriver: false, - }).start(() => onSwipeComplete(direction)); - console.log('Card.forceSwipe works'); - }; - - const onSwipeComplete = (direction: 'right' | 'left') => { - direction === 'right' ? onSwipeRight() : onSwipeLeft(); - position.setValue({ x: 0, y: 0 }); - }; - - const resetPosition = () => { - Animated.spring(position, { - toValue: { x: 0, y: 0 }, - useNativeDriver: false, - }).start(); - }; - - const getCardStyle = () => { - const rotate = position.x.interpolate({ - inputRange: [-SCREEN_WIDTH, 0, SCREEN_WIDTH], - outputRange: ['-60deg', '0deg', '60deg'], - }); - - return { - ...position.getLayout(), - transform: [{ rotate }], - }; - }; - - return ( - - {children} - - ); -}; - -const styles = StyleSheet.create({ - cardStyle: { - position: 'absolute', - width: SCREEN_WIDTH, - height: '80%', - alignItems: 'center', - justifyContent: 'center', - userSelect: 'none', - }, -}); - -export default CardView; diff --git a/src/Deck.tsx b/src/Deck.tsx index 9ce2319..2950553 100644 --- a/src/Deck.tsx +++ b/src/Deck.tsx @@ -1,54 +1,116 @@ import React, { useState } from 'react'; -import { View, StyleSheet } from 'react-native'; -import CardView from './Card'; +import { + View, + Animated, + PanResponder, + Dimensions, + StyleSheet, +} from 'react-native'; -interface DeckProps { - card_contents: React.ReactNode[]; // Allow any ReactNode as content +const SCREEN_WIDTH = Dimensions.get('window').width; +const SWIPE_THRESHOLD = 0.25 * SCREEN_WIDTH; +const SWIPE_OUT_DURATION = 250; + +interface SwipeableDeckProps { + data: React.ReactNode[]; } -const SwipeableDeck: React.FC = ({ card_contents }) => { +const SwipeableDeck: React.FC = ({ data }) => { const [currentIndex, setCurrentIndex] = useState(0); + const position = new Animated.ValueXY(); + + const panResponder = PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onPanResponderMove: (_, gesture) => { + position.setValue({ x: gesture.dx, y: gesture.dy }); + }, + onPanResponderRelease: (_, gesture) => { + if (gesture.dx > SWIPE_THRESHOLD) { + forceSwipe('right'); + } else if (gesture.dx < -SWIPE_THRESHOLD) { + forceSwipe('left'); + } else { + resetPosition(); + } + }, + }); + + const forceSwipe = (direction: 'right' | 'left') => { + const x = direction === 'right' ? SCREEN_WIDTH : -SCREEN_WIDTH; + Animated.timing(position, { + toValue: { x, y: 0 }, + duration: SWIPE_OUT_DURATION, + useNativeDriver: false, + }).start(() => onSwipeComplete(direction)); + }; + + const onSwipeComplete = (direction: 'right' | 'left') => { + direction === 'right' ? onSwipeRight() : onSwipeLeft(); + position.setValue({ x: 0, y: 0 }); + }; + + const resetPosition = () => { + Animated.spring(position, { + toValue: { x: 0, y: 0 }, + useNativeDriver: false, + }).start(); + }; + + const getCardStyle = () => { + const rotate = position.x.interpolate({ + inputRange: [-SCREEN_WIDTH, 0, SCREEN_WIDTH], + outputRange: ['-60deg', '0deg', '60deg'], + }); + + return { + ...position.getLayout(), + transform: [{ rotate }], + }; + }; + const onSwipeLeft = () => { - if (currentIndex < card_contents.length - 1) { - setCurrentIndex((prevIndex: number) => prevIndex + 1); - console.log('Deck.onSwipeLeft works'); + if (currentIndex < data.length - 1) { + setCurrentIndex((prevIndex) => prevIndex + 1); } else { - // Optional: Implement what happens when you reach the end of the deck - // For example, you can reset the currentIndex to 0 to start over. setCurrentIndex(0); } }; const onSwipeRight = () => { if (currentIndex > 0) { - setCurrentIndex((prevIndex: number) => prevIndex - 1); - console.log('Deck.onSwipeRight works'); - } else { - // Optional: Implement what happens when you reach the beginning of the deck - // For example, you can disable swiping to the left or show a message. + setCurrentIndex((prevIndex) => prevIndex - 1); } }; - // avoid using Non-null assertion operator (!): line 36. find another way to overcome TS2322 return ( - - + - {card_contents[currentIndex]} - + {data[currentIndex]} + ); }; const styles = StyleSheet.create({ deckContainer: { - flex: 1, + width: SCREEN_WIDTH, + height: '100%', justifyContent: 'center', alignItems: 'center', + overflow: 'hidden', + backgroundColor: 'yellow', + }, + cardStyle: { + width: 'auto', + height: 'auto', + alignItems: 'center', + justifyContent: 'center', + userSelect: 'none', + backgroundColor: 'black', }, });