@niibase/bottom-sheet-manager 1.2.0 → 1.4.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/README.md +414 -69
- package/lib/commonjs/events.js +100 -15
- package/lib/commonjs/events.js.map +1 -1
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/manager.js +153 -35
- package/lib/commonjs/manager.js.map +1 -1
- package/lib/commonjs/provider.js +92 -54
- package/lib/commonjs/provider.js.map +1 -1
- package/lib/commonjs/router/index.js +80 -21
- package/lib/commonjs/router/index.js.map +1 -1
- package/lib/commonjs/router/router.js +137 -12
- package/lib/commonjs/router/router.js.map +1 -1
- package/lib/commonjs/router/view.js +93 -126
- package/lib/commonjs/router/view.js.map +1 -1
- package/lib/commonjs/sheet.js +122 -98
- package/lib/commonjs/sheet.js.map +1 -1
- package/lib/module/events.js +100 -15
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/manager.js +154 -35
- package/lib/module/manager.js.map +1 -1
- package/lib/module/provider.js +87 -50
- package/lib/module/provider.js.map +1 -1
- package/lib/module/router/index.js +66 -19
- package/lib/module/router/index.js.map +1 -1
- package/lib/module/router/router.js +135 -11
- package/lib/module/router/router.js.map +1 -1
- package/lib/module/router/view.js +92 -126
- package/lib/module/router/view.js.map +1 -1
- package/lib/module/sheet.js +124 -100
- package/lib/module/sheet.js.map +1 -1
- package/lib/typescript/events.d.ts +46 -12
- package/lib/typescript/events.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/manager.d.ts +73 -7
- package/lib/typescript/manager.d.ts.map +1 -1
- package/lib/typescript/provider.d.ts +22 -16
- package/lib/typescript/provider.d.ts.map +1 -1
- package/lib/typescript/router/index.d.ts +47 -17
- package/lib/typescript/router/index.d.ts.map +1 -1
- package/lib/typescript/router/router.d.ts +44 -5
- package/lib/typescript/router/router.d.ts.map +1 -1
- package/lib/typescript/router/types.d.ts +142 -32
- package/lib/typescript/router/types.d.ts.map +1 -1
- package/lib/typescript/router/view.d.ts +3 -3
- package/lib/typescript/router/view.d.ts.map +1 -1
- package/lib/typescript/sheet.d.ts +1 -1
- package/lib/typescript/sheet.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +52 -21
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +14 -15
- package/src/events.ts +118 -27
- package/src/index.ts +2 -1
- package/src/manager.ts +209 -42
- package/src/provider.tsx +144 -71
- package/src/router/index.tsx +77 -33
- package/src/router/router.ts +188 -15
- package/src/router/types.ts +172 -57
- package/src/router/view.tsx +111 -213
- package/src/sheet.tsx +192 -124
- package/src/types.ts +51 -24
package/src/router/view.tsx
CHANGED
|
@@ -1,265 +1,163 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BottomSheetBackdrop,
|
|
3
|
-
BottomSheetModal,
|
|
4
|
-
BottomSheetModalProps,
|
|
5
|
-
BottomSheetModalProvider,
|
|
6
|
-
} from "@gorhom/bottom-sheet";
|
|
1
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
7
2
|
import { ParamListBase, useTheme } from "@react-navigation/native";
|
|
3
|
+
import { SNAP_POINT_TYPE } from "@gorhom/bottom-sheet";
|
|
8
4
|
import * as React from "react";
|
|
9
|
-
import { StatusBar } from "react-native";
|
|
10
|
-
import Animated, {
|
|
11
|
-
Easing,
|
|
12
|
-
interpolate,
|
|
13
|
-
interpolateColor,
|
|
14
|
-
runOnJS,
|
|
15
|
-
useAnimatedReaction,
|
|
16
|
-
useAnimatedStyle,
|
|
17
|
-
useSharedValue,
|
|
18
|
-
withSpring,
|
|
19
|
-
} from "react-native-reanimated";
|
|
20
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
21
5
|
|
|
22
6
|
import type {
|
|
23
7
|
BottomSheetDescriptorMap,
|
|
24
|
-
BottomSheetNavigationConfig,
|
|
25
8
|
BottomSheetNavigationHelpers,
|
|
26
|
-
BottomSheetNavigationProp,
|
|
27
9
|
BottomSheetNavigationState,
|
|
10
|
+
BottomSheetRoute,
|
|
28
11
|
} from "./types";
|
|
12
|
+
import { BottomSheetInstance, BottomSheetProps } from "../types";
|
|
13
|
+
import { BottomSheetActions } from "./router";
|
|
14
|
+
import BottomSheet from "../sheet";
|
|
29
15
|
|
|
30
|
-
type
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* @default false
|
|
35
|
-
*/
|
|
36
|
-
clickThrough?: boolean;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Opacity of the sheet's overlay.
|
|
40
|
-
* @default 0.45
|
|
41
|
-
*/
|
|
42
|
-
opacity?: number;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* IOS modal sheet type of animation
|
|
46
|
-
* @default false
|
|
47
|
-
*/
|
|
48
|
-
iosModalSheetTypeOfAnimation?: boolean;
|
|
16
|
+
type Props = {
|
|
17
|
+
state: BottomSheetNavigationState<ParamListBase>;
|
|
18
|
+
navigation: BottomSheetNavigationHelpers;
|
|
19
|
+
descriptors: BottomSheetDescriptorMap;
|
|
49
20
|
};
|
|
50
21
|
|
|
51
|
-
function
|
|
52
|
-
index,
|
|
53
|
-
navigation,
|
|
54
|
-
clickThrough,
|
|
55
|
-
iosModalSheetTypeOfAnimation,
|
|
56
|
-
opacity,
|
|
22
|
+
function BottomSheetScreen({
|
|
57
23
|
children,
|
|
24
|
+
navigation,
|
|
25
|
+
route,
|
|
58
26
|
...props
|
|
59
|
-
}:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
React.
|
|
65
|
-
ref.current?.present();
|
|
66
|
-
}, []);
|
|
27
|
+
}: BottomSheetProps & {
|
|
28
|
+
route: BottomSheetRoute<ParamListBase>;
|
|
29
|
+
navigation: BottomSheetNavigationHelpers;
|
|
30
|
+
}) {
|
|
31
|
+
const ref = React.useRef<BottomSheetInstance>(null);
|
|
32
|
+
const lastSnapIndexRef = React.useRef(route.snapToIndex ?? props.index ?? 0);
|
|
67
33
|
|
|
68
|
-
|
|
34
|
+
// Handle route closing state
|
|
69
35
|
React.useEffect(() => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
}, []);
|
|
36
|
+
if (route.closing) {
|
|
37
|
+
ref.current?.close();
|
|
38
|
+
}
|
|
39
|
+
}, [route.closing]);
|
|
74
40
|
|
|
41
|
+
// Handle snap point changes from navigation actions
|
|
75
42
|
React.useEffect(() => {
|
|
76
|
-
if (
|
|
77
|
-
ref.current?.snapToIndex(
|
|
43
|
+
if (route.snapToIndex != null && route.snapToIndex !== lastSnapIndexRef.current) {
|
|
44
|
+
ref.current?.snapToIndex(route.snapToIndex);
|
|
45
|
+
lastSnapIndexRef.current = route.snapToIndex;
|
|
78
46
|
}
|
|
79
|
-
}, [
|
|
47
|
+
}, [route.snapToIndex, route.snapToKey]);
|
|
48
|
+
|
|
49
|
+
const handleChange = React.useCallback(
|
|
50
|
+
(newIndex: number, position: number, type: SNAP_POINT_TYPE) => {
|
|
51
|
+
navigation.emit({
|
|
52
|
+
type: "sheetOnChange",
|
|
53
|
+
target: route.key,
|
|
54
|
+
data: { index: newIndex, position, type },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const currentIndex = lastSnapIndexRef.current;
|
|
58
|
+
lastSnapIndexRef.current = newIndex;
|
|
80
59
|
|
|
81
|
-
const onChange = React.useCallback(
|
|
82
|
-
(newIndex: number) => {
|
|
83
|
-
const currentIndex = lastIndexRef.current;
|
|
84
|
-
lastIndexRef.current = newIndex;
|
|
85
60
|
if (newIndex >= 0 && newIndex !== currentIndex) {
|
|
86
|
-
navigation.snapTo(newIndex);
|
|
61
|
+
navigation.dispatch(BottomSheetActions.snapTo(newIndex));
|
|
87
62
|
}
|
|
88
63
|
},
|
|
89
64
|
[navigation],
|
|
90
65
|
);
|
|
91
66
|
|
|
92
|
-
const onDismiss = React.useCallback(() => {
|
|
93
|
-
// BottomSheetModal will call onDismiss on unmount, be we do not want that since
|
|
94
|
-
// we already popped the screen.
|
|
95
|
-
if (isMounted.current) {
|
|
96
|
-
navigation.goBack();
|
|
97
|
-
}
|
|
98
|
-
}, [navigation]);
|
|
99
|
-
|
|
100
67
|
return (
|
|
101
|
-
<
|
|
102
|
-
ref={ref}
|
|
103
|
-
onDismiss={onDismiss}
|
|
104
|
-
onChange={onChange}
|
|
105
|
-
index={index}
|
|
106
|
-
backdropComponent={(props) => (
|
|
107
|
-
<BottomSheetBackdrop
|
|
108
|
-
{...props}
|
|
109
|
-
appearsOnIndex={0}
|
|
110
|
-
disappearsOnIndex={-1}
|
|
111
|
-
enableTouchThrough={!!clickThrough}
|
|
112
|
-
opacity={opacity || 0.45}
|
|
113
|
-
/>
|
|
114
|
-
)}
|
|
115
|
-
{...props}
|
|
116
|
-
>
|
|
68
|
+
<BottomSheet ref={ref} onChange={handleChange} {...props}>
|
|
117
69
|
{children}
|
|
118
|
-
</
|
|
70
|
+
</BottomSheet>
|
|
119
71
|
);
|
|
120
72
|
}
|
|
121
73
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
type Props = BottomSheetNavigationConfig & {
|
|
125
|
-
state: BottomSheetNavigationState<ParamListBase>;
|
|
126
|
-
navigation: BottomSheetNavigationHelpers;
|
|
127
|
-
descriptors: BottomSheetDescriptorMap;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export function BottomSheetView({ state, descriptors }: Props) {
|
|
74
|
+
export function BottomSheetView({ state, navigation, descriptors }: Props) {
|
|
131
75
|
const { colors } = useTheme();
|
|
132
|
-
const {
|
|
76
|
+
const { bottom, left, right } = useSafeAreaInsets();
|
|
77
|
+
|
|
133
78
|
const themeBackgroundStyle = React.useMemo(
|
|
134
79
|
() => ({
|
|
80
|
+
borderCurve: "continuous" as unknown as undefined,
|
|
135
81
|
backgroundColor: colors.card,
|
|
136
82
|
}),
|
|
137
83
|
[colors.card],
|
|
138
84
|
);
|
|
85
|
+
|
|
139
86
|
const themeHandleIndicatorStyle = React.useMemo(
|
|
140
87
|
() => ({
|
|
88
|
+
borderCurve: "continuous" as unknown as undefined,
|
|
141
89
|
backgroundColor: colors.border,
|
|
142
|
-
height: 5,
|
|
143
|
-
width: 50,
|
|
144
90
|
}),
|
|
145
91
|
[colors.border],
|
|
146
92
|
);
|
|
147
93
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
flex: 1,
|
|
152
|
-
backgroundColor: interpolateColor(
|
|
153
|
-
isFullScreen.value,
|
|
154
|
-
[0, 1],
|
|
155
|
-
["transparent", "#000"],
|
|
156
|
-
),
|
|
157
|
-
}));
|
|
158
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
159
|
-
flex: 1,
|
|
160
|
-
transform: [
|
|
161
|
-
{
|
|
162
|
-
scaleX: withSpring(interpolate(isFullScreen.value, [0, 1], [1, 0.92]), {
|
|
163
|
-
damping: 15,
|
|
164
|
-
stiffness: 100,
|
|
165
|
-
}),
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
translateY: withSpring(interpolate(isFullScreen.value, [0, 1], [0, top + 5]), {
|
|
169
|
-
damping: 15,
|
|
170
|
-
stiffness: 100,
|
|
171
|
-
}),
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
}));
|
|
175
|
-
|
|
176
|
-
// Since background color is white, we need to set status bar to light
|
|
177
|
-
const setStatusBar = StatusBar.setBarStyle;
|
|
178
|
-
useAnimatedReaction(
|
|
179
|
-
() => isFullScreen.value,
|
|
180
|
-
(currentValue) => {
|
|
181
|
-
"worklet";
|
|
182
|
-
if (currentValue > -1) {
|
|
183
|
-
runOnJS(setStatusBar)(currentValue >= 0.5 ? "light-content" : "default");
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
[],
|
|
94
|
+
const defaultStyle = React.useMemo(
|
|
95
|
+
() => ({ paddingBottom: bottom, paddingLeft: left, paddingRight: right }),
|
|
96
|
+
[bottom, left, right],
|
|
187
97
|
);
|
|
188
98
|
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
shouldRenderProvider.current = shouldRenderProvider.current || state.routes.length > 1;
|
|
192
|
-
|
|
193
|
-
const firstRoute = state.routes[0];
|
|
194
|
-
if (!firstRoute) {
|
|
195
|
-
// no routes at all, probably shouldn't happen, but let's be defensive
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const firstDescriptor = descriptors[firstRoute.key];
|
|
200
|
-
if (!firstDescriptor) {
|
|
201
|
-
// if we don't have a descriptor for the first route, bail out
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
99
|
+
const [baseRoute, ...sheetRoutes] = state.routes;
|
|
100
|
+
const baseDescriptor = baseRoute ? descriptors[baseRoute.key] : null;
|
|
204
101
|
|
|
205
102
|
return (
|
|
206
103
|
<>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
104
|
+
{baseDescriptor?.render()}
|
|
105
|
+
{sheetRoutes.map((route) => {
|
|
106
|
+
const descriptor = descriptors[route.key];
|
|
107
|
+
if (!descriptor) return null;
|
|
108
|
+
|
|
109
|
+
const { options, render } = descriptor;
|
|
110
|
+
const {
|
|
111
|
+
index = 0,
|
|
112
|
+
style,
|
|
113
|
+
backgroundStyle,
|
|
114
|
+
handleIndicatorStyle,
|
|
115
|
+
handleStyle,
|
|
116
|
+
...props
|
|
117
|
+
} = options;
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<BottomSheetScreen
|
|
121
|
+
key={route.key}
|
|
122
|
+
id={route.key}
|
|
123
|
+
route={route}
|
|
124
|
+
index={index}
|
|
125
|
+
navigation={navigation}
|
|
126
|
+
style={[defaultStyle, style]}
|
|
127
|
+
backgroundStyle={[themeBackgroundStyle, backgroundStyle]}
|
|
128
|
+
handleIndicatorStyle={[themeHandleIndicatorStyle, handleIndicatorStyle]}
|
|
129
|
+
handleStyle={[themeBackgroundStyle, { borderRadius: 24 }, handleStyle]}
|
|
130
|
+
onClose={(data) => {
|
|
131
|
+
navigation.dispatch({
|
|
132
|
+
...BottomSheetActions.remove(),
|
|
133
|
+
source: route.key,
|
|
134
|
+
});
|
|
135
|
+
navigation.emit({
|
|
136
|
+
type: "sheetDismiss",
|
|
137
|
+
target: route.key,
|
|
138
|
+
data,
|
|
139
|
+
});
|
|
140
|
+
}}
|
|
141
|
+
onBeforeShow={(data) => {
|
|
142
|
+
navigation.emit({
|
|
143
|
+
type: "sheetPresent",
|
|
144
|
+
target: route.key,
|
|
145
|
+
data,
|
|
146
|
+
});
|
|
147
|
+
}}
|
|
148
|
+
onAnimate={(fromIndex, toIndex, fromPosition, toPosition) => {
|
|
149
|
+
navigation.emit({
|
|
150
|
+
type: "sheetOnAnimate",
|
|
151
|
+
target: route.key,
|
|
152
|
+
data: { fromIndex, toIndex, fromPosition, toPosition },
|
|
153
|
+
});
|
|
154
|
+
}}
|
|
155
|
+
{...props}
|
|
156
|
+
>
|
|
157
|
+
{render()}
|
|
158
|
+
</BottomSheetScreen>
|
|
159
|
+
);
|
|
160
|
+
})}
|
|
263
161
|
</>
|
|
264
162
|
);
|
|
265
163
|
}
|