UNPKG

@gorhom/bottom-sheet

Version:

A performant interactive bottom sheet with fully configurable options 🚀

188 lines (180 loc) • 6.58 kB
"use strict"; import React, { memo, useMemo } from 'react'; import Animated, { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated'; import { INITIAL_LAYOUT_VALUE, KEYBOARD_BEHAVIOR, KEYBOARD_STATUS } from '../../constants'; import { useBottomSheetInternal } from '../../hooks'; import { animate } from '../../utilities'; import BottomSheetDraggableView from '../bottomSheetDraggableView'; import './constants'; import { jsx as _jsx } from "react/jsx-runtime"; function BottomSheetContentComponent({ detached, animationConfigs, overrideReduceMotion, keyboardBehavior, accessible, accessibilityLabel, accessibilityHint, accessibilityRole, children }) { //#region hooks const { enableDynamicSizing, overDragResistanceFactor, enableContentPanningGesture, animatedPosition, animatedLayoutState, animatedDetentsState, animatedSheetHeight, animatedKeyboardState, isInTemporaryPosition } = useBottomSheetInternal(); //#endregion //#region variables const animatedContentHeightMax = useDerivedValue(() => { const { containerHeight, handleHeight } = animatedLayoutState.get(); /** * if container height is not yet calculated, then we exit the method */ if (containerHeight === INITIAL_LAYOUT_VALUE) { return 0; } const { status: keyboardStatus, heightWithinContainer: keyboardHeightWithinContainer } = animatedKeyboardState.get(); let contentHeight = animatedSheetHeight.get() - Math.max(0, handleHeight); switch (keyboardBehavior) { case KEYBOARD_BEHAVIOR.extend: if (keyboardStatus === KEYBOARD_STATUS.SHOWN) { contentHeight = contentHeight - keyboardHeightWithinContainer; } break; case KEYBOARD_BEHAVIOR.fillParent: if (!isInTemporaryPosition.get()) { break; } if (keyboardStatus === KEYBOARD_STATUS.SHOWN) { contentHeight = containerHeight - handleHeight - keyboardHeightWithinContainer; } else { contentHeight = containerHeight - handleHeight; } break; case KEYBOARD_BEHAVIOR.interactive: { if (!isInTemporaryPosition.get()) { break; } const contentWithKeyboardHeight = contentHeight + keyboardHeightWithinContainer; if (keyboardStatus === KEYBOARD_STATUS.SHOWN) { if (keyboardHeightWithinContainer + animatedSheetHeight.get() > containerHeight) { contentHeight = containerHeight - keyboardHeightWithinContainer - handleHeight; } } else if (contentWithKeyboardHeight + handleHeight > containerHeight) { contentHeight = containerHeight - handleHeight; } else { contentHeight = contentWithKeyboardHeight; } break; } } /** * before the container is measured, `contentHeight` value will be below zero, * which will lead to freeze the scrollable. * * @link (https://github.com/gorhom/react-native-bottom-sheet/issues/470) */ return Math.max(contentHeight, 0); }, [animatedLayoutState, animatedKeyboardState, animatedSheetHeight, isInTemporaryPosition, keyboardBehavior]); const animatedPaddingBottom = useDerivedValue(() => { const containerHeight = animatedLayoutState.get().containerHeight; /** * if container height is not yet calculated, then we exit the method */ if (containerHeight === INITIAL_LAYOUT_VALUE) { return 0; } const { highestDetentPosition } = animatedDetentsState.get(); const highestSnapPoint = Math.max(highestDetentPosition ?? 0, animatedPosition.get()); /** * added safe area to prevent the sheet from floating above * the bottom of the screen, when sheet being over dragged or * when the sheet is resized. */ const overDragSafePaddingBottom = Math.sqrt(highestSnapPoint - containerHeight * -1) * overDragResistanceFactor; let paddingBottom = overDragSafePaddingBottom; /** * if keyboard is open, then we try to add padding to prevent content * from being covered by the keyboard. */ const { status: keyboardStatus, heightWithinContainer: keyboardHeightWithinContainer } = animatedKeyboardState.get(); if (keyboardStatus === KEYBOARD_STATUS.SHOWN) { paddingBottom = overDragSafePaddingBottom + keyboardHeightWithinContainer; } return paddingBottom; }, [overDragResistanceFactor, animatedPosition, animatedLayoutState, animatedDetentsState, animatedKeyboardState]); //#endregion //#region styles const contentMaskContainerAnimatedStyle = useAnimatedStyle(() => { const { containerHeight, contentHeight } = animatedLayoutState.get(); /** * if container height is not yet calculated, then we exit the method */ if (containerHeight === INITIAL_LAYOUT_VALUE) { return {}; } /** * if dynamic sizing is enabled, and content height * is still not set, then we exit method. */ if (enableDynamicSizing && contentHeight === INITIAL_LAYOUT_VALUE) { return {}; } const paddingBottom = detached ? 0 : animatedPaddingBottom.get(); const height = animatedContentHeightMax.get() + paddingBottom; return { paddingBottom: animate({ point: paddingBottom, configs: animationConfigs, overrideReduceMotion }), height: animate({ point: height, configs: animationConfigs, overrideReduceMotion }) }; }, [overDragResistanceFactor, enableDynamicSizing, detached, animationConfigs, overrideReduceMotion, animatedLayoutState, animatedContentHeightMax, animatedLayoutState]); const contentContainerStyle = useMemo(() => [detached ? { overflow: 'visible' } : { overflow: 'hidden' }, contentMaskContainerAnimatedStyle], [contentMaskContainerAnimatedStyle, detached]); //#endregion //#region render const DraggableView = enableContentPanningGesture ? BottomSheetDraggableView : Animated.View; return /*#__PURE__*/_jsx(DraggableView, { accessible: accessible, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint, accessibilityRole: accessibilityRole, style: contentContainerStyle, children: children }); //#endregion } export const BottomSheetContent = /*#__PURE__*/memo(BottomSheetContentComponent); BottomSheetContent.displayName = 'BottomSheetContent'; //# sourceMappingURL=BottomSheetContent.js.map