UNPKG

@gorhom/bottom-sheet

Version:

A performant interactive bottom sheet with fully configurable options 🚀

343 lines (327 loc) 10.1 kB
import type React from 'react'; import type { Insets, StyleProp, ViewStyle } from 'react-native'; import type { PanGesture } from 'react-native-gesture-handler'; import type { AnimateStyle, ReduceMotion, SharedValue, WithSpringConfig, WithTimingConfig, } from 'react-native-reanimated'; import type { ANIMATION_SOURCE, KEYBOARD_BEHAVIOR, KEYBOARD_BLUR_BEHAVIOR, KEYBOARD_INPUT_MODE, SNAP_POINT_TYPE, } from '../../constants'; import type { GestureEventsHandlersHookType, NullableAccessibilityProps, } from '../../types'; import type { BottomSheetBackdropProps } from '../bottomSheetBackdrop'; import type { BottomSheetBackgroundProps } from '../bottomSheetBackground'; import type { BottomSheetFooterProps } from '../bottomSheetFooter'; import type { BottomSheetHandleProps } from '../bottomSheetHandle'; export interface BottomSheetProps extends BottomSheetAnimationConfigs, Partial<BottomSheetGestureProps>, Omit<NullableAccessibilityProps, 'accessibilityHint'> { //#region configuration /** * Initial snap point index, provide `-1` to initiate bottom sheet in closed state. * @type number * @default 0 */ index?: number; /** * 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>>; /** * Defines how violently sheet has to be stopped while over dragging. * @type number * @default 2.5 */ overDragResistanceFactor?: number; /** * Defines whether the bottom sheet is attached to the bottom or no. * @type boolean * @default false */ detached?: boolean; /** * Enable content panning gesture interaction. * @type boolean * @default true */ enableContentPanningGesture?: boolean; /** * Enable handle panning gesture interaction. * @type boolean * @default true */ enableHandlePanningGesture?: boolean; /** * Enable over drag for the sheet. * @type boolean * @default true */ enableOverDrag?: boolean; /** * Enable pan down gesture to close the sheet. * @type boolean * @default false */ enablePanDownToClose?: boolean; /** * Enable dynamic sizing for content view and scrollable content size. * @type boolean * @default true */ enableDynamicSizing?: boolean; /** * To start the sheet closed and snap to initial index when it's mounted. * @type boolean * @default true */ animateOnMount?: boolean; /** * To override the user reduce motion setting. * - `ReduceMotion.System`: if the `Reduce motion` accessibility setting is enabled on the device, disable the animation. * - `ReduceMotion.Always`: disable the animation, even if `Reduce motion` accessibility setting is not enabled. * - `ReduceMotion.Never`: enable the animation, even if `Reduce motion` accessibility setting is enabled. * @type ReduceMotion * @see https://docs.swmansion.com/react-native-reanimated/docs/guides/accessibility * @default ReduceMotion.System */ overrideReduceMotion?: ReduceMotion; //#endregion //#region layout /** * Container height helps to calculate the internal sheet layouts, * if `containerHeight` not provided, the library internally will calculate it, * however this will cause an extra re-rendering. * @type number | SharedValue<number>; */ containerHeight?: number | SharedValue<number>; /** * Container offset helps to accurately detect container offsets. * @type SharedValue<number>; */ containerOffset?: SharedValue<Required<Insets>>; /** * Top inset value helps to calculate percentage snap points values, * usually comes from `@react-navigation/stack` hook `useHeaderHeight` or * from `react-native-safe-area-context` hook `useSafeArea`. * @type number * @default 0 */ topInset?: number; /** * Bottom inset value helps to calculate percentage snap points values, * usually comes from `react-native-safe-area-context` hook `useSafeArea`. * @type number * @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 /** * Defines the keyboard appearance behavior. * @enum * - `interactive`: offset the sheet by the size of the keyboard. * - `extend`: extend the sheet to its maximum snap point. * - `fillParent`: extend the sheet to fill parent. * @type `interactive` | `extend` | `fillParent` * @default interactive */ keyboardBehavior?: keyof typeof KEYBOARD_BEHAVIOR; /** * Defines the keyboard blur behavior. * - `none`: do nothing. * - `restore`: restore sheet position. */ keyboardBlurBehavior?: keyof typeof KEYBOARD_BLUR_BEHAVIOR; /** * Enable blurring the keyboard when user start to drag the bottom sheet. * @default false */ enableBlurKeyboardOnGesture?: boolean; /** * Defines keyboard input mode for Android only. * @link {https://developer.android.com/guide/topics/manifest/activity-element#wsoft} * @type `adjustPan` | `adjustResize` * @default `adjustPan` */ android_keyboardInputMode?: keyof typeof KEYBOARD_INPUT_MODE; //#endregion //#region styles /** * View style to be applied to the container. * @type ViewStyle * @default undefined */ containerStyle?: StyleProp<ViewStyle>; /** * View style to be applied to the sheet container component, * it also could be an Animated Style. * @type AnimateStyle<ViewStyle> * @default undefined */ style?: StyleProp< AnimateStyle< Omit< ViewStyle, | 'flexDirection' | 'position' | 'top' | 'left' | 'bottom' | 'right' | 'opacity' | 'transform' > > >; /** * View style to be applied to the background component. * @type ViewStyle * @default undefined */ backgroundStyle?: StyleProp< Omit<ViewStyle, 'position' | 'top' | 'left' | 'bottom' | 'right'> >; /** * View style to be applied to the handle component. * @type ViewStyle * @default undefined */ handleStyle?: StyleProp<ViewStyle>; /** * View style to be applied to the handle indicator component. * @type ViewStyle * @default undefined */ handleIndicatorStyle?: StyleProp<ViewStyle>; //#endregion /** * Custom hook to provide pan gesture events handler, which will allow advance and * customize handling for pan gesture. * @warning this is an experimental feature and the hook signature can change without a major version bump. * @type GestureEventsHandlersHookType * @default useGestureEventsHandlersDefault */ gestureEventsHandlersHook?: GestureEventsHandlersHookType; //#region animated nodes /** * Animated value to be used as a callback of the position node internally. * @type SharedValue<number> */ animatedPosition?: SharedValue<number>; /** * Animated value to be used as a callback for the position index node internally. * @type SharedValue<number> */ animatedIndex?: SharedValue<number>; //#endregion //#region callbacks /** * Callback when the sheet position changed to a provided point. * * @type (index: number) => void; */ onChange?: (index: number, position: number, type: SNAP_POINT_TYPE) => void; /** * Callback when the sheet close. * * @type () => void; */ onClose?: () => void; /** * Callback when the sheet about to animate to a new position. * * @type (fromIndex: number, toIndex: number) => void; */ onAnimate?: (fromIndex: number, toIndex: number) => void; //#endregion //#region components /** * Component to be placed as a sheet handle. * @see {BottomSheetHandleProps} * @type React.FC\<BottomSheetHandleProps\> */ handleComponent?: React.FC<BottomSheetHandleProps> | null; /** * Component to be placed as a sheet backdrop. * @see {BottomSheetBackdropProps} * @type React.FC\<BottomSheetBackdropProps\> * @default null */ backdropComponent?: React.FC<BottomSheetBackdropProps> | null; /** * Component to be placed as a background. * @see {BottomSheetBackgroundProps} * @type React.FC\<BottomSheetBackgroundProps\> */ backgroundComponent?: React.FC<BottomSheetBackgroundProps> | null; /** * Component to be placed as a footer. * @see {BottomSheetFooterProps} * @type React.FC\<BottomSheetFooterProps\> */ footerComponent?: React.FC<BottomSheetFooterProps>; /** * A scrollable node or normal view. * @type React.ReactNode */ children: React.ReactNode; //#endregion //#region private /** * An indicator whether if the sheet running in a modal. * @type boolean */ $modal?: boolean; //#endregion } export interface BottomSheetAnimationConfigs { /** * Animation configs, this could be created by: * - `useBottomSheetSpringConfigs` * - `useBottomSheetTimingConfigs` * @type WithSpringConfig | WithTimingConfig */ animationConfigs?: WithSpringConfig | WithTimingConfig; } export type AnimateToPositionType = ( position: number, source: ANIMATION_SOURCE, velocity?: number, configs?: WithTimingConfig | WithSpringConfig ) => void; export type BottomSheetGestureProps = { activeOffsetX: Parameters<PanGesture['activeOffsetX']>[0]; activeOffsetY: Parameters<PanGesture['activeOffsetY']>[0]; failOffsetY: Parameters<PanGesture['failOffsetY']>[0]; failOffsetX: Parameters<PanGesture['failOffsetX']>[0]; simultaneousHandlers: Parameters< PanGesture['simultaneousWithExternalGesture'] >[0]; waitFor: Parameters<PanGesture['requireExternalGestureToFail']>[0]; };