@mustmove/bottom-sheet 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/mock.js +231 -0
  4. package/package.json +107 -0
  5. package/src/components/bottomSheet/BottomSheet.tsx +1885 -0
  6. package/src/components/bottomSheet/BottomSheetBody.tsx +44 -0
  7. package/src/components/bottomSheet/BottomSheetContent.tsx +261 -0
  8. package/src/components/bottomSheet/constants.ts +58 -0
  9. package/src/components/bottomSheet/index.ts +2 -0
  10. package/src/components/bottomSheet/styles.ts +11 -0
  11. package/src/components/bottomSheet/types.d.ts +358 -0
  12. package/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx +165 -0
  13. package/src/components/bottomSheetBackdrop/constants.ts +22 -0
  14. package/src/components/bottomSheetBackdrop/index.ts +2 -0
  15. package/src/components/bottomSheetBackdrop/styles.ts +8 -0
  16. package/src/components/bottomSheetBackdrop/types.d.ts +58 -0
  17. package/src/components/bottomSheetBackground/BottomSheetBackground.tsx +20 -0
  18. package/src/components/bottomSheetBackground/BottomSheetBackgroundContainer.tsx +35 -0
  19. package/src/components/bottomSheetBackground/index.ts +2 -0
  20. package/src/components/bottomSheetBackground/styles.ts +9 -0
  21. package/src/components/bottomSheetBackground/types.d.ts +12 -0
  22. package/src/components/bottomSheetDebugView/BottomSheetDebugView.tsx +26 -0
  23. package/src/components/bottomSheetDebugView/ReText.tsx +72 -0
  24. package/src/components/bottomSheetDebugView/ReText.webx.tsx +55 -0
  25. package/src/components/bottomSheetDebugView/index.ts +1 -0
  26. package/src/components/bottomSheetDebugView/styles.ts +19 -0
  27. package/src/components/bottomSheetDebugView/styles.web.ts +20 -0
  28. package/src/components/bottomSheetDraggableView/BottomSheetDraggableView.tsx +123 -0
  29. package/src/components/bottomSheetDraggableView/index.ts +1 -0
  30. package/src/components/bottomSheetDraggableView/types.d.ts +9 -0
  31. package/src/components/bottomSheetFooter/BottomSheetFooter.tsx +119 -0
  32. package/src/components/bottomSheetFooter/BottomSheetFooterContainer.tsx +43 -0
  33. package/src/components/bottomSheetFooter/index.ts +3 -0
  34. package/src/components/bottomSheetFooter/styles.ts +12 -0
  35. package/src/components/bottomSheetFooter/types.d.ts +41 -0
  36. package/src/components/bottomSheetGestureHandlersProvider/BottomSheetGestureHandlersProvider.tsx +69 -0
  37. package/src/components/bottomSheetGestureHandlersProvider/index.ts +1 -0
  38. package/src/components/bottomSheetGestureHandlersProvider/types.d.ts +8 -0
  39. package/src/components/bottomSheetHandle/BottomSheetHandle.tsx +51 -0
  40. package/src/components/bottomSheetHandle/BottomSheetHandleContainer.tsx +187 -0
  41. package/src/components/bottomSheetHandle/constants.ts +12 -0
  42. package/src/components/bottomSheetHandle/index.ts +6 -0
  43. package/src/components/bottomSheetHandle/styles.ts +23 -0
  44. package/src/components/bottomSheetHandle/types.d.ts +52 -0
  45. package/src/components/bottomSheetHostingContainer/BottomSheetHostingContainer.tsx +130 -0
  46. package/src/components/bottomSheetHostingContainer/index.ts +2 -0
  47. package/src/components/bottomSheetHostingContainer/styles.ts +5 -0
  48. package/src/components/bottomSheetHostingContainer/styles.web.ts +11 -0
  49. package/src/components/bottomSheetHostingContainer/types.d.ts +17 -0
  50. package/src/components/bottomSheetModal/BottomSheetModal.tsx +482 -0
  51. package/src/components/bottomSheetModal/constants.ts +4 -0
  52. package/src/components/bottomSheetModal/index.ts +6 -0
  53. package/src/components/bottomSheetModal/types.d.ts +67 -0
  54. package/src/components/bottomSheetModalProvider/BottomSheetModalProvider.tsx +211 -0
  55. package/src/components/bottomSheetModalProvider/index.ts +1 -0
  56. package/src/components/bottomSheetModalProvider/types.d.ts +12 -0
  57. package/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx +84 -0
  58. package/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.tsx +1 -0
  59. package/src/components/bottomSheetRefreshControl/index.ts +20 -0
  60. package/src/components/bottomSheetScrollable/BottomSheetDraggableScrollable.tsx +23 -0
  61. package/src/components/bottomSheetScrollable/BottomSheetFlashList.tsx +88 -0
  62. package/src/components/bottomSheetScrollable/BottomSheetFlashList.web.tsx +1 -0
  63. package/src/components/bottomSheetScrollable/BottomSheetFlatList.tsx +26 -0
  64. package/src/components/bottomSheetScrollable/BottomSheetScrollView.tsx +27 -0
  65. package/src/components/bottomSheetScrollable/BottomSheetSectionList.tsx +29 -0
  66. package/src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx +27 -0
  67. package/src/components/bottomSheetScrollable/ScrollableContainer.android.tsx +55 -0
  68. package/src/components/bottomSheetScrollable/ScrollableContainer.tsx +22 -0
  69. package/src/components/bottomSheetScrollable/ScrollableContainer.web.tsx +102 -0
  70. package/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx +153 -0
  71. package/src/components/bottomSheetScrollable/index.ts +15 -0
  72. package/src/components/bottomSheetScrollable/styles.ts +8 -0
  73. package/src/components/bottomSheetScrollable/types.d.ts +280 -0
  74. package/src/components/bottomSheetScrollable/useBottomSheetContentSizeSetter.ts +32 -0
  75. package/src/components/bottomSheetTextInput/BottomSheetTextInput.tsx +127 -0
  76. package/src/components/bottomSheetTextInput/index.ts +2 -0
  77. package/src/components/bottomSheetTextInput/types.ts +3 -0
  78. package/src/components/bottomSheetView/BottomSheetView.tsx +93 -0
  79. package/src/components/bottomSheetView/index.ts +1 -0
  80. package/src/components/bottomSheetView/styles.ts +10 -0
  81. package/src/components/bottomSheetView/types.d.ts +24 -0
  82. package/src/components/touchables/Touchables.ios.tsx +5 -0
  83. package/src/components/touchables/Touchables.tsx +5 -0
  84. package/src/components/touchables/index.ts +20 -0
  85. package/src/constants.ts +159 -0
  86. package/src/contexts/external.ts +8 -0
  87. package/src/contexts/gesture.ts +13 -0
  88. package/src/contexts/index.ts +15 -0
  89. package/src/contexts/internal.ts +65 -0
  90. package/src/contexts/modal/external.ts +11 -0
  91. package/src/contexts/modal/internal.ts +25 -0
  92. package/src/hooks/index.ts +29 -0
  93. package/src/hooks/useAnimatedDetents.ts +119 -0
  94. package/src/hooks/useAnimatedKeyboard.ts +174 -0
  95. package/src/hooks/useAnimatedLayout.ts +109 -0
  96. package/src/hooks/useBottomSheet.ts +12 -0
  97. package/src/hooks/useBottomSheetContentContainerStyle.ts +88 -0
  98. package/src/hooks/useBottomSheetGestureHandlers.ts +12 -0
  99. package/src/hooks/useBottomSheetInternal.ts +25 -0
  100. package/src/hooks/useBottomSheetModal.ts +12 -0
  101. package/src/hooks/useBottomSheetModalInternal.ts +25 -0
  102. package/src/hooks/useBottomSheetScrollableCreator.tsx +60 -0
  103. package/src/hooks/useBottomSheetSpringConfigs.ts +11 -0
  104. package/src/hooks/useBottomSheetTimingConfigs.ts +36 -0
  105. package/src/hooks/useBoundingClientRect.ts +77 -0
  106. package/src/hooks/useGestureEventsHandlersDefault.tsx +436 -0
  107. package/src/hooks/useGestureEventsHandlersDefault.web.tsx +418 -0
  108. package/src/hooks/useGestureHandler.ts +90 -0
  109. package/src/hooks/usePropsValidator.ts +108 -0
  110. package/src/hooks/useReactiveSharedValue.ts +45 -0
  111. package/src/hooks/useScrollEventsHandlersDefault.ts +167 -0
  112. package/src/hooks/useScrollHandler.ts +72 -0
  113. package/src/hooks/useScrollHandler.web.ts +181 -0
  114. package/src/hooks/useScrollable.ts +131 -0
  115. package/src/hooks/useScrollableSetter.ts +56 -0
  116. package/src/hooks/useStableCallback.ts +26 -0
  117. package/src/index.ts +79 -0
  118. package/src/types.d.ts +336 -0
  119. package/src/utilities/animate.ts +56 -0
  120. package/src/utilities/clamp.ts +8 -0
  121. package/src/utilities/easingExp.ts +10 -0
  122. package/src/utilities/findNodeHandle.ts +1 -0
  123. package/src/utilities/findNodeHandle.web.ts +33 -0
  124. package/src/utilities/getKeyboardAnimationConfigs.ts +44 -0
  125. package/src/utilities/getRefNativeTag.web.ts +6 -0
  126. package/src/utilities/id.ts +6 -0
  127. package/src/utilities/index.ts +7 -0
  128. package/src/utilities/isFabricInstalled.ts +9 -0
  129. package/src/utilities/logger.ts +55 -0
  130. package/src/utilities/noop.ts +7 -0
  131. package/src/utilities/normalizeSnapPoint.ts +17 -0
  132. package/src/utilities/snapPoint.ts +11 -0
  133. package/src/utilities/validateSnapPoint.ts +20 -0
@@ -0,0 +1,358 @@
1
+ import type React from 'react';
2
+ import type { Insets, StyleProp, View, ViewStyle } from 'react-native';
3
+ import type { PanGesture } from 'react-native-gesture-handler';
4
+ import type {
5
+ AnimateStyle,
6
+ ReduceMotion,
7
+ SharedValue,
8
+ WithSpringConfig,
9
+ WithTimingConfig,
10
+ } from 'react-native-reanimated';
11
+ import type {
12
+ ANIMATION_SOURCE,
13
+ KEYBOARD_BEHAVIOR,
14
+ KEYBOARD_BLUR_BEHAVIOR,
15
+ KEYBOARD_INPUT_MODE,
16
+ SNAP_POINT_TYPE,
17
+ } from '../../constants';
18
+ import type {
19
+ ContainerLayoutState,
20
+ GestureEventsHandlersHookType,
21
+ NullableAccessibilityProps,
22
+ } from '../../types';
23
+ import type { BottomSheetBackdropProps } from '../bottomSheetBackdrop';
24
+ import type { BottomSheetBackgroundProps } from '../bottomSheetBackground';
25
+ import type { BottomSheetFooterProps } from '../bottomSheetFooter';
26
+ import type { BottomSheetHandleProps } from '../bottomSheetHandle';
27
+
28
+ export interface BottomSheetProps
29
+ extends BottomSheetAnimationConfigs,
30
+ Partial<BottomSheetGestureProps>,
31
+ Omit<NullableAccessibilityProps, 'accessibilityHint'> {
32
+ //#region configuration
33
+ /**
34
+ * Initial snap point index, provide `-1` to initiate bottom sheet in closed state.
35
+ * @type number
36
+ * @default 0
37
+ */
38
+ index?: number;
39
+ /**
40
+ * Points for the bottom sheet to snap to. It accepts array of number, string or mix.
41
+ * String values should be a percentage.
42
+ *
43
+ * ⚠️ This prop is required unless you set `enableDynamicSizing` to `true`.
44
+ * @example
45
+ * snapPoints={[200, 500]}
46
+ * snapPoints={[200, '%50']}
47
+ * snapPoints={['%100']}
48
+ * @type Array<string | number>
49
+ */
50
+ snapPoints?: Array<string | number> | SharedValue<Array<string | number>>;
51
+ /**
52
+ * Defines how violently sheet has to be stopped while over dragging.
53
+ * @type number
54
+ * @default 2.5
55
+ */
56
+ overDragResistanceFactor?: number;
57
+ /**
58
+ * Defines whether the bottom sheet is attached to the bottom or no.
59
+ * @type boolean
60
+ * @default false
61
+ */
62
+ detached?: boolean;
63
+ /**
64
+ * Enable content panning gesture interaction.
65
+ * @type boolean
66
+ * @default true
67
+ */
68
+ enableContentPanningGesture?: boolean;
69
+ /**
70
+ * Enable handle panning gesture interaction.
71
+ * @type boolean
72
+ * @default true
73
+ */
74
+ enableHandlePanningGesture?: boolean;
75
+ /**
76
+ * Enable over drag for the sheet.
77
+ * @type boolean
78
+ * @default true
79
+ */
80
+ enableOverDrag?: boolean;
81
+ /**
82
+ * Enable pan down gesture to close the sheet.
83
+ * @type boolean
84
+ * @default false
85
+ */
86
+ enablePanDownToClose?: boolean;
87
+ /**
88
+ * Enable dynamic sizing for content view and scrollable content size.
89
+ * @type boolean
90
+ * @default true
91
+ */
92
+ enableDynamicSizing?: boolean;
93
+ /**
94
+ * To start the sheet closed and snap to initial index when it's mounted.
95
+ * @type boolean
96
+ * @default true
97
+ */
98
+ animateOnMount?: boolean;
99
+ /**
100
+ * To override the user reduce motion setting.
101
+ * - `ReduceMotion.System`: if the `Reduce motion` accessibility setting is enabled on the device, disable the animation.
102
+ * - `ReduceMotion.Always`: disable the animation, even if `Reduce motion` accessibility setting is not enabled.
103
+ * - `ReduceMotion.Never`: enable the animation, even if `Reduce motion` accessibility setting is enabled.
104
+ * @type ReduceMotion
105
+ * @see https://docs.swmansion.com/react-native-reanimated/docs/guides/accessibility
106
+ * @default ReduceMotion.System
107
+ */
108
+ overrideReduceMotion?: ReduceMotion;
109
+ //#endregion
110
+
111
+ //#region layout
112
+ /**
113
+ * Container height helps to calculate the internal sheet layouts,
114
+ * if `containerHeight` not provided, the library internally will calculate it,
115
+ * however this will cause an extra re-rendering.
116
+ * @type number | SharedValue<number>;
117
+ * @deprecated please use `containerLayoutState` instead.
118
+ */
119
+ containerHeight?: number | SharedValue<number>;
120
+ /**
121
+ * Container offset helps to accurately detect container offsets.
122
+ * @type SharedValue<number>;
123
+ * @deprecated please use `containerLayoutState` instead.
124
+ */
125
+ containerOffset?: SharedValue<Required<Insets>>;
126
+ /**
127
+ * Container layout state, this is used to calculate the container height and offsets.
128
+ * If not provided, the library will use the default container layout state.
129
+ * @type SharedValue<ContainerLayoutState>
130
+ * @default undefined
131
+ */
132
+ containerLayoutState?: SharedValue<ContainerLayoutState>;
133
+ /**
134
+ * Top inset value helps to calculate percentage snap points values,
135
+ * usually comes from `@react-navigation/stack` hook `useHeaderHeight` or
136
+ * from `react-native-safe-area-context` hook `useSafeArea`.
137
+ * @type number
138
+ * @default 0
139
+ */
140
+ topInset?: number;
141
+ /**
142
+ * Bottom inset value helps to calculate percentage snap points values,
143
+ * usually comes from `react-native-safe-area-context` hook `useSafeArea`.
144
+ * @type number
145
+ * @default 0
146
+ */
147
+ bottomInset?: number;
148
+ /**
149
+ * Max dynamic content size height to limit the bottom sheet height
150
+ * from exceeding a provided size.
151
+ * @type number
152
+ * @default container height
153
+ */
154
+ maxDynamicContentSize?: number;
155
+ //#endregion
156
+
157
+ //#region keyboard
158
+ /**
159
+ * Defines the keyboard appearance behavior.
160
+ * @enum
161
+ * - `interactive`: offset the sheet by the size of the keyboard.
162
+ * - `extend`: extend the sheet to its maximum snap point.
163
+ * - `fillParent`: extend the sheet to fill parent.
164
+ * @type `interactive` | `extend` | `fillParent`
165
+ * @default interactive
166
+ */
167
+ keyboardBehavior?: keyof typeof KEYBOARD_BEHAVIOR;
168
+ /**
169
+ * Defines the keyboard blur behavior.
170
+ * - `none`: do nothing.
171
+ * - `restore`: restore sheet position.
172
+ */
173
+ keyboardBlurBehavior?: keyof typeof KEYBOARD_BLUR_BEHAVIOR;
174
+ /**
175
+ * Enable blurring the keyboard when user start to drag the bottom sheet.
176
+ * @default false
177
+ */
178
+ enableBlurKeyboardOnGesture?: boolean;
179
+ /**
180
+ * Defines keyboard input mode for Android only.
181
+ * @link {https://developer.android.com/guide/topics/manifest/activity-element#wsoft}
182
+ * @type `adjustPan` | `adjustResize`
183
+ * @default `adjustPan`
184
+ */
185
+ android_keyboardInputMode?: keyof typeof KEYBOARD_INPUT_MODE;
186
+
187
+ //#endregion
188
+
189
+ //#region styles
190
+ /**
191
+ * View style to be applied to the container.
192
+ * @type ViewStyle
193
+ * @default undefined
194
+ */
195
+ containerStyle?: StyleProp<ViewStyle>;
196
+ /**
197
+ * View style to be applied to the sheet container component,
198
+ * it also could be an Animated Style.
199
+ * @type AnimateStyle<ViewStyle>
200
+ * @default undefined
201
+ */
202
+ style?: StyleProp<
203
+ AnimateStyle<
204
+ Omit<
205
+ ViewStyle,
206
+ | 'flexDirection'
207
+ | 'position'
208
+ | 'top'
209
+ | 'left'
210
+ | 'bottom'
211
+ | 'right'
212
+ | 'opacity'
213
+ | 'transform'
214
+ >
215
+ >
216
+ >;
217
+ /**
218
+ * View style to be applied to the background component.
219
+ * @type ViewStyle
220
+ * @default undefined
221
+ */
222
+ backgroundStyle?: StyleProp<
223
+ Omit<ViewStyle, 'position' | 'top' | 'left' | 'bottom' | 'right'>
224
+ >;
225
+ /**
226
+ * View style to be applied to the handle component.
227
+ * @type ViewStyle
228
+ * @default undefined
229
+ */
230
+ handleStyle?: StyleProp<ViewStyle>;
231
+ /**
232
+ * View style to be applied to the handle indicator component.
233
+ * @type ViewStyle
234
+ * @default undefined
235
+ */
236
+ handleIndicatorStyle?: StyleProp<ViewStyle>;
237
+ //#endregion
238
+
239
+ /**
240
+ * Custom hook to provide pan gesture events handler, which will allow advance and
241
+ * customize handling for pan gesture.
242
+ * @warning this is an experimental feature and the hook signature can change without a major version bump.
243
+ * @type GestureEventsHandlersHookType
244
+ * @default useGestureEventsHandlersDefault
245
+ */
246
+ gestureEventsHandlersHook?: GestureEventsHandlersHookType;
247
+
248
+ //#region animated nodes
249
+ /**
250
+ * Animated value to be used as a callback of the position node internally.
251
+ * @type SharedValue<number>
252
+ */
253
+ animatedPosition?: SharedValue<number>;
254
+ /**
255
+ * Animated value to be used as a callback for the position index node internally.
256
+ * @type SharedValue<number>
257
+ */
258
+ animatedIndex?: SharedValue<number>;
259
+ //#endregion
260
+
261
+ //#region callbacks
262
+ /**
263
+ * Callback when the sheet position changed to a provided point.
264
+ *
265
+ * @type (index: number) => void;
266
+ */
267
+ onChange?: (index: number, position: number, type: SNAP_POINT_TYPE) => void;
268
+ /**
269
+ * Callback when the sheet close.
270
+ *
271
+ * @type () => void;
272
+ */
273
+ onClose?: () => void;
274
+ /**
275
+ * Callback when the sheet about to animate to a new position.
276
+ *
277
+ * @type (fromIndex: number, toIndex: number, fromPosition: number, toPosition: number) => void;
278
+ */
279
+ onAnimate?: (
280
+ fromIndex: number,
281
+ toIndex: number,
282
+ fromPosition: number,
283
+ toPosition: number
284
+ ) => void;
285
+ //#endregion
286
+
287
+ //#region components
288
+ /**
289
+ * Component to be placed as a sheet handle.
290
+ * @see {BottomSheetHandleProps}
291
+ * @type React.FC\<BottomSheetHandleProps\>
292
+ */
293
+ handleComponent?: React.FC<BottomSheetHandleProps> | null;
294
+
295
+ /**
296
+ * Component to be placed as a sheet backdrop.
297
+ * @see {BottomSheetBackdropProps}
298
+ * @type React.FC\<BottomSheetBackdropProps\>
299
+ * @default undefined
300
+ */
301
+ backdropComponent?: React.FC<BottomSheetBackdropProps>;
302
+ /**
303
+ * Component to be placed as a background.
304
+ * @see {BottomSheetBackgroundProps}
305
+ * @type React.FC\<BottomSheetBackgroundProps\>
306
+ */
307
+ backgroundComponent?: React.FC<BottomSheetBackgroundProps> | null;
308
+ /**
309
+ * Component to be placed as a footer.
310
+ * @see {BottomSheetFooterProps}
311
+ * @type React.FC\<BottomSheetFooterProps\>
312
+ */
313
+ footerComponent?: React.FC<BottomSheetFooterProps>;
314
+ /**
315
+ * A scrollable node or normal view.
316
+ * @type React.ReactNode
317
+ */
318
+ children: React.ReactNode;
319
+ //#endregion
320
+
321
+ //#region private
322
+ /**
323
+ * An indicator whether if the sheet running in a modal.
324
+ * @type boolean
325
+ */
326
+ $modal?: boolean;
327
+ //#endregion
328
+ }
329
+
330
+ export interface BottomSheetAnimationConfigs {
331
+ /**
332
+ * Animation configs, this could be created by:
333
+ * - `useBottomSheetSpringConfigs`
334
+ * - `useBottomSheetTimingConfigs`
335
+ * @type WithSpringConfig | WithTimingConfig
336
+ */
337
+ animationConfigs?: WithSpringConfig | WithTimingConfig;
338
+ }
339
+
340
+ export type AnimateToPositionType = (
341
+ position: number,
342
+ source: ANIMATION_SOURCE,
343
+ velocity?: number,
344
+ configs?: WithTimingConfig | WithSpringConfig
345
+ ) => void;
346
+
347
+ export type BottomSheetGestureProps = {
348
+ activeOffsetX: Parameters<PanGesture['activeOffsetX']>[0];
349
+ activeOffsetY: Parameters<PanGesture['activeOffsetY']>[0];
350
+
351
+ failOffsetY: Parameters<PanGesture['failOffsetY']>[0];
352
+ failOffsetX: Parameters<PanGesture['failOffsetX']>[0];
353
+
354
+ simultaneousHandlers: Parameters<
355
+ PanGesture['simultaneousWithExternalGesture']
356
+ >[0];
357
+ waitFor: Parameters<PanGesture['requireExternalGestureToFail']>[0];
358
+ };
@@ -0,0 +1,165 @@
1
+ import React, {
2
+ memo,
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ } from 'react';
9
+ import type { ViewProps } from 'react-native';
10
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
11
+ import Animated, {
12
+ interpolate,
13
+ useAnimatedStyle,
14
+ useAnimatedReaction,
15
+ runOnJS,
16
+ Extrapolation,
17
+ } from 'react-native-reanimated';
18
+ import { useBottomSheet } from '../../hooks';
19
+ import {
20
+ DEFAULT_ACCESSIBILITY_HINT,
21
+ DEFAULT_ACCESSIBILITY_LABEL,
22
+ DEFAULT_ACCESSIBILITY_ROLE,
23
+ DEFAULT_ACCESSIBLE,
24
+ DEFAULT_APPEARS_ON_INDEX,
25
+ DEFAULT_DISAPPEARS_ON_INDEX,
26
+ DEFAULT_ENABLE_TOUCH_THROUGH,
27
+ DEFAULT_OPACITY,
28
+ DEFAULT_PRESS_BEHAVIOR,
29
+ } from './constants';
30
+ import { styles } from './styles';
31
+ import type { BottomSheetDefaultBackdropProps } from './types';
32
+
33
+ const BottomSheetBackdropComponent = ({
34
+ animatedIndex,
35
+ opacity: _providedOpacity,
36
+ appearsOnIndex: _providedAppearsOnIndex,
37
+ disappearsOnIndex: _providedDisappearsOnIndex,
38
+ enableTouchThrough: _providedEnableTouchThrough,
39
+ pressBehavior = DEFAULT_PRESS_BEHAVIOR,
40
+ onPress,
41
+ style,
42
+ children,
43
+ accessible: _providedAccessible = DEFAULT_ACCESSIBLE,
44
+ accessibilityRole: _providedAccessibilityRole = DEFAULT_ACCESSIBILITY_ROLE,
45
+ accessibilityLabel: _providedAccessibilityLabel = DEFAULT_ACCESSIBILITY_LABEL,
46
+ accessibilityHint: _providedAccessibilityHint = DEFAULT_ACCESSIBILITY_HINT,
47
+ }: BottomSheetDefaultBackdropProps) => {
48
+ //#region hooks
49
+ const { snapToIndex, close } = useBottomSheet();
50
+ const isMounted = useRef(false);
51
+ //#endregion
52
+
53
+ //#region defaults
54
+ const opacity = _providedOpacity ?? DEFAULT_OPACITY;
55
+ const appearsOnIndex = _providedAppearsOnIndex ?? DEFAULT_APPEARS_ON_INDEX;
56
+ const disappearsOnIndex =
57
+ _providedDisappearsOnIndex ?? DEFAULT_DISAPPEARS_ON_INDEX;
58
+ const enableTouchThrough =
59
+ _providedEnableTouchThrough ?? DEFAULT_ENABLE_TOUCH_THROUGH;
60
+ //#endregion
61
+
62
+ //#region variables
63
+ const [pointerEvents, setPointerEvents] = useState<
64
+ ViewProps['pointerEvents']
65
+ >(enableTouchThrough ? 'none' : 'auto');
66
+ //#endregion
67
+
68
+ //#region callbacks
69
+ const handleOnPress = useCallback(() => {
70
+ onPress?.();
71
+
72
+ if (pressBehavior === 'close') {
73
+ close();
74
+ } else if (pressBehavior === 'collapse') {
75
+ snapToIndex(disappearsOnIndex as number);
76
+ } else if (typeof pressBehavior === 'number') {
77
+ snapToIndex(pressBehavior);
78
+ }
79
+ }, [snapToIndex, close, disappearsOnIndex, pressBehavior, onPress]);
80
+ const handleContainerTouchability = useCallback(
81
+ (shouldDisableTouchability: boolean) => {
82
+ isMounted.current &&
83
+ setPointerEvents(shouldDisableTouchability ? 'none' : 'auto');
84
+ },
85
+ []
86
+ );
87
+ //#endregion
88
+
89
+ //#region tap gesture
90
+ const tapHandler = useMemo(() => {
91
+ const gesture = Gesture.Tap().onEnd(() => {
92
+ runOnJS(handleOnPress)();
93
+ });
94
+ return gesture;
95
+ }, [handleOnPress]);
96
+ //#endregion
97
+
98
+ //#region styles
99
+ const containerAnimatedStyle = useAnimatedStyle(
100
+ () => ({
101
+ opacity: interpolate(
102
+ animatedIndex.value,
103
+ [-1, disappearsOnIndex, appearsOnIndex],
104
+ [0, 0, opacity],
105
+ Extrapolation.CLAMP
106
+ ),
107
+ }),
108
+ [animatedIndex, appearsOnIndex, disappearsOnIndex, opacity]
109
+ );
110
+ const containerStyle = useMemo(
111
+ () => [styles.backdrop, style, containerAnimatedStyle],
112
+ [style, containerAnimatedStyle]
113
+ );
114
+ //#endregion
115
+
116
+ //#region effects
117
+ useAnimatedReaction(
118
+ () => animatedIndex.value <= disappearsOnIndex,
119
+ (shouldDisableTouchability, previous) => {
120
+ if (shouldDisableTouchability === previous) {
121
+ return;
122
+ }
123
+ runOnJS(handleContainerTouchability)(shouldDisableTouchability);
124
+ },
125
+ [disappearsOnIndex]
126
+ );
127
+
128
+ // addressing updating the state after unmounting.
129
+ // [link](https://github.com/gorhom/react-native-bottom-sheet/issues/1376)
130
+ useEffect(() => {
131
+ isMounted.current = true;
132
+ return () => {
133
+ isMounted.current = false;
134
+ };
135
+ }, []);
136
+ //#endregion
137
+
138
+ const AnimatedView = (
139
+ <Animated.View
140
+ style={containerStyle}
141
+ pointerEvents={pointerEvents}
142
+ accessible={_providedAccessible ?? undefined}
143
+ accessibilityRole={_providedAccessibilityRole ?? undefined}
144
+ accessibilityLabel={_providedAccessibilityLabel ?? undefined}
145
+ accessibilityHint={
146
+ _providedAccessibilityHint
147
+ ? _providedAccessibilityHint
148
+ : `Tap to ${
149
+ typeof pressBehavior === 'string' ? pressBehavior : 'move'
150
+ } the Bottom Sheet`
151
+ }
152
+ >
153
+ {children}
154
+ </Animated.View>
155
+ );
156
+
157
+ return pressBehavior !== 'none' ? (
158
+ <GestureDetector gesture={tapHandler}>{AnimatedView}</GestureDetector>
159
+ ) : (
160
+ AnimatedView
161
+ );
162
+ };
163
+
164
+ export const BottomSheetBackdrop = memo(BottomSheetBackdropComponent);
165
+ BottomSheetBackdrop.displayName = 'BottomSheetBackdrop';
@@ -0,0 +1,22 @@
1
+ const DEFAULT_OPACITY = 0.5;
2
+ const DEFAULT_APPEARS_ON_INDEX = 1;
3
+ const DEFAULT_DISAPPEARS_ON_INDEX = 0;
4
+ const DEFAULT_ENABLE_TOUCH_THROUGH = false;
5
+ const DEFAULT_PRESS_BEHAVIOR = 'close' as const;
6
+
7
+ const DEFAULT_ACCESSIBLE = true;
8
+ const DEFAULT_ACCESSIBILITY_ROLE = 'button';
9
+ const DEFAULT_ACCESSIBILITY_LABEL = 'Bottom sheet backdrop';
10
+ const DEFAULT_ACCESSIBILITY_HINT = 'Tap to close the bottom sheet';
11
+
12
+ export {
13
+ DEFAULT_OPACITY,
14
+ DEFAULT_APPEARS_ON_INDEX,
15
+ DEFAULT_DISAPPEARS_ON_INDEX,
16
+ DEFAULT_ENABLE_TOUCH_THROUGH,
17
+ DEFAULT_PRESS_BEHAVIOR,
18
+ DEFAULT_ACCESSIBLE,
19
+ DEFAULT_ACCESSIBILITY_ROLE,
20
+ DEFAULT_ACCESSIBILITY_LABEL,
21
+ DEFAULT_ACCESSIBILITY_HINT,
22
+ };
@@ -0,0 +1,2 @@
1
+ export { BottomSheetBackdrop } from './BottomSheetBackdrop';
2
+ export type { BottomSheetBackdropProps } from './types';
@@ -0,0 +1,8 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export const styles = StyleSheet.create({
4
+ backdrop: {
5
+ ...StyleSheet.absoluteFillObject,
6
+ backgroundColor: 'black',
7
+ },
8
+ });
@@ -0,0 +1,58 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ViewProps } from 'react-native';
3
+ import type {
4
+ BottomSheetVariables,
5
+ NullableAccessibilityProps,
6
+ } from '../../types';
7
+ import type { BottomSheetProps } from '../bottomSheet/types';
8
+
9
+ export interface BottomSheetBackdropProps
10
+ extends Pick<ViewProps, 'style'>,
11
+ BottomSheetVariables {}
12
+
13
+ export type BackdropPressBehavior = 'none' | 'close' | 'collapse' | number;
14
+
15
+ export interface BottomSheetDefaultBackdropProps
16
+ extends BottomSheetBackdropProps,
17
+ NullableAccessibilityProps {
18
+ /**
19
+ * Backdrop opacity.
20
+ * @type number
21
+ * @default 0.5
22
+ */
23
+ opacity?: number;
24
+ /**
25
+ * Snap point index when backdrop will appears on.
26
+ * @type number
27
+ * @default 1
28
+ */
29
+ appearsOnIndex?: number;
30
+ /**
31
+ * Snap point index when backdrop will disappears on.
32
+ * @type number
33
+ * @default 0
34
+ */
35
+ disappearsOnIndex?: number;
36
+ /**
37
+ * Enable touch through backdrop component.
38
+ * @type boolean
39
+ * @default false
40
+ */
41
+ enableTouchThrough?: boolean;
42
+ /**
43
+ * What should happen when user press backdrop?
44
+ * @type BackdropPressBehavior
45
+ * @default 'close'
46
+ */
47
+ pressBehavior?: BackdropPressBehavior;
48
+
49
+ /**
50
+ * Function which will be executed on pressing backdrop component
51
+ * @type {Function}
52
+ */
53
+ onPress?: () => void;
54
+ /**
55
+ * Child component that will be rendered on backdrop.
56
+ */
57
+ children?: ReactNode | ReactNode[];
58
+ }
@@ -0,0 +1,20 @@
1
+ import React, { memo } from 'react';
2
+ import { View } from 'react-native';
3
+ import { styles } from './styles';
4
+ import type { BottomSheetBackgroundProps } from './types';
5
+
6
+ const BottomSheetBackgroundComponent = ({
7
+ pointerEvents,
8
+ style,
9
+ }: BottomSheetBackgroundProps) => (
10
+ <View
11
+ pointerEvents={pointerEvents}
12
+ accessible={true}
13
+ accessibilityRole="adjustable"
14
+ accessibilityLabel="Bottom Sheet"
15
+ style={[styles.background, style]}
16
+ />
17
+ );
18
+
19
+ export const BottomSheetBackground = memo(BottomSheetBackgroundComponent);
20
+ BottomSheetBackground.displayName = 'BottomSheetBackground';
@@ -0,0 +1,35 @@
1
+ import React, { memo, useMemo } from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+ import { BottomSheetBackground } from './BottomSheetBackground';
4
+ import { styles } from './styles';
5
+ import type { BottomSheetBackgroundContainerProps } from './types';
6
+
7
+ const BottomSheetBackgroundContainerComponent = ({
8
+ animatedIndex,
9
+ animatedPosition,
10
+ backgroundComponent: _providedBackgroundComponent,
11
+ backgroundStyle: _providedBackgroundStyle,
12
+ }: BottomSheetBackgroundContainerProps) => {
13
+ //#region style
14
+ const backgroundStyle = useMemo(
15
+ () => StyleSheet.flatten([styles.container, _providedBackgroundStyle]),
16
+ [_providedBackgroundStyle]
17
+ );
18
+ //#endregion
19
+
20
+ const BackgroundComponent =
21
+ _providedBackgroundComponent ?? BottomSheetBackground;
22
+ return (
23
+ <BackgroundComponent
24
+ pointerEvents="none"
25
+ animatedIndex={animatedIndex}
26
+ animatedPosition={animatedPosition}
27
+ style={backgroundStyle}
28
+ />
29
+ );
30
+ };
31
+
32
+ export const BottomSheetBackgroundContainer = memo(
33
+ BottomSheetBackgroundContainerComponent
34
+ );
35
+ BottomSheetBackgroundContainer.displayName = 'BottomSheetBackgroundContainer';
@@ -0,0 +1,2 @@
1
+ export { BottomSheetBackgroundContainer } from './BottomSheetBackgroundContainer';
2
+ export type { BottomSheetBackgroundProps } from './types';
@@ -0,0 +1,9 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export const styles = StyleSheet.create({
4
+ container: StyleSheet.absoluteFillObject,
5
+ background: {
6
+ backgroundColor: 'white',
7
+ borderRadius: 15,
8
+ },
9
+ });
@@ -0,0 +1,12 @@
1
+ import type { ViewProps } from 'react-native';
2
+ import type { BottomSheetVariables } from '../../types';
3
+ import type { BottomSheetProps } from '../bottomSheet';
4
+ export interface BottomSheetBackgroundProps
5
+ extends Pick<ViewProps, 'pointerEvents' | 'style'>,
6
+ BottomSheetVariables {}
7
+
8
+ export type BottomSheetBackgroundContainerProps = Pick<
9
+ BottomSheetProps,
10
+ 'backgroundComponent' | 'backgroundStyle'
11
+ > &
12
+ BottomSheetBackgroundProps;