@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.
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/mock.js +231 -0
- package/package.json +107 -0
- package/src/components/bottomSheet/BottomSheet.tsx +1885 -0
- package/src/components/bottomSheet/BottomSheetBody.tsx +44 -0
- package/src/components/bottomSheet/BottomSheetContent.tsx +261 -0
- package/src/components/bottomSheet/constants.ts +58 -0
- package/src/components/bottomSheet/index.ts +2 -0
- package/src/components/bottomSheet/styles.ts +11 -0
- package/src/components/bottomSheet/types.d.ts +358 -0
- package/src/components/bottomSheetBackdrop/BottomSheetBackdrop.tsx +165 -0
- package/src/components/bottomSheetBackdrop/constants.ts +22 -0
- package/src/components/bottomSheetBackdrop/index.ts +2 -0
- package/src/components/bottomSheetBackdrop/styles.ts +8 -0
- package/src/components/bottomSheetBackdrop/types.d.ts +58 -0
- package/src/components/bottomSheetBackground/BottomSheetBackground.tsx +20 -0
- package/src/components/bottomSheetBackground/BottomSheetBackgroundContainer.tsx +35 -0
- package/src/components/bottomSheetBackground/index.ts +2 -0
- package/src/components/bottomSheetBackground/styles.ts +9 -0
- package/src/components/bottomSheetBackground/types.d.ts +12 -0
- package/src/components/bottomSheetDebugView/BottomSheetDebugView.tsx +26 -0
- package/src/components/bottomSheetDebugView/ReText.tsx +72 -0
- package/src/components/bottomSheetDebugView/ReText.webx.tsx +55 -0
- package/src/components/bottomSheetDebugView/index.ts +1 -0
- package/src/components/bottomSheetDebugView/styles.ts +19 -0
- package/src/components/bottomSheetDebugView/styles.web.ts +20 -0
- package/src/components/bottomSheetDraggableView/BottomSheetDraggableView.tsx +123 -0
- package/src/components/bottomSheetDraggableView/index.ts +1 -0
- package/src/components/bottomSheetDraggableView/types.d.ts +9 -0
- package/src/components/bottomSheetFooter/BottomSheetFooter.tsx +119 -0
- package/src/components/bottomSheetFooter/BottomSheetFooterContainer.tsx +43 -0
- package/src/components/bottomSheetFooter/index.ts +3 -0
- package/src/components/bottomSheetFooter/styles.ts +12 -0
- package/src/components/bottomSheetFooter/types.d.ts +41 -0
- package/src/components/bottomSheetGestureHandlersProvider/BottomSheetGestureHandlersProvider.tsx +69 -0
- package/src/components/bottomSheetGestureHandlersProvider/index.ts +1 -0
- package/src/components/bottomSheetGestureHandlersProvider/types.d.ts +8 -0
- package/src/components/bottomSheetHandle/BottomSheetHandle.tsx +51 -0
- package/src/components/bottomSheetHandle/BottomSheetHandleContainer.tsx +187 -0
- package/src/components/bottomSheetHandle/constants.ts +12 -0
- package/src/components/bottomSheetHandle/index.ts +6 -0
- package/src/components/bottomSheetHandle/styles.ts +23 -0
- package/src/components/bottomSheetHandle/types.d.ts +52 -0
- package/src/components/bottomSheetHostingContainer/BottomSheetHostingContainer.tsx +130 -0
- package/src/components/bottomSheetHostingContainer/index.ts +2 -0
- package/src/components/bottomSheetHostingContainer/styles.ts +5 -0
- package/src/components/bottomSheetHostingContainer/styles.web.ts +11 -0
- package/src/components/bottomSheetHostingContainer/types.d.ts +17 -0
- package/src/components/bottomSheetModal/BottomSheetModal.tsx +482 -0
- package/src/components/bottomSheetModal/constants.ts +4 -0
- package/src/components/bottomSheetModal/index.ts +6 -0
- package/src/components/bottomSheetModal/types.d.ts +67 -0
- package/src/components/bottomSheetModalProvider/BottomSheetModalProvider.tsx +211 -0
- package/src/components/bottomSheetModalProvider/index.ts +1 -0
- package/src/components/bottomSheetModalProvider/types.d.ts +12 -0
- package/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.android.tsx +84 -0
- package/src/components/bottomSheetRefreshControl/BottomSheetRefreshControl.tsx +1 -0
- package/src/components/bottomSheetRefreshControl/index.ts +20 -0
- package/src/components/bottomSheetScrollable/BottomSheetDraggableScrollable.tsx +23 -0
- package/src/components/bottomSheetScrollable/BottomSheetFlashList.tsx +88 -0
- package/src/components/bottomSheetScrollable/BottomSheetFlashList.web.tsx +1 -0
- package/src/components/bottomSheetScrollable/BottomSheetFlatList.tsx +26 -0
- package/src/components/bottomSheetScrollable/BottomSheetScrollView.tsx +27 -0
- package/src/components/bottomSheetScrollable/BottomSheetSectionList.tsx +29 -0
- package/src/components/bottomSheetScrollable/BottomSheetVirtualizedList.tsx +27 -0
- package/src/components/bottomSheetScrollable/ScrollableContainer.android.tsx +55 -0
- package/src/components/bottomSheetScrollable/ScrollableContainer.tsx +22 -0
- package/src/components/bottomSheetScrollable/ScrollableContainer.web.tsx +102 -0
- package/src/components/bottomSheetScrollable/createBottomSheetScrollableComponent.tsx +153 -0
- package/src/components/bottomSheetScrollable/index.ts +15 -0
- package/src/components/bottomSheetScrollable/styles.ts +8 -0
- package/src/components/bottomSheetScrollable/types.d.ts +280 -0
- package/src/components/bottomSheetScrollable/useBottomSheetContentSizeSetter.ts +32 -0
- package/src/components/bottomSheetTextInput/BottomSheetTextInput.tsx +127 -0
- package/src/components/bottomSheetTextInput/index.ts +2 -0
- package/src/components/bottomSheetTextInput/types.ts +3 -0
- package/src/components/bottomSheetView/BottomSheetView.tsx +93 -0
- package/src/components/bottomSheetView/index.ts +1 -0
- package/src/components/bottomSheetView/styles.ts +10 -0
- package/src/components/bottomSheetView/types.d.ts +24 -0
- package/src/components/touchables/Touchables.ios.tsx +5 -0
- package/src/components/touchables/Touchables.tsx +5 -0
- package/src/components/touchables/index.ts +20 -0
- package/src/constants.ts +159 -0
- package/src/contexts/external.ts +8 -0
- package/src/contexts/gesture.ts +13 -0
- package/src/contexts/index.ts +15 -0
- package/src/contexts/internal.ts +65 -0
- package/src/contexts/modal/external.ts +11 -0
- package/src/contexts/modal/internal.ts +25 -0
- package/src/hooks/index.ts +29 -0
- package/src/hooks/useAnimatedDetents.ts +119 -0
- package/src/hooks/useAnimatedKeyboard.ts +174 -0
- package/src/hooks/useAnimatedLayout.ts +109 -0
- package/src/hooks/useBottomSheet.ts +12 -0
- package/src/hooks/useBottomSheetContentContainerStyle.ts +88 -0
- package/src/hooks/useBottomSheetGestureHandlers.ts +12 -0
- package/src/hooks/useBottomSheetInternal.ts +25 -0
- package/src/hooks/useBottomSheetModal.ts +12 -0
- package/src/hooks/useBottomSheetModalInternal.ts +25 -0
- package/src/hooks/useBottomSheetScrollableCreator.tsx +60 -0
- package/src/hooks/useBottomSheetSpringConfigs.ts +11 -0
- package/src/hooks/useBottomSheetTimingConfigs.ts +36 -0
- package/src/hooks/useBoundingClientRect.ts +77 -0
- package/src/hooks/useGestureEventsHandlersDefault.tsx +436 -0
- package/src/hooks/useGestureEventsHandlersDefault.web.tsx +418 -0
- package/src/hooks/useGestureHandler.ts +90 -0
- package/src/hooks/usePropsValidator.ts +108 -0
- package/src/hooks/useReactiveSharedValue.ts +45 -0
- package/src/hooks/useScrollEventsHandlersDefault.ts +167 -0
- package/src/hooks/useScrollHandler.ts +72 -0
- package/src/hooks/useScrollHandler.web.ts +181 -0
- package/src/hooks/useScrollable.ts +131 -0
- package/src/hooks/useScrollableSetter.ts +56 -0
- package/src/hooks/useStableCallback.ts +26 -0
- package/src/index.ts +79 -0
- package/src/types.d.ts +336 -0
- package/src/utilities/animate.ts +56 -0
- package/src/utilities/clamp.ts +8 -0
- package/src/utilities/easingExp.ts +10 -0
- package/src/utilities/findNodeHandle.ts +1 -0
- package/src/utilities/findNodeHandle.web.ts +33 -0
- package/src/utilities/getKeyboardAnimationConfigs.ts +44 -0
- package/src/utilities/getRefNativeTag.web.ts +6 -0
- package/src/utilities/id.ts +6 -0
- package/src/utilities/index.ts +7 -0
- package/src/utilities/isFabricInstalled.ts +9 -0
- package/src/utilities/logger.ts +55 -0
- package/src/utilities/noop.ts +7 -0
- package/src/utilities/normalizeSnapPoint.ts +17 -0
- package/src/utilities/snapPoint.ts +11 -0
- 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,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,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;
|