Skip to content
Open
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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ A performant interactive bottom sheet with fully configurable options 🚀
- Support [pull to refresh](https://gorhom.dev/react-native-bottom-sheet/pull-to-refresh) for scrollables.
- Support `FlatList`, `SectionList`, `ScrollView` & `View` scrolling interactions, [read more](https://gorhom.dev/react-native-bottom-sheet/scrollables).
- Support `React Navigation` Integration, [read more](https://gorhom.dev/react-native-bottom-sheet/react-navigation-integration).
- Compatible with `Reanimated` v1-3.
- Compatible with `Reanimated` v1-4.
- Compatible with `Expo`.
- Accessibility support.
- Written in `TypeScript`.
Expand All @@ -34,13 +34,23 @@ Check out [the documentation website](https://gorhom.dev/react-native-bottom-she

This library been written in 3 versions of `Reanimated`, and kept all implementation in separate branches:

- **`v6`** | [branch](https://github.com/gorhom/react-native-bottom-sheet/tree/master) | [changelog](https://github.com/gorhom/react-native-bottom-sheet/blob/master/CHANGELOG.md) : written with `Reanimated v4` & `Gesture Handler v2`.

- **`v5`** | [branch](https://github.com/gorhom/react-native-bottom-sheet/tree/master) | [changelog](https://github.com/gorhom/react-native-bottom-sheet/blob/master/CHANGELOG.md) : written with `Reanimated v3` & `Gesture Handler v2`.

- `v4` (not maintained) | [branch](https://github.com/gorhom/react-native-bottom-sheet/tree/v4) | [changelog](https://github.com/gorhom/react-native-bottom-sheet/blob/v4/CHANGELOG.md) : written with `Reanimated v2`.

- `v2` (not maintained) | [branch](https://github.com/gorhom/react-native-bottom-sheet/tree/v2) | [changelog](https://github.com/gorhom/react-native-bottom-sheet/blob/v2/CHANGELOG.md) : written with `Reanimated v1` & compatible with `Reanimated v2`.

> I highly recommend to use `v5` which provides more stability with all latest features.
> I highly recommend to use `v6` which provides more stability with all latest features.

### React Native Reanimated 4 Support

Starting from v5.1.8, this library supports `react-native-reanimated` v4. When using Reanimated 4:

- **New Architecture is required** - Reanimated 4 only supports the New Architecture
- **`react-native-worklets` dependency is required** - Install it alongside `react-native-reanimated`
- The babel plugin has been updated to use `react-native-worklets/plugin`

## Author

Expand Down
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'],
plugins: ['react-native-worklets/plugin'],
};
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gorhom/bottom-sheet",
"version": "5.2.10",
"version": "6.0.0-alpha.0",
"description": "A performant interactive bottom sheet with fully configurable options 🚀",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down Expand Up @@ -61,6 +61,7 @@
"react-native-builder-bob": "^0.30.3",
"react-native-gesture-handler": "~2.20.2",
"react-native-reanimated": "~3.19.1",
"react-native-worklets": ">=0.5.1",
"release-it": "^19.0.4",
"typescript": "^5.8.3"
},
Expand All @@ -70,7 +71,8 @@
"react": "*",
"react-native": "*",
"react-native-gesture-handler": ">=2.16.1",
"react-native-reanimated": ">=3.16.0 || >=4.0.0-"
"react-native-reanimated": ">=3.16.0 || >=4.0.0",
"react-native-worklets": ">=0.5.1"
},
"peerDependenciesMeta": {
"@types/react-native": {
Expand Down
44 changes: 18 additions & 26 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ import React, {
} from 'react';
import { Platform, StyleSheet } from 'react-native';
import { State } from 'react-native-gesture-handler';
import Animated, {
import {
cancelAnimation,
Extrapolation,
interpolate,
ReduceMotion,
runOnJS,
runOnUI,
useAnimatedReaction,
useDerivedValue,
useReducedMotion,
useSharedValue,
type WithSpringConfig,
type WithTimingConfig,
} from 'react-native-reanimated';
import { scheduleOnRN, scheduleOnUI } from 'react-native-worklets';
import {
ANIMATION_SOURCE,
ANIMATION_STATUS,
Expand Down Expand Up @@ -85,9 +84,8 @@ import {
} from './constants';
import type { AnimateToPositionType, BottomSheetProps } from './types';

Animated.addWhitelistedUIProps({
decelerationRate: true,
});
// NOTE: addWhitelistedUIProps was removed in Reanimated 4
// and decelerationRate is now handled by default.

type BottomSheet = BottomSheetMethods;

Expand Down Expand Up @@ -538,7 +536,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
const { nextIndex, nextPosition } = animatedAnimationState.get();

if (__DEV__) {
runOnJS(print)({
scheduleOnRN(print, {
component: 'BottomSheet',
method: 'animateToPositionCompleted',
params: {
Expand All @@ -555,11 +553,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(

// callbacks
if (nextIndex !== animatedCurrentIndex.get()) {
runOnJS(handleOnChange)(nextIndex, nextPosition);
scheduleOnRN(handleOnChange, nextIndex, nextPosition);
}

if (nextIndex === -1) {
runOnJS(handleOnClose)();
scheduleOnRN(handleOnClose);
}

animatedCurrentIndex.set(nextIndex);
Expand Down Expand Up @@ -593,7 +591,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
) {
'worklet';
if (__DEV__) {
runOnJS(print)({
scheduleOnRN(print, {
component: 'BottomSheet',
method: 'animateToPosition',
params: {
Expand Down Expand Up @@ -684,7 +682,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
/**
* fire `onAnimate` callback
*/
runOnJS(handleOnAnimate)(index, position);
scheduleOnRN(handleOnAnimate, index, position);

/**
* start animation
Expand Down Expand Up @@ -740,7 +738,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
}

if (__DEV__) {
runOnJS(print)({
scheduleOnRN(print, {
component: 'BottomSheet',
method: 'setToPosition',
params: {
Expand Down Expand Up @@ -1140,8 +1138,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
isInTemporaryPosition.value = false;

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1189,8 +1186,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
isInTemporaryPosition.value = true;

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1243,8 +1239,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
isInTemporaryPosition.value = false;

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1303,8 +1298,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
};
});

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1358,8 +1352,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
isInTemporaryPosition.value = false;

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1413,8 +1406,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
isInTemporaryPosition.value = false;

runOnUI(animateToPosition)(
targetPosition,
scheduleOnUI(animateToPosition, targetPosition,
ANIMATION_SOURCE.USER,
0,
animationConfigs
Expand Down Expand Up @@ -1601,7 +1593,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
}

if (__DEV__) {
runOnJS(print)({
scheduleOnRN(print, {
component: 'BottomSheet',
method: 'useAnimatedReaction::OnSnapPointChange',
category: 'effect',
Expand Down Expand Up @@ -1669,7 +1661,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
: Math.abs(height - containerOffset.bottom);

if (__DEV__) {
runOnJS(print)({
scheduleOnRN(print, {
component: 'BottomSheet',
method: 'useAnimatedReaction::OnKeyboardStateChange',
category: 'effect',
Expand Down
6 changes: 3 additions & 3 deletions src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
Extrapolation,
interpolate,
runOnJS,
useAnimatedReaction,
useAnimatedStyle,
} from 'react-native-reanimated';
import { scheduleOnRN } from 'react-native-worklets';
import { useBottomSheet } from '../../hooks';
import {
DEFAULT_ACCESSIBILITY_HINT,
Expand Down Expand Up @@ -89,7 +89,7 @@ const BottomSheetBackdropComponent = ({
//#region tap gesture
const tapHandler = useMemo(() => {
const gesture = Gesture.Tap().onEnd(() => {
runOnJS(handleOnPress)();
scheduleOnRN(handleOnPress);
});
return gesture;
}, [handleOnPress]);
Expand Down Expand Up @@ -125,7 +125,7 @@ const BottomSheetBackdropComponent = ({
if (shouldDisableTouchability === previous) {
return;
}
runOnJS(handleContainerTouchability)(shouldDisableTouchability);
scheduleOnRN(handleContainerTouchability, shouldDisableTouchability);
},
[disappearsOnIndex]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ const BottomSheetDraggableViewComponent = ({
let gesture = Gesture.Pan()
.enabled(enableContentPanningGesture)
.shouldCancelWhenOutside(false)
.runOnJS(false)
.onStart(contentPanGestureHandler.handleOnStart)
.onChange(contentPanGestureHandler.handleOnChange)
.onEnd(contentPanGestureHandler.handleOnEnd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ function BottomSheetHandleContainerComponent({
let gesture = Gesture.Pan()
.enabled(enableHandlePanningGesture)
.shouldCancelWhenOutside(false)
.runOnJS(false)
.onStart(handlePanGestureHandler.handleOnStart)
.onChange(handlePanGestureHandler.handleOnChange)
.onEnd(handlePanGestureHandler.handleOnEnd)
Expand Down
8 changes: 5 additions & 3 deletions src/hooks/useAnimatedKeyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import {
Platform,
} from 'react-native';
import {
runOnUI,
useAnimatedReaction,
useSharedValue,
} from 'react-native-reanimated';
import { scheduleOnUI } from 'react-native-worklets';
import { KEYBOARD_STATUS, SCREEN_HEIGHT } from '../constants';
import type { KeyboardState } from '../types';

Expand Down Expand Up @@ -107,7 +107,8 @@ export const useAnimatedKeyboard = () => {
//#region effects
useEffect(() => {
const handleOnKeyboardShow = (event: KeyboardEvent) => {
runOnUI(handleKeyboardEvent)(
scheduleOnUI(
handleKeyboardEvent,
KEYBOARD_STATUS.SHOWN,
event.endCoordinates.height,
event.duration,
Expand All @@ -118,7 +119,8 @@ export const useAnimatedKeyboard = () => {
);
};
const handleOnKeyboardHide = (event: KeyboardEvent) => {
runOnUI(handleKeyboardEvent)(
scheduleOnUI(
handleKeyboardEvent,
KEYBOARD_STATUS.HIDDEN,
event.endCoordinates.height,
event.duration,
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useBottomSheetContentContainerStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
type ViewProps,
type ViewStyle,
} from 'react-native';
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
import { useAnimatedReaction } from 'react-native-reanimated';
import { scheduleOnRN } from 'react-native-worklets';
import { useBottomSheetInternal } from './useBottomSheetInternal';

export function useBottomSheetContentContainerStyle(
Expand Down Expand Up @@ -63,7 +64,7 @@ export function useBottomSheetContentContainerStyle(
if (!enableFooterMarginAdjustment) {
return;
}
runOnJS(setFooterHeight)(result);
scheduleOnRN(setFooterHeight, result);

if (Platform.OS === 'web') {
/**
Expand Down
7 changes: 4 additions & 3 deletions src/hooks/useGestureEventsHandlersDefault.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback } from 'react';
import { Keyboard, Platform } from 'react-native';
import { runOnJS, useSharedValue } from 'react-native-reanimated';
import { scheduleOnRN } from 'react-native-worklets';
import { useSharedValue } from 'react-native-reanimated';
import {
ANIMATION_SOURCE,
GESTURE_SOURCE,
Expand Down Expand Up @@ -75,7 +76,7 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
initialKeyboardStatus === KEYBOARD_STATUS.SHOWN
) {
initialKeyboardStatus = KEYBOARD_STATUS.HIDDEN;
runOnJS(dismissKeyboard)();
scheduleOnRN(dismissKeyboard);
}

// store current animated position
Expand Down Expand Up @@ -355,7 +356,7 @@ export const useGestureEventsHandlersDefault: GestureEventsHandlersHookType =
animatedKeyboardState.get().heightWithinContainer
)
) {
runOnJS(dismissKeyboard)();
scheduleOnRN(dismissKeyboard);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useGestureEventsHandlersDefault.web.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback } from 'react';
import { Keyboard, Platform } from 'react-native';
import { runOnJS, useSharedValue } from 'react-native-reanimated';
import { scheduleOnRN } from 'react-native-worklets';
import { useSharedValue } from 'react-native-reanimated';
import {
ANIMATION_SOURCE,
GESTURE_SOURCE,
Expand All @@ -27,7 +28,7 @@ const INITIAL_CONTEXT: GestureEventContextType = {
isScrollablePositionLocked: false,
};

const dismissKeyboardOnJs = runOnJS(Keyboard.dismiss);
const dismissKeyboardOnJs = () => scheduleOnRN(Keyboard.dismiss);

// biome-ignore lint: to be addressed!
const resetContext = (context: any) => {
Expand Down
Loading