Skip to content

Commit

Permalink
feat: added enable pan down to close (#437)
Browse files Browse the repository at this point in the history
* refactor: converted all internal variables into shared values

* chore: updated dev screen

* feat: added enablePanDownToClose prop

* refactor: updated bottom sheet modal to utilise enable pan down to close prop

* chore: disabled memoised bottom sheet handle container

* chore: updated examples

* chore: fixed gesture handler on handle
  • Loading branch information
gorhom committed May 11, 2021
1 parent 89098e9 commit 1f103b0
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 157 deletions.
36 changes: 33 additions & 3 deletions example/src/screens/modal/SimpleExample.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React, { useCallback, useMemo, useRef } from 'react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, StyleSheet } from 'react-native';
import { BottomSheetModal } from '@gorhom/bottom-sheet';
import Button from '../../components/button';
import ContactListContainer from '../../components/contactListContainer';
import withModalProvider from '../withModalProvider';

const SimpleExample = () => {
//#region state
const [enablePanDownToClose, setEnablePanDownToClose] = useState(true);
const [enableDismissOnClose, setEnableDismissOnClose] = useState(true);
//#endregion

// refs
const bottomSheetRef = useRef<BottomSheetModal>(null);

// variables
const snapPoints = useMemo(() => ['25%', '50%'], []);

// callbacks
//#region callbacks
const handleChange = useCallback((index: number) => {
// eslint-disable-next-line no-console
console.log('index', index);
Expand All @@ -24,6 +29,9 @@ const SimpleExample = () => {
const handleDismissPress = useCallback(() => {
bottomSheetRef.current!.dismiss();
}, []);
const handleClosePress = useCallback(() => {
bottomSheetRef.current!.close();
}, []);
const handleExpandPress = useCallback(() => {
bottomSheetRef.current!.expand();
}, []);
Expand All @@ -33,6 +41,13 @@ const SimpleExample = () => {
const handlePresentPress = useCallback(() => {
bottomSheetRef.current!.present();
}, []);
const handleEnablePanDownToClosePress = useCallback(() => {
setEnablePanDownToClose(state => !state);
}, []);
const handleEnableDismissOnClosePress = useCallback(() => {
setEnableDismissOnClose(state => !state);
}, []);
//#endregion

// renders
return (
Expand All @@ -41,14 +56,29 @@ const SimpleExample = () => {
<Button label="Dismiss Modal" onPress={handleDismissPress} />
<Button label="Expand" onPress={handleExpandPress} />
<Button label="Collapse" onPress={handleCollapsePress} />
<Button label="Close" onPress={handleClosePress} />
<Button
label={`${
enablePanDownToClose ? 'Disable' : 'Enable'
} Pan Down To Close`}
onPress={handleEnablePanDownToClosePress}
/>
<Button
label={`${
enableDismissOnClose ? 'Disable' : 'Enable'
} Dismiss On Close`}
onPress={handleEnableDismissOnClosePress}
/>
<BottomSheetModal
ref={bottomSheetRef}
snapPoints={snapPoints}
animationDuration={250}
enablePanDownToClose={enablePanDownToClose}
enableDismissOnClose={enableDismissOnClose}
onDismiss={handleDismiss}
onChange={handleChange}
>
<ContactListContainer title="Modal FlatList" type="FlatList" />
<ContactListContainer title="Modal FlatList" count={3} type="View" />
</BottomSheetModal>
</View>
);
Expand Down
4 changes: 1 addition & 3 deletions example/src/screens/modal/StackExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ const StackExample = () => {
<Button label="Dismiss Modal B" onPress={handleDismissBPress} />
<Button label="Present Modal C" onPress={handlePresentCPress} />
<Button label="Dismiss Modal C" onPress={handleDismissCPress} />

<Button label="Dismiss All Modal" onPress={handleDismissAllPress} />

<Button label="Dismiss A By Hook" onPress={handleDismissByHookPress} />

<BottomSheetModal
Expand All @@ -98,7 +96,7 @@ const StackExample = () => {
ref={bottomSheetModalCRef}
index={1}
snapPoints={snapPoints}
dismissOnPanDown={false}
enablePanDownToClose={false}
children={renderBottomSheetContent('Modal C', handleDismissCPress)}
/>
</View>
Expand Down
38 changes: 30 additions & 8 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
INITIAL_HANDLE_HEIGHT,
INITIAL_POSITION,
INITIAL_SNAP_POINT,
DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
} from './constants';
import type { ScrollableRef, BottomSheetMethods } from '../../types';
import type { BottomSheetProps } from './types';
Expand Down Expand Up @@ -96,6 +97,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
enableHandlePanningGesture = DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
enableOverDrag = DEFAULT_ENABLE_OVER_DRAG,
enableFlashScrollableIndicatorOnExpand = DEFAULT_ENABLE_FLASH_SCROLLABLE_INDICATOR_ON_EXPAND,
enablePanDownToClose = DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
overDragResistanceFactor = DEFAULT_OVER_DRAG_RESISTANCE_FACTOR,
style: _providedStyle,

Expand Down Expand Up @@ -360,11 +362,9 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
method: handleOnChange.name,
params: {
index,
animatedCurrentIndex: animatedCurrentIndex.value,
},
});
if (index === animatedCurrentIndex.value) {
return;
}

if (isClosing.current && (index === 0 || index === -1)) {
isClosing.current = false;
Expand Down Expand Up @@ -487,12 +487,14 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
] = useInteractivePanGestureHandler({
type: GESTURE.CONTENT,
enableOverDrag,
enablePanDownToClose,
overDragResistanceFactor,
keyboardState,
keyboardHeight,
keyboardBehavior: keyboardBehavior,
animatedPosition,
animatedSnapPoints,
animatedContainerHeight,
isExtendedByKeyboard: isInTemporaryPosition,
scrollableContentOffsetY,
animateToPoint: animateToPosition,
Expand All @@ -503,12 +505,14 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
] = useInteractivePanGestureHandler({
type: GESTURE.HANDLE,
enableOverDrag,
enablePanDownToClose,
overDragResistanceFactor,
keyboardState,
keyboardHeight,
keyboardBehavior,
animatedPosition,
animatedSnapPoints,
animatedContainerHeight,
isExtendedByKeyboard: isInTemporaryPosition,
animateToPoint: animateToPosition,
});
Expand Down Expand Up @@ -665,12 +669,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
const internalContextVariables = useMemo(
() => ({
enableContentPanningGesture,
animatedAnimationState,
animatedSheetState,
animatedScrollableState,
animatedIndex,
animatedPosition,
animationState: animatedAnimationState,
animatedSheetState,
contentPanGestureHandler,
scrollableState: animatedScrollableState,
scrollableContentOffsetY,
shouldHandleKeyboardEvents,
simultaneousHandlers: _providedSimultaneousHandlers,
Expand All @@ -679,6 +682,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
activeOffsetY: _providedActiveOffsetY,
failOffsetX: _providedFailOffsetX,
failOffsetY: _providedFailOffsetY,
contentPanGestureHandler,
setScrollableRef: handleSettingScrollableRef,
removeScrollableRef,
}),
Expand Down Expand Up @@ -806,10 +810,23 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
useAnimatedReaction(
() => animatedSnapPoints.value,
_animatedSnapPoints => {
if (!isLayoutCalculated.value || !isAnimatedOnMount.value) {
if (
!isLayoutCalculated.value ||
!isAnimatedOnMount.value ||
animatedAnimationState.value === ANIMATION_STATE.RUNNING
) {
return;
}

runOnJS(print)({
component: BottomSheet.name,
method: 'useAnimatedReaction::OnSnapPointChange',
params: {
animatedSnapPoints: _animatedSnapPoints,
animatedCurrentIndex: animatedCurrentIndex.value,
},
});

const nextPosition = _animatedSnapPoints[animatedCurrentIndex.value];
animateToPosition(nextPosition);
}
Expand Down Expand Up @@ -930,6 +947,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
}) => {
if (
_animatedIndex % 1 === 0 &&
_animatedIndex !== animatedCurrentIndex.value &&
_animationState === ANIMATION_STATE.STOPPED &&
(_contentGestureState === State.END ||
_contentGestureState === State.UNDETERMINED) &&
Expand Down Expand Up @@ -1008,6 +1026,10 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
animatedPosition={animatedPosition}
handleHeight={animatedHandleHeight}
enableHandlePanningGesture={enableHandlePanningGesture}
enableOverDrag={enableOverDrag}
enablePanDownToClose={enablePanDownToClose}
overDragResistanceFactor={overDragResistanceFactor}
keyboardBehavior={keyboardBehavior}
handlePanGestureHandler={handlePanGestureHandler}
handleComponent={handleComponent}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/components/bottomSheet/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const DEFAULT_ENABLE_CONTENT_PANNING_GESTURE = true;
const DEFAULT_ENABLE_HANDLE_PANNING_GESTURE = true;
const DEFAULT_ENABLE_OVER_DRAG = true;
const DEFAULT_ENABLE_FLASH_SCROLLABLE_INDICATOR_ON_EXPAND = true;
const DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE = false;
const DEFAULT_ANIMATE_ON_MOUNT = false;
const DEFAULT_KEYBOARD_BEHAVIOR = KEYBOARD_BEHAVIOR.none;
const DEFAULT_KEYBOARD_BLUR_BEHAVIOR = KEYBOARD_BLUR_BEHAVIOR.none;
Expand All @@ -34,6 +35,7 @@ export {
DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
DEFAULT_ENABLE_OVER_DRAG,
DEFAULT_ENABLE_FLASH_SCROLLABLE_INDICATOR_ON_EXPAND,
DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
DEFAULT_ANIMATE_ON_MOUNT,
DEFAULT_KEYBOARD_BEHAVIOR,
DEFAULT_KEYBOARD_BLUR_BEHAVIOR,
Expand Down
6 changes: 6 additions & 0 deletions src/components/bottomSheet/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ export interface BottomSheetProps
* @default true
*/
enableFlashScrollableIndicatorOnExpand?: boolean;
/**
* Enable pan down gesture to close the sheet.
* @type boolean
* @default false
*/
enablePanDownToClose?: boolean;
/**
* To start the sheet closed and snap to initial index when it's mounted.
* @type boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ function BottomSheetHandleContainerComponent({
waitFor={waitFor}
simultaneousHandlers={simultaneousHandlers}
shouldCancelWhenOutside={false}
onGestureEvent={handlePanGestureHandler}
activeOffsetX={activeOffsetX}
activeOffsetY={activeOffsetY}
failOffsetX={failOffsetX}
failOffsetY={failOffsetY}
onGestureEvent={handlePanGestureHandler}
>
<Animated.View
accessible={true}
Expand Down
9 changes: 8 additions & 1 deletion src/components/bottomSheetHandleContainer/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ import type { PanGestureHandlerProperties } from 'react-native-gesture-handler';
import type Animated from 'react-native-reanimated';
import type { BottomSheetProps } from '../bottomSheet';
import type { BottomSheetHandleProps } from '../bottomSheetHandle';
import type { useInteractivePanGestureHandlerConfigs } from '../../hooks/useInteractivePanGestureHandler';

export interface BottomSheetHandleContainerProps
extends Pick<PanGestureHandlerProperties, 'simultaneousHandlers'>,
Pick<BottomSheetProps, 'handleComponent' | 'enableHandlePanningGesture'>,
Pick<
useInteractivePanGestureHandlerConfigs,
| 'enableOverDrag'
| 'enablePanDownToClose'
| 'overDragResistanceFactor'
| 'keyboardBehavior'
>,
BottomSheetHandleProps {
handlePanGestureHandler: any;

handleHeight: Animated.SharedValue<number>;
}
Loading

0 comments on commit 1f103b0

Please sign in to comment.