@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
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,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,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,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
|
+
};
|