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
21 changes: 3 additions & 18 deletions example/app/src/screens/advanced/DynamicSnapPointExample.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import BottomSheet, {
BottomSheetView,
useBottomSheetDynamicSnapPoints,
} from '@gorhom/bottom-sheet';
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Button } from '../../components/button';

const DynamicSnapPointExample = () => {
// state
const [count, setCount] = useState(0);
const initialSnapPoints = useMemo(() => ['CONTENT_HEIGHT'], []);

// hooks
const { bottom: safeBottomArea } = useSafeAreaInsets();
const bottomSheetRef = useRef<BottomSheet>(null);
const {
animatedHandleHeight,
animatedSnapPoints,
animatedContentHeight,
handleContentLayout,
} = useBottomSheetDynamicSnapPoints(initialSnapPoints);

// callbacks
const handleIncreaseContentPress = useCallback(() => {
Expand Down Expand Up @@ -59,16 +49,11 @@ const DynamicSnapPointExample = () => {
<Button label="Close" onPress={handleClosePress} />
<BottomSheet
ref={bottomSheetRef}
snapPoints={animatedSnapPoints}
handleHeight={animatedHandleHeight}
contentHeight={animatedContentHeight}
enableDynamicSizing={true}
enablePanDownToClose={true}
animateOnMount={true}
>
<BottomSheetView
style={contentContainerStyle}
onLayout={handleContentLayout}
>
<BottomSheetView style={contentContainerStyle}>
<Text style={styles.message}>
Could this sheet resize to its content height ?
</Text>
Expand Down
22 changes: 3 additions & 19 deletions example/app/src/screens/modal/DynamicSnapPointExample.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import {
BottomSheetModal,
BottomSheetView,
useBottomSheetDynamicSnapPoints,
} from '@gorhom/bottom-sheet';
import { BottomSheetModal, BottomSheetView } from '@gorhom/bottom-sheet';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Button } from '../../components/button';
import { withModalProvider } from './withModalProvider';

const DynamicSnapPointExample = () => {
// state
const [count, setCount] = useState(0);
const initialSnapPoints = useMemo(() => ['CONTENT_HEIGHT'], []);

// hooks
const { bottom: safeBottomArea } = useSafeAreaInsets();
const bottomSheetRef = useRef<BottomSheetModal>(null);
const {
animatedHandleHeight,
animatedSnapPoints,
animatedContentHeight,
handleContentLayout,
} = useBottomSheetDynamicSnapPoints(initialSnapPoints);

// callbacks
const handleIncreaseContentPress = useCallback(() => {
Expand Down Expand Up @@ -62,15 +51,10 @@ const DynamicSnapPointExample = () => {
<Button label="Dismiss" onPress={handleDismissPress} />
<BottomSheetModal
ref={bottomSheetRef}
snapPoints={animatedSnapPoints}
handleHeight={animatedHandleHeight}
contentHeight={animatedContentHeight}
enableDynamicSizing={true}
enablePanDownToClose={true}
>
<BottomSheetView
style={contentContainerStyle}
onLayout={handleContentLayout}
>
<BottomSheetView style={contentContainerStyle}>
<Text style={styles.message}>
Could this sheet modal resize to its content height ?
</Text>
Expand Down
46 changes: 31 additions & 15 deletions src/components/bottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import {
DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
INITIAL_CONTAINER_OFFSET,
INITIAL_VALUE,
DEFAULT_DYNAMIC_SIZING,
} from './constants';
import type { BottomSheetMethods, Insets } from '../../types';
import type { BottomSheetProps, AnimateToPositionType } from './types';
Expand Down Expand Up @@ -104,6 +105,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
enableHandlePanningGesture = DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
enableOverDrag = DEFAULT_ENABLE_OVER_DRAG,
enablePanDownToClose = DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
enableDynamicSizing = DEFAULT_DYNAMIC_SIZING,
overDragResistanceFactor = DEFAULT_OVER_DRAG_RESISTANCE_FACTOR,

// styles
Expand All @@ -128,6 +130,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
containerOffset: _providedContainerOffset,
topInset = 0,
bottomInset = 0,
maxDynamicContentSize,

// animated callback shared values
animatedPosition: _providedAnimatedPosition,
Expand Down Expand Up @@ -185,12 +188,14 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
_providedHandleHeight ?? INITIAL_HANDLE_HEIGHT
);
const animatedFooterHeight = useSharedValue(0);
const animatedContentHeight = useSharedValue(INITIAL_CONTAINER_HEIGHT);
const animatedSnapPoints = useNormalizedSnapPoints(
_providedSnapPoints,
animatedContainerHeight,
topInset,
bottomInset,
$modal
animatedContentHeight,
animatedHandleHeight,
enableDynamicSizing,
maxDynamicContentSize
);
const animatedHighestSnapPoint = useDerivedValue(
() => animatedSnapPoints.value[animatedSnapPoints.value.length - 1]
Expand Down Expand Up @@ -388,7 +393,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
return SCROLLABLE_STATE.LOCKED;
});
// dynamic
const animatedContentHeight = useDerivedValue(() => {
const animatedContentHeightMax = useDerivedValue(() => {
const keyboardHeightInContainer = animatedKeyboardHeightInContainer.value;
const handleHeight = Math.max(0, animatedHandleHeight.value);
let contentHeight = animatedSheetHeight.value - handleHeight;
Expand Down Expand Up @@ -807,9 +812,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
*/
const nextPosition = normalizeSnapPoint(
position,
animatedContainerHeight.value,
topInset,
bottomInset
animatedContainerHeight.value
);

/**
Expand Down Expand Up @@ -1054,6 +1057,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
const internalContextVariables = useMemo(
() => ({
enableContentPanningGesture,
enableDynamicSizing,
overDragResistanceFactor,
enableOverDrag,
enablePanDownToClose,
Expand Down Expand Up @@ -1121,6 +1125,7 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
overDragResistanceFactor,
enableOverDrag,
enablePanDownToClose,
enableDynamicSizing,
_providedSimultaneousHandlers,
_providedWaitFor,
_providedActiveOffsetX,
Expand Down Expand Up @@ -1175,6 +1180,17 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
[_providedStyle, containerAnimatedStyle]
);
const contentContainerAnimatedStyle = useAnimatedStyle(() => {
/**
* if dynamic sizing is enabled, and content height
* is still not set, then we exit method.
*/
if (
enableDynamicSizing &&
animatedContentHeight.value === INITIAL_CONTAINER_HEIGHT
) {
return {};
}

/**
* if content height was provided, then we skip setting
* calculated height.
Expand All @@ -1185,11 +1201,11 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(

return {
height: animate({
point: animatedContentHeight.value,
point: animatedContentHeightMax.value,
configs: _providedAnimationConfigs,
}),
};
}, [animatedContentHeight, _providedContentHeight]);
}, [animatedContentHeightMax, enableDynamicSizing, animatedContentHeight]);
const contentContainerStyle = useMemo(
() => [styles.contentContainer, contentContainerAnimatedStyle],
[contentContainerAnimatedStyle]
Expand Down Expand Up @@ -1664,18 +1680,18 @@ const BottomSheetComponent = forwardRef<BottomSheet, BottomSheetProps>(
// topInset,
// bottomInset,
animatedSheetState,
animatedScrollableState,
animatedScrollableOverrideState,
// animatedScrollableState,
// animatedScrollableOverrideState,
// isScrollableRefreshable,
// animatedScrollableContentOffsetY,
// keyboardState,
// animatedIndex,
// animatedCurrentIndex,
// animatedPosition,
// animatedContainerHeight,
// animatedSheetHeight,
// animatedHandleHeight,
// animatedContentHeight,
animatedContainerHeight,
animatedSheetHeight,
animatedHandleHeight,
animatedContentHeight,
// // keyboardHeight,
// isLayoutCalculated,
// isContentHeightFixed,
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 @@ -13,6 +13,7 @@ const DEFAULT_ENABLE_HANDLE_PANNING_GESTURE = true;
const DEFAULT_ENABLE_OVER_DRAG = true;
const DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE = false;
const DEFAULT_ANIMATE_ON_MOUNT = true;
const DEFAULT_DYNAMIC_SIZING = false;

// keyboard
const DEFAULT_KEYBOARD_BEHAVIOR = KEYBOARD_BEHAVIOR.interactive;
Expand All @@ -39,6 +40,7 @@ export {
DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
DEFAULT_ENABLE_OVER_DRAG,
DEFAULT_ENABLE_PAN_DOWN_TO_CLOSE,
DEFAULT_DYNAMIC_SIZING,
DEFAULT_ANIMATE_ON_MOUNT,
// keyboard
DEFAULT_KEYBOARD_BEHAVIOR,
Expand Down
18 changes: 17 additions & 1 deletion src/components/bottomSheet/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export interface BottomSheetProps
/**
* Points for the bottom sheet to snap to. It accepts array of number, string or mix.
* String values should be a percentage.
*
* ⚠️ This prop is required unless you set `enableDynamicSizing` to `true`.
* @example
* snapPoints={[200, 500]}
* snapPoints={[200, '%50']}
* snapPoints={['%100']}
* @type Array<string | number>
*/
snapPoints: Array<string | number> | SharedValue<Array<string | number>>;
snapPoints?: Array<string | number> | SharedValue<Array<string | number>>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything we can do with the type annotation to tell users that this is only not required when the enableDynamicSizing prop is true?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm not sure how could we achieve that, but if customers did not provide snap points and dynamic sizing prop, it will throw an exception https://github.com/gorhom/react-native-bottom-sheet/pull/1513/files#diff-620b7ea703632ea948b10134aaea17e0efd09781b64f587ecab4395812f9a3ccR26

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just in the JSDoc comment above I was thinking. Should show in most IDEs when you hover over the prop or while you're typing

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Eli-Nathan i have added an extra description in the latest commit

/**
* Defines how violently sheet has to be stopped while over dragging.
* @type number
Expand Down Expand Up @@ -85,6 +87,13 @@ export interface BottomSheetProps
* @default false
*/
enablePanDownToClose?: boolean;
/**
* Enable dynamic sizing for content view and scrollable
* content size.
* @type boolean
* @default false
*/
enableDynamicSizing?: boolean;
/**
* To start the sheet closed and snap to initial index when it's mounted.
* @type boolean
Expand Down Expand Up @@ -133,6 +142,13 @@ export interface BottomSheetProps
* @default 0
*/
bottomInset?: number;
/**
* Max dynamic content size height to limit the bottom sheet height
* from exceeding a provided size.
* @type number
* @default container height
*/
maxDynamicContentSize?: number;
//#endregion

//#region keyboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
useScrollHandler,
useScrollableSetter,
useBottomSheetInternal,
useStableCallback,
} from '../../hooks';
import {
GESTURE_SOURCE,
Expand Down Expand Up @@ -41,6 +42,7 @@ export function createBottomSheetScrollableComponent<T, P>(
onScroll,
onScrollBeginDrag,
onScrollEndDrag,
onContentSizeChange,
...rest
}: any = props;

Expand All @@ -61,6 +63,7 @@ export function createBottomSheetScrollableComponent<T, P>(
enableContentPanningGesture,
animatedFooterHeight,
animatedScrollableState,
animatedContentHeight,
} = useBottomSheetInternal();
//#endregion

Expand All @@ -77,6 +80,18 @@ export function createBottomSheetScrollableComponent<T, P>(
);
//#endregion

//#region callbacks
const handleContentSizeChange = useStableCallback(
(contentWidth: number, contentHeight: number) => {
animatedContentHeight.value = contentHeight;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this mean that I can't have additional content inside my bottom sheet if I'm using a scrollable component? The height of the sheet will be set to the height of the scrollable component instead of using the height of all the content in the sheet..


if (onContentSizeChange) {
onContentSizeChange(contentWidth, contentHeight);
}
}
);
//#endregion

//#region styles
const containerAnimatedStyle = useAnimatedStyle(
() => ({
Expand Down Expand Up @@ -124,6 +139,7 @@ export function createBottomSheetScrollableComponent<T, P>(
overScrollMode={overScrollMode}
keyboardDismissMode={keyboardDismissMode}
onScroll={scrollHandler}
onContentSizeChange={handleContentSizeChange}
style={containerStyle}
/>
</NativeViewGestureHandler>
Expand Down Expand Up @@ -174,6 +190,7 @@ export function createBottomSheetScrollableComponent<T, P>(
progressViewOffset={progressViewOffset}
refreshControl={refreshControl}
onScroll={scrollHandler}
onContentSizeChange={handleContentSizeChange}
style={containerStyle}
/>
</NativeViewGestureHandler>
Expand Down
Loading