@niibase/bottom-sheet-manager 1.1.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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/lib/commonjs/events.js +35 -0
  4. package/lib/commonjs/events.js.map +1 -0
  5. package/lib/commonjs/index.js +85 -0
  6. package/lib/commonjs/index.js.map +1 -0
  7. package/lib/commonjs/manager.js +171 -0
  8. package/lib/commonjs/manager.js.map +1 -0
  9. package/lib/commonjs/provider.js +229 -0
  10. package/lib/commonjs/provider.js.map +1 -0
  11. package/lib/commonjs/router/index.js +100 -0
  12. package/lib/commonjs/router/index.js.map +1 -0
  13. package/lib/commonjs/router/router.js +72 -0
  14. package/lib/commonjs/router/router.js.map +1 -0
  15. package/lib/commonjs/router/types.js +6 -0
  16. package/lib/commonjs/router/types.js.map +1 -0
  17. package/lib/commonjs/router/view.js +180 -0
  18. package/lib/commonjs/router/view.js.map +1 -0
  19. package/lib/commonjs/sheet.js +240 -0
  20. package/lib/commonjs/sheet.js.map +1 -0
  21. package/lib/commonjs/types.js +6 -0
  22. package/lib/commonjs/types.js.map +1 -0
  23. package/lib/module/events.js +29 -0
  24. package/lib/module/events.js.map +1 -0
  25. package/lib/module/index.js +6 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/module/manager.js +165 -0
  28. package/lib/module/manager.js.map +1 -0
  29. package/lib/module/provider.js +210 -0
  30. package/lib/module/provider.js.map +1 -0
  31. package/lib/module/router/index.js +79 -0
  32. package/lib/module/router/index.js.map +1 -0
  33. package/lib/module/router/router.js +65 -0
  34. package/lib/module/router/router.js.map +1 -0
  35. package/lib/module/router/types.js +2 -0
  36. package/lib/module/router/types.js.map +1 -0
  37. package/lib/module/router/view.js +173 -0
  38. package/lib/module/router/view.js.map +1 -0
  39. package/lib/module/sheet.js +232 -0
  40. package/lib/module/sheet.js.map +1 -0
  41. package/lib/module/types.js +2 -0
  42. package/lib/module/types.js.map +1 -0
  43. package/lib/typescript/events.d.ts +16 -0
  44. package/lib/typescript/events.d.ts.map +1 -0
  45. package/lib/typescript/index.d.ts +6 -0
  46. package/lib/typescript/index.d.ts.map +1 -0
  47. package/lib/typescript/manager.d.ts +78 -0
  48. package/lib/typescript/manager.d.ts.map +1 -0
  49. package/lib/typescript/provider.d.ts +69 -0
  50. package/lib/typescript/provider.d.ts.map +1 -0
  51. package/lib/typescript/router/index.d.ts +59 -0
  52. package/lib/typescript/router/index.d.ts.map +1 -0
  53. package/lib/typescript/router/router.d.ts +47 -0
  54. package/lib/typescript/router/router.d.ts.map +1 -0
  55. package/lib/typescript/router/types.d.ts +46 -0
  56. package/lib/typescript/router/types.d.ts.map +1 -0
  57. package/lib/typescript/router/view.d.ts +11 -0
  58. package/lib/typescript/router/view.d.ts.map +1 -0
  59. package/lib/typescript/sheet.d.ts +19 -0
  60. package/lib/typescript/sheet.d.ts.map +1 -0
  61. package/lib/typescript/types.d.ts +125 -0
  62. package/lib/typescript/types.d.ts.map +1 -0
  63. package/package.json +102 -0
  64. package/src/events.ts +40 -0
  65. package/src/index.ts +11 -0
  66. package/src/manager.ts +223 -0
  67. package/src/provider.tsx +293 -0
  68. package/src/router/index.tsx +130 -0
  69. package/src/router/router.ts +94 -0
  70. package/src/router/types.ts +117 -0
  71. package/src/router/view.tsx +265 -0
  72. package/src/sheet.tsx +350 -0
  73. package/src/types.ts +153 -0
@@ -0,0 +1,293 @@
1
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
2
+ import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
3
+ import { StatusBar } from "react-native";
4
+ import React from "react";
5
+ import Animated, {
6
+ interpolate,
7
+ interpolateColor,
8
+ runOnJS,
9
+ SharedValue,
10
+ useAnimatedReaction,
11
+ useAnimatedStyle,
12
+ useSharedValue,
13
+ withSpring,
14
+ withTiming,
15
+ } from "react-native-reanimated";
16
+
17
+ import { BottomSheetInstance, SheetPayload, Sheets } from "./types";
18
+ import { eventManager } from "./events";
19
+
20
+ export const providerRegistryStack: string[] = [];
21
+
22
+ /**
23
+ * An object that holds all the sheet components against their ids.
24
+ */
25
+ export const sheetsRegistry: {
26
+ [context: string]: { [id: string]: React.ElementType };
27
+ } = {
28
+ global: {},
29
+ };
30
+
31
+ export interface SheetProps<SheetId extends keyof Sheets = never> {
32
+ sheetId: SheetId;
33
+ payload?: Sheets[SheetId]["payload"];
34
+ }
35
+
36
+ // Registers your Sheet with the SheetProvider.
37
+ export function registerSheet<SheetId extends keyof Sheets = never>(
38
+ id: SheetId | (string & {}),
39
+ Sheet: React.ElementType,
40
+ ...contexts: string[]
41
+ ) {
42
+ if (!id || !Sheet) return;
43
+ if (!contexts || contexts.length === 0) contexts = ["global"];
44
+ for (let context of contexts) {
45
+ const registry = !sheetsRegistry[context]
46
+ ? (sheetsRegistry[context] = {})
47
+ : sheetsRegistry[context];
48
+ registry[id as string] = Sheet;
49
+ eventManager.publish(`${context}-on-register`);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * The SheetProvider makes available the sheets in a given context. The default context is
55
+ * `global`. However if you want to render a Sheet within another sheet or if you want to render
56
+ * Sheets in a modal. You can use a separate Provider with a custom context value.
57
+ *
58
+ * For example
59
+ * ```ts
60
+ * // Define your SheetProvider in the component/modal where
61
+ * // you want to show some Sheets.
62
+ * <SheetProvider context="local-context" />
63
+ *
64
+ * // Then register your sheet when for example the
65
+ * // Modal component renders.
66
+ *
67
+ * registerSheet('local-sheet', LocalSheet,'local-context');
68
+ *
69
+ * ```
70
+ */
71
+ export function SheetProvider({
72
+ iosModalSheetTypeOfAnimation = false,
73
+ context = "global",
74
+ duration = 300,
75
+ children,
76
+ }: React.PropsWithChildren<{
77
+ context?: string;
78
+ duration?: number;
79
+ iosModalSheetTypeOfAnimation?: boolean;
80
+ }>) {
81
+ const { top } = useSafeAreaInsets();
82
+ const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
83
+ const sheetIds = Object.keys(sheetsRegistry[context] || sheetsRegistry["global"] || {});
84
+
85
+ // Rerender when a new sheet is added.
86
+ const onRegister = React.useCallback(forceUpdate, [forceUpdate]);
87
+
88
+ // IOS modal sheet type of animation
89
+ const isFullScreen = useSharedValue(-1);
90
+ const colorStyle = useAnimatedStyle(() => ({
91
+ flex: 1,
92
+ backgroundColor: interpolateColor(
93
+ isFullScreen.value,
94
+ [0, 1],
95
+ ["transparent", "#000"],
96
+ ),
97
+ }));
98
+ const animatedStyle = useAnimatedStyle(
99
+ () => ({
100
+ flex: 1,
101
+ overflow: "hidden",
102
+ borderRadius: interpolate(isFullScreen.value, [0, 0.8, 1], [0, 20, 24], "clamp"),
103
+ transform: [
104
+ {
105
+ scaleX: withTiming(
106
+ interpolate(isFullScreen.value, [0, 0.98, 1], [1, 1, 0.92], "clamp"),
107
+ { duration },
108
+ ),
109
+ },
110
+ {
111
+ translateY: withSpring(
112
+ interpolate(isFullScreen.value, [0, 0.99, 1], [0, top, top + 5], "clamp"),
113
+ { duration, dampingRatio: 1.5 },
114
+ ),
115
+ },
116
+ ],
117
+ }),
118
+ [duration],
119
+ );
120
+
121
+ // Since background color is white, we need to set status bar to light
122
+ const setStatusBar = StatusBar.setBarStyle;
123
+ useAnimatedReaction(
124
+ () => isFullScreen.value,
125
+ (currentValue) => {
126
+ "worklet";
127
+ if (currentValue > -1) {
128
+ runOnJS(setStatusBar)(currentValue >= 0.5 ? "light-content" : "default");
129
+ }
130
+ },
131
+ [],
132
+ );
133
+
134
+ React.useEffect(() => {
135
+ providerRegistryStack.indexOf(context) > -1
136
+ ? providerRegistryStack.indexOf(context)
137
+ : providerRegistryStack.push(context) - 1;
138
+ const unsub = eventManager.subscribe(`${context}-on-register`, onRegister);
139
+ return () => {
140
+ providerRegistryStack.splice(providerRegistryStack.indexOf(context), 1);
141
+ unsub?.unsubscribe();
142
+ };
143
+ }, [context, onRegister]);
144
+
145
+ return (
146
+ <SheetAnimationContext.Provider
147
+ value={{ isFullScreen, iosModalSheetTypeOfAnimation }}
148
+ >
149
+ <Animated.View style={colorStyle}>
150
+ <Animated.View style={animatedStyle}>{children}</Animated.View>
151
+ </Animated.View>
152
+ <BottomSheetModalProvider>
153
+ {sheetIds.map((id) => (
154
+ <RenderSheet key={id} id={id} context={context} duration={duration} />
155
+ ))}
156
+ </BottomSheetModalProvider>
157
+ </SheetAnimationContext.Provider>
158
+ );
159
+ }
160
+ const ProviderContext = React.createContext("global");
161
+ const SheetIDContext = React.createContext<string | undefined>(undefined);
162
+ const SheetAnimationContext = React.createContext<{
163
+ iosModalSheetTypeOfAnimation: boolean;
164
+ isFullScreen: SharedValue<number>;
165
+ }>({ isFullScreen: { value: 0 } as any, iosModalSheetTypeOfAnimation: false });
166
+
167
+ export const SheetRefContext = React.createContext<
168
+ React.RefObject<BottomSheetInstance | null>
169
+ >({} as any);
170
+
171
+ const SheetPayloadContext = React.createContext<any>(undefined);
172
+
173
+ /**
174
+ * Get id of the current context.
175
+ */
176
+ export const useProviderContext = () => React.useContext(ProviderContext);
177
+ /**
178
+ * Get id of the current sheet
179
+ */
180
+ export const useSheetIDContext = () => React.useContext(SheetIDContext);
181
+ /**
182
+ * Get the current sheet animation context.
183
+ */
184
+ export const useSheetAnimationContext = () => React.useContext(SheetAnimationContext);
185
+ /**
186
+ * Get the current Sheet's internal ref.
187
+ */
188
+ export const useSheetRef = <
189
+ SheetId extends keyof Sheets = never,
190
+ >(): React.MutableRefObject<BottomSheetInstance<SheetId>> =>
191
+ React.useContext(SheetRefContext) as React.MutableRefObject<
192
+ BottomSheetInstance<SheetId>
193
+ >;
194
+
195
+ /**
196
+ * Get the payload this sheet was opened with.
197
+ */
198
+ export function useSheetPayload<SheetId extends keyof Sheets = never>() {
199
+ return React.useContext(SheetPayloadContext) as Sheets[SheetId]["payload"];
200
+ }
201
+
202
+ /**
203
+ * Listen to sheet events.
204
+ */
205
+ export function useOnSheet<SheetId extends keyof Sheets = never>(
206
+ id: SheetId | (string & {}),
207
+ type: "show" | "hide" | "onclose",
208
+ listener: (payload: SheetPayload<SheetId>, context: string, ...args: any[]) => void,
209
+ ) {
210
+ React.useEffect(() => {
211
+ const subscription = eventManager.subscribe(`${type}_${id}`, listener);
212
+ return () => subscription.unsubscribe();
213
+ }, [id, listener]);
214
+ }
215
+
216
+ const RenderSheet = ({
217
+ id,
218
+ context,
219
+ duration,
220
+ }: {
221
+ id: string;
222
+ context: string;
223
+ duration: number;
224
+ }) => {
225
+ const [payload, setPayload] = React.useState();
226
+ const [visible, setVisible] = React.useState(false);
227
+ const ref = React.useRef<BottomSheetInstance | null>(null);
228
+ const Sheet = context.startsWith("$$-auto-")
229
+ ? sheetsRegistry?.global?.[id]
230
+ : sheetsRegistry[context]
231
+ ? sheetsRegistry[context]?.[id]
232
+ : undefined;
233
+
234
+ const onShow = React.useCallback(
235
+ (data: any, ctx = "global", reopened?: boolean) => {
236
+ if (ctx !== context) return;
237
+ if (!reopened) setPayload(data);
238
+ setVisible(true);
239
+ },
240
+ [context],
241
+ );
242
+
243
+ const onClose = React.useCallback(
244
+ (_data: any, ctx = "global", reopened?: boolean) => {
245
+ if (context !== ctx) return;
246
+ if (!reopened) {
247
+ setPayload(undefined);
248
+ setTimeout(() => setVisible(false), Math.max(duration ?? 300, 300));
249
+ } else {
250
+ setVisible(false);
251
+ }
252
+ },
253
+ [context],
254
+ );
255
+
256
+ const onHide = React.useCallback(
257
+ (data: any, ctx = "global") => {
258
+ eventManager.publish(`hide_${id}`, data, ctx);
259
+ },
260
+ [id],
261
+ );
262
+
263
+ React.useEffect(() => {
264
+ if (visible) {
265
+ eventManager.publish(`show_${id}`, payload, context);
266
+ }
267
+ }, [context, id, payload, visible]);
268
+
269
+ React.useEffect(() => {
270
+ let subs = [
271
+ eventManager.subscribe(`show_wrap_${id}`, onShow),
272
+ eventManager.subscribe(`onclose_${id}`, onClose),
273
+ eventManager.subscribe(`hide_wrap_${id}`, onHide),
274
+ ];
275
+ return () => {
276
+ subs.forEach((s) => s.unsubscribe());
277
+ };
278
+ }, [id, context, onShow, onHide, onClose]);
279
+
280
+ if (!Sheet) return null;
281
+
282
+ return visible ? (
283
+ <ProviderContext.Provider value={context}>
284
+ <SheetIDContext.Provider value={id}>
285
+ <SheetRefContext.Provider value={ref}>
286
+ <SheetPayloadContext.Provider value={payload}>
287
+ <Sheet id={id} payload={payload} context={context} />
288
+ </SheetPayloadContext.Provider>
289
+ </SheetRefContext.Provider>
290
+ </SheetIDContext.Provider>
291
+ </ProviderContext.Provider>
292
+ ) : null;
293
+ };
@@ -0,0 +1,130 @@
1
+ import {
2
+ createNavigatorFactory,
3
+ NavigatorTypeBagBase,
4
+ ParamListBase,
5
+ StaticConfig,
6
+ TypedNavigator,
7
+ useNavigationBuilder,
8
+ } from "@react-navigation/native";
9
+ import React from "react";
10
+
11
+ import { BottomSheetRouter, BottomSheetRouterOptions } from "./router";
12
+ import type {
13
+ BottomSheetActionHelpers,
14
+ BottomSheetNavigationEventMap,
15
+ BottomSheetNavigationOptions,
16
+ BottomSheetNavigationProp,
17
+ BottomSheetNavigationState,
18
+ BottomSheetNavigatorProps,
19
+ } from "./types";
20
+ import { BottomSheetView } from "./view";
21
+
22
+ function BottomSheetNavigator({
23
+ id,
24
+ children,
25
+ screenListeners,
26
+ screenOptions,
27
+ ...rest
28
+ }: BottomSheetNavigatorProps) {
29
+ const { state, descriptors, navigation, NavigationContent } = useNavigationBuilder<
30
+ BottomSheetNavigationState<ParamListBase>,
31
+ BottomSheetRouterOptions,
32
+ BottomSheetActionHelpers<ParamListBase>,
33
+ BottomSheetNavigationOptions,
34
+ BottomSheetNavigationEventMap
35
+ >(BottomSheetRouter, {
36
+ id,
37
+ children,
38
+ screenListeners,
39
+ screenOptions,
40
+ });
41
+
42
+ return (
43
+ <NavigationContent>
44
+ <BottomSheetView
45
+ {...rest}
46
+ state={state}
47
+ navigation={navigation}
48
+ descriptors={descriptors}
49
+ />
50
+ </NavigationContent>
51
+ );
52
+ }
53
+
54
+ /**
55
+ * To use BottomSheetNavigator with expo-router, the first screen should be your app content
56
+ * and add a border radius of 24px to the root view if want to snap to 100%.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * import {
61
+ * createBottomSheetNavigator,
62
+ * BottomSheetNavigationOptions,
63
+ * BottomSheetNavigationEventMap,
64
+ * BottomSheetNavigationState,
65
+ * } from "@repo/bottom-sheet";
66
+ * import { Slot, withLayoutContext } from "expo-router";
67
+ *
68
+ * const { Navigator } = createBottomSheetNavigator();
69
+ *
70
+ * const BottomSheet = withLayoutContext<
71
+ * BottomSheetNavigationOptions,
72
+ * typeof Navigator,
73
+ * BottomSheetNavigationState<any>,
74
+ * BottomSheetNavigationEventMap
75
+ * >(Navigator);
76
+ *
77
+ * export const unstable_settings = {
78
+ * initialRouteName: "index",
79
+ * };
80
+ *
81
+ * export default function Layout() {
82
+ * if (typeof window === "undefined") return <Slot />;
83
+ * return (
84
+ * <BottomSheet
85
+ * screenOptions={
86
+ * {
87
+ * // API Reference: `@repo/design/bottom-sheet/types.ts`
88
+ * // And: https://gorhom.github.io/react-native-bottom-sheet/modal/props/
89
+ * }
90
+ * }
91
+ *. />
92
+ * );
93
+ * }
94
+ * ```
95
+ */
96
+ export function createBottomSheetNavigator<
97
+ const ParamList extends ParamListBase,
98
+ const NavigatorID extends string | undefined = undefined,
99
+ // We'll define a type bag specialized for bottom sheets:
100
+ const TypeBag extends NavigatorTypeBagBase = {
101
+ // The param list from the user
102
+ ParamList: ParamList;
103
+ // Optional ID for this navigator
104
+ NavigatorID: NavigatorID;
105
+ // The state shape
106
+ State: BottomSheetNavigationState<ParamList>;
107
+ // The screen options
108
+ ScreenOptions: BottomSheetNavigationOptions;
109
+ // The event map
110
+ EventMap: BottomSheetNavigationEventMap;
111
+ // The type of the "navigation" object used by each screen in the navigator
112
+ NavigationList: {
113
+ [RouteName in keyof ParamList]: BottomSheetNavigationProp<
114
+ ParamList,
115
+ RouteName,
116
+ NavigatorID
117
+ >;
118
+ };
119
+ // The navigator component
120
+ Navigator: typeof BottomSheetNavigator;
121
+ },
122
+ // The static config allows for "static" route config
123
+ const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>,
124
+ >(config?: Config): TypedNavigator<TypeBag, Config> {
125
+ // We call `createNavigatorFactory` with our un-typed navigator
126
+ // but pass in the config to get the typed container
127
+ return createNavigatorFactory(BottomSheetNavigator)(config);
128
+ }
129
+
130
+ export * from "./types";
@@ -0,0 +1,94 @@
1
+ import {
2
+ ParamListBase,
3
+ Router,
4
+ StackActions,
5
+ StackActionType,
6
+ StackRouter,
7
+ StackRouterOptions,
8
+ } from "@react-navigation/native";
9
+ import { nanoid } from "nanoid/non-secure";
10
+
11
+ import type { BottomSheetNavigationState } from "./types";
12
+
13
+ export type BottomSheetRouterOptions = StackRouterOptions;
14
+
15
+ export type BottomSheetActionType =
16
+ | StackActionType
17
+ | {
18
+ type: "SNAP_TO";
19
+ index: number;
20
+ source?: string;
21
+ target?: string;
22
+ };
23
+
24
+ export const BottomSheetActions = {
25
+ ...StackActions,
26
+ snapTo(index: number): BottomSheetActionType {
27
+ return { type: "SNAP_TO", index };
28
+ },
29
+ };
30
+
31
+ export function BottomSheetRouter(
32
+ routerOptions: StackRouterOptions,
33
+ ): Router<BottomSheetNavigationState<ParamListBase>, BottomSheetActionType> {
34
+ const baseRouter = StackRouter(routerOptions) as unknown as Router<
35
+ BottomSheetNavigationState<ParamListBase>,
36
+ BottomSheetActionType
37
+ >;
38
+ return {
39
+ ...baseRouter,
40
+ type: "bottom-sheet",
41
+ getInitialState(options) {
42
+ const state = baseRouter.getInitialState(options);
43
+
44
+ return {
45
+ ...state,
46
+ stale: false,
47
+ type: "bottom-sheet",
48
+ key: `bottom-sheet-${nanoid()}`,
49
+ };
50
+ },
51
+ getStateForAction(state, action, options) {
52
+ switch (action.type) {
53
+ case "SNAP_TO": {
54
+ const index =
55
+ action.target === state.key && action.source
56
+ ? state.routes.findIndex((r) => r.key === action.source)
57
+ : state.index;
58
+
59
+ return {
60
+ ...state,
61
+ routes: state.routes.map((route, i) =>
62
+ i === index
63
+ ? {
64
+ ...route,
65
+ snapToIndex: action.index,
66
+ }
67
+ : route,
68
+ ),
69
+ };
70
+ }
71
+ default:
72
+ return baseRouter.getStateForAction(state, action, options);
73
+ }
74
+ },
75
+ getRehydratedState(partialState, { routeNames, routeParamList, routeGetIdList }) {
76
+ if (partialState.stale === false) {
77
+ return partialState;
78
+ }
79
+
80
+ const state = baseRouter.getRehydratedState(partialState, {
81
+ routeNames,
82
+ routeParamList,
83
+ routeGetIdList,
84
+ });
85
+
86
+ return {
87
+ ...state,
88
+ type: "bottom-sheet",
89
+ key: `bottom-sheet-${nanoid()}`,
90
+ };
91
+ },
92
+ actionCreators: BottomSheetActions,
93
+ };
94
+ }
@@ -0,0 +1,117 @@
1
+ import type { BottomSheetModalProps } from "@gorhom/bottom-sheet";
2
+ import type {
3
+ DefaultNavigatorOptions,
4
+ Descriptor,
5
+ NavigationHelpers,
6
+ NavigationProp,
7
+ NavigationState,
8
+ ParamListBase,
9
+ RouteProp,
10
+ StackActionHelpers,
11
+ } from "@react-navigation/native";
12
+
13
+ // TODO: Sheet open / close / snap / events.
14
+ export type BottomSheetNavigationEventMap = {};
15
+
16
+ export type BottomSheetNavigationState<ParamList extends ParamListBase> = Omit<
17
+ NavigationState<ParamList>,
18
+ "routes"
19
+ > & {
20
+ type: "bottom-sheet";
21
+ routes: (NavigationState<ParamList>["routes"][number] & {
22
+ snapToIndex?: number | null;
23
+ })[];
24
+ };
25
+
26
+ export type BottomSheetActionHelpers<ParamList extends ParamListBase> =
27
+ StackActionHelpers<ParamList> & {
28
+ /**
29
+ * Snap the drawer to a point.
30
+ */
31
+ snapTo(index?: number): void;
32
+ };
33
+
34
+ export type BottomSheetNavigationProp<
35
+ ParamList extends ParamListBase,
36
+ RouteName extends keyof ParamList = string,
37
+ NavigatorID extends string | undefined = undefined,
38
+ > = NavigationProp<
39
+ ParamList,
40
+ RouteName,
41
+ NavigatorID,
42
+ BottomSheetNavigationState<ParamList>,
43
+ BottomSheetNavigationOptions,
44
+ BottomSheetNavigationEventMap
45
+ > &
46
+ BottomSheetActionHelpers<ParamList>;
47
+
48
+ export type BottomSheetScreenProps<
49
+ ParamList extends ParamListBase,
50
+ RouteName extends keyof ParamList = string,
51
+ NavigatorID extends string | undefined = undefined,
52
+ > = {
53
+ navigation: BottomSheetNavigationProp<ParamList, RouteName, NavigatorID>;
54
+ route: RouteProp<ParamList, RouteName>;
55
+ };
56
+
57
+ export type BottomSheetNavigationHelpers = NavigationHelpers<
58
+ ParamListBase,
59
+ BottomSheetNavigationEventMap
60
+ >;
61
+
62
+ // We want it to be an empty object because navigator does not have any additional props
63
+ export type BottomSheetNavigationConfig = {};
64
+
65
+ export type BottomSheetNavigationOptions = Omit<
66
+ BottomSheetModalProps,
67
+ // Remove some props that aren't useful as navigation options.
68
+ | "containerHeight"
69
+ | "snapPoints"
70
+ | "gestureEventsHandlersHook"
71
+ | "animatedPosition"
72
+ | "animatedIndex"
73
+ | "topInset"
74
+ | "onChange"
75
+ | "onAnimate"
76
+ | "onClose"
77
+ | "children"
78
+ | "$modal"
79
+ | "waitFor"
80
+ | "simultaneousHandlers"
81
+ > & {
82
+ /**
83
+ * Points for the bottom sheet to snap to. It accepts array of number, string or mix.
84
+ * String values should be a percentage.
85
+ * @example
86
+ * snapPoints={[200, 500]}
87
+ * snapPoints={[200, '%50']}
88
+ * snapPoints={['%100']}
89
+ * @type Array<string | number>
90
+ */
91
+ snapPoints?: Array<string | number>;
92
+ /**
93
+ * When `true`, tapping on the backdrop will not dismiss the modal.
94
+ * @default false
95
+ */
96
+ clickThrough?: boolean;
97
+ };
98
+
99
+ export type BottomSheetNavigatorProps = DefaultNavigatorOptions<
100
+ ParamListBase,
101
+ undefined, // or your ID if you want a named ID, e.g. 'BottomSheetNavigator'
102
+ BottomSheetNavigationState<ParamListBase>,
103
+ BottomSheetNavigationOptions,
104
+ BottomSheetNavigationEventMap,
105
+ BottomSheetNavigationHelpers
106
+ > &
107
+ BottomSheetNavigationConfig;
108
+
109
+ export type BottomSheetDescriptor = Descriptor<
110
+ BottomSheetNavigationOptions,
111
+ BottomSheetNavigationProp<ParamListBase>,
112
+ RouteProp<ParamListBase>
113
+ >;
114
+
115
+ export type BottomSheetDescriptorMap = {
116
+ [key: string]: BottomSheetDescriptor;
117
+ };