@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
package/src/index.ts ADDED
@@ -0,0 +1,79 @@
1
+ // bottom sheet
2
+ export { default } from './components/bottomSheet';
3
+
4
+ // bottom sheet modal
5
+ export { default as BottomSheetModal } from './components/bottomSheetModal';
6
+ export { default as BottomSheetModalProvider } from './components/bottomSheetModalProvider';
7
+
8
+ //#region hooks
9
+ export { useBottomSheet } from './hooks/useBottomSheet';
10
+ export { useBottomSheetModal } from './hooks/useBottomSheetModal';
11
+ export { useBottomSheetSpringConfigs } from './hooks/useBottomSheetSpringConfigs';
12
+ export { useBottomSheetTimingConfigs } from './hooks/useBottomSheetTimingConfigs';
13
+ export { useBottomSheetInternal } from './hooks/useBottomSheetInternal';
14
+ export { useBottomSheetModalInternal } from './hooks/useBottomSheetModalInternal';
15
+ export { useScrollEventsHandlersDefault } from './hooks/useScrollEventsHandlersDefault';
16
+ export { useGestureEventsHandlersDefault } from './hooks/useGestureEventsHandlersDefault';
17
+ export { useBottomSheetGestureHandlers } from './hooks/useBottomSheetGestureHandlers';
18
+ export { useScrollHandler } from './hooks/useScrollHandler';
19
+ export { useScrollableSetter } from './hooks/useScrollableSetter';
20
+ export { useBottomSheetScrollableCreator } from './hooks/useBottomSheetScrollableCreator';
21
+ //#endregion
22
+
23
+ //#region components
24
+ export {
25
+ BottomSheetScrollView,
26
+ BottomSheetSectionList,
27
+ BottomSheetFlatList,
28
+ BottomSheetVirtualizedList,
29
+ BottomSheetFlashList,
30
+ } from './components/bottomSheetScrollable';
31
+ export { BottomSheetHandle } from './components/bottomSheetHandle';
32
+ export { default as BottomSheetDraggableView } from './components/bottomSheetDraggableView';
33
+ export { default as BottomSheetView } from './components/bottomSheetView';
34
+ export { default as BottomSheetTextInput } from './components/bottomSheetTextInput';
35
+ export { BottomSheetBackdrop } from './components/bottomSheetBackdrop';
36
+ export {
37
+ BottomSheetFooter,
38
+ BottomSheetFooterContainer,
39
+ } from './components/bottomSheetFooter';
40
+
41
+ // touchables
42
+ import BottomSheetTouchable from './components/touchables';
43
+ export const {
44
+ TouchableHighlight,
45
+ TouchableOpacity,
46
+ TouchableWithoutFeedback,
47
+ } = BottomSheetTouchable;
48
+ // utils
49
+ export { createBottomSheetScrollableComponent } from './components/bottomSheetScrollable';
50
+ //#endregion
51
+
52
+ //#region types
53
+ export type { BottomSheetProps } from './components/bottomSheet';
54
+ export type { BottomSheetModalProps } from './components/bottomSheetModal';
55
+ export type { BottomSheetHandleProps } from './components/bottomSheetHandle';
56
+ export type { BottomSheetBackgroundProps } from './components/bottomSheetBackground';
57
+ export type { BottomSheetBackdropProps } from './components/bottomSheetBackdrop';
58
+ export type { BottomSheetFooterProps } from './components/bottomSheetFooter';
59
+
60
+ export type {
61
+ BottomSheetFlatListMethods,
62
+ BottomSheetScrollViewMethods,
63
+ BottomSheetSectionListMethods,
64
+ BottomSheetVirtualizedListMethods,
65
+ BottomSheetScrollableProps,
66
+ } from './components/bottomSheetScrollable';
67
+
68
+ export type {
69
+ ScrollEventsHandlersHookType,
70
+ GestureEventsHandlersHookType,
71
+ ScrollEventHandlerCallbackType,
72
+ GestureEventHandlerCallbackType,
73
+ } from './types';
74
+ //#endregion
75
+
76
+ //#region utilities
77
+ export * from './constants';
78
+ export { enableLogging } from './utilities/logger';
79
+ //#endregion
package/src/types.d.ts ADDED
@@ -0,0 +1,336 @@
1
+ import type React from 'react';
2
+ import type {
3
+ AccessibilityProps,
4
+ FlatList,
5
+ Insets,
6
+ KeyboardEventEasing,
7
+ NativeScrollEvent,
8
+ NativeSyntheticEvent,
9
+ ScrollView,
10
+ SectionList,
11
+ } from 'react-native';
12
+ import type {
13
+ GestureEventPayload,
14
+ GestureStateChangeEvent,
15
+ GestureUpdateEvent,
16
+ PanGestureChangeEventPayload,
17
+ PanGestureHandlerEventPayload,
18
+ State,
19
+ } from 'react-native-gesture-handler';
20
+ import type {
21
+ EasingFunction,
22
+ EasingFunctionFactory,
23
+ ReduceMotion,
24
+ SharedValue,
25
+ WithSpringConfig,
26
+ WithTimingConfig,
27
+ } from 'react-native-reanimated';
28
+ import type {
29
+ ANIMATION_SOURCE,
30
+ ANIMATION_STATUS,
31
+ GESTURE_SOURCE,
32
+ KEYBOARD_STATUS,
33
+ SCROLLABLE_STATUS,
34
+ SCROLLABLE_TYPE,
35
+ } from './constants';
36
+
37
+ //#region Methods
38
+ export interface BottomSheetMethods {
39
+ /**
40
+ * Snap to one of the provided points from `snapPoints`.
41
+ * @param index snap point index.
42
+ * @param animationConfigs snap animation configs.
43
+ *
44
+ * @see {WithSpringConfig}
45
+ * @see {WithTimingConfig}
46
+ */
47
+ snapToIndex: (
48
+ index: number,
49
+ animationConfigs?: WithSpringConfig | WithTimingConfig
50
+ ) => void;
51
+ /**
52
+ * Snap to a position out of provided `snapPoints`.
53
+ * @param position position in pixel or percentage.
54
+ * @param animationConfigs snap animation configs.
55
+ *
56
+ * @see {WithSpringConfig}
57
+ * @see {WithTimingConfig}
58
+ */
59
+ snapToPosition: (
60
+ position: number | string,
61
+ animationConfigs?: WithSpringConfig | WithTimingConfig
62
+ ) => void;
63
+ /**
64
+ * Snap to the maximum provided point from `snapPoints`.
65
+ * @param animationConfigs snap animation configs.
66
+ *
67
+ * @see {WithSpringConfig}
68
+ * @see {WithTimingConfig}
69
+ */
70
+ expand: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
71
+ /**
72
+ * Snap to the minimum provided point from `snapPoints`.
73
+ * @param animationConfigs snap animation configs.
74
+ *
75
+ * @see {WithSpringConfig}
76
+ * @see {WithTimingConfig}
77
+ */
78
+ collapse: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
79
+ /**
80
+ * Close the bottom sheet.
81
+ * @param animationConfigs snap animation configs.
82
+ *
83
+ * @see {WithSpringConfig}
84
+ * @see {WithTimingConfig}
85
+ */
86
+ close: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
87
+ /**
88
+ * Force close the bottom sheet, this prevent any interruptions till the sheet is closed.
89
+ * @param animationConfigs snap animation configs.
90
+ *
91
+ * @see {WithSpringConfig}
92
+ * @see {WithTimingConfig}
93
+ */
94
+ forceClose: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
95
+ }
96
+
97
+ // biome-ignore lint/suspicious/noExplicitAny: Using 'any' allows users to define their own strict types for 'data' property.
98
+ export interface BottomSheetModalMethods<T = any> extends BottomSheetMethods {
99
+ /**
100
+ * Mount and present the bottom sheet modal to the initial snap point.
101
+ * @param data to be passed to the modal.
102
+ */
103
+ present: (data?: T) => void;
104
+ /**
105
+ * Close and unmount the bottom sheet modal.
106
+ * @param animationConfigs snap animation configs.
107
+ *
108
+ * @see {WithSpringConfig}
109
+ * @see {WithTimingConfig}
110
+ */
111
+ dismiss: (animationConfigs?: WithSpringConfig | WithTimingConfig) => void;
112
+ }
113
+ //#endregion
114
+
115
+ export interface BottomSheetVariables {
116
+ /**
117
+ * Current sheet position index.
118
+ * @type SharedValue<number>
119
+ */
120
+ animatedIndex: SharedValue<number>;
121
+ /**
122
+ * Current sheet position.
123
+ * @type SharedValue<number>
124
+ */
125
+ animatedPosition: SharedValue<number>;
126
+ }
127
+
128
+ //#region scrollable
129
+ export type ScrollableState = {
130
+ type: SCROLLABLE_TYPE;
131
+ contentOffsetY: number;
132
+ refreshable: boolean;
133
+ };
134
+ export type Scrollable = FlatList | ScrollView | SectionList;
135
+ export type ScrollableRef = {
136
+ id: number;
137
+ node: React.RefObject<Scrollable>;
138
+ };
139
+ export type ScrollableEvent = (
140
+ event: Pick<NativeSyntheticEvent<NativeScrollEvent>, 'nativeEvent'>
141
+ ) => void;
142
+ //#endregion
143
+
144
+ //#region utils
145
+ export interface TimingConfig {
146
+ duration?: number;
147
+ reduceMotion?: ReduceMotion;
148
+ easing?: EasingFunction | EasingFunctionFactory;
149
+ }
150
+
151
+ export type SpringConfig = {
152
+ stiffness?: number;
153
+ overshootClamping?: boolean;
154
+ restDisplacementThreshold?: number;
155
+ restSpeedThreshold?: number;
156
+ velocity?: number;
157
+ reduceMotion?: ReduceMotion;
158
+ } & (
159
+ | {
160
+ mass?: number;
161
+ damping?: number;
162
+ duration?: never;
163
+ dampingRatio?: never;
164
+ clamp?: never;
165
+ }
166
+ | {
167
+ mass?: never;
168
+ damping?: never;
169
+ duration?: number;
170
+ dampingRatio?: number;
171
+ clamp?: { min?: number; max?: number };
172
+ }
173
+ );
174
+
175
+ export type Primitive = string | number | boolean;
176
+ //#endregion
177
+
178
+ //#region hooks
179
+ export type GestureEventPayloadType = GestureEventPayload &
180
+ PanGestureHandlerEventPayload;
181
+
182
+ export type GestureEventContextType = {
183
+ didStart?: boolean;
184
+ };
185
+
186
+ export type GestureEventHandlerCallbackType = (
187
+ source: GESTURE_SOURCE,
188
+ payload: GestureEventPayloadType
189
+ ) => void;
190
+
191
+ export type GestureEventsHandlersHookType = () => {
192
+ handleOnStart: GestureEventHandlerCallbackType;
193
+ handleOnChange: GestureEventHandlerCallbackType;
194
+ handleOnEnd: GestureEventHandlerCallbackType;
195
+ handleOnFinalize: GestureEventHandlerCallbackType;
196
+ };
197
+
198
+ export type GestureHandlersHookType = (
199
+ source: GESTURE_SOURCE,
200
+ state: SharedValue<State>,
201
+ gestureSource: SharedValue<GESTURE_SOURCE>,
202
+ onStart: GestureEventHandlerCallbackType,
203
+ onChange: GestureEventHandlerCallbackType,
204
+ onEnd: GestureEventHandlerCallbackType,
205
+ onFinalize: GestureEventHandlerCallbackType
206
+ ) => {
207
+ handleOnStart: (
208
+ event: GestureStateChangeEvent<PanGestureHandlerEventPayload>
209
+ ) => void;
210
+ handleOnChange: (
211
+ event: GestureUpdateEvent<
212
+ PanGestureHandlerEventPayload & PanGestureChangeEventPayload
213
+ >
214
+ ) => void;
215
+ handleOnEnd: (
216
+ event: GestureStateChangeEvent<PanGestureHandlerEventPayload>
217
+ ) => void;
218
+ handleOnFinalize: (
219
+ event: GestureStateChangeEvent<PanGestureHandlerEventPayload>
220
+ ) => void;
221
+ };
222
+
223
+ type ScrollEventHandlerCallbackType<C = never> = (
224
+ payload: NativeScrollEvent,
225
+ context: C
226
+ ) => void;
227
+
228
+ export type ScrollEventsHandlersHookType = (
229
+ ref: React.RefObject<Scrollable>,
230
+ contentOffsetY: SharedValue<number>
231
+ ) => {
232
+ handleOnScroll?: ScrollEventHandlerCallbackType;
233
+ handleOnBeginDrag?: ScrollEventHandlerCallbackType;
234
+ handleOnEndDrag?: ScrollEventHandlerCallbackType;
235
+ handleOnMomentumBegin?: ScrollEventHandlerCallbackType;
236
+ handleOnMomentumEnd?: ScrollEventHandlerCallbackType;
237
+ };
238
+ //#endregion
239
+
240
+ //#region accessibility
241
+ export interface NullableAccessibilityProps extends AccessibilityProps {
242
+ accessible?: AccessibilityProps['accessible'] | null;
243
+ accessibilityLabel?: AccessibilityProps['accessibilityLabel'] | null;
244
+ accessibilityHint?: AccessibilityProps['accessibilityHint'] | null;
245
+ accessibilityRole?: AccessibilityProps['accessibilityRole'] | null;
246
+ }
247
+ //#endregion
248
+
249
+ //#region states
250
+ export type KeyboardState = {
251
+ target?: number;
252
+ status: KEYBOARD_STATUS;
253
+ height: number;
254
+ heightWithinContainer: number;
255
+ easing: KeyboardEventEasing;
256
+ duration: number;
257
+ };
258
+
259
+ /**
260
+ * Represents the state of an animation, including its current status and the source that triggered it.
261
+ */
262
+ export type AnimationState = {
263
+ /**
264
+ * The current status of the animation, this can be one of the values defined in the `ANIMATION_STATUS` enum, such as 'idle', 'running', 'completed', etc.
265
+ */
266
+ status: ANIMATION_STATUS;
267
+ /**
268
+ * The source of the animation which indicates where the animation was initiated from, such as user interaction, system event, or programmatic trigger.
269
+ * It is represented by the `ANIMATION_SOURCE` enum, which includes values like 'user', 'system', etc.
270
+ */
271
+ source: ANIMATION_SOURCE;
272
+ /**
273
+ * The index of the next snap point that the animation is targeting.
274
+ */
275
+ nextIndex?: number;
276
+ /**
277
+ * The next position in pixels that the animation is targeting.
278
+ */
279
+ nextPosition?: number;
280
+ /**
281
+ * Indicates whether the animation is forced closing to prevent any interruptions.
282
+ */
283
+ isForcedClosing?: boolean;
284
+ };
285
+
286
+ /**
287
+ * Represents the layout state of the bottom sheet container.
288
+ */
289
+ export type ContainerLayoutState = {
290
+ /**
291
+ * The height of the container in pixels.
292
+ */
293
+ height: number;
294
+ /**
295
+ * The required insets applied to the container, such as padding or safe area.
296
+ */
297
+ offset: Required<Insets>;
298
+ };
299
+
300
+ /**
301
+ * Represents the layout state of the bottom sheet components.
302
+ */
303
+ export type LayoutState = {
304
+ /**
305
+ * The original height of the container before any adjustments.
306
+ */
307
+ rawContainerHeight: number;
308
+ /**
309
+ * The adjusted height of the container after applying insets or other modifications.
310
+ */
311
+ containerHeight: number;
312
+ /**
313
+ * The required insets applied to the container, such as padding or safe area.
314
+ */
315
+ containerOffset: Required<Insets>;
316
+ /**
317
+ * The height of the handle element used to drag the bottom sheet.
318
+ */
319
+ handleHeight: number;
320
+ /**
321
+ * The height of the footer section within the bottom sheet.
322
+ */
323
+ footerHeight: number;
324
+ /**
325
+ * The total height of the content inside the bottom sheet.
326
+ */
327
+ contentHeight: number;
328
+ };
329
+
330
+ export type DetentsState = {
331
+ detents?: number[];
332
+ dynamicDetentIndex?: number;
333
+ highestDetentPosition?: number;
334
+ closedDetentPosition?: number;
335
+ };
336
+ //#endregion
@@ -0,0 +1,56 @@
1
+ import {
2
+ type AnimationCallback,
3
+ type ReduceMotion,
4
+ type WithSpringConfig,
5
+ type WithTimingConfig,
6
+ withSpring,
7
+ withTiming,
8
+ } from 'react-native-reanimated';
9
+ import { ANIMATION_CONFIGS, ANIMATION_METHOD } from '../constants';
10
+
11
+ interface AnimateParams {
12
+ point: number;
13
+ velocity?: number;
14
+ configs?: WithSpringConfig | WithTimingConfig;
15
+ overrideReduceMotion?: ReduceMotion;
16
+ onComplete?: AnimationCallback;
17
+ }
18
+
19
+ export const animate = ({
20
+ point,
21
+ configs,
22
+ velocity = 0,
23
+ overrideReduceMotion,
24
+ onComplete,
25
+ }: AnimateParams) => {
26
+ 'worklet';
27
+
28
+ if (!configs) {
29
+ configs = ANIMATION_CONFIGS;
30
+ }
31
+
32
+ // Users might have an accessibility setting to reduce motion turned on.
33
+ // This prevents the animation from running when presenting the sheet, which results in
34
+ // the bottom sheet not even appearing so we need to override it to ensure the animation runs.
35
+ // configs.reduceMotion = ReduceMotion.Never;
36
+
37
+ if (overrideReduceMotion) {
38
+ configs.reduceMotion = overrideReduceMotion;
39
+ }
40
+
41
+ // detect animation type
42
+ const type =
43
+ 'duration' in configs || 'easing' in configs
44
+ ? ANIMATION_METHOD.TIMING
45
+ : ANIMATION_METHOD.SPRING;
46
+
47
+ if (type === ANIMATION_METHOD.TIMING) {
48
+ return withTiming(point, configs as WithTimingConfig, onComplete);
49
+ }
50
+
51
+ return withSpring(
52
+ point,
53
+ Object.assign({ velocity }, configs) as WithSpringConfig,
54
+ onComplete
55
+ );
56
+ };
@@ -0,0 +1,8 @@
1
+ export const clamp = (
2
+ value: number,
3
+ lowerBound: number,
4
+ upperBound: number
5
+ ) => {
6
+ 'worklet';
7
+ return Math.min(Math.max(lowerBound, value), upperBound);
8
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A modified version of the default AnimatedEasing.exp,
3
+ * to insure its value never goes below `0`.
4
+ * @see https://github.com/software-mansion/react-native-reanimated/issues/1610
5
+ * @param t number
6
+ */
7
+ export const exp = (t: number) => {
8
+ 'worklet';
9
+ return Math.min(Math.max(0, Math.pow(2, 10 * (t - 1))), 1);
10
+ };
@@ -0,0 +1 @@
1
+ export { findNodeHandle } from 'react-native';
@@ -0,0 +1,33 @@
1
+ import {
2
+ type NodeHandle,
3
+ findNodeHandle as _findNodeHandle,
4
+ } from 'react-native';
5
+
6
+ export function findNodeHandle(
7
+ componentOrHandle: Parameters<typeof _findNodeHandle>['0']
8
+ ) {
9
+ let nodeHandle: NodeHandle | null;
10
+ try {
11
+ nodeHandle = _findNodeHandle(componentOrHandle);
12
+ if (nodeHandle) {
13
+ return nodeHandle;
14
+ }
15
+ } catch {}
16
+
17
+ try {
18
+ // @ts-ignore
19
+ nodeHandle = componentOrHandle.getNativeScrollRef();
20
+ if (nodeHandle) {
21
+ return nodeHandle;
22
+ }
23
+ } catch {}
24
+
25
+ // @ts-ignore https://github.com/facebook/react-native/blob/a314e34d6ee875830d36e4df1789a897c7262056/packages/virtualized-lists/Lists/VirtualizedList.js#L1252
26
+ nodeHandle = componentOrHandle._scrollRef;
27
+ if (nodeHandle) {
28
+ return nodeHandle;
29
+ }
30
+
31
+ console.warn('could not find scrollable ref!');
32
+ return componentOrHandle;
33
+ }
@@ -0,0 +1,44 @@
1
+ import type { KeyboardEventEasing } from 'react-native';
2
+ import { Easing } from 'react-native-reanimated';
3
+
4
+ export const getKeyboardAnimationConfigs = (
5
+ easing: KeyboardEventEasing,
6
+ duration: number
7
+ ) => {
8
+ 'worklet';
9
+ switch (easing) {
10
+ case 'easeIn':
11
+ return {
12
+ easing: Easing.in(Easing.ease),
13
+ duration,
14
+ };
15
+
16
+ case 'easeOut':
17
+ return {
18
+ easing: Easing.out(Easing.ease),
19
+ duration,
20
+ };
21
+
22
+ case 'easeInEaseOut':
23
+ return {
24
+ easing: Easing.inOut(Easing.ease),
25
+ duration,
26
+ };
27
+
28
+ case 'linear':
29
+ return {
30
+ easing: Easing.linear,
31
+ duration,
32
+ };
33
+
34
+ case 'keyboard':
35
+ return {
36
+ damping: 500,
37
+ stiffness: 1000,
38
+ mass: 3,
39
+ overshootClamping: true,
40
+ restDisplacementThreshold: 10,
41
+ restSpeedThreshold: 10,
42
+ };
43
+ }
44
+ };
@@ -0,0 +1,6 @@
1
+ import type { RefObject } from 'react';
2
+ import { findNodeHandle } from 'react-native';
3
+
4
+ export function getRefNativeTag(ref: RefObject<never>) {
5
+ return findNodeHandle(ref?.current) || null;
6
+ }
@@ -0,0 +1,6 @@
1
+ let current = 0;
2
+
3
+ export const id = () => {
4
+ current = (current + 1) % Number.MAX_SAFE_INTEGER;
5
+ return current;
6
+ };
@@ -0,0 +1,7 @@
1
+ export { normalizeSnapPoint } from './normalizeSnapPoint';
2
+ export { animate } from './animate';
3
+ export { getKeyboardAnimationConfigs } from './getKeyboardAnimationConfigs';
4
+ export { print } from './logger';
5
+ export { noop, workletNoop } from './noop';
6
+ export { isFabricInstalled } from './isFabricInstalled';
7
+ export { findNodeHandle } from './findNodeHandle';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Checks if the Fabric renderer is installed in the current environment.
3
+ *
4
+ * @returns {boolean} `true` if Fabric is installed, otherwise `false`.
5
+ */
6
+ export function isFabricInstalled() {
7
+ // @ts-ignore
8
+ return global?.nativeFabricUIManager != null;
9
+ }
@@ -0,0 +1,55 @@
1
+ interface PrintOptions {
2
+ component?: string;
3
+ category?: 'layout' | 'effect' | 'callback';
4
+ method?: string;
5
+ params?: Record<string, unknown> | string | number | boolean;
6
+ }
7
+
8
+ type Print = (options: PrintOptions) => void;
9
+
10
+ let _isLoggingEnabled = false;
11
+ let _excludeCategories: PrintOptions['category'][] | undefined;
12
+
13
+ const enableLogging = (excludeCategories?: PrintOptions['category'][]) => {
14
+ if (!__DEV__) {
15
+ console.warn('[BottomSheet] could not enable logging on production!');
16
+ return;
17
+ }
18
+
19
+ _isLoggingEnabled = true;
20
+ _excludeCategories = excludeCategories;
21
+ };
22
+
23
+ let print: Print = () => {};
24
+
25
+ if (__DEV__) {
26
+ print = ({ component, method, params, category }) => {
27
+ if (!_isLoggingEnabled) {
28
+ return;
29
+ }
30
+
31
+ if (
32
+ category &&
33
+ _excludeCategories &&
34
+ _excludeCategories.includes(category)
35
+ ) {
36
+ return;
37
+ }
38
+
39
+ let message = '';
40
+
41
+ if (typeof params === 'object') {
42
+ message = Object.keys(params)
43
+ .map(key => `${key}:${params[key]}`)
44
+ .join(' ');
45
+ } else {
46
+ message = `${params ?? ''}`;
47
+ }
48
+ // biome-ignore lint/suspicious/noConsole: used for debugging
49
+ console.log(`[${[component, method].filter(Boolean).join('::')}]`, message);
50
+ };
51
+ }
52
+
53
+ Object.freeze(print);
54
+
55
+ export { print, enableLogging };
@@ -0,0 +1,7 @@
1
+ const workletNoop = () => {
2
+ 'worklet';
3
+ };
4
+
5
+ const noop = () => {};
6
+
7
+ export { noop, workletNoop };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Converts a snap point to fixed numbers.
3
+ */
4
+ export const normalizeSnapPoint = (
5
+ snapPoint: number | string,
6
+ containerHeight: number
7
+ ) => {
8
+ 'worklet';
9
+ let normalizedSnapPoint = snapPoint;
10
+
11
+ // percentage snap point
12
+ if (typeof normalizedSnapPoint === 'string') {
13
+ normalizedSnapPoint =
14
+ (Number(normalizedSnapPoint.split('%')[0]) * containerHeight) / 100;
15
+ }
16
+ return Math.max(0, containerHeight - normalizedSnapPoint);
17
+ };