Skip to content

Commit 353a378

Browse files
committed
feat: add one snap point change per one swipe
1 parent d12f3f7 commit 353a378

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

src/components/bottomSheet/BottomSheet.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import {
7979
DEFAULT_KEYBOARD_BLUR_BEHAVIOR,
8080
DEFAULT_KEYBOARD_INDEX,
8181
DEFAULT_KEYBOARD_INPUT_MODE,
82+
DEFAULT_ONE_SNAP_POINT_PER_SWIPE,
8283
DEFAULT_OVER_DRAG_RESISTANCE_FACTOR,
8384
INITIAL_POSITION,
8485
INITIAL_VALUE,
@@ -107,6 +108,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
107108
enableOverDrag = DEFAULT_ENABLE_OVER_DRAG,
108109
enablePanDownToClose = DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
109110
enableDynamicSizing = DEFAULT_DYNAMIC_SIZING,
111+
enableOneSnapPointPerSwipe = DEFAULT_ONE_SNAP_POINT_PER_SWIPE,
110112
overDragResistanceFactor = DEFAULT_OVER_DRAG_RESISTANCE_FACTOR,
111113
overrideReduceMotion: _providedOverrideReduceMotion,
112114

@@ -1436,6 +1438,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
14361438
overDragResistanceFactor,
14371439
enableOverDrag,
14381440
enablePanDownToClose,
1441+
enableOneSnapPointPerSwipe,
14391442
animatedAnimationState,
14401443
animatedSheetState,
14411444
animatedScrollableState,
@@ -1480,6 +1483,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
14801483
overDragResistanceFactor,
14811484
enableOverDrag,
14821485
enablePanDownToClose,
1486+
enableOneSnapPointPerSwipe,
14831487
enableDynamicSizing,
14841488
enableBlurKeyboardOnGesture,
14851489
_providedSimultaneousHandlers,

src/components/bottomSheet/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const DEFAULT_ENABLE_OVER_DRAG = true;
1414
const DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE = false;
1515
const DEFAULT_ANIMATE_ON_MOUNT = true;
1616
const DEFAULT_DYNAMIC_SIZING = true;
17+
const DEFAULT_ONE_SNAP_POINT_PER_SWIPE = false;
1718

1819
// keyboard
1920
const DEFAULT_KEYBOARD_BEHAVIOR = KEYBOARD_BEHAVIOR.interactive;
@@ -35,6 +36,7 @@ const DEFAULT_ACCESSIBILITY_ROLE = 'adjustable';
3536
export {
3637
DEFAULT_HANDLE_HEIGHT,
3738
DEFAULT_OVER_DRAG_RESISTANCE_FACTOR,
39+
DEFAULT_ONE_SNAP_POINT_PER_SWIPE,
3840
DEFAULT_ENABLE_CONTENT_PANNING_GESTURE,
3941
DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
4042
DEFAULT_ENABLE_OVER_DRAG,

src/components/bottomSheet/types.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type React from 'react';
2-
import type { Insets, StyleProp, View, ViewStyle } from 'react-native';
2+
import type { Insets, StyleProp, ViewStyle } from 'react-native';
33
import type { PanGesture } from 'react-native-gesture-handler';
44
import type {
55
AnimateStyle,
@@ -90,6 +90,13 @@ export interface BottomSheetProps
9090
* @default true
9191
*/
9292
enableDynamicSizing?: boolean;
93+
/**
94+
* Enable change of one snap point per one swipe.
95+
* Works only with default Gesture Events Handlers.
96+
* @type boolean
97+
* @default false
98+
*/
99+
enableOneSnapPointPerSwipe?: boolean;
93100
/**
94101
* To start the sheet closed and snap to initial index when it's mounted.
95102
* @type boolean

src/contexts/internal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface BottomSheetInternalContextType
2828
| 'enableDynamicSizing'
2929
| 'enableBlurKeyboardOnGesture'
3030
| 'overDragResistanceFactor'
31+
| 'enableOneSnapPointPerSwipe'
3132
>
3233
> {
3334
// animated states

src/hooks/useGestureEventsHandlersDefault.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const dismissKeyboard = Keyboard.dismiss;
3333
// biome-ignore lint: to be addressed!
3434
const resetContext = (context: any) => {
3535
'worklet';
36-
Object.keys(context).map(key => {
36+
Object.keys(context).forEach(key => {
3737
context[key] = undefined;
3838
});
3939
};
@@ -49,6 +49,7 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
4949
animatedLayoutState,
5050
enableOverDrag,
5151
enablePanDownToClose,
52+
enableOneSnapPointPerSwipe,
5253
overDragResistanceFactor,
5354
isInTemporaryPosition,
5455
enableBlurKeyboardOnGesture,
@@ -142,10 +143,20 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
142143
}
143144

144145
const { containerHeight } = animatedLayoutState.get();
145-
const lowestSnapPoint = enablePanDownToClose
146+
let lowestSnapPoint = enablePanDownToClose
146147
? containerHeight
147148
: detents[0];
148149

150+
if (enableOneSnapPointPerSwipe) {
151+
const currentIndex = detents.indexOf(context.value.initialPosition);
152+
153+
const nextIndex = Math.min(currentIndex + 1, detents.length - 1);
154+
const prevIndex = Math.max(currentIndex - 1, 0);
155+
156+
highestSnapPoint = detents[nextIndex];
157+
lowestSnapPoint = detents[prevIndex];
158+
}
159+
149160
/**
150161
* if scrollable is refreshable and sheet position at the highest
151162
* point, then do not interact with current gesture.
@@ -261,6 +272,7 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
261272
[
262273
enableOverDrag,
263274
enablePanDownToClose,
275+
enableOneSnapPointPerSwipe,
264276
overDragResistanceFactor,
265277
isInTemporaryPosition,
266278
animatedScrollableState,
@@ -401,6 +413,24 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
401413
return;
402414
}
403415

416+
if (enableOneSnapPointPerSwipe) {
417+
const currentIndex = snapPoints.indexOf(destinationPoint);
418+
const prevIndex = snapPoints.indexOf(context.value.initialPosition);
419+
420+
if (Math.abs(prevIndex - currentIndex) > 1) {
421+
const newIndex =
422+
prevIndex > currentIndex ? currentIndex + 1 : currentIndex - 1;
423+
424+
animateToPosition(
425+
snapPoints[newIndex],
426+
ANIMATION_SOURCE.GESTURE,
427+
velocityY / 2
428+
);
429+
430+
return;
431+
}
432+
}
433+
404434
animateToPosition(
405435
destinationPoint,
406436
ANIMATION_SOURCE.GESTURE,
@@ -409,6 +439,7 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
409439
},
410440
[
411441
enablePanDownToClose,
442+
enableOneSnapPointPerSwipe,
412443
isInTemporaryPosition,
413444
animatedScrollableState,
414445
animatedDetentsState,

src/hooks/useGestureEventsHandlersDefault.web.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const dismissKeyboardOnJs = runOnJS(Keyboard.dismiss);
3232
// biome-ignore lint: to be addressed!
3333
const resetContext = (context: any) => {
3434
'worklet';
35-
Object.keys(context).map(key => {
35+
Object.keys(context).forEach(key => {
3636
context[key] = undefined;
3737
});
3838
};

0 commit comments

Comments
 (0)