Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions example/src/screens/modal/SimpleExample.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React, { useCallback, useRef } from 'react';
import React, { useCallback, useMemo, useRef } 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 = () => {
// refs
const bottomSheetRef = useRef<BottomSheetModal>(null);

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

// callbacks
const handleChange = useCallback((index: number) => {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -55,7 +59,7 @@ const SimpleExample = () => {
/>
<BottomSheetModal
ref={bottomSheetRef}
snapPoints={['25%', '50%']}
snapPoints={snapPoints}
animationDuration={250}
onDismiss={handleDismiss}
onChange={handleChange}
Expand Down
120 changes: 74 additions & 46 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import Animated, {
Extrapolate,
runOnUI,
useWorkletCallback,
withTiming,
} from 'react-native-reanimated';
import { State } from 'react-native-gesture-handler';
import {
Expand All @@ -42,7 +41,13 @@ import BottomSheetHandleContainer from '../bottomSheetHandleContainer';
import BottomSheetBackgroundContainer from '../bottomSheetBackgroundContainer';
import BottomSheetDraggableView from '../bottomSheetDraggableView';
// import BottomSheetDebugView from '../bottomSheetDebugView';
import { GESTURE, ANIMATION_STATE, WINDOW_HEIGHT } from '../../constants';
import {
GESTURE,
ANIMATION_STATE,
WINDOW_HEIGHT,
ANIMATION_METHOD,
} from '../../constants';
import { animate } from '../../utilities';
import {
DEFAULT_ANIMATION_EASING,
DEFAULT_ANIMATION_DURATION,
Expand Down Expand Up @@ -74,8 +79,8 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
//#region extract props
const {
// animations configurations
animationDuration = DEFAULT_ANIMATION_DURATION,
animationEasing = DEFAULT_ANIMATION_EASING,
animationDuration: _providedAnimationDuration = DEFAULT_ANIMATION_DURATION,
animationEasing: _providedAnimationEasing = DEFAULT_ANIMATION_EASING,
animationConfigs: _providedAnimationConfigs,

// configurations
Expand Down Expand Up @@ -289,39 +294,52 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
animationState.value = ANIMATION_STATE.STOPPED;
}, [animatedIndex, animationState, handleOnChange, refreshUIElements]);
const animateToPoint = useWorkletCallback(
(point: number, velocity: number = 0) => {
(
point: number,
velocity: number = 0,
animationDuration?: number,
animationEasing?: Animated.EasingFunction
) => {
animationState.value = ANIMATION_STATE.RUNNING;
runOnJS(handleOnAnimate)(point);

if (_providedAnimationConfigs) {
/**
* force animation configs from parameters, if provided
*/
if (animationDuration !== undefined) {
animatedPosition.value = animate(ANIMATION_METHOD.TIMING, {
duration: animationDuration,
easing: animationEasing
? animationEasing
: DEFAULT_ANIMATION_EASING,
})(point, velocity, animateToPointCompleted);
} else if (_providedAnimationConfigs) {
/**
* use animationConfigs callback, if provided
*/
animatedPosition.value = _providedAnimationConfigs(
point,
velocity,
animateToPointCompleted
);
return;
} else {
/**
* @deprecated this will be removed in next major release.
*/
animatedPosition.value = animate(ANIMATION_METHOD.TIMING, {
duration: _providedAnimationDuration,
easing: _providedAnimationEasing,
})(point, velocity, animateToPointCompleted);
}

/**
* @deprecated this will be removed in next major release.
*/
animatedPosition.value = withTiming(
point,
{
duration: animationDuration,
easing: animationEasing,
},
animateToPointCompleted
);
},
[
_providedAnimationConfigs,
animationState,
animatedPosition,
animationDuration,
animationEasing,
animateToPointCompleted,
handleOnAnimate,
_providedAnimationConfigs,
_providedAnimationDuration,
_providedAnimationEasing,
]
);

Expand Down Expand Up @@ -368,7 +386,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(

//#region public methods
const handleSnapTo = useCallback(
(index: number) => {
(index: number, ...args) => {
invariant(
index >= -1 && index <= snapPoints.length - 1,
`'index' was provided but out of the provided snap points range! expected value to be between -1, ${
Expand All @@ -379,31 +397,40 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
return;
}
const newSnapPoint = snapPoints[index];
runOnUI(animateToPoint)(newSnapPoint);
runOnUI(animateToPoint)(newSnapPoint, 0, ...args);
},
[animateToPoint, snapPoints]
);
const handleClose = useCallback(
(...args) => {
if (isClosing.current) {
return;
}
isClosing.current = true;
runOnUI(animateToPoint)(safeContainerHeight, 0, ...args);
},
[animateToPoint, safeContainerHeight]
);
const handleExpand = useCallback(
(...args) => {
if (isClosing.current) {
return;
}
const newSnapPoint = snapPoints[snapPoints.length - 1];
runOnUI(animateToPoint)(newSnapPoint, 0, ...args);
},
[animateToPoint, snapPoints]
);
const handleCollapse = useCallback(
(...args) => {
if (isClosing.current) {
return;
}
const newSnapPoint = snapPoints[0];
runOnUI(animateToPoint)(newSnapPoint, 0, ...args);
},
[animateToPoint, snapPoints]
);
const handleClose = useCallback(() => {
if (isClosing.current) {
return;
}
isClosing.current = true;
runOnUI(animateToPoint)(safeContainerHeight);
}, [animateToPoint, safeContainerHeight]);
const handleExpand = useCallback(() => {
if (isClosing.current) {
return;
}
const newSnapPoint = snapPoints[snapPoints.length - 1];
runOnUI(animateToPoint)(newSnapPoint);
}, [animateToPoint, snapPoints]);
const handleCollapse = useCallback(() => {
if (isClosing.current) {
return;
}
const newSnapPoint = snapPoints[0];
runOnUI(animateToPoint)(newSnapPoint);
}, [animateToPoint, snapPoints]);
useImperativeHandle(ref, () => ({
snapTo: handleSnapTo,
expand: handleExpand,
Expand Down Expand Up @@ -512,7 +539,8 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
isLayoutCalculated &&
didMountOnAnimate.current === false &&
isClosing.current === false &&
snapPoints[_providedIndex] !== safeContainerHeight
snapPoints[_providedIndex] !== safeContainerHeight &&
_providedIndex !== -1
) {
const newSnapPoint = snapPoints[_providedIndex];
requestAnimationFrame(() => runOnUI(animateToPoint)(newSnapPoint));
Expand Down
82 changes: 46 additions & 36 deletions src/components/bottomSheetModal/BottomSheetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ const BottomSheetModalComponent = forwardRef<
forcedDismissed.current = false;
}, []);
const adjustIndex = useCallback(
(_index: number) => (dismissOnPanDown ? _index - 1 : _index),
(_index: number, internal = true) =>
dismissOnPanDown ? (internal ? _index - 1 : _index + 1) : _index,
[dismissOnPanDown]
);
const unmount = useCallback(() => {
Expand All @@ -113,34 +114,40 @@ const BottomSheetModalComponent = forwardRef<
//#endregion

//#region bottom sheet methods
const handleSnapTo = useCallback(() => {
if (minimized.current) {
return;
}
const handleSnapTo = useCallback(
(_index: number, ...args) => {
if (minimized.current) {
return;
}

bottomSheetRef.current?.snapTo(adjustIndex(currentIndexRef.current));
}, [adjustIndex]);
const handleExpand = useCallback(() => {
bottomSheetRef.current?.snapTo(adjustIndex(_index, false), ...args);
},
[adjustIndex]
);
const handleExpand = useCallback((...args) => {
if (minimized.current) {
return;
}
bottomSheetRef.current?.expand();
bottomSheetRef.current?.expand(...args);
}, []);
const handleCollapse = useCallback(() => {
if (minimized.current) {
return;
}
if (dismissOnPanDown) {
bottomSheetRef.current?.snapTo(1);
} else {
bottomSheetRef.current?.collapse();
}
}, [dismissOnPanDown]);
const handleClose = useCallback(() => {
const handleCollapse = useCallback(
(...args) => {
if (minimized.current) {
return;
}
if (dismissOnPanDown) {
bottomSheetRef.current?.snapTo(1, ...args);
} else {
bottomSheetRef.current?.collapse(...args);
}
},
[dismissOnPanDown]
);
const handleClose = useCallback((...args) => {
if (minimized.current) {
return;
}
bottomSheetRef.current?.close();
bottomSheetRef.current?.close(...args);
}, []);
//#endregion

Expand All @@ -151,22 +158,25 @@ const BottomSheetModalComponent = forwardRef<
mountSheet(key, ref, stackBehavior);
});
}, [key, stackBehavior, ref, mountSheet]);
const handleDismiss = useCallback(() => {
/**
* if modal is already been dismiss, we exit the method.
*/
if (currentIndexRef.current === -1 && minimized.current === false) {
return;
}
const handleDismiss = useCallback(
(...args) => {
/**
* if modal is already been dismiss, we exit the method.
*/
if (currentIndexRef.current === -1 && minimized.current === false) {
return;
}

if (minimized.current) {
unmount();
return;
}
willUnmountSheet(key);
forcedDismissed.current = true;
bottomSheetRef.current?.close();
}, [willUnmountSheet, unmount, key]);
if (minimized.current) {
unmount();
return;
}
willUnmountSheet(key);
forcedDismissed.current = true;
bottomSheetRef.current?.close(...args);
},
[willUnmountSheet, unmount, key]
);
const handleMinimize = useCallback(() => {
if (minimized.current) {
return;
Expand Down
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ enum ANIMATION_STATE {
STOPPED,
}

enum ANIMATION_METHOD {
TIMING,
SPRING,
}

const MODAL_STACK_BEHAVIOR = {
replace: 'replace',
push: 'push',
Expand All @@ -24,5 +29,6 @@ export {
WINDOW_WIDTH,
GESTURE,
ANIMATION_STATE,
ANIMATION_METHOD,
MODAL_STACK_BEHAVIOR,
};
21 changes: 8 additions & 13 deletions src/hooks/useBottomSheetSpringConfigs.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import Animated, {
useWorkletCallback,
withSpring,
} from 'react-native-reanimated';
import Animated from 'react-native-reanimated';
import { ANIMATION_METHOD } from '../constants';
import { animate } from '../utilities';

/**
* Generate spring animation configs.
* @param configs overridable configs.
*/
export const useBottomSheetSpringConfigs = (
configs: Omit<Animated.WithSpringConfig, 'velocity'>
) => {
const animationConfig = useWorkletCallback(
(point: number, velocity: number = 0, callback: () => void) => {
// @ts-ignore override velocity
configs.velocity = velocity;
return withSpring(point, configs, callback);
},
[configs]
);
return animationConfig;
return animate(ANIMATION_METHOD.SPRING, configs);
};
Loading