@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,6 @@
1
1
  import type { BottomSheetProps as RNBottomSheetProps } from "@gorhom/bottom-sheet";
2
2
  import type { WithSpringConfig, WithTimingConfig } from "react-native-reanimated";
3
+ import { StatusBarStyle } from "react-native";
3
4
  import React from "react";
4
5
  export interface Sheets {
5
6
  }
@@ -26,9 +27,30 @@ export interface SheetDefinition<Payload = never, ReturnValue = never> {
26
27
  * - `replace`: Closes current sheet and opens new one. Previous sheet is
27
28
  * removed from stack (not restored on close).
28
29
  *
29
- * - `push`: (experimental) Stacks new sheet on top. Previous sheet remains visible underneath.
30
+ * - `push`: Stacks new sheet on top. Previous sheet remains visible underneath.
30
31
  */
31
32
  export type StackBehavior = "switch" | "replace" | "push";
33
+ export type SheetProviderProps = React.PropsWithChildren<{
34
+ context?: string;
35
+ /** @default default */
36
+ statusBar?: StatusBarStyle;
37
+ scaleConfig?: {
38
+ /** Scale factor when sheet is open (default: 0.92) */
39
+ scale?: number;
40
+ /** Vertical translation when sheet is open (default: 5) */
41
+ translateY?: number;
42
+ /** Border radius when sheet is open (default: 24) */
43
+ borderRadius?: number;
44
+ /** Animation config - timing or spring (default: timing with 300ms duration) */
45
+ animation?: {
46
+ type: "timing";
47
+ config?: WithTimingConfig;
48
+ } | {
49
+ type: "spring";
50
+ config?: WithSpringConfig;
51
+ };
52
+ };
53
+ }>;
32
54
  export interface BottomSheetInstance<Id extends SheetIds = SheetIds> {
33
55
  /**
34
56
  * Close the bottom sheet.
@@ -76,11 +98,11 @@ export interface BottomSheetInstance<Id extends SheetIds = SheetIds> {
76
98
  */
77
99
  readonly snapToPosition: (position: string | number, animationConfigs?: AnimationConfigs) => void;
78
100
  }
79
- export type BottomSheetProps = Omit<RNBottomSheetProps, "children" | "onClose"> & {
101
+ export type BottomSheetProps<Id extends SheetIds = SheetIds> = Omit<RNBottomSheetProps, "children" | "onClose"> & {
80
102
  /**
81
103
  * ID of the `BottomSheet`.
82
104
  */
83
- id?: SheetID<SheetIds>;
105
+ id?: SheetID<Id>;
84
106
  /**
85
107
  * Content of the `BottomSheet`.
86
108
  */
@@ -91,23 +113,23 @@ export type BottomSheetProps = Omit<RNBottomSheetProps, "children" | "onClose">
91
113
  */
92
114
  hardwareBackPressToClose?: boolean;
93
115
  /**
94
- * Callback when the sheet close.
116
+ * Callback when the sheet closes. Return a value to override the close data
117
+ * forwarded to `SheetManager.show()` callers.
95
118
  *
96
- * @type () => any;
97
- * @returns The data returned by the sheet to be returned when closed.
119
+ * @returns Optionally return a new value to pass back to the caller.
98
120
  */
99
- onClose?: (data?: unknown) => unknown;
121
+ onClose?: (data?: SheetReturnValue<Id>) => SheetReturnValue<Id> | void;
100
122
  /**
101
123
  * Event called before sheets is visible.
102
124
  * @param data Payload of the sheet if any.
103
125
  * @type () => void;
104
126
  */
105
- onBeforeShow?: (data?: unknown) => void;
127
+ onBeforeShow?: (data?: SheetPayload<Id>) => void;
106
128
  /**
107
129
  * Can click through the sheet to the underlying view.
108
130
  * @default false
109
131
  */
110
- clickThrough?: boolean;
132
+ passThrough?: boolean;
111
133
  /**
112
134
  * Opacity of the sheet's overlay.
113
135
  * @default 0.45
@@ -118,7 +140,7 @@ export type BottomSheetProps = Omit<RNBottomSheetProps, "children" | "onClose">
118
140
  *
119
141
  * - `switch`: (default) Dismisses the current sheet before showing the new one.
120
142
  * - `replace`: Swaps the current sheet's content with smooth crossfade animation.
121
- * - `push`: (experimental) Pushes new sheet on top, creating a navigable stack.
143
+ * - `push`: Pushes new sheet on top, creating a navigable stack.
122
144
  *
123
145
  * @default "switch"
124
146
  */
@@ -130,11 +152,6 @@ export type BottomSheetProps = Omit<RNBottomSheetProps, "children" | "onClose">
130
152
  * @default false
131
153
  */
132
154
  iosModalSheetTypeOfAnimation?: boolean;
133
- className?: string;
134
- handleIndicatorClassName?: string;
135
- backgroundClassName?: string;
136
- containerClassName?: string;
137
- handleClassName?: string;
138
155
  };
139
156
  export {};
140
157
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@niibase/bottom-sheet-manager",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "A bottom sheet manager for react-native based on @gorhom/bottom-sheet",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -14,9 +14,10 @@
14
14
  "build": "bob build && yarn copy-dts && yarn delete-dts.js",
15
15
  "copy-dts": "copyfiles -u 1 \"src/**/*.d.ts\" lib/typescript",
16
16
  "delete-dts.js": "find ./lib/commonjs -name '*.d.js*' -delete && find ./lib/module -name '*.d.js*' -delete",
17
- "release": "rm -rf lib && yarn build && release-it",
17
+ "postinstall": "node scripts/postinstall.mjs",
18
+ "bootstrap": "yarn install && yarn example",
18
19
  "example": "yarn --cwd example",
19
- "bootstrap": "yarn install && yarn example"
20
+ "patch": "patch-package"
20
21
  },
21
22
  "repository": {
22
23
  "type": "git",
@@ -46,16 +47,17 @@
46
47
  "files": [
47
48
  "src",
48
49
  "lib",
50
+ "scripts",
49
51
  "LICENSE"
50
52
  ],
51
53
  "peerDependencies": {
52
- "@react-navigation/native": ">=6.0.0 || >=7.0.0-",
54
+ "@react-navigation/native": ">=7.1.8",
53
55
  "@types/react": "*",
54
56
  "@types/react-native": "*",
55
57
  "react": "*",
56
58
  "react-native": "*",
57
- "react-native-gesture-handler": ">=2.16.1",
58
- "react-native-reanimated": ">=3.16.0 || >=4.0.0-",
59
+ "react-native-gesture-handler": ">=2.28.0",
60
+ "react-native-reanimated": ">=3.16.0 || >=4.0.0",
59
61
  "react-native-safe-area-context": "*"
60
62
  },
61
63
  "peerDependenciesMeta": {
@@ -67,27 +69,25 @@
67
69
  }
68
70
  },
69
71
  "dependencies": {
70
- "@gorhom/bottom-sheet": "^5.2.6",
72
+ "@gorhom/bottom-sheet": "^5.2.8",
71
73
  "nanoid": "^5.1.6"
72
74
  },
73
75
  "devDependencies": {
74
- "@commitlint/cli": "^19.8.1",
75
- "@commitlint/config-conventional": "^19.8.1",
76
- "@ianvs/prettier-plugin-sort-imports": "file:patched/prettier-plugin-sort-imports",
77
- "@react-navigation/native": "^7.1.9",
78
- "@release-it/conventional-changelog": "^10.0.1",
76
+ "@ianvs/prettier-plugin-sort-imports": "4.7.0",
77
+ "@react-navigation/native": "^7.1.8",
79
78
  "@types/react": "~18.3.12",
80
79
  "@types/react-native": "~0.73.0",
81
80
  "copyfiles": "^2.4.1",
82
81
  "metro-react-native-babel-preset": "^0.77.0",
82
+ "patch-package": "^8.0.1",
83
83
  "prettier": "3.6.2",
84
84
  "react": "18.3.1",
85
85
  "react-native": "0.76.0",
86
86
  "react-native-builder-bob": "^0.23.2",
87
- "react-native-gesture-handler": "~2.20.2",
87
+ "react-native-gesture-handler": "~2.28.0",
88
88
  "react-native-reanimated": "~3.19.1",
89
89
  "react-native-safe-area-context": "~5.6.0",
90
- "release-it": "^19.0.4",
90
+ "react-native-screens": "~4.16.0",
91
91
  "typescript": "^5.8.3"
92
92
  },
93
93
  "react-native-builder-bob": {
@@ -99,4 +99,4 @@
99
99
  "typescript"
100
100
  ]
101
101
  }
102
- }
102
+ }
@@ -0,0 +1,36 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { execSync } from "node:child_process";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ // Get the package root (one level up from scripts/)
10
+ const packageRoot = dirname(__dirname);
11
+ const maybeNodeModules = resolve(packageRoot, "../");
12
+ const isInNodeModules =
13
+ maybeNodeModules.endsWith("node_modules") ||
14
+ maybeNodeModules.endsWith("node_modules/@niibase");
15
+
16
+ if (isInNodeModules) {
17
+ // Fix keyboard not closing issue: https://github.com/gorhom/react-native-bottom-sheet/pull/2511
18
+ const gorhamBottomSheet = join(
19
+ maybeNodeModules,
20
+ "@gorhom/bottom-sheet/src/components/bottomSheet/BottomSheet.tsx",
21
+ );
22
+
23
+ try {
24
+ const content = readFileSync(gorhamBottomSheet, "utf-8");
25
+ const updated = content.replace(
26
+ /index\s*=\s*highestDetentPosition\s*\?\?\s*DEFAULT_KEYBOARD_INDEX\s*;/g,
27
+ "index = detents?.indexOf(highestDetentPosition ?? 0) ?? DEFAULT_KEYBOARD_INDEX;",
28
+ );
29
+ writeFileSync(gorhamBottomSheet, updated, "utf-8");
30
+ console.log("Applied patch for @gorhom/bottom-sheet");
31
+ } catch (error) {
32
+ console.error("Error updating @gorhom/bottom-sheet:", error.message);
33
+ }
34
+ } else {
35
+ execSync("yarn run patch", { stdio: "inherit" });
36
+ }
package/src/index.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export { default as BottomSheet } from "./sheet";
2
- export { SheetManager } from "./manager";
2
+ export { SheetManager, PrivateManager } from "./manager";
3
3
  export * from "./router";
4
4
  export * from "./types";
5
5
  export {
6
- SheetProvider,
7
- useSheetPayload,
8
- useSheetRef,
9
- useOnSheet,
10
- useStackBehaviorContext,
11
- registerSheet,
6
+ SheetProvider,
7
+ useSheetPayload,
8
+ useSheetRef,
9
+ useOnSheet,
10
+ useStackBehaviorContext as useSheetStackBehavior,
11
+ registerSheet,
12
12
  } from "./provider";
package/src/manager.ts CHANGED
@@ -25,16 +25,26 @@ export const PrivateManager = {
25
25
  context(options?: { context?: string; id?: string }) {
26
26
  if (!options) options = {};
27
27
  if (!options?.context) {
28
- // If no context is provided, use the current top-most context
29
- // to render the sheet.
30
- for (const context of providerRegistryStack.slice().reverse()) {
31
- // We only automatically select nested sheet providers.
32
- if (
33
- context.startsWith("$$-auto") &&
34
- !context.includes(options?.id as string)
35
- ) {
36
- options.context = context;
37
- break;
28
+ // First try to find a context where this sheet is registered
29
+ if (options?.id) {
30
+ for (const context of providerRegistryStack.slice().reverse()) {
31
+ if (sheetsRegistry[context]?.[options.id]) {
32
+ options.context = context;
33
+ break;
34
+ }
35
+ }
36
+ }
37
+
38
+ // Fall back to the top-most auto-generated nested context
39
+ if (!options.context) {
40
+ for (const context of providerRegistryStack.slice().reverse()) {
41
+ if (
42
+ context.startsWith("$$-auto") &&
43
+ !context.includes(options?.id as string)
44
+ ) {
45
+ options.context = context;
46
+ break;
47
+ }
38
48
  }
39
49
  }
40
50
  }
@@ -130,6 +140,16 @@ export const PrivateManager = {
130
140
  clearHistory: () => {
131
141
  PrivateManager.history = [];
132
142
  },
143
+
144
+ /**
145
+ * Reset all internal state. Useful for testing or HMR.
146
+ */
147
+ reset: () => {
148
+ ids.length = 0;
149
+ keys.length = 0;
150
+ for (const key in refs) delete refs[key];
151
+ PrivateManager.history = [];
152
+ },
133
153
  };
134
154
 
135
155
  class _SheetManager {
@@ -185,18 +205,21 @@ class _SheetManager {
185
205
 
186
206
  const sub = eventManager.subscribe(`onclose_${id}`, handler);
187
207
 
188
- // Handle existing sheets based on stack behavior
189
- const currentStack = PrivateManager.stack();
190
- if (currentStack.length > 0) {
191
- currentStack.forEach(({ id: sheetId, context }) => {
192
- eventManager.publish(
193
- `hide_${sheetId}`,
194
- undefined,
195
- context,
196
- true,
197
- behavior,
198
- );
199
- });
208
+ // Handle existing sheets based on stack behavior.
209
+ // For "push" we do NOT hide existing sheets — they stay underneath.
210
+ if (behavior !== "push") {
211
+ const currentStack = PrivateManager.stack();
212
+ if (currentStack.length > 0) {
213
+ currentStack.forEach(({ id: sheetId, context }) => {
214
+ eventManager.publish(
215
+ `hide_${sheetId}`,
216
+ undefined,
217
+ context,
218
+ true,
219
+ behavior,
220
+ );
221
+ });
222
+ }
200
223
  }
201
224
 
202
225
  // Check if the sheet is registered with any `SheetProviders`.
@@ -306,6 +329,7 @@ class _SheetManager {
306
329
  /**
307
330
  * Push a new sheet on top of the current one, creating a stack.
308
331
  * This is a convenience method for show() with stackBehavior: 'push'.
332
+ *
309
333
  */
310
334
  async push<SheetId extends keyof Sheets>(
311
335
  id: SheetId | (string & {}),
@@ -329,6 +353,19 @@ class _SheetManager {
329
353
  }
330
354
  }
331
355
 
356
+ /**
357
+ * Get the internal ref of a sheet instance.
358
+ *
359
+ * @param id Id of the sheet
360
+ * @param context Optional context of the SheetProvider
361
+ */
362
+ get<SheetId extends keyof Sheets>(
363
+ id: SheetId | (string & {}),
364
+ context?: string,
365
+ ): BottomSheetInstance<SheetId> | undefined {
366
+ return PrivateManager.get(id, context)?.current ?? undefined;
367
+ }
368
+
332
369
  /**
333
370
  * Check if a specific sheet is currently visible.
334
371
  */
@@ -338,6 +375,13 @@ class _SheetManager {
338
375
  ): boolean {
339
376
  return PrivateManager.isSheetVisible(id, context);
340
377
  }
378
+
379
+ /**
380
+ * Reset all internal state. Useful for testing environments.
381
+ */
382
+ reset(): void {
383
+ PrivateManager.reset();
384
+ }
341
385
  }
342
386
 
343
387
  /**
package/src/provider.tsx CHANGED
@@ -7,13 +7,20 @@ import Animated, {
7
7
  useAnimatedStyle,
8
8
  useSharedValue,
9
9
  withSpring,
10
+ withTiming,
10
11
  } from "react-native-reanimated";
11
12
  import { useSafeAreaInsets } from "react-native-safe-area-context";
12
13
  import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
13
14
  import { StatusBar } from "react-native";
14
15
  import React from "react";
15
16
 
16
- import { BottomSheetInstance, SheetPayload, Sheets, StackBehavior } from "./types";
17
+ import {
18
+ BottomSheetInstance,
19
+ SheetPayload,
20
+ SheetProviderProps,
21
+ Sheets,
22
+ StackBehavior,
23
+ } from "./types";
17
24
  import { eventManager } from "./events";
18
25
 
19
26
  export const providerRegistryStack: string[] = [];
@@ -45,47 +52,33 @@ export function registerSheet<SheetId extends keyof Sheets = never>(
45
52
  ? (sheetsRegistry[context] = {})
46
53
  : sheetsRegistry[context];
47
54
  registry[id as string] = Sheet;
48
- eventManager.publish(`${context}-on-register`);
55
+ eventManager.publishAsync(`${context}-on-register`);
49
56
  }
50
57
  }
51
58
 
52
- /**
53
- * Animation configuration for iOS modal sheet style animations.
54
- * @deprecated Use duration prop directly instead
55
- */
56
- export interface ModalSheetAnimationConfig {
57
- /** Duration of the animation in milliseconds */
58
- duration: number;
59
- }
60
-
61
59
  /**
62
60
  * The SheetProvider makes available the sheets in a given context. The default context is
63
61
  * `global`. However if you want to render a Sheet within another sheet or if you want to render
64
62
  * Sheets in a modal. You can use a separate Provider with a custom context value.
65
63
  *
66
- * For example
64
+ * > **Note:** Context names must be unique across all `SheetProvider` instances.
65
+ *
66
+ * @example
67
67
  * ```ts
68
68
  * // Define your SheetProvider in the component/modal where
69
69
  * // you want to show some Sheets.
70
70
  * <SheetProvider context="local-context" />
71
71
  *
72
- * // Then register your sheet when for example the
73
- * // Modal component renders.
74
- *
75
- * registerSheet('local-sheet', LocalSheet,'local-context');
76
- *
72
+ * // Then register your sheet at module level (outside JSX):
73
+ * registerSheet('local-sheet', LocalSheet, 'local-context');
77
74
  * ```
78
75
  */
79
76
  export function SheetProvider({
80
- iosModalSheetTypeOfAnimation = false,
81
77
  context = "global",
82
- duration = 150,
78
+ statusBar,
79
+ scaleConfig,
83
80
  children,
84
- }: React.PropsWithChildren<{
85
- context?: string;
86
- duration?: number;
87
- iosModalSheetTypeOfAnimation?: boolean;
88
- }>) {
81
+ }: SheetProviderProps) {
89
82
  const { top } = useSafeAreaInsets();
90
83
  const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
91
84
  const sheetIds = Object.keys(sheetsRegistry[context] || sheetsRegistry["global"] || {});
@@ -94,33 +87,58 @@ export function SheetProvider({
94
87
  const isFullScreen = useSharedValue(-1);
95
88
  const colorStyle = useAnimatedStyle(() => ({
96
89
  flex: 1,
97
- backgroundColor: withSpring(
98
- interpolateColor(isFullScreen.value, [0, 1], ["transparent", "#000"]),
99
- { duration },
90
+ backgroundColor: interpolateColor(
91
+ isFullScreen.value,
92
+ [0, 1],
93
+ ["transparent", "#000"],
100
94
  ),
101
95
  }));
102
- const animatedStyle = useAnimatedStyle(
103
- () => ({
96
+ const animatedStyle = useAnimatedStyle(() => {
97
+ const radius = interpolate(
98
+ isFullScreen.value,
99
+ [0, 0.3],
100
+ [0, scaleConfig?.borderRadius ?? 24],
101
+ "clamp",
102
+ );
103
+ const scale = interpolate(
104
+ isFullScreen.value,
105
+ [0.5, 0.8],
106
+ [1, scaleConfig?.scale ?? 0.92],
107
+ "clamp",
108
+ );
109
+ const translateY = interpolate(
110
+ isFullScreen.value,
111
+ [0.5, 0.7],
112
+ [0, top + (scaleConfig?.translateY ?? 5)],
113
+ "clamp",
114
+ );
115
+
116
+ return {
104
117
  flex: 1,
105
118
  overflow: "hidden",
106
- borderRadius: interpolate(isFullScreen.value, [0, 0.8, 1], [0, 20, 24], "clamp"),
119
+ borderRadius:
120
+ scaleConfig?.animation?.type === "spring"
121
+ ? withSpring(radius, scaleConfig.animation.config)
122
+ : withTiming(radius, scaleConfig?.animation?.config ?? { duration: 200 }),
107
123
  transform: [
108
124
  {
109
- scaleX: withSpring(
110
- interpolate(isFullScreen.value, [0, 0.8], [1, 0.92], "clamp"),
111
- { duration },
112
- ),
125
+ scaleX:
126
+ scaleConfig?.animation?.type === "spring"
127
+ ? withSpring(scale, scaleConfig.animation.config)
128
+ : withTiming(scale, scaleConfig?.animation?.config ?? { duration: 200 }),
113
129
  },
114
130
  {
115
- translateY: withSpring(
116
- interpolate(isFullScreen.value, [0, 0.8, 1], [0, top, top + 5], "clamp"),
117
- { duration, dampingRatio: 1.5 },
118
- ),
131
+ translateY:
132
+ scaleConfig?.animation?.type === "spring"
133
+ ? withSpring(translateY, scaleConfig.animation.config)
134
+ : withTiming(
135
+ translateY,
136
+ scaleConfig?.animation?.config ?? { duration: 200 },
137
+ ),
119
138
  },
120
139
  ],
121
- }),
122
- [duration],
123
- );
140
+ };
141
+ }, [top, scaleConfig]);
124
142
 
125
143
  // Since background color is white, we need to set status bar to light
126
144
  const setStatusBar = StatusBar.setBarStyle;
@@ -128,8 +146,11 @@ export function SheetProvider({
128
146
  () => isFullScreen.value,
129
147
  (currentValue) => {
130
148
  "worklet";
131
- if (currentValue > -1) {
132
- runOnJS(setStatusBar)(currentValue >= 0.5 ? "light-content" : "default");
149
+ if (currentValue >= 0) {
150
+ runOnJS(setStatusBar)(
151
+ currentValue >= 0.5 ? "light-content" : (statusBar ?? "default"),
152
+ true,
153
+ );
133
154
  }
134
155
  },
135
156
  [],
@@ -147,9 +168,7 @@ export function SheetProvider({
147
168
  }, [context, forceUpdate]);
148
169
 
149
170
  return (
150
- <SheetAnimationContext.Provider
151
- value={{ isFullScreen, iosModalSheetTypeOfAnimation, duration }}
152
- >
171
+ <SheetSharedContext.Provider value={{ isFullScreen, topInset: top }}>
153
172
  <Animated.View style={colorStyle}>
154
173
  <Animated.View style={animatedStyle}>{children}</Animated.View>
155
174
  </Animated.View>
@@ -158,19 +177,18 @@ export function SheetProvider({
158
177
  <RenderSheet key={id} id={id} context={context} />
159
178
  ))}
160
179
  </BottomSheetModalProvider>
161
- </SheetAnimationContext.Provider>
180
+ </SheetSharedContext.Provider>
162
181
  );
163
182
  }
183
+
164
184
  const ProviderContext = React.createContext("global");
165
185
  const SheetIDContext = React.createContext<string | undefined>(undefined);
166
- const SheetAnimationContext = React.createContext<{
167
- iosModalSheetTypeOfAnimation: boolean;
186
+ const SheetSharedContext = React.createContext<{
168
187
  isFullScreen: SharedValue<number>;
169
- duration: number;
188
+ topInset: number;
170
189
  }>({
171
190
  isFullScreen: { value: 0 } as SharedValue<number>,
172
- iosModalSheetTypeOfAnimation: false,
173
- duration: 300,
191
+ topInset: 0,
174
192
  });
175
193
 
176
194
  export const SheetRefContext = React.createContext<
@@ -203,13 +221,14 @@ export const useSheetIDContext = () => React.useContext(SheetIDContext);
203
221
  /**
204
222
  * Get the current sheet animation context.
205
223
  */
206
- export const useSheetAnimationContext = () => React.useContext(SheetAnimationContext);
224
+ export const useSheetSharedContext = () => React.useContext(SheetSharedContext);
207
225
  /**
208
226
  * Get stack behavior context for the current sheet.
209
227
  */
210
228
  export const useStackBehaviorContext = () => React.useContext(StackBehaviorContext);
211
229
  /**
212
230
  * Get the current Sheet's internal ref.
231
+ * Note: `current` may be null before the sheet is fully mounted.
213
232
  */
214
233
  export const useSheetRef = <
215
234
  SheetId extends keyof Sheets = never,