@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,482 @@
1
+ import { Portal, usePortal } from '@gorhom/portal';
2
+ import React, {
3
+ forwardRef,
4
+ memo,
5
+ type RefObject,
6
+ useCallback,
7
+ useImperativeHandle,
8
+ useMemo,
9
+ useRef,
10
+ useState,
11
+ } from 'react';
12
+ import type { SNAP_POINT_TYPE } from '../../constants';
13
+ import { useBottomSheetModalInternal } from '../../hooks';
14
+ import type { BottomSheetMethods, BottomSheetModalMethods } from '../../types';
15
+ import { print } from '../../utilities';
16
+ import { id } from '../../utilities/id';
17
+ import BottomSheet from '../bottomSheet';
18
+ import {
19
+ DEFAULT_ENABLE_DISMISS_ON_CLOSE,
20
+ DEFAULT_STACK_BEHAVIOR,
21
+ } from './constants';
22
+ import type {
23
+ BottomSheetModalPrivateMethods,
24
+ BottomSheetModalProps,
25
+ BottomSheetModalState,
26
+ } from './types';
27
+
28
+ const INITIAL_STATE: BottomSheetModalState = {
29
+ mount: false,
30
+ data: undefined,
31
+ };
32
+
33
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
34
+ type BottomSheetModal<T = any> = BottomSheetModalMethods<T>;
35
+
36
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
37
+ function BottomSheetModalComponent<T = any>(
38
+ props: BottomSheetModalProps<T>,
39
+ ref: React.ForwardedRef<BottomSheetModal<T>>
40
+ ) {
41
+ const {
42
+ // modal props
43
+ name,
44
+ stackBehavior = DEFAULT_STACK_BEHAVIOR,
45
+ enableDismissOnClose = DEFAULT_ENABLE_DISMISS_ON_CLOSE,
46
+ onDismiss: _providedOnDismiss,
47
+ onAnimate: _providedOnAnimate,
48
+
49
+ // bottom sheet props
50
+ index = 0,
51
+ snapPoints,
52
+ enablePanDownToClose = true,
53
+ animateOnMount = true,
54
+ containerComponent: ContainerComponent = React.Fragment,
55
+
56
+ // callbacks
57
+ onChange: _providedOnChange,
58
+
59
+ // components
60
+ children: Content,
61
+ ...bottomSheetProps
62
+ } = props;
63
+
64
+ //#region state
65
+ const [{ mount, data }, setState] =
66
+ useState<BottomSheetModalState<T>>(INITIAL_STATE);
67
+ //#endregion
68
+
69
+ //#region hooks
70
+ const {
71
+ hostName,
72
+ containerLayoutState,
73
+ mountSheet,
74
+ unmountSheet,
75
+ willUnmountSheet,
76
+ } = useBottomSheetModalInternal();
77
+ const { removePortal: unmountPortal } = usePortal(hostName);
78
+ //#endregion
79
+
80
+ //#region refs
81
+ const bottomSheetRef = useRef<BottomSheet>(null);
82
+ const currentIndexRef = useRef(!animateOnMount ? index : -1);
83
+ const nextIndexRef = useRef<number | null>(null);
84
+ const restoreIndexRef = useRef(-1);
85
+ const minimized = useRef(false);
86
+ const forcedDismissed = useRef(false);
87
+ const mounted = useRef(false);
88
+ mounted.current = mount;
89
+ //#endregion
90
+
91
+ //#region variables
92
+ const key = useMemo(() => name || `bottom-sheet-modal-${id()}`, [name]);
93
+ //#endregion
94
+
95
+ //#region private methods
96
+ const resetVariables = useCallback(function resetVariables() {
97
+ print({
98
+ component: BottomSheetModal.name,
99
+ method: resetVariables.name,
100
+ });
101
+ currentIndexRef.current = -1;
102
+ restoreIndexRef.current = -1;
103
+ minimized.current = false;
104
+ mounted.current = false;
105
+ forcedDismissed.current = false;
106
+ }, []);
107
+ const unmount = useCallback(
108
+ function unmount() {
109
+ if (__DEV__) {
110
+ print({
111
+ component: BottomSheetModal.name,
112
+ method: unmount.name,
113
+ });
114
+ }
115
+ const _mounted = mounted.current;
116
+
117
+ // reset variables
118
+ resetVariables();
119
+
120
+ // unmount sheet and portal
121
+ unmountSheet(key);
122
+ unmountPortal(key);
123
+
124
+ // unmount the node, if sheet is still mounted
125
+ if (_mounted) {
126
+ setState(INITIAL_STATE);
127
+ }
128
+
129
+ // fire `onDismiss` callback
130
+ if (_providedOnDismiss) {
131
+ _providedOnDismiss();
132
+ }
133
+ },
134
+ [key, resetVariables, unmountSheet, unmountPortal, _providedOnDismiss]
135
+ );
136
+ //#endregion
137
+
138
+ //#region bottom sheet methods
139
+ const handleSnapToIndex = useCallback<BottomSheetMethods['snapToIndex']>(
140
+ (...args) => {
141
+ if (minimized.current) {
142
+ return;
143
+ }
144
+ bottomSheetRef.current?.snapToIndex(...args);
145
+ },
146
+ []
147
+ );
148
+ const handleSnapToPosition = useCallback<
149
+ BottomSheetMethods['snapToPosition']
150
+ >((...args) => {
151
+ if (minimized.current) {
152
+ return;
153
+ }
154
+ bottomSheetRef.current?.snapToPosition(...args);
155
+ }, []);
156
+ const handleExpand: BottomSheetMethods['expand'] = useCallback((...args) => {
157
+ if (minimized.current) {
158
+ return;
159
+ }
160
+ bottomSheetRef.current?.expand(...args);
161
+ }, []);
162
+ const handleCollapse: BottomSheetMethods['collapse'] = useCallback(
163
+ (...args) => {
164
+ if (minimized.current) {
165
+ return;
166
+ }
167
+ bottomSheetRef.current?.collapse(...args);
168
+ },
169
+ []
170
+ );
171
+ const handleClose: BottomSheetMethods['close'] = useCallback((...args) => {
172
+ if (minimized.current) {
173
+ return;
174
+ }
175
+ bottomSheetRef.current?.close(...args);
176
+ }, []);
177
+ const handleForceClose: BottomSheetMethods['forceClose'] = useCallback(
178
+ (...args) => {
179
+ if (minimized.current) {
180
+ return;
181
+ }
182
+ bottomSheetRef.current?.forceClose(...args);
183
+ },
184
+ []
185
+ );
186
+ //#endregion
187
+
188
+ //#region bottom sheet modal methods
189
+ // biome-ignore lint/correctness/useExhaustiveDependencies(BottomSheetModal.name): used for debug only
190
+ // biome-ignore lint/correctness/useExhaustiveDependencies(ref): ref is a stable object
191
+ const handlePresent = useCallback(
192
+ function handlePresent(_data?: T) {
193
+ requestAnimationFrame(() => {
194
+ setState({
195
+ mount: true,
196
+ data: _data,
197
+ });
198
+ mountSheet(
199
+ key,
200
+ ref as unknown as RefObject<BottomSheetModalPrivateMethods>,
201
+ stackBehavior
202
+ );
203
+ ref;
204
+
205
+ if (__DEV__) {
206
+ print({
207
+ component: BottomSheetModal.name,
208
+ method: handlePresent.name,
209
+ });
210
+ }
211
+ });
212
+ },
213
+ // eslint-disable-next-line react-hooks/exhaustive-deps
214
+ [key, stackBehavior, mountSheet]
215
+ );
216
+ // biome-ignore lint/correctness/useExhaustiveDependencies(BottomSheetModal.name): used for debug only
217
+ const handleDismiss = useCallback<BottomSheetModalMethods['dismiss']>(
218
+ function handleDismiss(animationConfigs) {
219
+ if (__DEV__) {
220
+ print({
221
+ component: BottomSheetModal.name,
222
+ method: handleDismiss.name,
223
+ params: {
224
+ currentIndexRef: currentIndexRef.current,
225
+ minimized: minimized.current,
226
+ },
227
+ });
228
+ }
229
+
230
+ const animating = nextIndexRef.current != null;
231
+
232
+ /**
233
+ * early exit, if not minimized, it is in closed position and not animating
234
+ */
235
+ if (
236
+ currentIndexRef.current === -1 &&
237
+ minimized.current === false &&
238
+ !animating
239
+ ) {
240
+ return;
241
+ }
242
+
243
+ /**
244
+ * unmount and early exit, if minimized or it is in closed position and not animating
245
+ */
246
+ if (
247
+ !animating &&
248
+ (minimized.current ||
249
+ (currentIndexRef.current === -1 && enablePanDownToClose))
250
+ ) {
251
+ unmount();
252
+ return;
253
+ }
254
+ willUnmountSheet(key);
255
+ forcedDismissed.current = true;
256
+ bottomSheetRef.current?.forceClose(animationConfigs);
257
+ },
258
+ [willUnmountSheet, unmount, key, enablePanDownToClose]
259
+ );
260
+ const handleMinimize = useCallback(
261
+ function handleMinimize() {
262
+ if (__DEV__) {
263
+ print({
264
+ component: BottomSheetModal.name,
265
+ method: handleMinimize.name,
266
+ params: {
267
+ minimized: minimized.current,
268
+ },
269
+ });
270
+ }
271
+ if (minimized.current) {
272
+ return;
273
+ }
274
+ minimized.current = true;
275
+
276
+ /**
277
+ * if modal got minimized before it finish its mounting
278
+ * animation, we set the `restoreIndexRef` to the
279
+ * provided index.
280
+ */
281
+ if (currentIndexRef.current === -1) {
282
+ restoreIndexRef.current = index;
283
+ } else {
284
+ restoreIndexRef.current = currentIndexRef.current;
285
+ }
286
+ bottomSheetRef.current?.close();
287
+ },
288
+ [index]
289
+ );
290
+ // biome-ignore lint/correctness/useExhaustiveDependencies(BottomSheetModal.name): used for debug only
291
+ const handleRestore = useCallback(function handleRestore() {
292
+ if (__DEV__) {
293
+ print({
294
+ component: BottomSheetModal.name,
295
+ method: handleRestore.name,
296
+ params: {
297
+ minimized: minimized.current,
298
+ forcedDismissed: forcedDismissed.current,
299
+ },
300
+ });
301
+ }
302
+ if (!minimized.current || forcedDismissed.current) {
303
+ return;
304
+ }
305
+ minimized.current = false;
306
+ bottomSheetRef.current?.snapToIndex(restoreIndexRef.current);
307
+ }, []);
308
+ //#endregion
309
+
310
+ //#region callbacks
311
+ const handlePortalOnUnmount = useCallback(
312
+ function handlePortalOnUnmount() {
313
+ if (__DEV__) {
314
+ print({
315
+ component: BottomSheetModal.name,
316
+ method: handlePortalOnUnmount.name,
317
+ params: {
318
+ minimized: minimized.current,
319
+ forcedDismissed: forcedDismissed.current,
320
+ },
321
+ });
322
+ }
323
+ /**
324
+ * if modal is already been dismiss, we exit the method.
325
+ */
326
+ if (currentIndexRef.current === -1 && minimized.current === false) {
327
+ return;
328
+ }
329
+
330
+ mounted.current = false;
331
+ forcedDismissed.current = true;
332
+
333
+ if (minimized.current) {
334
+ unmount();
335
+ return;
336
+ }
337
+ willUnmountSheet(key);
338
+ bottomSheetRef.current?.close();
339
+ },
340
+ [key, unmount, willUnmountSheet]
341
+ );
342
+ const handlePortalRender = useCallback(function handlePortalRender(
343
+ render: () => void
344
+ ) {
345
+ if (mounted.current) {
346
+ render();
347
+ }
348
+ }, []);
349
+ // biome-ignore lint/correctness/useExhaustiveDependencies(BottomSheetModal.name): used for debug only
350
+ const handleBottomSheetOnChange = useCallback(
351
+ function handleBottomSheetOnChange(
352
+ _index: number,
353
+ _position: number,
354
+ _type: SNAP_POINT_TYPE
355
+ ) {
356
+ if (__DEV__) {
357
+ print({
358
+ component: BottomSheetModal.name,
359
+ method: handleBottomSheetOnChange.name,
360
+ category: 'callback',
361
+ params: {
362
+ minimized: minimized.current,
363
+ forcedDismissed: forcedDismissed.current,
364
+ },
365
+ });
366
+ }
367
+ currentIndexRef.current = _index;
368
+ nextIndexRef.current = null;
369
+
370
+ if (_providedOnChange) {
371
+ _providedOnChange(_index, _position, _type);
372
+ }
373
+ },
374
+ [_providedOnChange]
375
+ );
376
+ const handleBottomSheetOnAnimate = useCallback(
377
+ (
378
+ fromIndex: number,
379
+ toIndex: number,
380
+ fromPosition: number,
381
+ toPosition: number
382
+ ) => {
383
+ nextIndexRef.current = toIndex;
384
+
385
+ if (_providedOnAnimate) {
386
+ _providedOnAnimate(fromIndex, toIndex, fromPosition, toPosition);
387
+ }
388
+ },
389
+ [_providedOnAnimate]
390
+ );
391
+ // biome-ignore lint/correctness/useExhaustiveDependencies(BottomSheetModal.name): used for debug only
392
+ const handleBottomSheetOnClose = useCallback(
393
+ function handleBottomSheetOnClose() {
394
+ if (__DEV__) {
395
+ print({
396
+ component: BottomSheetModal.name,
397
+ method: handleBottomSheetOnClose.name,
398
+ category: 'callback',
399
+ params: {
400
+ minimized: minimized.current,
401
+ forcedDismissed: forcedDismissed.current,
402
+ },
403
+ });
404
+ }
405
+
406
+ if (minimized.current) {
407
+ return;
408
+ }
409
+
410
+ if (enableDismissOnClose) {
411
+ unmount();
412
+ }
413
+ },
414
+ [enableDismissOnClose, unmount]
415
+ );
416
+ //#endregion
417
+
418
+ //#region expose methods
419
+ useImperativeHandle(ref, () => ({
420
+ // sheet
421
+ snapToIndex: handleSnapToIndex,
422
+ snapToPosition: handleSnapToPosition,
423
+ expand: handleExpand,
424
+ collapse: handleCollapse,
425
+ close: handleClose,
426
+ forceClose: handleForceClose,
427
+ // modal methods
428
+ dismiss: handleDismiss,
429
+ present: handlePresent,
430
+ // internal
431
+ minimize: handleMinimize,
432
+ restore: handleRestore,
433
+ }));
434
+ //#endregion
435
+
436
+ // render
437
+ return mount ? (
438
+ <Portal
439
+ key={key}
440
+ name={key}
441
+ hostName={hostName}
442
+ handleOnMount={handlePortalRender}
443
+ handleOnUpdate={handlePortalRender}
444
+ handleOnUnmount={handlePortalOnUnmount}
445
+ >
446
+ <ContainerComponent key={key}>
447
+ <BottomSheet
448
+ {...bottomSheetProps}
449
+ ref={bottomSheetRef}
450
+ key={key}
451
+ index={index}
452
+ snapPoints={snapPoints}
453
+ enablePanDownToClose={enablePanDownToClose}
454
+ animateOnMount={animateOnMount}
455
+ containerLayoutState={containerLayoutState}
456
+ onChange={handleBottomSheetOnChange}
457
+ onClose={handleBottomSheetOnClose}
458
+ onAnimate={handleBottomSheetOnAnimate}
459
+ $modal={true}
460
+ >
461
+ {typeof Content === 'function' ? <Content data={data} /> : Content}
462
+ </BottomSheet>
463
+ </ContainerComponent>
464
+ </Portal>
465
+ ) : null;
466
+ }
467
+
468
+ const BottomSheetModal = memo(forwardRef(BottomSheetModalComponent)) as <
469
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
470
+ T = any,
471
+ >(
472
+ props: BottomSheetModalProps<T> & {
473
+ ref?: React.ForwardedRef<BottomSheetModal<T>>;
474
+ }
475
+ ) => ReturnType<typeof BottomSheetModalComponent>;
476
+ (
477
+ BottomSheetModal as React.MemoExoticComponent<
478
+ typeof BottomSheetModalComponent
479
+ >
480
+ ).displayName = 'BottomSheetModal';
481
+
482
+ export default BottomSheetModal;
@@ -0,0 +1,4 @@
1
+ const DEFAULT_STACK_BEHAVIOR = 'switch';
2
+ const DEFAULT_ENABLE_DISMISS_ON_CLOSE = true;
3
+
4
+ export { DEFAULT_STACK_BEHAVIOR, DEFAULT_ENABLE_DISMISS_ON_CLOSE };
@@ -0,0 +1,6 @@
1
+ export { default } from './BottomSheetModal';
2
+ export type {
3
+ BottomSheetModalProps,
4
+ BottomSheetModalPrivateMethods,
5
+ BottomSheetModalStackBehavior,
6
+ } from './types';
@@ -0,0 +1,67 @@
1
+ import type React from 'react';
2
+ import type { View } from 'react-native';
3
+ import type { MODAL_STACK_BEHAVIOR } from '../../constants';
4
+ import type { BottomSheetProps } from '../bottomSheet';
5
+
6
+ export interface BottomSheetModalPrivateMethods {
7
+ dismiss: (force?: boolean) => void;
8
+ minimize: () => void;
9
+ restore: () => void;
10
+ }
11
+
12
+ export type BottomSheetModalStackBehavior = keyof typeof MODAL_STACK_BEHAVIOR;
13
+
14
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
15
+ export interface BottomSheetModalProps<T = any>
16
+ extends Omit<BottomSheetProps, 'containerHeight' | 'onClose'> {
17
+ /**
18
+ * Modal name to help identify the modal for later on.
19
+ * @type string
20
+ * @default generated unique key.
21
+ */
22
+ name?: string;
23
+
24
+ /**
25
+ * Defines the stack behavior when modal mount.
26
+ * - `push` it will mount the modal on top of the current one.
27
+ * - `switch` it will minimize the current modal then mount the new one.
28
+ * - `replace` it will dismiss the current modal then mount the new one.
29
+ * @type `push` | `switch` | `replace`
30
+ * @default switch
31
+ */
32
+ stackBehavior?: BottomSheetModalStackBehavior;
33
+
34
+ /**
35
+ * Enable dismiss the modal when it is closed.
36
+ * @type boolean
37
+ * @default true
38
+ */
39
+ enableDismissOnClose?: boolean;
40
+
41
+ /**
42
+ * Add a custom container like FullWindowOverlay
43
+ * allow to fix issue like https://github.com/gorhom/react-native-bottom-sheet/issues/832
44
+ * @type React.ComponentType
45
+ * @default undefined
46
+ */
47
+ containerComponent?: React.ComponentType<React.PropsWithChildren>;
48
+
49
+ // callbacks
50
+ /**
51
+ * Callback when the modal dismissed.
52
+ * @type () => void;
53
+ */
54
+ onDismiss?: () => void;
55
+
56
+ /**
57
+ * A scrollable node or normal view.
58
+ * @type React.ReactNode[] | React.ReactNode | (({ data: any }?) => React.ReactElement)
59
+ */
60
+ children: React.FC<{ data?: T }> | React.ReactNode[] | React.ReactNode;
61
+ }
62
+
63
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
64
+ export interface BottomSheetModalState<T = any> {
65
+ mount: boolean;
66
+ data: T | undefined;
67
+ }