@niibase/bottom-sheet-manager 1.3.0 → 1.4.1

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 (55) hide show
  1. package/README.md +204 -193
  2. package/lib/commonjs/index.js +9 -2
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/manager.js +56 -16
  5. package/lib/commonjs/manager.js.map +1 -1
  6. package/lib/commonjs/provider.js +41 -44
  7. package/lib/commonjs/provider.js.map +1 -1
  8. package/lib/commonjs/router/index.js +37 -7
  9. package/lib/commonjs/router/index.js.map +1 -1
  10. package/lib/commonjs/router/router.js.map +1 -1
  11. package/lib/commonjs/router/view.js +77 -220
  12. package/lib/commonjs/router/view.js.map +1 -1
  13. package/lib/commonjs/sheet.js +61 -85
  14. package/lib/commonjs/sheet.js.map +1 -1
  15. package/lib/module/index.js +2 -2
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/manager.js +56 -16
  18. package/lib/module/manager.js.map +1 -1
  19. package/lib/module/provider.js +39 -42
  20. package/lib/module/provider.js.map +1 -1
  21. package/lib/module/router/index.js +39 -8
  22. package/lib/module/router/index.js.map +1 -1
  23. package/lib/module/router/router.js.map +1 -1
  24. package/lib/module/router/view.js +76 -220
  25. package/lib/module/router/view.js.map +1 -1
  26. package/lib/module/sheet.js +63 -87
  27. package/lib/module/sheet.js.map +1 -1
  28. package/lib/typescript/index.d.ts +2 -2
  29. package/lib/typescript/index.d.ts.map +1 -1
  30. package/lib/typescript/manager.d.ts +16 -0
  31. package/lib/typescript/manager.d.ts.map +1 -1
  32. package/lib/typescript/provider.d.ts +10 -23
  33. package/lib/typescript/provider.d.ts.map +1 -1
  34. package/lib/typescript/router/index.d.ts +21 -7
  35. package/lib/typescript/router/index.d.ts.map +1 -1
  36. package/lib/typescript/router/router.d.ts.map +1 -1
  37. package/lib/typescript/router/types.d.ts +75 -61
  38. package/lib/typescript/router/types.d.ts.map +1 -1
  39. package/lib/typescript/router/view.d.ts +3 -3
  40. package/lib/typescript/router/view.d.ts.map +1 -1
  41. package/lib/typescript/sheet.d.ts +1 -1
  42. package/lib/typescript/sheet.d.ts.map +1 -1
  43. package/lib/typescript/types.d.ts +32 -15
  44. package/lib/typescript/types.d.ts.map +1 -1
  45. package/package.json +15 -15
  46. package/scripts/postinstall.mjs +36 -0
  47. package/src/index.ts +7 -7
  48. package/src/manager.ts +66 -22
  49. package/src/provider.tsx +72 -53
  50. package/src/router/index.tsx +46 -9
  51. package/src/router/router.ts +6 -2
  52. package/src/router/types.ts +109 -91
  53. package/src/router/view.tsx +86 -308
  54. package/src/sheet.tsx +111 -123
  55. package/src/types.ts +146 -133
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  createNavigatorFactory,
3
+ EventArg,
4
+ StackActions,
3
5
  useNavigationBuilder,
4
6
  type NavigatorTypeBagBase,
5
7
  type ParamListBase,
@@ -19,7 +21,15 @@ import type {
19
21
  import { BottomSheetRouter, type BottomSheetRouterOptions } from "./router";
20
22
  import { BottomSheetView } from "./view";
21
23
 
22
- function BottomSheetNavigator({
24
+ /**
25
+ * Unified Navigator that renders the first screen as the base content
26
+ * and all subsequent screens as bottom sheet overlays.
27
+ *
28
+ * Uses BottomSheetRouter (extending StackRouter) to manage navigation state,
29
+ * with react-native-screens ScreenStack for the base screen rendering
30
+ * and BottomSheetView for the sheet overlays.
31
+ */
32
+ function Navigator({
23
33
  id,
24
34
  children,
25
35
  screenListeners,
@@ -41,6 +51,27 @@ function BottomSheetNavigator({
41
51
  initialRouteName,
42
52
  });
43
53
 
54
+ // Handle tab press → popToTop behavior
55
+ React.useEffect(() => {
56
+ // @ts-expect-error: there may not be a tab navigator in parent
57
+ return navigation?.addListener?.("tabPress", (e: any) => {
58
+ const isFocused = navigation.isFocused();
59
+
60
+ requestAnimationFrame(() => {
61
+ if (
62
+ state.index > 0 &&
63
+ isFocused &&
64
+ !(e as EventArg<"tabPress", true>).defaultPrevented
65
+ ) {
66
+ navigation.dispatch({
67
+ ...StackActions.popToTop(),
68
+ target: state.key,
69
+ });
70
+ }
71
+ });
72
+ });
73
+ }, [navigation, state.index, state.key]);
74
+
44
75
  return (
45
76
  <NavigationContent>
46
77
  <BottomSheetView
@@ -54,10 +85,8 @@ function BottomSheetNavigator({
54
85
  }
55
86
 
56
87
  /**
57
- * Creates a bottom sheet navigator that renders screens as bottom sheet modals.
58
- *
59
- * The first screen in the navigator is rendered as the main content,
60
- * and subsequent screens are rendered as bottom sheet modals on top.
88
+ * Creates a bottom sheet navigator that renders the first screen as the
89
+ * main content and all subsequent screens as bottom sheet modals.
61
90
  *
62
91
  * @example
63
92
  * ```tsx
@@ -106,13 +135,21 @@ function BottomSheetNavigator({
106
135
  * // SSR guard - navigator doesn't work on server
107
136
  * if (typeof window === "undefined") return <Slot />;
108
137
  *
109
- * return <BottomSheet />;
138
+ * return (
139
+ * <BottomSheet>
140
+ * <BottomSheet.Screen name="index" />
141
+ * <BottomSheet.Screen
142
+ * name="details"
143
+ * options={{ snapPoints: ["50%"] }}
144
+ * />
145
+ * </BottomSheet>
146
+ * );
110
147
  * }
111
148
  * ```
112
149
  */
113
150
  export function createBottomSheetNavigator<
114
151
  const ParamList extends ParamListBase,
115
- const NavigatorID extends string | undefined = undefined,
152
+ const NavigatorID extends string | undefined = string | undefined,
116
153
  const TypeBag extends NavigatorTypeBagBase = {
117
154
  ParamList: ParamList;
118
155
  NavigatorID: NavigatorID;
@@ -126,11 +163,11 @@ export function createBottomSheetNavigator<
126
163
  NavigatorID
127
164
  >;
128
165
  };
129
- Navigator: typeof BottomSheetNavigator;
166
+ Navigator: typeof Navigator;
130
167
  },
131
168
  const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>,
132
169
  >(config?: Config): TypedNavigator<TypeBag, Config> {
133
- return createNavigatorFactory(BottomSheetNavigator)(config);
170
+ return createNavigatorFactory(Navigator)(config);
134
171
  }
135
172
 
136
173
  export * from "./types";
@@ -85,7 +85,10 @@ const ensureBaseRoute = <T extends { routes: { name: string }[] }>(
85
85
 
86
86
  export const BottomSheetRouter = (
87
87
  routerOptions: StackRouterOptions,
88
- ): Router<BottomSheetNavigationState<ParamListBase>, BottomSheetActionType> => {
88
+ ): Router<
89
+ BottomSheetNavigationState<ParamListBase>,
90
+ BottomSheetActionType
91
+ > => {
89
92
  const baseRouter = StackRouter(routerOptions) as unknown as Router<
90
93
  BottomSheetNavigationState<ParamListBase>,
91
94
  BottomSheetActionType
@@ -260,4 +263,5 @@ export const BottomSheetRouter = (
260
263
  */
261
264
  export const useBottomSheetNavigation = <
262
265
  T extends ParamListBase = ParamListBase,
263
- >(): BottomSheetNavigationProp<T> => useNavigation<BottomSheetNavigationProp<T>>();
266
+ >(): BottomSheetNavigationProp<T> =>
267
+ useNavigation<BottomSheetNavigationProp<T>>();
@@ -7,8 +7,66 @@ import type {
7
7
  ParamListBase,
8
8
  RouteProp,
9
9
  StackActionHelpers,
10
+ StackNavigationState,
11
+ StackRouterOptions,
10
12
  } from "@react-navigation/native";
11
- import type { BottomSheetModalProps } from "@gorhom/bottom-sheet";
13
+ import type { BottomSheetModalProps, SNAP_POINT_TYPE } from "@gorhom/bottom-sheet";
14
+
15
+ /**
16
+ * Bottom-sheet-specific screen options.
17
+ * These only take effect when `presentation: "bottomSheet"`.
18
+ */
19
+ export type BottomSheetScreenOptions = Omit<
20
+ BottomSheetModalProps,
21
+ // Remove props that are managed by the navigator
22
+ | "containerHeight"
23
+ | "snapPoints"
24
+ | "gestureEventsHandlersHook"
25
+ | "iosModalSheetTypeOfAnimation"
26
+ | "animatedPosition"
27
+ | "onBeforeShow"
28
+ | "onChange"
29
+ | "onClose"
30
+ | "onDismiss"
31
+ | "onAnimate"
32
+ | "children"
33
+ | "$modal"
34
+ | "waitFor"
35
+ | "simultaneousHandlers"
36
+ > & {
37
+ /**
38
+ * Points for the bottom sheet to snap to.
39
+ * Accepts an array of numbers (pixels) or strings (percentages).
40
+ *
41
+ * @example
42
+ * snapPoints={[200, 500]}
43
+ * snapPoints={[200, '50%']}
44
+ * snapPoints={['100%']}
45
+ *
46
+ * @default ['66%']
47
+ */
48
+ snapPoints?: Array<string | number>;
49
+
50
+ /**
51
+ * When `true`, tapping on the backdrop will not dismiss the sheet.
52
+ * @default false
53
+ */
54
+ passThrough?: boolean;
55
+
56
+ /**
57
+ * Opacity of the backdrop overlay.
58
+ * @default 0.45
59
+ */
60
+ opacity?: number;
61
+ };
62
+
63
+ /**
64
+ * Navigation options for the bottom sheet navigator.
65
+ *
66
+ * The first screen is rendered as the base content.
67
+ * All subsequent screens are rendered as bottom sheets using these options.
68
+ */
69
+ export type BottomSheetNavigationOptions = Partial<BottomSheetScreenOptions>;
12
70
 
13
71
  /**
14
72
  * Navigation events emitted by the bottom sheet navigator.
@@ -17,11 +75,32 @@ export type BottomSheetNavigationEventMap = {
17
75
  /**
18
76
  * Event emitted when a sheet is presented.
19
77
  */
20
- sheetPresent: { data: undefined };
78
+ sheetPresent: { data: unknown };
21
79
  /**
22
80
  * Event emitted when a sheet is dismissed.
23
81
  */
24
- sheetDismiss: { data: undefined };
82
+ sheetDismiss: { data: unknown };
83
+ /**
84
+ * Event emitted when a sheet changes between position/snap points
85
+ */
86
+ sheetOnChange: {
87
+ data: {
88
+ index: number;
89
+ position: number;
90
+ type: SNAP_POINT_TYPE;
91
+ };
92
+ };
93
+ /**
94
+ * Event emitted when a sheet animates between snap points.
95
+ */
96
+ sheetOnAnimate: {
97
+ data: {
98
+ fromIndex: number;
99
+ toIndex: number;
100
+ fromPosition: number;
101
+ toPosition: number;
102
+ };
103
+ };
25
104
  };
26
105
 
27
106
  /**
@@ -45,14 +124,15 @@ export type BottomSheetRoute<ParamList extends ParamListBase = ParamListBase> =
45
124
 
46
125
  /**
47
126
  * Navigation state type for the bottom sheet navigator.
127
+ *
128
+ * Extends `StackNavigationState` with bottom-sheet-specific route properties
129
+ * and a `"bottom-sheet"` type discriminator.
48
130
  */
49
- export type BottomSheetNavigationState<ParamList extends ParamListBase> = Omit<
50
- NavigationState<ParamList>,
51
- "routes" | "type"
52
- > & {
53
- type: "bottom-sheet";
54
- routes: BottomSheetRoute<ParamList>[];
55
- };
131
+ export type BottomSheetNavigationState<ParamList extends ParamListBase = ParamListBase> =
132
+ Omit<StackNavigationState<ParamList>, "routes" | "type"> & {
133
+ type: "bottom-sheet";
134
+ routes: BottomSheetRoute<ParamList>[];
135
+ };
56
136
 
57
137
  /**
58
138
  * Action helpers available on the navigation object.
@@ -75,14 +155,14 @@ export type BottomSheetActionHelpers<ParamList extends ParamListBase> =
75
155
  * Navigation prop type for screens in the bottom sheet navigator.
76
156
  */
77
157
  export type BottomSheetNavigationProp<
78
- ParamList extends ParamListBase,
158
+ ParamList extends ParamListBase = ParamListBase,
79
159
  RouteName extends keyof ParamList = string,
80
160
  NavigatorID extends string | undefined = undefined,
81
161
  > = NavigationProp<
82
162
  ParamList,
83
163
  RouteName,
84
164
  NavigatorID,
85
- BottomSheetNavigationState<ParamList>,
165
+ BottomSheetNavigationState<ParamListBase>,
86
166
  BottomSheetNavigationOptions,
87
167
  BottomSheetNavigationEventMap
88
168
  > &
@@ -109,100 +189,25 @@ export type BottomSheetNavigationHelpers = NavigationHelpers<
109
189
  > &
110
190
  BottomSheetActionHelpers<ParamListBase>;
111
191
 
112
- /**
113
- * Configuration options for the bottom sheet navigator.
114
- */
115
- export type BottomSheetNavigationConfig = {
116
- /**
117
- * Whether to detach inactive sheets from the view hierarchy.
118
- * @default false
119
- */
120
- detachInactiveScreens?: boolean;
121
- };
122
-
123
- /**
124
- * Screen options available for bottom sheet screens.
125
- */
126
- export type BottomSheetNavigationOptions = Omit<
127
- BottomSheetModalProps,
128
- // Remove props that are managed by the navigator
129
- | "containerHeight"
130
- | "snapPoints"
131
- | "gestureEventsHandlersHook"
132
- | "animatedPosition"
133
- | "onChange"
134
- | "onClose"
135
- | "children"
136
- | "$modal"
137
- | "waitFor"
138
- | "simultaneousHandlers"
139
- > & {
140
- /**
141
- * Points for the bottom sheet to snap to.
142
- * Accepts an array of numbers (pixels) or strings (percentages).
143
- *
144
- * @example
145
- * snapPoints={[200, 500]}
146
- * snapPoints={[200, '50%']}
147
- * snapPoints={['100%']}
148
- *
149
- * @default ['66%']
150
- */
151
- snapPoints?: Array<string | number>;
152
-
153
- /**
154
- * When `true`, tapping on the backdrop will not dismiss the sheet.
155
- * @default false
156
- */
157
- clickThrough?: boolean;
158
-
159
- /**
160
- * Whether the bottom sheet is an iOS 18 modal sheet type of animation.
161
- * When enabled at snap point 90%, the content behind the sheet scales down and gets a
162
- * border radius, similar to iOS 18 system sheets.
163
- * @default false
164
- */
165
- iosModalSheetTypeOfAnimation?: boolean;
166
-
167
- /**
168
- * Opacity of the backdrop overlay.
169
- * @default 0.45
170
- */
171
- opacity?: number;
172
- };
173
-
174
- export type BottomSheetModalScreenProps = Omit<BottomSheetModalProps, "onDismiss"> & {
175
- route: BottomSheetRoute;
176
- navigation: BottomSheetNavigationHelpers;
177
-
178
- clickThrough?: boolean;
179
- opacity?: number;
180
-
181
- /**
182
- * Callback when sheet animation changes.
183
- */
184
- onSheetAnimate?: (from: number, to: number) => void;
185
- };
186
-
187
192
  /**
188
193
  * Props for the bottom sheet navigator component.
189
194
  */
190
195
  export type BottomSheetNavigatorProps = DefaultNavigatorOptions<
191
196
  ParamListBase,
192
- undefined, // or your ID if you want a named ID, e.g. 'BottomSheetNavigator'
197
+ string | undefined,
193
198
  BottomSheetNavigationState<ParamListBase>,
194
199
  BottomSheetNavigationOptions,
195
200
  BottomSheetNavigationEventMap,
196
- BottomSheetNavigationHelpers
201
+ BottomSheetNavigationProp<ParamListBase>
197
202
  > &
198
- BottomSheetNavigationConfig;
203
+ StackRouterOptions;
199
204
 
200
205
  /**
201
206
  * Descriptor type for bottom sheet screens.
202
207
  */
203
208
  export type BottomSheetDescriptor = Descriptor<
204
209
  BottomSheetNavigationOptions,
205
- BottomSheetNavigationProp<ParamListBase>,
210
+ BottomSheetNavigationProp<ParamListBase, string, undefined>,
206
211
  RouteProp<ParamListBase>
207
212
  >;
208
213
 
@@ -212,3 +217,16 @@ export type BottomSheetDescriptor = Descriptor<
212
217
  export type BottomSheetDescriptorMap = {
213
218
  [key: string]: BottomSheetDescriptor;
214
219
  };
220
+
221
+ export type BottomSheetModalScreenProps = Omit<BottomSheetModalProps, "onDismiss"> & {
222
+ route: BottomSheetRoute;
223
+ navigation: BottomSheetNavigationHelpers;
224
+
225
+ passThrough?: boolean;
226
+ opacity?: number;
227
+
228
+ /**
229
+ * Callback when sheet animation changes.
230
+ */
231
+ onSheetAnimate?: (from: number, to: number) => void;
232
+ };