From 65f1d98b36b670227a207c7dd1e738d34045b398 Mon Sep 17 00:00:00 2001 From: Spencer Vaughn Date: Wed, 23 Jul 2025 12:32:56 -0500 Subject: [PATCH 1/4] Add combo left swipe functionality to GestureDetectorComponent --- src/__tests__/index.test.tsx | 1 - src/components/GestureDetectorComponent.tsx | 10 +- .../SwipeRevealWrapper/SwipeRevealWrapper.tsx | 3 +- src/constants.ts | 1 + src/hooks/usePanXGesture.ts | 104 ++++++++++++------ 5 files changed, 84 insertions(+), 35 deletions(-) delete mode 100644 src/__tests__/index.test.tsx diff --git a/src/__tests__/index.test.tsx b/src/__tests__/index.test.tsx deleted file mode 100644 index bf84291..0000000 --- a/src/__tests__/index.test.tsx +++ /dev/null @@ -1 +0,0 @@ -it.todo('write a test'); diff --git a/src/components/GestureDetectorComponent.tsx b/src/components/GestureDetectorComponent.tsx index 040248f..c5f311e 100644 --- a/src/components/GestureDetectorComponent.tsx +++ b/src/components/GestureDetectorComponent.tsx @@ -42,6 +42,13 @@ export const GestureDetectorComponent = ({ return animationType === EAnimationType['right-full-swipe']; }, [animationType]); + const isComboLeftSwipe = useMemo(() => { + return ( + animationType === EAnimationType['combo-left-swipe'] && + leftSwipeViewWidth !== 0 + ); + }, [animationType, leftSwipeViewWidth, rightSwipeViewWidth]); + const { panXAnimatedStyles, panXGesture } = usePanXGesture( leftSwipeViewWidth, rightSwipeViewWidth, @@ -52,10 +59,11 @@ export const GestureDetectorComponent = ({ isRightSwipe, isLeftFullSwipe, isRightFullSwipe, + isComboLeftSwipe, itemWidth ); - return isLeftSwipe || isRightSwipe || isLeftFullSwipe || isRightFullSwipe ? ( + return isLeftSwipe || isRightSwipe || isLeftFullSwipe || isRightFullSwipe || isComboLeftSwipe ? ( {(animationType === EAnimationType['left-swipe'] || - animationType === EAnimationType['left-right-swipe']) && + animationType === EAnimationType['left-right-swipe'] || + animationType === EAnimationType['combo-left-swipe']) && leftSwipeView ? ( { //this is used to make scrollview active with pangesture @@ -145,18 +146,30 @@ export const usePanXGesture = ( } } if (dragDirectionShared.value === EDraggingDirection.left) { - if (!isLeftSwipe && !isLeftFullSwipe) { - return; - } - if (dragX < 0) { - if (isLeftSwipe && getLeftPanX(dragX) > leftSwipeViewWidth) { - return; + if (isComboLeftSwipe) { + if (dragX < 0) { + // Limit to leftSwipeViewWidth for half swipe, allow up to -itemWidth for full swipe + if (getLeftPanX(dragX) > itemWidth) { + return; + } + offsetX.value = dragX; + } else { + resetOffsets(); } - //drag item to left - offsetX.value = dragX; } else { - //while dragging left, if dragged to rightmost end reset values - resetOffsets(); + if (!isLeftSwipe && !isLeftFullSwipe) { + return; + } + if (dragX < 0) { + if (isLeftSwipe && getLeftPanX(dragX) > leftSwipeViewWidth) { + return; + } + //drag item to left + offsetX.value = dragX; + } else { + //while dragging left, if dragged to rightmost end reset values + resetOffsets(); + } } } }) @@ -200,27 +213,9 @@ export const usePanXGesture = ( } } else if (dragDirectionShared.value === EDraggingDirection.left) { //moving to left side - - if (isLeftSwipe) { - if (getLeftPanX(offsetX.value) >= leftSwipeViewWidth / 2) { - //move to left drag boundary - - //we set -leftSwipeViewWidth, as moving from left to right, values should be negative. - offsetX.value = withTiming(-leftSwipeViewWidth, { - duration: ANIMATION_DURATION, - }); - startX.value = -leftSwipeViewWidth; - } else if (getLeftPanX(offsetX.value) < leftSwipeViewWidth / 2) { - //move to rightmost end - resetOffsets(ANIMATION_DURATION); - } - } - - if (isLeftFullSwipe) { + if (isComboLeftSwipe) { if (getLeftPanX(offsetX.value) >= itemWidth / 2) { - //move to leftmost end and remove item - - //we set -itemWidth, as moving from left to right, values should be negative. + // Full swipe: move off screen and call function offsetX.value = withTiming( -itemWidth, { @@ -233,10 +228,55 @@ export const usePanXGesture = ( } ); startX.value = -itemWidth; - } else if (getLeftPanX(offsetX.value) < itemWidth / 2) { - //move to rightmost end + } else if (getLeftPanX(offsetX.value) >= leftSwipeViewWidth / 2) { + // Half swipe: snap to leftSwipeViewWidth + offsetX.value = withTiming(-leftSwipeViewWidth, { + duration: ANIMATION_DURATION, + }); + startX.value = -leftSwipeViewWidth; + } else { + // Not enough swipe: reset resetOffsets(ANIMATION_DURATION); } + } else { + + if (isLeftSwipe) { + if (getLeftPanX(offsetX.value) >= leftSwipeViewWidth / 2) { + //move to left drag boundary + + //we set -leftSwipeViewWidth, as moving from left to right, values should be negative. + offsetX.value = withTiming(-leftSwipeViewWidth, { + duration: ANIMATION_DURATION, + }); + startX.value = -leftSwipeViewWidth; + } else if (getLeftPanX(offsetX.value) < leftSwipeViewWidth / 2) { + //move to rightmost end + resetOffsets(ANIMATION_DURATION); + } + } + + if (isLeftFullSwipe) { + if (getLeftPanX(offsetX.value) >= itemWidth / 2) { + //move to leftmost end and remove item + + //we set -itemWidth, as moving from left to right, values should be negative. + offsetX.value = withTiming( + -itemWidth, + { + duration: ANIMATION_DURATION, + }, + () => { + if (typeof onLeftFullSwipe === 'function') { + runOnJS(onLeftFullSwipe)(id); + } + } + ); + startX.value = -itemWidth; + } else if (getLeftPanX(offsetX.value) < itemWidth / 2) { + //move to rightmost end + resetOffsets(ANIMATION_DURATION); + } + } } } else { //reset all values From d3bb88c9f84851ea3096b34d36a4ab8332003dbf Mon Sep 17 00:00:00 2001 From: Spencer Vaughn Date: Wed, 23 Jul 2025 12:45:22 -0500 Subject: [PATCH 2/4] chore: update version to 0.2.0 and change repository URL --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3b70843..60e82e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-swipe-reveal", - "version": "0.1.6", + "version": "0.2.0", "description": "✨ Buttery-smooth Swipeable Wrapper for React Native - Powered by Reanimated V3 ✨", "source": "./src/index.tsx", "main": "./lib/commonjs/index.js", @@ -53,7 +53,7 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/varunkukade/react-native-swipe-reveal.git" + "url": "git+https://github.com/savaughn/react-native-swipe-reveal.git" }, "author": "varunkukade (https://github.com/varunkukade)", "license": "MIT", From 2f913f28cf4c9dc394fcf2b41ba0231b8f5eb708 Mon Sep 17 00:00:00 2001 From: Spencer Vaughn Date: Wed, 23 Jul 2025 14:42:27 -0500 Subject: [PATCH 3/4] Refactor build commands and update animation types; add pnpm workspace configuration --- example/ios/Podfile | 2 +- example/metro.config.js | 6 ++++++ example/package.json | 12 ++++++------ example/src/constants.ts | 2 +- example/src/screens/List.tsx | 7 +++++-- package.json | 1 + pnpm-workspace.yaml | 3 +++ 7 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/example/ios/Podfile b/example/ios/Podfile index 7e7d601..3a06d97 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -32,7 +32,7 @@ target 'SwipeRevealExample' do pre_install do |installer| - system("cd ../../ && npx bob build --target codegen") + system("cd ../../ && npx react-native codegen") end post_install do |installer| diff --git a/example/metro.config.js b/example/metro.config.js index 7ddf7e0..761d9d3 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -19,5 +19,11 @@ module.exports = wrapWithReanimatedMetroConfig( root, pkg, project: __dirname, + watchFolders: [ + path.resolve(root, 'src'), + ], + extraNodeModules: { + 'react-native-swipe-reveal': path.resolve(root, 'src'), + }, }) ); diff --git a/example/package.json b/example/package.json index 01b3283..c7917f4 100644 --- a/example/package.json +++ b/example/package.json @@ -3,11 +3,11 @@ "version": "0.0.1", "private": true, "scripts": { - "android": "react-native run-android", - "ios": "react-native run-ios", - "start": "react-native start", - "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"", - "build:ios": "react-native build-ios --scheme SwipeRevealExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" + "android": "npx react-native run-android", + "ios": "npx react-native run-ios", + "start": "npx react-native start", + "build:android": "npx react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"", + "build:ios": "npx react-native build-ios --scheme SwipeRevealExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" }, "dependencies": { "react": "18.3.1", @@ -18,7 +18,7 @@ "devDependencies": { "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", - "@babel/runtime": "^7.25.0", + "@babel/runtime": "^7.27.6", "@react-native-community/cli": "15.0.1", "@react-native-community/cli-platform-android": "15.0.1", "@react-native-community/cli-platform-ios": "15.0.1", diff --git a/example/src/constants.ts b/example/src/constants.ts index 541ffcc..de9fea9 100644 --- a/example/src/constants.ts +++ b/example/src/constants.ts @@ -22,7 +22,7 @@ export const SONGS = [ title: 'Viva La Vida', singer: 'Coldplay', imageSrc: 'https://i.ytimg.com/vi/dvgZkm1xWPE/maxresdefault.jpg', - type: EAnimationType['left-right-swipe'], + type: EAnimationType['combo-left-swipe'], }, { id: 3, diff --git a/example/src/screens/List.tsx b/example/src/screens/List.tsx index 20b76a5..b876e06 100644 --- a/example/src/screens/List.tsx +++ b/example/src/screens/List.tsx @@ -27,7 +27,8 @@ export const List = () => { animationType={item.type} leftSwipeView={ item.type === EAnimationType['left-swipe'] || - item.type === EAnimationType['left-right-swipe'] ? ( + item.type === EAnimationType['left-right-swipe'] || + item.type === EAnimationType['combo-left-swipe'] ? ( { ) : undefined } leftFullSwipeView={ - item.type === EAnimationType['left-full-swipe'] ? ( + item.type === EAnimationType['left-full-swipe'] || + item.type === EAnimationType['combo-left-swipe'] ? ( { )} keyExtractor={(item) => item.id.toString()} + contentContainerStyle={styles.listContentContainer} /> ); diff --git a/package.json b/package.json index 60e82e8..8fc49ac 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "registry": "https://registry.npmjs.org/" }, "devDependencies": { + "@babel/runtime": "^7.27.6", "@commitlint/config-conventional": "^17.0.2", "@evilmartians/lefthook": "^1.5.0", "@react-native-community/cli": "15.0.1", diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..d8d4606 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'example' + - '.' \ No newline at end of file From be55a6df03ad9b2d42ecc3e96999068a006097be Mon Sep 17 00:00:00 2001 From: Spencer Vaughn Date: Wed, 23 Jul 2025 14:59:52 -0500 Subject: [PATCH 4/4] prep for fork merge --- README.md | 3 ++- example/ios/Podfile | 2 +- example/metro.config.js | 6 ------ example/package.json | 12 ++++++------ package.json | 8 +++++++- src/__tests__/index.test.tsx | 1 + 6 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 src/__tests__/index.test.tsx diff --git a/README.md b/README.md index 63d394d..fb7c5b2 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,8 @@ enum EAnimationType { 'right-swipe' = 'right-swipe', // Reveals content when swiping right 'left-right-swipe' = 'left-right-swipe', // Reveals content when swiping either direction 'right-full-swipe' = 'right-full-swipe', // Triggers action on full right swipe - 'left-full-swipe' = 'left-full-swipe' // Triggers action on full left swipe + 'left-full-swipe' = 'left-full-swipe', // Triggers action on full left swipe + 'combo-left-swipe' = 'combo-left-swipe', // Combines full left swipe with left swipe actions (e.g. iOS notifications) } ``` diff --git a/example/ios/Podfile b/example/ios/Podfile index 3a06d97..7e7d601 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -32,7 +32,7 @@ target 'SwipeRevealExample' do pre_install do |installer| - system("cd ../../ && npx react-native codegen") + system("cd ../../ && npx bob build --target codegen") end post_install do |installer| diff --git a/example/metro.config.js b/example/metro.config.js index 761d9d3..7ddf7e0 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -19,11 +19,5 @@ module.exports = wrapWithReanimatedMetroConfig( root, pkg, project: __dirname, - watchFolders: [ - path.resolve(root, 'src'), - ], - extraNodeModules: { - 'react-native-swipe-reveal': path.resolve(root, 'src'), - }, }) ); diff --git a/example/package.json b/example/package.json index c7917f4..01b3283 100644 --- a/example/package.json +++ b/example/package.json @@ -3,11 +3,11 @@ "version": "0.0.1", "private": true, "scripts": { - "android": "npx react-native run-android", - "ios": "npx react-native run-ios", - "start": "npx react-native start", - "build:android": "npx react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"", - "build:ios": "npx react-native build-ios --scheme SwipeRevealExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" + "android": "react-native run-android", + "ios": "react-native run-ios", + "start": "react-native start", + "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"", + "build:ios": "react-native build-ios --scheme SwipeRevealExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" }, "dependencies": { "react": "18.3.1", @@ -18,7 +18,7 @@ "devDependencies": { "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", - "@babel/runtime": "^7.27.6", + "@babel/runtime": "^7.25.0", "@react-native-community/cli": "15.0.1", "@react-native-community/cli-platform-android": "15.0.1", "@react-native-community/cli-platform-ios": "15.0.1", diff --git a/package.json b/package.json index 8fc49ac..46737d9 100644 --- a/package.json +++ b/package.json @@ -53,9 +53,15 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/savaughn/react-native-swipe-reveal.git" + "url": "git+https://github.com/varunkukade/react-native-swipe-reveal.git" }, "author": "varunkukade (https://github.com/varunkukade)", + "contributors": [ + { + "name": "savaughn", + "url": "https://github.com/savaughn" + } + ], "license": "MIT", "bugs": { "url": "https://github.com/varunkukade/react-native-swipe-reveal/issues" diff --git a/src/__tests__/index.test.tsx b/src/__tests__/index.test.tsx new file mode 100644 index 0000000..b20e78e --- /dev/null +++ b/src/__tests__/index.test.tsx @@ -0,0 +1 @@ +it.todo('write a test'); \ No newline at end of file