@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.
Files changed (64) hide show
  1. package/README.md +414 -69
  2. package/lib/commonjs/events.js +100 -15
  3. package/lib/commonjs/events.js.map +1 -1
  4. package/lib/commonjs/index.js +14 -0
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/manager.js +153 -35
  7. package/lib/commonjs/manager.js.map +1 -1
  8. package/lib/commonjs/provider.js +92 -54
  9. package/lib/commonjs/provider.js.map +1 -1
  10. package/lib/commonjs/router/index.js +80 -21
  11. package/lib/commonjs/router/index.js.map +1 -1
  12. package/lib/commonjs/router/router.js +137 -12
  13. package/lib/commonjs/router/router.js.map +1 -1
  14. package/lib/commonjs/router/view.js +93 -126
  15. package/lib/commonjs/router/view.js.map +1 -1
  16. package/lib/commonjs/sheet.js +122 -98
  17. package/lib/commonjs/sheet.js.map +1 -1
  18. package/lib/module/events.js +100 -15
  19. package/lib/module/events.js.map +1 -1
  20. package/lib/module/index.js +2 -2
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/module/manager.js +154 -35
  23. package/lib/module/manager.js.map +1 -1
  24. package/lib/module/provider.js +87 -50
  25. package/lib/module/provider.js.map +1 -1
  26. package/lib/module/router/index.js +66 -19
  27. package/lib/module/router/index.js.map +1 -1
  28. package/lib/module/router/router.js +135 -11
  29. package/lib/module/router/router.js.map +1 -1
  30. package/lib/module/router/view.js +92 -126
  31. package/lib/module/router/view.js.map +1 -1
  32. package/lib/module/sheet.js +124 -100
  33. package/lib/module/sheet.js.map +1 -1
  34. package/lib/typescript/events.d.ts +46 -12
  35. package/lib/typescript/events.d.ts.map +1 -1
  36. package/lib/typescript/index.d.ts +2 -2
  37. package/lib/typescript/index.d.ts.map +1 -1
  38. package/lib/typescript/manager.d.ts +73 -7
  39. package/lib/typescript/manager.d.ts.map +1 -1
  40. package/lib/typescript/provider.d.ts +22 -16
  41. package/lib/typescript/provider.d.ts.map +1 -1
  42. package/lib/typescript/router/index.d.ts +47 -17
  43. package/lib/typescript/router/index.d.ts.map +1 -1
  44. package/lib/typescript/router/router.d.ts +44 -5
  45. package/lib/typescript/router/router.d.ts.map +1 -1
  46. package/lib/typescript/router/types.d.ts +142 -32
  47. package/lib/typescript/router/types.d.ts.map +1 -1
  48. package/lib/typescript/router/view.d.ts +3 -3
  49. package/lib/typescript/router/view.d.ts.map +1 -1
  50. package/lib/typescript/sheet.d.ts +1 -1
  51. package/lib/typescript/sheet.d.ts.map +1 -1
  52. package/lib/typescript/types.d.ts +52 -21
  53. package/lib/typescript/types.d.ts.map +1 -1
  54. package/package.json +14 -15
  55. package/src/events.ts +118 -27
  56. package/src/index.ts +2 -1
  57. package/src/manager.ts +209 -42
  58. package/src/provider.tsx +144 -71
  59. package/src/router/index.tsx +77 -33
  60. package/src/router/router.ts +188 -15
  61. package/src/router/types.ts +172 -57
  62. package/src/router/view.tsx +111 -213
  63. package/src/sheet.tsx +192 -124
  64. package/src/types.ts +51 -24
@@ -1,13 +1,23 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
- import { createNavigatorFactory, useNavigationBuilder } from "@react-navigation/native";
3
- import React from "react";
2
+ import { createNavigatorFactory, StackActions, useNavigationBuilder } from "@react-navigation/native";
3
+ import * as React from "react";
4
4
  import { BottomSheetRouter } from "./router";
5
5
  import { BottomSheetView } from "./view";
6
- function BottomSheetNavigator({
6
+
7
+ /**
8
+ * Unified Navigator that renders the first screen as the base content
9
+ * and all subsequent screens as bottom sheet overlays.
10
+ *
11
+ * Uses BottomSheetRouter (extending StackRouter) to manage navigation state,
12
+ * with react-native-screens ScreenStack for the base screen rendering
13
+ * and BottomSheetView for the sheet overlays.
14
+ */
15
+ function Navigator({
7
16
  id,
8
17
  children,
9
18
  screenListeners,
10
19
  screenOptions,
20
+ initialRouteName,
11
21
  ...rest
12
22
  }) {
13
23
  const {
@@ -19,8 +29,25 @@ function BottomSheetNavigator({
19
29
  id,
20
30
  children,
21
31
  screenListeners,
22
- screenOptions
32
+ screenOptions,
33
+ initialRouteName
23
34
  });
35
+
36
+ // Handle tab press → popToTop behavior
37
+ React.useEffect(() => {
38
+ // @ts-expect-error: there may not be a tab navigator in parent
39
+ return navigation?.addListener?.("tabPress", e => {
40
+ const isFocused = navigation.isFocused();
41
+ requestAnimationFrame(() => {
42
+ if (state.index > 0 && isFocused && !e.defaultPrevented) {
43
+ navigation.dispatch({
44
+ ...StackActions.popToTop(),
45
+ target: state.key
46
+ });
47
+ }
48
+ });
49
+ });
50
+ }, [navigation, state.index, state.key]);
24
51
  return /*#__PURE__*/React.createElement(NavigationContent, null, /*#__PURE__*/React.createElement(BottomSheetView, _extends({}, rest, {
25
52
  state: state,
26
53
  navigation: navigation,
@@ -29,18 +56,38 @@ function BottomSheetNavigator({
29
56
  }
30
57
 
31
58
  /**
32
- * To use BottomSheetNavigator with expo-router, the first screen should be your app content
33
- * and add a border radius of 24px to the root view if want to snap to 100%.
59
+ * Creates a bottom sheet navigator that renders the first screen as the
60
+ * main content and all subsequent screens as bottom sheet modals.
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * // With React Navigation
65
+ * const { Navigator, Screen } = createBottomSheetNavigator();
66
+ *
67
+ * function App() {
68
+ * return (
69
+ * <Navigator>
70
+ * <Screen name="Home" component={HomeScreen} />
71
+ * <Screen
72
+ * name="Details"
73
+ * component={DetailsSheet}
74
+ * options={{ snapPoints: ['50%', '100%'] }}
75
+ * />
76
+ * </Navigator>
77
+ * );
78
+ * }
79
+ * ```
34
80
  *
35
81
  * @example
36
82
  * ```tsx
83
+ * // With Expo Router
84
+ * import { Slot, withLayoutContext } from "expo-router";
37
85
  * import {
38
86
  * createBottomSheetNavigator,
39
87
  * BottomSheetNavigationOptions,
40
88
  * BottomSheetNavigationEventMap,
41
89
  * BottomSheetNavigationState,
42
- * } from "@repo/bottom-sheet";
43
- * import { Slot, withLayoutContext } from "expo-router";
90
+ * } from "@niibase/bottom-sheet-manager";
44
91
  *
45
92
  * const { Navigator } = createBottomSheetNavigator();
46
93
  *
@@ -56,24 +103,24 @@ function BottomSheetNavigator({
56
103
  * };
57
104
  *
58
105
  * export default function Layout() {
106
+ * // SSR guard - navigator doesn't work on server
59
107
  * if (typeof window === "undefined") return <Slot />;
108
+ *
60
109
  * return (
61
- * <BottomSheet
62
- * screenOptions={
63
- * {
64
- * // API Reference: `@repo/design/bottom-sheet/types.ts`
65
- * // And: https://gorhom.github.io/react-native-bottom-sheet/modal/props/
66
- * }
67
- * }
68
- *. />
110
+ * <BottomSheet>
111
+ * <BottomSheet.Screen name="index" />
112
+ * <BottomSheet.Screen
113
+ * name="details"
114
+ * options={{ snapPoints: ["50%"] }}
115
+ * />
116
+ * </BottomSheet>
69
117
  * );
70
118
  * }
71
119
  * ```
72
120
  */
73
121
  export function createBottomSheetNavigator(config) {
74
- // We call `createNavigatorFactory` with our un-typed navigator
75
- // but pass in the config to get the typed container
76
- return createNavigatorFactory(BottomSheetNavigator)(config);
122
+ return createNavigatorFactory(Navigator)(config);
77
123
  }
78
124
  export * from "./types";
125
+ export { BottomSheetActions, useBottomSheetNavigation } from "./router";
79
126
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["createNavigatorFactory","useNavigationBuilder","React","BottomSheetRouter","BottomSheetView","BottomSheetNavigator","id","children","screenListeners","screenOptions","rest","state","descriptors","navigation","NavigationContent","createElement","_extends","createBottomSheetNavigator","config"],"sourceRoot":"../../../src","sources":["router/index.tsx"],"mappings":";AAAA,SACEA,sBAAsB,EAKtBC,oBAAoB,QACf,0BAA0B;AACjC,OAAOC,KAAK,MAAM,OAAO;AAEzB,SAASC,iBAAiB,QAAkC,UAAU;AAStE,SAASC,eAAe,QAAQ,QAAQ;AAExC,SAASC,oBAAoBA,CAAC;EAC5BC,EAAE;EACFC,QAAQ;EACRC,eAAe;EACfC,aAAa;EACb,GAAGC;AACsB,CAAC,EAAE;EAC5B,MAAM;IAAEC,KAAK;IAAEC,WAAW;IAAEC,UAAU;IAAEC;EAAkB,CAAC,GAAGb,oBAAoB,CAMhFE,iBAAiB,EAAE;IACnBG,EAAE;IACFC,QAAQ;IACRC,eAAe;IACfC;EACF,CAAC,CAAC;EAEF,oBACEP,KAAA,CAAAa,aAAA,CAACD,iBAAiB,qBAChBZ,KAAA,CAAAa,aAAA,CAACX,eAAe,EAAAY,QAAA,KACVN,IAAI;IACRC,KAAK,EAAEA,KAAM;IACbE,UAAU,EAAEA,UAAW;IACvBD,WAAW,EAAEA;EAAY,EAC1B,CACgB,CAAC;AAExB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,0BAA0BA,CA4BxCC,MAAe,EAAmC;EAClD;EACA;EACA,OAAOlB,sBAAsB,CAACK,oBAAoB,CAAC,CAACa,MAAM,CAAC;AAC7D;AAEA,cAAc,SAAS","ignoreList":[]}
1
+ {"version":3,"names":["createNavigatorFactory","StackActions","useNavigationBuilder","React","BottomSheetRouter","BottomSheetView","Navigator","id","children","screenListeners","screenOptions","initialRouteName","rest","state","descriptors","navigation","NavigationContent","useEffect","addListener","e","isFocused","requestAnimationFrame","index","defaultPrevented","dispatch","popToTop","target","key","createElement","_extends","createBottomSheetNavigator","config","BottomSheetActions","useBottomSheetNavigation"],"sourceRoot":"../../../src","sources":["router/index.tsx"],"mappings":";AAAA,SACEA,sBAAsB,EAEtBC,YAAY,EACZC,oBAAoB,QAKf,0BAA0B;AACjC,OAAO,KAAKC,KAAK,MAAM,OAAO;AAU9B,SAASC,iBAAiB,QAAuC,UAAU;AAC3E,SAASC,eAAe,QAAQ,QAAQ;;AAExC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,SAASA,CAAC;EACjBC,EAAE;EACFC,QAAQ;EACRC,eAAe;EACfC,aAAa;EACbC,gBAAgB;EAChB,GAAGC;AACsB,CAAC,EAAE;EAC5B,MAAM;IAAEC,KAAK;IAAEC,WAAW;IAAEC,UAAU;IAAEC;EAAkB,CAAC,GAAGd,oBAAoB,CAMhFE,iBAAiB,EAAE;IACnBG,EAAE;IACFC,QAAQ;IACRC,eAAe;IACfC,aAAa;IACbC;EACF,CAAC,CAAC;;EAEF;EACAR,KAAK,CAACc,SAAS,CAAC,MAAM;IACpB;IACA,OAAOF,UAAU,EAAEG,WAAW,GAAG,UAAU,EAAGC,CAAM,IAAK;MACvD,MAAMC,SAAS,GAAGL,UAAU,CAACK,SAAS,CAAC,CAAC;MAExCC,qBAAqB,CAAC,MAAM;QAC1B,IACER,KAAK,CAACS,KAAK,GAAG,CAAC,IACfF,SAAS,IACT,CAAED,CAAC,CAAgCI,gBAAgB,EACnD;UACAR,UAAU,CAACS,QAAQ,CAAC;YAClB,GAAGvB,YAAY,CAACwB,QAAQ,CAAC,CAAC;YAC1BC,MAAM,EAAEb,KAAK,CAACc;UAChB,CAAC,CAAC;QACJ;MACF,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ,CAAC,EAAE,CAACZ,UAAU,EAAEF,KAAK,CAACS,KAAK,EAAET,KAAK,CAACc,GAAG,CAAC,CAAC;EAExC,oBACExB,KAAA,CAAAyB,aAAA,CAACZ,iBAAiB,qBAChBb,KAAA,CAAAyB,aAAA,CAACvB,eAAe,EAAAwB,QAAA,KACVjB,IAAI;IACRC,KAAK,EAAEA,KAAM;IACbE,UAAU,EAAEA,UAAW;IACvBD,WAAW,EAAEA;EAAY,EAC1B,CACgB,CAAC;AAExB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASgB,0BAA0BA,CAmBxCC,MAAe,EAAmC;EAClD,OAAO/B,sBAAsB,CAACM,SAAS,CAAC,CAACyB,MAAM,CAAC;AAClD;AAEA,cAAc,SAAS;AACvB,SAASC,kBAAkB,EAAEC,wBAAwB,QAAQ,UAAU","ignoreList":[]}
@@ -1,23 +1,63 @@
1
- import { StackActions, StackRouter } from "@react-navigation/native";
1
+ import { StackActions, StackRouter, useNavigation } from "@react-navigation/native";
2
2
  import { nanoid } from "nanoid/non-secure";
3
3
  export const BottomSheetActions = {
4
4
  ...StackActions,
5
- snapTo(index) {
5
+ /**
6
+ * Snap the bottom sheet to a specific index.
7
+ */
8
+ snapTo: index => ({
9
+ type: "SNAP_TO",
10
+ index
11
+ }),
12
+ /**
13
+ * Dismiss the current bottom sheet.
14
+ */
15
+ dismiss: () => ({
16
+ type: "DISMISS"
17
+ }),
18
+ /**
19
+ * Remove the sheet from navigation state after dismiss animation completes.
20
+ */
21
+ remove: () => ({
22
+ type: "REMOVE"
23
+ })
24
+ };
25
+
26
+ /**
27
+ * Ensures the base route (first screen) exists in the navigation state.
28
+ * This is important because the first screen is the main content,
29
+ * and subsequent screens are rendered as bottom sheets.
30
+ */
31
+ const ensureBaseRoute = (state, baseRouteName, routeParamList) => {
32
+ if (!baseRouteName) {
33
+ return state;
34
+ }
35
+ const hasBaseRoute = state.routes.some(r => r.name === baseRouteName);
36
+ if (!hasBaseRoute) {
37
+ const baseRoute = {
38
+ key: `${baseRouteName}-${nanoid()}`,
39
+ name: baseRouteName,
40
+ params: routeParamList?.[baseRouteName]
41
+ };
6
42
  return {
7
- type: "SNAP_TO",
8
- index
43
+ ...state,
44
+ index: state.routes.length,
45
+ routes: [baseRoute, ...state.routes]
9
46
  };
10
47
  }
48
+ return state;
11
49
  };
12
- export function BottomSheetRouter(routerOptions) {
50
+ export const BottomSheetRouter = routerOptions => {
13
51
  const baseRouter = StackRouter(routerOptions);
14
52
  return {
15
53
  ...baseRouter,
16
54
  type: "bottom-sheet",
17
55
  getInitialState(options) {
18
56
  const state = baseRouter.getInitialState(options);
57
+ const baseRouteName = routerOptions.initialRouteName ?? options.routeNames[0];
58
+ const stateWithBaseRoute = ensureBaseRoute(state, baseRouteName, options.routeParamList);
19
59
  return {
20
- ...state,
60
+ ...stateWithBaseRoute,
21
61
  stale: false,
22
62
  type: "bottom-sheet",
23
63
  key: `bottom-sheet-${nanoid()}`
@@ -27,15 +67,76 @@ export function BottomSheetRouter(routerOptions) {
27
67
  switch (action.type) {
28
68
  case "SNAP_TO":
29
69
  {
30
- const index = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
70
+ const routeIndex = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
71
+ return {
72
+ ...state,
73
+ routes: state.routes.map((route, i) => i === routeIndex ? {
74
+ ...route,
75
+ snapToIndex: action.index,
76
+ snapToKey: (route.snapToKey ?? 0) + 1
77
+ } : route)
78
+ };
79
+ }
80
+ case "GO_BACK":
81
+ case "DISMISS":
82
+ {
83
+ return this.getStateForAction(state, StackActions.pop(1), options);
84
+ }
85
+ case "POP":
86
+ {
87
+ // Only base screen remains - let parent navigator handle it
88
+ if (state.routes.length <= 1) {
89
+ return null;
90
+ }
91
+ const count = "payload" in action && typeof action.payload?.count === "number" ? action.payload.count : 1;
92
+
93
+ // Calculate how many routes we can actually pop (don't pop base screen)
94
+ const maxPopCount = state.routes.length - 1;
95
+ const actualCount = Math.min(count, maxPopCount);
96
+
97
+ // Base screen - let parent navigator handle it
98
+ if (actualCount <= 0) {
99
+ return null;
100
+ }
101
+
102
+ // Target index is the route we want to stay on (land on after pop)
103
+ // closingIndex is the first route to be dismissed (the one after target)
104
+ const targetIndex = state.routes.length - 1 - actualCount;
105
+ const closingIndex = targetIndex + 1;
106
+
107
+ // Mark only the bottom-most route to pop as closing
108
+ // The sheet's dismiss() will handle dismissing sheets above it first
31
109
  return {
32
110
  ...state,
33
- routes: state.routes.map((route, i) => i === index ? {
111
+ index: closingIndex,
112
+ routes: state.routes.map((route, i) => i === closingIndex ? {
34
113
  ...route,
35
- snapToIndex: action.index
114
+ closing: true
36
115
  } : route)
37
116
  };
38
117
  }
118
+ case "POP_TO_TOP":
119
+ {
120
+ const popCount = state.routes.length - 1;
121
+ return this.getStateForAction(state, StackActions.pop(popCount), options);
122
+ }
123
+ case "REMOVE":
124
+ {
125
+ // Actually remove the closing route and all routes above it
126
+ const routeKey = action.source;
127
+ const routeIndex = routeKey ? state.routes.findIndex(r => r.key === routeKey) : state.routes.findIndex(r => r.closing);
128
+ if (routeIndex === -1) {
129
+ return state;
130
+ }
131
+
132
+ // Remove the route and all routes above it (they were dismissed together)
133
+ const routes = state.routes.filter((_, i) => i < routeIndex);
134
+ return {
135
+ ...state,
136
+ index: Math.min(state.index, routes.length - 1),
137
+ routes
138
+ };
139
+ }
39
140
  default:
40
141
  return baseRouter.getStateForAction(state, action, options);
41
142
  }
@@ -53,13 +154,36 @@ export function BottomSheetRouter(routerOptions) {
53
154
  routeParamList,
54
155
  routeGetIdList
55
156
  });
157
+ const baseRouteName = routerOptions.initialRouteName ?? routeNames[0];
158
+ const stateWithBaseRoute = ensureBaseRoute(state, baseRouteName, routeParamList);
56
159
  return {
57
- ...state,
160
+ ...stateWithBaseRoute,
58
161
  type: "bottom-sheet",
59
162
  key: `bottom-sheet-${nanoid()}`
60
163
  };
61
164
  },
62
165
  actionCreators: BottomSheetActions
63
166
  };
64
- }
167
+ };
168
+
169
+ /**
170
+ * Hook to access BottomSheet navigation with the snapTo helper.
171
+ *
172
+ * @example
173
+ * ```tsx
174
+ * function MySheet() {
175
+ * const navigation = useBottomSheetNavigation();
176
+ *
177
+ * // Snap to a specific index
178
+ * const handleExpand = () => {
179
+ * navigation.snapTo(1); // Snap to second index
180
+ * };
181
+ *
182
+ * return (
183
+ * <Button title="Expand" onPress={handleExpand} />
184
+ * );
185
+ * }
186
+ * ```
187
+ */
188
+ export const useBottomSheetNavigation = () => useNavigation();
65
189
  //# sourceMappingURL=router.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["StackActions","StackRouter","nanoid","BottomSheetActions","snapTo","index","type","BottomSheetRouter","routerOptions","baseRouter","getInitialState","options","state","stale","key","getStateForAction","action","target","source","routes","findIndex","r","map","route","i","snapToIndex","getRehydratedState","partialState","routeNames","routeParamList","routeGetIdList","actionCreators"],"sourceRoot":"../../../src","sources":["router/router.ts"],"mappings":"AAAA,SAGIA,YAAY,EAEZC,WAAW,QAER,0BAA0B;AACjC,SAASC,MAAM,QAAQ,mBAAmB;AAe1C,OAAO,MAAMC,kBAAkB,GAAG;EAC9B,GAAGH,YAAY;EACfI,MAAMA,CAACC,KAAa,EAAyB;IACzC,OAAO;MAAEC,IAAI,EAAE,SAAS;MAAED;IAAM,CAAC;EACrC;AACJ,CAAC;AAED,OAAO,SAASE,iBAAiBA,CAC7BC,aAAiC,EACuC;EACxE,MAAMC,UAAU,GAAGR,WAAW,CAACO,aAAa,CAG3C;EACD,OAAO;IACH,GAAGC,UAAU;IACbH,IAAI,EAAE,cAAc;IACpBI,eAAeA,CAACC,OAAO,EAAE;MACrB,MAAMC,KAAK,GAAGH,UAAU,CAACC,eAAe,CAACC,OAAO,CAAC;MAEjD,OAAO;QACH,GAAGC,KAAK;QACRC,KAAK,EAAE,KAAK;QACZP,IAAI,EAAE,cAAc;QACpBQ,GAAG,EAAE,gBAAgBZ,MAAM,CAAC,CAAC;MACjC,CAAC;IACL,CAAC;IACDa,iBAAiBA,CAACH,KAAK,EAAEI,MAAM,EAAEL,OAAO,EAAE;MACtC,QAAQK,MAAM,CAACV,IAAI;QACf,KAAK,SAAS;UAAE;YACZ,MAAMD,KAAK,GACPW,MAAM,CAACC,MAAM,KAAKL,KAAK,CAACE,GAAG,IAAIE,MAAM,CAACE,MAAM,GACtCN,KAAK,CAACO,MAAM,CAACC,SAAS,CAAEC,CAAC,IAAKA,CAAC,CAACP,GAAG,KAAKE,MAAM,CAACE,MAAM,CAAC,GACtDN,KAAK,CAACP,KAAK;YAErB,OAAO;cACH,GAAGO,KAAK;cACRO,MAAM,EAAEP,KAAK,CAACO,MAAM,CAACG,GAAG,CAAC,CAACC,KAAK,EAAEC,CAAC,KAC9BA,CAAC,KAAKnB,KAAK,GACL;gBACI,GAAGkB,KAAK;gBACRE,WAAW,EAAET,MAAM,CAACX;cACxB,CAAC,GACDkB,KACV;YACJ,CAAC;UACL;QACA;UACI,OAAOd,UAAU,CAACM,iBAAiB,CAACH,KAAK,EAAEI,MAAM,EAAEL,OAAO,CAAC;MACnE;IACJ,CAAC;IACDe,kBAAkBA,CAACC,YAAY,EAAE;MAAEC,UAAU;MAAEC,cAAc;MAAEC;IAAe,CAAC,EAAE;MAC7E,IAAIH,YAAY,CAACd,KAAK,KAAK,KAAK,EAAE;QAC9B,OAAOc,YAAY;MACvB;MAEA,MAAMf,KAAK,GAAGH,UAAU,CAACiB,kBAAkB,CAACC,YAAY,EAAE;QACtDC,UAAU;QACVC,cAAc;QACdC;MACJ,CAAC,CAAC;MAEF,OAAO;QACH,GAAGlB,KAAK;QACRN,IAAI,EAAE,cAAc;QACpBQ,GAAG,EAAE,gBAAgBZ,MAAM,CAAC,CAAC;MACjC,CAAC;IACL,CAAC;IACD6B,cAAc,EAAE5B;EACpB,CAAC;AACL","ignoreList":[]}
1
+ {"version":3,"names":["StackActions","StackRouter","useNavigation","nanoid","BottomSheetActions","snapTo","index","type","dismiss","remove","ensureBaseRoute","state","baseRouteName","routeParamList","hasBaseRoute","routes","some","r","name","baseRoute","key","params","length","BottomSheetRouter","routerOptions","baseRouter","getInitialState","options","initialRouteName","routeNames","stateWithBaseRoute","stale","getStateForAction","action","routeIndex","target","source","findIndex","map","route","i","snapToIndex","snapToKey","pop","count","payload","maxPopCount","actualCount","Math","min","targetIndex","closingIndex","closing","popCount","routeKey","filter","_","getRehydratedState","partialState","routeGetIdList","actionCreators","useBottomSheetNavigation"],"sourceRoot":"../../../src","sources":["router/router.ts"],"mappings":"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","ignoreList":[]}
@@ -1,173 +1,139 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
- import { BottomSheetBackdrop, BottomSheetModal, BottomSheetModalProvider } from "@gorhom/bottom-sheet";
2
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
3
3
  import { useTheme } from "@react-navigation/native";
4
4
  import * as React from "react";
5
- import { StatusBar } from "react-native";
6
- import Animated, { Easing, interpolate, interpolateColor, runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue, withSpring } from "react-native-reanimated";
7
- import { useSafeAreaInsets } from "react-native-safe-area-context";
8
- function BottomSheetModalScreen({
9
- index,
10
- navigation,
11
- clickThrough,
12
- iosModalSheetTypeOfAnimation,
13
- opacity,
5
+ import { BottomSheetActions } from "./router";
6
+ import BottomSheet from "../sheet";
7
+ function BottomSheetScreen({
14
8
  children,
9
+ navigation,
10
+ route,
15
11
  ...props
16
12
  }) {
17
13
  const ref = React.useRef(null);
18
- const lastIndexRef = React.useRef(index);
14
+ const lastSnapIndexRef = React.useRef(route.snapToIndex ?? props.index ?? 0);
19
15
 
20
- // Present on mount.
21
- React.useEffect(() => {
22
- ref.current?.present();
23
- }, []);
24
- const isMounted = React.useRef(true);
16
+ // Handle route closing state
25
17
  React.useEffect(() => {
26
- return () => {
27
- isMounted.current = false;
28
- };
29
- }, []);
18
+ if (route.closing) {
19
+ ref.current?.close();
20
+ }
21
+ }, [route.closing]);
22
+
23
+ // Handle snap point changes from navigation actions
30
24
  React.useEffect(() => {
31
- if (index != null && lastIndexRef.current !== index) {
32
- ref.current?.snapToIndex(index);
25
+ if (route.snapToIndex != null && route.snapToIndex !== lastSnapIndexRef.current) {
26
+ ref.current?.snapToIndex(route.snapToIndex);
27
+ lastSnapIndexRef.current = route.snapToIndex;
33
28
  }
34
- }, [index]);
35
- const onChange = React.useCallback(newIndex => {
36
- const currentIndex = lastIndexRef.current;
37
- lastIndexRef.current = newIndex;
29
+ }, [route.snapToIndex, route.snapToKey]);
30
+ const handleChange = React.useCallback((newIndex, position, type) => {
31
+ navigation.emit({
32
+ type: "sheetOnChange",
33
+ target: route.key,
34
+ data: {
35
+ index: newIndex,
36
+ position,
37
+ type
38
+ }
39
+ });
40
+ const currentIndex = lastSnapIndexRef.current;
41
+ lastSnapIndexRef.current = newIndex;
38
42
  if (newIndex >= 0 && newIndex !== currentIndex) {
39
- navigation.snapTo(newIndex);
40
- }
41
- }, [navigation]);
42
- const onDismiss = React.useCallback(() => {
43
- // BottomSheetModal will call onDismiss on unmount, be we do not want that since
44
- // we already popped the screen.
45
- if (isMounted.current) {
46
- navigation.goBack();
43
+ navigation.dispatch(BottomSheetActions.snapTo(newIndex));
47
44
  }
48
45
  }, [navigation]);
49
- return /*#__PURE__*/React.createElement(BottomSheetModal, _extends({
46
+ return /*#__PURE__*/React.createElement(BottomSheet, _extends({
50
47
  ref: ref,
51
- onDismiss: onDismiss,
52
- onChange: onChange,
53
- index: index,
54
- backdropComponent: props => /*#__PURE__*/React.createElement(BottomSheetBackdrop, _extends({}, props, {
55
- appearsOnIndex: 0,
56
- disappearsOnIndex: -1,
57
- enableTouchThrough: !!clickThrough,
58
- opacity: opacity || 0.45
59
- }))
48
+ onChange: handleChange
60
49
  }, props), children);
61
50
  }
62
- const DEFAULT_SNAP_POINTS = ["66%"];
63
51
  export function BottomSheetView({
64
52
  state,
53
+ navigation,
65
54
  descriptors
66
55
  }) {
67
56
  const {
68
57
  colors
69
58
  } = useTheme();
70
59
  const {
71
- top
60
+ bottom,
61
+ left,
62
+ right
72
63
  } = useSafeAreaInsets();
73
64
  const themeBackgroundStyle = React.useMemo(() => ({
65
+ borderCurve: "continuous",
74
66
  backgroundColor: colors.card
75
67
  }), [colors.card]);
76
68
  const themeHandleIndicatorStyle = React.useMemo(() => ({
77
- backgroundColor: colors.border,
78
- height: 5,
79
- width: 50
69
+ borderCurve: "continuous",
70
+ backgroundColor: colors.border
80
71
  }), [colors.border]);
81
-
82
- // IOS modal sheet type of animation
83
- const isFullScreen = useSharedValue(0);
84
- const colorStyle = useAnimatedStyle(() => ({
85
- flex: 1,
86
- backgroundColor: interpolateColor(isFullScreen.value, [0, 1], ["transparent", "#000"])
87
- }));
88
- const animatedStyle = useAnimatedStyle(() => ({
89
- flex: 1,
90
- transform: [{
91
- scaleX: withSpring(interpolate(isFullScreen.value, [0, 1], [1, 0.92]), {
92
- damping: 15,
93
- stiffness: 100
94
- })
95
- }, {
96
- translateY: withSpring(interpolate(isFullScreen.value, [0, 1], [0, top + 5]), {
97
- damping: 15,
98
- stiffness: 100
99
- })
100
- }]
101
- }));
102
-
103
- // Since background color is white, we need to set status bar to light
104
- const setStatusBar = StatusBar.setBarStyle;
105
- useAnimatedReaction(() => isFullScreen.value, currentValue => {
106
- "worklet";
107
-
108
- if (currentValue > -1) {
109
- runOnJS(setStatusBar)(currentValue >= 0.5 ? "light-content" : "default");
110
- }
111
- }, []);
112
-
113
- // Avoid rendering provider if we only have one screen.
114
- const shouldRenderProvider = React.useRef(false);
115
- shouldRenderProvider.current = shouldRenderProvider.current || state.routes.length > 1;
116
- const firstRoute = state.routes[0];
117
- if (!firstRoute) {
118
- // no routes at all, probably shouldn't happen, but let's be defensive
119
- return null;
120
- }
121
- const firstDescriptor = descriptors[firstRoute.key];
122
- if (!firstDescriptor) {
123
- // if we don't have a descriptor for the first route, bail out
124
- return null;
125
- }
126
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Animated.View, {
127
- style: colorStyle
128
- }, /*#__PURE__*/React.createElement(Animated.View, {
129
- style: animatedStyle
130
- }, firstDescriptor.render?.())), shouldRenderProvider.current && /*#__PURE__*/React.createElement(BottomSheetModalProvider, null, state.routes.slice(1).map(route => {
72
+ const defaultStyle = React.useMemo(() => ({
73
+ paddingBottom: bottom,
74
+ paddingLeft: left,
75
+ paddingRight: right
76
+ }), [bottom, left, right]);
77
+ const [baseRoute, ...sheetRoutes] = state.routes;
78
+ const baseDescriptor = baseRoute ? descriptors[baseRoute.key] : null;
79
+ return /*#__PURE__*/React.createElement(React.Fragment, null, baseDescriptor?.render(), sheetRoutes.map(route => {
131
80
  const descriptor = descriptors[route.key];
132
81
  if (!descriptor) return null;
133
82
  const {
134
83
  options,
135
- navigation,
136
84
  render
137
85
  } = descriptor;
138
86
  const {
139
- index,
140
- snapPoints,
141
- handleStyle,
87
+ index = 0,
88
+ style,
142
89
  backgroundStyle,
143
90
  handleIndicatorStyle,
144
- enableDynamicSizing,
145
- ...sheetProps
91
+ handleStyle,
92
+ ...props
146
93
  } = options;
147
- return /*#__PURE__*/React.createElement(BottomSheetModalScreen, _extends({
148
- key: route.key
149
- // Make sure index is in range, it could be out if snapToIndex is persisted
150
- // and snapPoints is changed.
151
- ,
152
- index: Math.min(route.snapToIndex ?? index ?? 0, !!snapPoints ? snapPoints.length - 1 : 0),
153
- snapPoints: !snapPoints && !enableDynamicSizing ? DEFAULT_SNAP_POINTS : snapPoints,
154
- onAnimate: (_, to) => {
155
- // @ts-ignore TODO: Fix types
156
- isFullScreen.value = ["%100", "100%"].includes(snapPoints?.[to]) ? 1 : 0;
157
- },
158
- animationConfigs: {
159
- duration: 300,
160
- easing: Easing.bezier(0.25, 0.1, 0.25, 1)
161
- },
162
- topInset: top + 18,
94
+ return /*#__PURE__*/React.createElement(BottomSheetScreen, _extends({
95
+ key: route.key,
96
+ id: route.key,
97
+ route: route,
98
+ index: index,
163
99
  navigation: navigation,
164
- enableDynamicSizing: enableDynamicSizing,
100
+ style: [defaultStyle, style],
165
101
  backgroundStyle: [themeBackgroundStyle, backgroundStyle],
166
102
  handleIndicatorStyle: [themeHandleIndicatorStyle, handleIndicatorStyle],
167
103
  handleStyle: [themeBackgroundStyle, {
168
- borderRadius: 20
169
- }, handleStyle]
170
- }, sheetProps), render?.());
171
- })));
104
+ borderRadius: 24
105
+ }, handleStyle],
106
+ onClose: data => {
107
+ navigation.dispatch({
108
+ ...BottomSheetActions.remove(),
109
+ source: route.key
110
+ });
111
+ navigation.emit({
112
+ type: "sheetDismiss",
113
+ target: route.key,
114
+ data
115
+ });
116
+ },
117
+ onBeforeShow: data => {
118
+ navigation.emit({
119
+ type: "sheetPresent",
120
+ target: route.key,
121
+ data
122
+ });
123
+ },
124
+ onAnimate: (fromIndex, toIndex, fromPosition, toPosition) => {
125
+ navigation.emit({
126
+ type: "sheetOnAnimate",
127
+ target: route.key,
128
+ data: {
129
+ fromIndex,
130
+ toIndex,
131
+ fromPosition,
132
+ toPosition
133
+ }
134
+ });
135
+ }
136
+ }, props), render());
137
+ }));
172
138
  }
173
139
  //# sourceMappingURL=view.js.map