@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,102 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
type ComponentProps,
|
|
3
|
+
forwardRef,
|
|
4
|
+
useCallback,
|
|
5
|
+
useRef,
|
|
6
|
+
} from 'react';
|
|
7
|
+
import type { LayoutChangeEvent, ViewProps } from 'react-native';
|
|
8
|
+
import type { SimultaneousGesture } from 'react-native-gesture-handler';
|
|
9
|
+
import Animated from 'react-native-reanimated';
|
|
10
|
+
import { INITIAL_LAYOUT_VALUE } from '../../constants';
|
|
11
|
+
import { useBottomSheetInternal } from '../../hooks';
|
|
12
|
+
import { BottomSheetDraggableScrollable } from './BottomSheetDraggableScrollable';
|
|
13
|
+
|
|
14
|
+
interface ScrollableContainerProps {
|
|
15
|
+
nativeGesture: SimultaneousGesture;
|
|
16
|
+
setContentSize: (contentHeight: number) => void;
|
|
17
|
+
// biome-ignore lint/suspicious/noExplicitAny: 🤷♂️
|
|
18
|
+
ScrollableComponent: any;
|
|
19
|
+
onLayout: ViewProps['onLayout'];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Detect if the current browser is Safari or not.
|
|
24
|
+
*/
|
|
25
|
+
const isWebkit = () => {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
return navigator.userAgent.indexOf('Safari') > -1;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ScrollableContainer = forwardRef<
|
|
31
|
+
never,
|
|
32
|
+
ScrollableContainerProps & { animatedProps: never }
|
|
33
|
+
>(function ScrollableContainer(
|
|
34
|
+
{
|
|
35
|
+
nativeGesture,
|
|
36
|
+
ScrollableComponent,
|
|
37
|
+
animatedProps,
|
|
38
|
+
setContentSize,
|
|
39
|
+
onLayout,
|
|
40
|
+
...rest
|
|
41
|
+
},
|
|
42
|
+
ref
|
|
43
|
+
) {
|
|
44
|
+
//#region refs
|
|
45
|
+
const isInitialContentHeightCaptured = useRef(false);
|
|
46
|
+
//#endregion
|
|
47
|
+
|
|
48
|
+
//#region hooks
|
|
49
|
+
const { animatedLayoutState } = useBottomSheetInternal();
|
|
50
|
+
//#endregion
|
|
51
|
+
|
|
52
|
+
//#region callbacks
|
|
53
|
+
const renderScrollComponent = useCallback(
|
|
54
|
+
(props: ComponentProps<typeof Animated.ScrollView>) => (
|
|
55
|
+
<Animated.ScrollView {...props} animatedProps={animatedProps} />
|
|
56
|
+
),
|
|
57
|
+
[animatedProps]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A workaround a bug in React Native Web [#1502](https://github.com/necolas/react-native-web/issues/1502),
|
|
62
|
+
* where the `onContentSizeChange` won't be call on initial render.
|
|
63
|
+
*/
|
|
64
|
+
const handleOnLayout = useCallback(
|
|
65
|
+
(event: LayoutChangeEvent) => {
|
|
66
|
+
if (onLayout) {
|
|
67
|
+
onLayout(event);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!isInitialContentHeightCaptured.current) {
|
|
71
|
+
isInitialContentHeightCaptured.current = true;
|
|
72
|
+
if (!isWebkit()) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* early exit if the content height been calculated.
|
|
78
|
+
*/
|
|
79
|
+
if (animatedLayoutState.get().contentHeight !== INITIAL_LAYOUT_VALUE) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
window.requestAnimationFrame(() => {
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
setContentSize(event.nativeEvent.target.clientHeight);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
[onLayout, setContentSize, animatedLayoutState]
|
|
90
|
+
);
|
|
91
|
+
//#endregion
|
|
92
|
+
return (
|
|
93
|
+
<BottomSheetDraggableScrollable scrollableGesture={nativeGesture}>
|
|
94
|
+
<ScrollableComponent
|
|
95
|
+
ref={ref}
|
|
96
|
+
{...rest}
|
|
97
|
+
onLayout={handleOnLayout}
|
|
98
|
+
renderScrollComponent={renderScrollComponent}
|
|
99
|
+
/>
|
|
100
|
+
</BottomSheetDraggableScrollable>
|
|
101
|
+
);
|
|
102
|
+
});
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useContext,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useMemo,
|
|
6
|
+
} from 'react';
|
|
7
|
+
import { Gesture } from 'react-native-gesture-handler';
|
|
8
|
+
import { useAnimatedProps } from 'react-native-reanimated';
|
|
9
|
+
import {
|
|
10
|
+
SCROLLABLE_DECELERATION_RATE_MAPPER,
|
|
11
|
+
SCROLLABLE_STATUS,
|
|
12
|
+
type SCROLLABLE_TYPE,
|
|
13
|
+
} from '../../constants';
|
|
14
|
+
import { BottomSheetDraggableContext } from '../../contexts/gesture';
|
|
15
|
+
import {
|
|
16
|
+
useBottomSheetContentContainerStyle,
|
|
17
|
+
useBottomSheetInternal,
|
|
18
|
+
useScrollHandler,
|
|
19
|
+
useScrollableSetter,
|
|
20
|
+
useStableCallback,
|
|
21
|
+
} from '../../hooks';
|
|
22
|
+
import { ScrollableContainer } from './ScrollableContainer';
|
|
23
|
+
import { useBottomSheetContentSizeSetter } from './useBottomSheetContentSizeSetter';
|
|
24
|
+
|
|
25
|
+
export function createBottomSheetScrollableComponent<T, P>(
|
|
26
|
+
type: SCROLLABLE_TYPE,
|
|
27
|
+
// biome-ignore lint: to be addressed!
|
|
28
|
+
ScrollableComponent: any
|
|
29
|
+
) {
|
|
30
|
+
return forwardRef<T, P>((props, ref) => {
|
|
31
|
+
//#region props
|
|
32
|
+
const {
|
|
33
|
+
// hooks
|
|
34
|
+
focusHook,
|
|
35
|
+
scrollEventsHandlersHook,
|
|
36
|
+
// props
|
|
37
|
+
enableFooterMarginAdjustment = false,
|
|
38
|
+
overScrollMode = 'never',
|
|
39
|
+
keyboardDismissMode = 'interactive',
|
|
40
|
+
showsVerticalScrollIndicator = true,
|
|
41
|
+
contentContainerStyle: _providedContentContainerStyle,
|
|
42
|
+
refreshing,
|
|
43
|
+
onRefresh,
|
|
44
|
+
progressViewOffset,
|
|
45
|
+
refreshControl,
|
|
46
|
+
// events
|
|
47
|
+
onScroll,
|
|
48
|
+
onScrollBeginDrag,
|
|
49
|
+
onScrollEndDrag,
|
|
50
|
+
onContentSizeChange,
|
|
51
|
+
...rest
|
|
52
|
+
// biome-ignore lint: to be addressed!
|
|
53
|
+
}: any = props;
|
|
54
|
+
//#endregion
|
|
55
|
+
|
|
56
|
+
//#region hooks
|
|
57
|
+
const draggableGesture = useContext(BottomSheetDraggableContext);
|
|
58
|
+
const { scrollableRef, scrollableContentOffsetY, scrollHandler } =
|
|
59
|
+
useScrollHandler(
|
|
60
|
+
scrollEventsHandlersHook,
|
|
61
|
+
onScroll,
|
|
62
|
+
onScrollBeginDrag,
|
|
63
|
+
onScrollEndDrag
|
|
64
|
+
);
|
|
65
|
+
const {
|
|
66
|
+
animatedScrollableStatus: animatedScrollableState,
|
|
67
|
+
enableContentPanningGesture,
|
|
68
|
+
} = useBottomSheetInternal();
|
|
69
|
+
const { setContentSize } = useBottomSheetContentSizeSetter();
|
|
70
|
+
//#endregion
|
|
71
|
+
|
|
72
|
+
if (!draggableGesture && enableContentPanningGesture) {
|
|
73
|
+
throw "'Scrollable' cannot be used out of the BottomSheet!";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//#region variables
|
|
77
|
+
const scrollableAnimatedProps = useAnimatedProps(
|
|
78
|
+
() => ({
|
|
79
|
+
decelerationRate:
|
|
80
|
+
SCROLLABLE_DECELERATION_RATE_MAPPER[animatedScrollableState.value],
|
|
81
|
+
showsVerticalScrollIndicator: showsVerticalScrollIndicator
|
|
82
|
+
? animatedScrollableState.value === SCROLLABLE_STATUS.UNLOCKED
|
|
83
|
+
: showsVerticalScrollIndicator,
|
|
84
|
+
}),
|
|
85
|
+
[animatedScrollableState, showsVerticalScrollIndicator]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const scrollableGesture = useMemo(
|
|
89
|
+
() =>
|
|
90
|
+
draggableGesture
|
|
91
|
+
? Gesture.Native()
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
.simultaneousWithExternalGesture(draggableGesture)
|
|
94
|
+
.shouldCancelWhenOutside(false)
|
|
95
|
+
: undefined,
|
|
96
|
+
[draggableGesture]
|
|
97
|
+
);
|
|
98
|
+
//#endregion
|
|
99
|
+
|
|
100
|
+
//#region callbacks
|
|
101
|
+
const handleContentSizeChange = useStableCallback(
|
|
102
|
+
(contentWidth: number, contentHeight: number) => {
|
|
103
|
+
setContentSize(contentHeight);
|
|
104
|
+
if (onContentSizeChange) {
|
|
105
|
+
onContentSizeChange(contentWidth, contentHeight);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
//#endregion
|
|
110
|
+
|
|
111
|
+
//#region styles
|
|
112
|
+
const contentContainerStyle = useBottomSheetContentContainerStyle(
|
|
113
|
+
enableFooterMarginAdjustment,
|
|
114
|
+
_providedContentContainerStyle
|
|
115
|
+
);
|
|
116
|
+
//#endregion
|
|
117
|
+
|
|
118
|
+
//#region effects
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
useImperativeHandle(ref, () => scrollableRef.current);
|
|
121
|
+
useScrollableSetter(
|
|
122
|
+
scrollableRef,
|
|
123
|
+
type,
|
|
124
|
+
scrollableContentOffsetY,
|
|
125
|
+
onRefresh !== undefined,
|
|
126
|
+
focusHook
|
|
127
|
+
);
|
|
128
|
+
//#endregion
|
|
129
|
+
|
|
130
|
+
//#region render
|
|
131
|
+
return (
|
|
132
|
+
<ScrollableContainer
|
|
133
|
+
ref={scrollableRef}
|
|
134
|
+
nativeGesture={scrollableGesture}
|
|
135
|
+
animatedProps={scrollableAnimatedProps}
|
|
136
|
+
overScrollMode={overScrollMode}
|
|
137
|
+
keyboardDismissMode={keyboardDismissMode}
|
|
138
|
+
refreshing={refreshing}
|
|
139
|
+
scrollEventThrottle={16}
|
|
140
|
+
progressViewOffset={progressViewOffset}
|
|
141
|
+
contentContainerStyle={contentContainerStyle}
|
|
142
|
+
onRefresh={onRefresh}
|
|
143
|
+
onScroll={scrollHandler}
|
|
144
|
+
onContentSizeChange={handleContentSizeChange}
|
|
145
|
+
setContentSize={setContentSize}
|
|
146
|
+
ScrollableComponent={ScrollableComponent}
|
|
147
|
+
refreshControl={refreshControl}
|
|
148
|
+
{...rest}
|
|
149
|
+
/>
|
|
150
|
+
);
|
|
151
|
+
//#endregion
|
|
152
|
+
});
|
|
153
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { createBottomSheetScrollableComponent } from './createBottomSheetScrollableComponent';
|
|
2
|
+
export { default as BottomSheetSectionList } from './BottomSheetSectionList';
|
|
3
|
+
export { default as BottomSheetFlatList } from './BottomSheetFlatList';
|
|
4
|
+
export { default as BottomSheetScrollView } from './BottomSheetScrollView';
|
|
5
|
+
export { default as BottomSheetVirtualizedList } from './BottomSheetVirtualizedList';
|
|
6
|
+
|
|
7
|
+
export { default as BottomSheetFlashList } from './BottomSheetFlashList';
|
|
8
|
+
|
|
9
|
+
export type {
|
|
10
|
+
BottomSheetFlatListMethods,
|
|
11
|
+
BottomSheetScrollViewMethods,
|
|
12
|
+
BottomSheetSectionListMethods,
|
|
13
|
+
BottomSheetVirtualizedListMethods,
|
|
14
|
+
BottomSheetScrollableProps,
|
|
15
|
+
} from './types';
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DependencyList,
|
|
3
|
+
EffectCallback,
|
|
4
|
+
ReactNode,
|
|
5
|
+
Ref,
|
|
6
|
+
RefObject,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import type {
|
|
9
|
+
FlatListProps,
|
|
10
|
+
NodeHandle,
|
|
11
|
+
ScrollResponderMixin,
|
|
12
|
+
ScrollViewComponent,
|
|
13
|
+
ScrollViewProps,
|
|
14
|
+
SectionListProps,
|
|
15
|
+
SectionListScrollParams,
|
|
16
|
+
View,
|
|
17
|
+
VirtualizedListProps,
|
|
18
|
+
} from 'react-native';
|
|
19
|
+
import type Animated from 'react-native-reanimated';
|
|
20
|
+
import type { ScrollEventsHandlersHookType } from '../../types';
|
|
21
|
+
|
|
22
|
+
export interface BottomSheetScrollableProps {
|
|
23
|
+
/**
|
|
24
|
+
* Adjust the scrollable bottom margin to avoid the animated footer.
|
|
25
|
+
*
|
|
26
|
+
* @type boolean
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
enableFooterMarginAdjustment?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This needed when bottom sheet used with multiple scrollables to allow bottom sheet
|
|
33
|
+
* detect the current scrollable ref, especially when used with `React Navigation`.
|
|
34
|
+
* You will need to provide `useFocusEffect` from `@react-navigation/native`.
|
|
35
|
+
*
|
|
36
|
+
* @type (effect: EffectCallback, deps?: DependencyList) => void
|
|
37
|
+
* @default useEffect
|
|
38
|
+
*/
|
|
39
|
+
focusHook?: (effect: EffectCallback, deps?: DependencyList) => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Custom hook to provide scroll events handler, which will allow advance and
|
|
43
|
+
* customize handling for scrollables.
|
|
44
|
+
*
|
|
45
|
+
* @warning this is an experimental feature and the hook signature can change without a major version bump.
|
|
46
|
+
* @type ScrollEventsHandlersHookType
|
|
47
|
+
* @default useScrollEventsHandlersDefault
|
|
48
|
+
*/
|
|
49
|
+
scrollEventsHandlersHook?: ScrollEventsHandlersHookType;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type ScrollableProps<T> =
|
|
53
|
+
| ScrollViewProps
|
|
54
|
+
| FlatListProps<T>
|
|
55
|
+
| SectionListProps<T>;
|
|
56
|
+
|
|
57
|
+
//#region FlatList
|
|
58
|
+
export type BottomSheetFlatListProps<T> = Omit<
|
|
59
|
+
Animated.AnimateProps<FlatListProps<T>>,
|
|
60
|
+
'decelerationRate' | 'onScroll' | 'scrollEventThrottle'
|
|
61
|
+
> &
|
|
62
|
+
BottomSheetScrollableProps & {
|
|
63
|
+
ref?: Ref<BottomSheetFlatListMethods>;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export interface BottomSheetFlatListMethods {
|
|
67
|
+
/**
|
|
68
|
+
* Scrolls to the end of the content. May be janky without `getItemLayout` prop.
|
|
69
|
+
*/
|
|
70
|
+
scrollToEnd: (params?: { animated?: boolean | null }) => void;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Scrolls to the item at the specified index such that it is positioned in the viewable area
|
|
74
|
+
* such that viewPosition 0 places it at the top, 1 at the bottom, and 0.5 centered in the middle.
|
|
75
|
+
* Cannot scroll to locations outside the render window without specifying the getItemLayout prop.
|
|
76
|
+
*/
|
|
77
|
+
scrollToIndex: (params: {
|
|
78
|
+
animated?: boolean | null;
|
|
79
|
+
index: number;
|
|
80
|
+
viewOffset?: number;
|
|
81
|
+
viewPosition?: number;
|
|
82
|
+
}) => void;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Requires linear scan through data - use `scrollToIndex` instead if possible.
|
|
86
|
+
* May be janky without `getItemLayout` prop.
|
|
87
|
+
*/
|
|
88
|
+
scrollToItem: (params: {
|
|
89
|
+
animated?: boolean | null;
|
|
90
|
+
// biome-ignore lint: to be addressed!
|
|
91
|
+
item: any;
|
|
92
|
+
viewPosition?: number;
|
|
93
|
+
}) => void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Scroll to a specific content pixel offset, like a normal `ScrollView`.
|
|
97
|
+
*/
|
|
98
|
+
scrollToOffset: (params: {
|
|
99
|
+
animated?: boolean | null;
|
|
100
|
+
offset: number;
|
|
101
|
+
}) => void;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Tells the list an interaction has occured, which should trigger viewability calculations,
|
|
105
|
+
* e.g. if waitForInteractions is true and the user has not scrolled. This is typically called
|
|
106
|
+
* by taps on items or by navigation actions.
|
|
107
|
+
*/
|
|
108
|
+
recordInteraction: () => void;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Displays the scroll indicators momentarily.
|
|
112
|
+
*/
|
|
113
|
+
flashScrollIndicators: () => void;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Provides a handle to the underlying scroll responder.
|
|
117
|
+
*/
|
|
118
|
+
getScrollResponder: () => ScrollResponderMixin | null | undefined;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Provides a reference to the underlying host component
|
|
122
|
+
*/
|
|
123
|
+
getNativeScrollRef: () =>
|
|
124
|
+
| RefObject<View>
|
|
125
|
+
| RefObject<ScrollViewComponent>
|
|
126
|
+
| null
|
|
127
|
+
| undefined;
|
|
128
|
+
|
|
129
|
+
// biome-ignore lint: to be addressed!
|
|
130
|
+
getScrollableNode: () => any;
|
|
131
|
+
|
|
132
|
+
// biome-ignore lint: to be addressed!
|
|
133
|
+
setNativeProps: (props: { [key: string]: any }) => void;
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
|
|
137
|
+
//#region ScrollView
|
|
138
|
+
export type BottomSheetScrollViewProps = Omit<
|
|
139
|
+
Animated.AnimateProps<ScrollViewProps>,
|
|
140
|
+
'decelerationRate' | 'scrollEventThrottle'
|
|
141
|
+
> &
|
|
142
|
+
BottomSheetScrollableProps & {
|
|
143
|
+
ref?: Ref<BottomSheetScrollViewMethods>;
|
|
144
|
+
children: ReactNode | ReactNode[];
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export interface BottomSheetScrollViewMethods {
|
|
148
|
+
/**
|
|
149
|
+
* Scrolls to a given x, y offset, either immediately or with a smooth animation.
|
|
150
|
+
* Syntax:
|
|
151
|
+
*
|
|
152
|
+
* scrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})
|
|
153
|
+
*
|
|
154
|
+
* Note: The weird argument signature is due to the fact that, for historical reasons,
|
|
155
|
+
* the function also accepts separate arguments as an alternative to the options object.
|
|
156
|
+
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
|
157
|
+
*/
|
|
158
|
+
scrollTo(
|
|
159
|
+
y?: number | { x?: number; y?: number; animated?: boolean },
|
|
160
|
+
x?: number,
|
|
161
|
+
animated?: boolean
|
|
162
|
+
): void;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A helper function that scrolls to the end of the scrollview;
|
|
166
|
+
* If this is a vertical ScrollView, it scrolls to the bottom.
|
|
167
|
+
* If this is a horizontal ScrollView scrolls to the right.
|
|
168
|
+
*
|
|
169
|
+
* The options object has an animated prop, that enables the scrolling animation or not.
|
|
170
|
+
* The animated prop defaults to true
|
|
171
|
+
*/
|
|
172
|
+
scrollToEnd(options?: { animated: boolean }): void;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Returns a reference to the underlying scroll responder, which supports
|
|
176
|
+
* operations like `scrollTo`. All ScrollView-like components should
|
|
177
|
+
* implement this method so that they can be composed while providing access
|
|
178
|
+
* to the underlying scroll responder's methods.
|
|
179
|
+
*/
|
|
180
|
+
getScrollResponder(): ScrollResponderMixin;
|
|
181
|
+
|
|
182
|
+
// biome-ignore lint: to be addressed!
|
|
183
|
+
getScrollableNode(): any;
|
|
184
|
+
|
|
185
|
+
// biome-ignore lint: to be addressed!
|
|
186
|
+
getInnerViewNode(): any;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @deprecated Use scrollTo instead
|
|
190
|
+
*/
|
|
191
|
+
scrollWithoutAnimationTo?: (y: number, x: number) => void;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* This function sends props straight to native. They will not participate in
|
|
195
|
+
* future diff process - this means that if you do not include them in the
|
|
196
|
+
* next render, they will remain active (see [Direct
|
|
197
|
+
* Manipulation](https://reactnative.dev/docs/direct-manipulation)).
|
|
198
|
+
*/
|
|
199
|
+
setNativeProps(nativeProps: object): void;
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
|
|
203
|
+
//#region SectionList
|
|
204
|
+
export type BottomSheetSectionListProps<ItemT, SectionT> = Omit<
|
|
205
|
+
Animated.AnimateProps<SectionListProps<ItemT, SectionT>>,
|
|
206
|
+
'decelerationRate' | 'scrollEventThrottle'
|
|
207
|
+
> &
|
|
208
|
+
BottomSheetScrollableProps & {
|
|
209
|
+
ref?: Ref<BottomSheetSectionListMethods>;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export interface BottomSheetSectionListMethods {
|
|
213
|
+
/**
|
|
214
|
+
* Scrolls to the item at the specified sectionIndex and itemIndex (within the section)
|
|
215
|
+
* positioned in the viewable area such that viewPosition 0 places it at the top
|
|
216
|
+
* (and may be covered by a sticky header), 1 at the bottom, and 0.5 centered in the middle.
|
|
217
|
+
*/
|
|
218
|
+
scrollToLocation(params: SectionListScrollParams): void;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Tells the list an interaction has occurred, which should trigger viewability calculations, e.g.
|
|
222
|
+
* if `waitForInteractions` is true and the user has not scrolled. This is typically called by
|
|
223
|
+
* taps on items or by navigation actions.
|
|
224
|
+
*/
|
|
225
|
+
recordInteraction(): void;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Displays the scroll indicators momentarily.
|
|
229
|
+
*
|
|
230
|
+
* @platform ios
|
|
231
|
+
*/
|
|
232
|
+
flashScrollIndicators(): void;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Provides a handle to the underlying scroll responder.
|
|
236
|
+
*/
|
|
237
|
+
getScrollResponder(): ScrollResponderMixin | undefined;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Provides a handle to the underlying scroll node.
|
|
241
|
+
*/
|
|
242
|
+
getScrollableNode(): NodeHandle | undefined;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
|
|
246
|
+
//#region
|
|
247
|
+
export type BottomSheetVirtualizedListProps<T> = Omit<
|
|
248
|
+
Animated.AnimateProps<VirtualizedListProps<T>>,
|
|
249
|
+
'decelerationRate' | 'scrollEventThrottle'
|
|
250
|
+
> &
|
|
251
|
+
BottomSheetScrollableProps & {
|
|
252
|
+
ref?: Ref<BottomSheetVirtualizedListMethods>;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export interface BottomSheetVirtualizedListMethods {
|
|
256
|
+
scrollToEnd: (params?: { animated?: boolean }) => void;
|
|
257
|
+
scrollToIndex: (params: {
|
|
258
|
+
animated?: boolean;
|
|
259
|
+
index: number;
|
|
260
|
+
viewOffset?: number;
|
|
261
|
+
viewPosition?: number;
|
|
262
|
+
}) => void;
|
|
263
|
+
scrollToItem: (params: {
|
|
264
|
+
animated?: boolean;
|
|
265
|
+
// biome-ignore lint: to be addressed!
|
|
266
|
+
item: any;
|
|
267
|
+
viewPosition?: number;
|
|
268
|
+
}) => void;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Scroll to a specific content pixel offset in the list.
|
|
272
|
+
* Param `offset` expects the offset to scroll to. In case of horizontal is true, the
|
|
273
|
+
* offset is the x-value, in any other case the offset is the y-value.
|
|
274
|
+
* Param `animated` (true by default) defines whether the list should do an animation while scrolling.
|
|
275
|
+
*/
|
|
276
|
+
scrollToOffset: (params: { animated?: boolean; offset: number }) => void;
|
|
277
|
+
|
|
278
|
+
recordInteraction: () => void;
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useBottomSheetInternal } from '../../hooks';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A hook to set the content size properly into the bottom sheet,
|
|
6
|
+
* internals.
|
|
7
|
+
*/
|
|
8
|
+
export function useBottomSheetContentSizeSetter() {
|
|
9
|
+
//#region hooks
|
|
10
|
+
const { enableDynamicSizing, animatedLayoutState } = useBottomSheetInternal();
|
|
11
|
+
//#endregion
|
|
12
|
+
|
|
13
|
+
//#region methods
|
|
14
|
+
const setContentSize = useCallback(
|
|
15
|
+
(contentHeight: number) => {
|
|
16
|
+
if (!enableDynamicSizing) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
animatedLayoutState.modify(state => {
|
|
20
|
+
'worklet';
|
|
21
|
+
state.contentHeight = contentHeight;
|
|
22
|
+
return state;
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
[enableDynamicSizing, animatedLayoutState]
|
|
26
|
+
);
|
|
27
|
+
//#endregion
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
setContentSize,
|
|
31
|
+
};
|
|
32
|
+
}
|