@niibase/bottom-sheet-manager 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +414 -69
- package/lib/commonjs/events.js +100 -15
- package/lib/commonjs/events.js.map +1 -1
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/manager.js +153 -35
- package/lib/commonjs/manager.js.map +1 -1
- package/lib/commonjs/provider.js +92 -54
- package/lib/commonjs/provider.js.map +1 -1
- package/lib/commonjs/router/index.js +80 -21
- package/lib/commonjs/router/index.js.map +1 -1
- package/lib/commonjs/router/router.js +137 -12
- package/lib/commonjs/router/router.js.map +1 -1
- package/lib/commonjs/router/view.js +93 -126
- package/lib/commonjs/router/view.js.map +1 -1
- package/lib/commonjs/sheet.js +122 -98
- package/lib/commonjs/sheet.js.map +1 -1
- package/lib/module/events.js +100 -15
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/manager.js +154 -35
- package/lib/module/manager.js.map +1 -1
- package/lib/module/provider.js +87 -50
- package/lib/module/provider.js.map +1 -1
- package/lib/module/router/index.js +66 -19
- package/lib/module/router/index.js.map +1 -1
- package/lib/module/router/router.js +135 -11
- package/lib/module/router/router.js.map +1 -1
- package/lib/module/router/view.js +92 -126
- package/lib/module/router/view.js.map +1 -1
- package/lib/module/sheet.js +124 -100
- package/lib/module/sheet.js.map +1 -1
- package/lib/typescript/events.d.ts +46 -12
- package/lib/typescript/events.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/manager.d.ts +73 -7
- package/lib/typescript/manager.d.ts.map +1 -1
- package/lib/typescript/provider.d.ts +22 -16
- package/lib/typescript/provider.d.ts.map +1 -1
- package/lib/typescript/router/index.d.ts +47 -17
- package/lib/typescript/router/index.d.ts.map +1 -1
- package/lib/typescript/router/router.d.ts +44 -5
- package/lib/typescript/router/router.d.ts.map +1 -1
- package/lib/typescript/router/types.d.ts +142 -32
- package/lib/typescript/router/types.d.ts.map +1 -1
- package/lib/typescript/router/view.d.ts +3 -3
- package/lib/typescript/router/view.d.ts.map +1 -1
- package/lib/typescript/sheet.d.ts +1 -1
- package/lib/typescript/sheet.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +52 -21
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +14 -15
- package/src/events.ts +118 -27
- package/src/index.ts +2 -1
- package/src/manager.ts +209 -42
- package/src/provider.tsx +144 -71
- package/src/router/index.tsx +77 -33
- package/src/router/router.ts +188 -15
- package/src/router/types.ts +172 -57
- package/src/router/view.tsx +111 -213
- package/src/sheet.tsx +192 -124
- package/src/types.ts +51 -24
package/src/sheet.tsx
CHANGED
|
@@ -19,29 +19,28 @@ import {
|
|
|
19
19
|
type NativeEventSubscription,
|
|
20
20
|
} from "react-native";
|
|
21
21
|
import {
|
|
22
|
-
Easing,
|
|
23
22
|
interpolate,
|
|
24
23
|
useAnimatedReaction,
|
|
25
24
|
useSharedValue,
|
|
26
25
|
} from "react-native-reanimated";
|
|
27
26
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
28
|
-
import { useTheme } from "@react-navigation/native";
|
|
29
27
|
import React from "react";
|
|
30
28
|
|
|
31
29
|
import {
|
|
32
30
|
useProviderContext,
|
|
33
|
-
useSheetAnimationContext,
|
|
34
31
|
useSheetIDContext,
|
|
35
32
|
useSheetRef,
|
|
33
|
+
useSheetSharedContext,
|
|
34
|
+
useStackBehaviorContext,
|
|
36
35
|
} from "./provider";
|
|
37
|
-
import { BottomSheetInstance, BottomSheetProps, SheetIds } from "./types";
|
|
36
|
+
import { BottomSheetInstance, BottomSheetProps, SheetIds, StackBehavior } from "./types";
|
|
38
37
|
import { PrivateManager } from "./manager";
|
|
39
38
|
import { eventManager } from "./events";
|
|
40
39
|
|
|
41
40
|
interface BottomSheetFC
|
|
42
41
|
extends React.MemoExoticComponent<React.ForwardRefExoticComponent<BottomSheetProps>> {
|
|
43
42
|
<Id extends SheetIds>(
|
|
44
|
-
props: BottomSheetProps & React.RefAttributes<BottomSheetInstance<Id>>,
|
|
43
|
+
props: BottomSheetProps<Id> & React.RefAttributes<BottomSheetInstance<Id>>,
|
|
45
44
|
): React.JSX.Element;
|
|
46
45
|
|
|
47
46
|
// Components
|
|
@@ -57,6 +56,9 @@ interface BottomSheetFC
|
|
|
57
56
|
TextInput: typeof BottomSheetTextInput;
|
|
58
57
|
}
|
|
59
58
|
|
|
59
|
+
const FULL_SCREEN_POINTS: (string | number)[] =
|
|
60
|
+
Platform.OS === "ios" ? ["%90", "90%"] : ["%93", "93%"];
|
|
61
|
+
|
|
60
62
|
const useSheetManager = ({
|
|
61
63
|
id,
|
|
62
64
|
onHide,
|
|
@@ -64,79 +66,105 @@ const useSheetManager = ({
|
|
|
64
66
|
onContextUpdate,
|
|
65
67
|
}: {
|
|
66
68
|
id?: string;
|
|
67
|
-
onHide: (data?:
|
|
68
|
-
onBeforeShow?: (data?:
|
|
69
|
+
onHide: (data?: unknown, dismiss?: boolean, behavior?: StackBehavior) => void;
|
|
70
|
+
onBeforeShow?: (data?: unknown, behavior?: StackBehavior) => void;
|
|
69
71
|
onContextUpdate: () => void;
|
|
70
72
|
}) => {
|
|
71
|
-
const [visible, setVisible] = React.useState(false);
|
|
72
73
|
const currentContext = useProviderContext();
|
|
74
|
+
const hasShownRef = React.useRef(false);
|
|
73
75
|
|
|
74
76
|
React.useEffect(() => {
|
|
75
77
|
if (!id) return undefined;
|
|
76
78
|
|
|
77
79
|
const subscriptions = [
|
|
78
|
-
eventManager.subscribe(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
eventManager.subscribe(
|
|
81
|
+
`show_${id}`,
|
|
82
|
+
(data: unknown, context?: string, behavior?: StackBehavior) => {
|
|
83
|
+
if (currentContext !== context) return;
|
|
84
|
+
if (!hasShownRef.current) {
|
|
85
|
+
hasShownRef.current = true;
|
|
86
|
+
onContextUpdate?.();
|
|
87
|
+
onBeforeShow?.(data, behavior);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
),
|
|
91
|
+
eventManager.subscribe(
|
|
92
|
+
`hide_${id}`,
|
|
93
|
+
(data: unknown, context: string, dismiss?: boolean, behavior?: StackBehavior) => {
|
|
94
|
+
if (currentContext !== context) return;
|
|
95
|
+
hasShownRef.current = false;
|
|
96
|
+
onHide?.(data, dismiss, behavior);
|
|
97
|
+
},
|
|
98
|
+
),
|
|
88
99
|
];
|
|
100
|
+
|
|
89
101
|
return () => {
|
|
102
|
+
hasShownRef.current = false;
|
|
90
103
|
subscriptions.forEach((s) => s?.unsubscribe?.());
|
|
91
104
|
};
|
|
92
105
|
}, [id, onHide, onBeforeShow, onContextUpdate, currentContext]);
|
|
93
|
-
|
|
94
|
-
return { visible, setVisible };
|
|
95
106
|
};
|
|
96
107
|
|
|
97
108
|
const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetProps>(
|
|
98
109
|
(
|
|
99
110
|
{
|
|
100
111
|
children,
|
|
101
|
-
snapPoints,
|
|
102
112
|
onClose,
|
|
103
113
|
onBeforeShow,
|
|
104
114
|
stackBehavior = "switch",
|
|
105
115
|
hardwareBackPressToClose = true,
|
|
106
116
|
enableDynamicSizing = false,
|
|
107
117
|
handleIndicatorStyle,
|
|
108
|
-
iosModalSheetTypeOfAnimation
|
|
118
|
+
iosModalSheetTypeOfAnimation,
|
|
119
|
+
snapPoints: defaultSnapPoints,
|
|
120
|
+
animatedIndex: defaultAnimatedIndex,
|
|
109
121
|
backgroundStyle,
|
|
122
|
+
onAnimate,
|
|
110
123
|
handleStyle,
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
style,
|
|
125
|
+
passThrough,
|
|
113
126
|
opacity,
|
|
114
|
-
|
|
115
127
|
...props
|
|
116
128
|
},
|
|
117
129
|
ref,
|
|
118
130
|
) => {
|
|
119
131
|
const currentSheetRef = useSheetRef();
|
|
120
132
|
const currentCtx = useProviderContext();
|
|
133
|
+
const stackContext = useStackBehaviorContext();
|
|
121
134
|
|
|
122
|
-
const { isFullScreen, iosModalSheetTypeOfAnimation } = useSheetAnimationContext();
|
|
123
135
|
const animatedIndex = useSharedValue(0);
|
|
124
136
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
() => ({
|
|
133
|
-
|
|
134
|
-
height: 5,
|
|
135
|
-
width: 50,
|
|
136
|
-
}),
|
|
137
|
-
[colors.border],
|
|
137
|
+
const [currentStackBehavior, setCurrentStackBehavior] =
|
|
138
|
+
React.useState<StackBehavior>(stackBehavior);
|
|
139
|
+
const isPushed = currentStackBehavior === "push";
|
|
140
|
+
|
|
141
|
+
const { bottom, left, right } = useSafeAreaInsets();
|
|
142
|
+
|
|
143
|
+
const defaultStyle = React.useMemo(
|
|
144
|
+
() => ({ paddingBottom: bottom, paddingLeft: left, paddingRight: right }),
|
|
145
|
+
[bottom, left, right],
|
|
138
146
|
);
|
|
139
147
|
|
|
148
|
+
const { isFullScreen } = useSheetSharedContext();
|
|
149
|
+
const [snapPoints, fullScreenIndex] = React.useMemo(() => {
|
|
150
|
+
let resolved = defaultSnapPoints;
|
|
151
|
+
|
|
152
|
+
if (
|
|
153
|
+
Platform.OS === "android" &&
|
|
154
|
+
iosModalSheetTypeOfAnimation &&
|
|
155
|
+
Array.isArray(resolved)
|
|
156
|
+
) {
|
|
157
|
+
resolved = resolved.map((p) => (p === "90%" || p === "%90" ? "93%" : p));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const fullScreenIndex =
|
|
161
|
+
resolved instanceof Array
|
|
162
|
+
? resolved.findIndex((p) => FULL_SCREEN_POINTS.includes(p))
|
|
163
|
+
: resolved?.value?.findIndex((p) => FULL_SCREEN_POINTS.includes(p)) || -1;
|
|
164
|
+
|
|
165
|
+
return [resolved, fullScreenIndex] as const;
|
|
166
|
+
}, [defaultSnapPoints, iosModalSheetTypeOfAnimation]);
|
|
167
|
+
|
|
140
168
|
const valueRef = React.useRef<unknown>(null);
|
|
141
169
|
const bottomSheetRef = React.useRef<BottomSheetModal>(null);
|
|
142
170
|
const hardwareBackPressEvent = React.useRef<NativeEventSubscription>(
|
|
@@ -145,11 +173,28 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
145
173
|
|
|
146
174
|
const id = useSheetIDContext();
|
|
147
175
|
const sheetId = props.id || id;
|
|
176
|
+
|
|
177
|
+
const hideSheetRef = React.useRef<
|
|
178
|
+
(
|
|
179
|
+
data?: unknown,
|
|
180
|
+
fromManager?: boolean,
|
|
181
|
+
dismiss?: boolean,
|
|
182
|
+
incomingBehavior?: StackBehavior,
|
|
183
|
+
) => void
|
|
184
|
+
>(null!);
|
|
185
|
+
|
|
148
186
|
useSheetManager({
|
|
149
187
|
id: sheetId,
|
|
150
|
-
onHide: (data, dismiss) =>
|
|
151
|
-
|
|
152
|
-
|
|
188
|
+
onHide: (data, dismiss, behavior) => {
|
|
189
|
+
// Update state for future renders, but also pass behavior directly
|
|
190
|
+
// so hideSheet doesn't read a stale closure value (React state update
|
|
191
|
+
// is async — hideSheet runs before the re-render).
|
|
192
|
+
if (behavior) setCurrentStackBehavior(behavior);
|
|
193
|
+
hideSheetRef.current(data, true, dismiss, behavior);
|
|
194
|
+
},
|
|
195
|
+
onBeforeShow: (data, behavior) => {
|
|
196
|
+
if (behavior) setCurrentStackBehavior(behavior);
|
|
197
|
+
onBeforeShow?.(data as never);
|
|
153
198
|
valueRef.current = undefined;
|
|
154
199
|
currentSheetRef.current = getInstance();
|
|
155
200
|
},
|
|
@@ -164,70 +209,107 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
164
209
|
});
|
|
165
210
|
|
|
166
211
|
useAnimatedReaction(
|
|
167
|
-
() =>
|
|
168
|
-
if (!!iosModalSheetTypeOfAnimation || !!pageAnimation) {
|
|
169
|
-
isFullScreen.value = 0;
|
|
170
|
-
}
|
|
171
|
-
return animatedIndex.value;
|
|
172
|
-
},
|
|
212
|
+
() => animatedIndex.value,
|
|
173
213
|
(index) => {
|
|
174
214
|
"worklet";
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
isFullScreen.value = interpolate(
|
|
187
|
-
index,
|
|
188
|
-
[checkFullScreen - 1, checkFullScreen],
|
|
189
|
-
[0, 1],
|
|
215
|
+
if (defaultAnimatedIndex) {
|
|
216
|
+
defaultAnimatedIndex.set(index);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (iosModalSheetTypeOfAnimation) {
|
|
220
|
+
isFullScreen.set(
|
|
221
|
+
interpolate(
|
|
222
|
+
index,
|
|
223
|
+
[fullScreenIndex - 1, fullScreenIndex, fullScreenIndex + 1],
|
|
224
|
+
[0, 1, 0],
|
|
225
|
+
),
|
|
190
226
|
);
|
|
191
227
|
}
|
|
192
228
|
},
|
|
193
|
-
[
|
|
229
|
+
[iosModalSheetTypeOfAnimation],
|
|
194
230
|
);
|
|
195
231
|
|
|
196
232
|
const hideSheet = React.useCallback(
|
|
197
|
-
(
|
|
233
|
+
(
|
|
234
|
+
data?: unknown,
|
|
235
|
+
fromManager?: boolean,
|
|
236
|
+
dismiss?: boolean,
|
|
237
|
+
incomingBehavior?: StackBehavior,
|
|
238
|
+
) => {
|
|
239
|
+
// Use the freshly-delivered behavior from the event when available.
|
|
240
|
+
// currentStackBehavior comes from React state which may not have flushed
|
|
241
|
+
// yet when this callback fires synchronously from the manager.
|
|
242
|
+
const activeBehavior = incomingBehavior ?? currentStackBehavior;
|
|
243
|
+
|
|
198
244
|
let value = data ?? valueRef.current;
|
|
199
245
|
|
|
200
|
-
|
|
201
|
-
|
|
246
|
+
hardwareBackPressEvent.current?.remove();
|
|
247
|
+
|
|
248
|
+
const closeValue = onClose?.(value as never);
|
|
249
|
+
if (closeValue !== undefined) value = closeValue;
|
|
250
|
+
|
|
251
|
+
if (dismiss && activeBehavior === "push") {
|
|
252
|
+
// For push behavior, a "dismiss" event means another sheet wants to
|
|
253
|
+
// appear on top — do not close this sheet.
|
|
254
|
+
if (fromManager) valueRef.current = data;
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (activeBehavior !== "replace" || !dismiss) {
|
|
202
259
|
bottomSheetRef.current?.close();
|
|
203
|
-
const closeValue = onClose?.(value);
|
|
204
|
-
if (undefined !== closeValue) value = closeValue;
|
|
205
260
|
}
|
|
206
261
|
|
|
207
262
|
if (sheetId) {
|
|
208
|
-
PrivateManager.
|
|
209
|
-
|
|
263
|
+
const hasHistory = PrivateManager.history.length > 0;
|
|
264
|
+
const shouldRestorePrevious = activeBehavior !== "replace";
|
|
210
265
|
|
|
211
|
-
const history = PrivateManager.history.length >= 1;
|
|
212
266
|
eventManager.publish(
|
|
213
267
|
`onclose_${sheetId}`,
|
|
214
268
|
value,
|
|
215
269
|
currentCtx,
|
|
216
|
-
|
|
270
|
+
hasHistory || !!dismiss,
|
|
271
|
+
activeBehavior,
|
|
217
272
|
);
|
|
218
273
|
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
274
|
+
if (shouldRestorePrevious) {
|
|
275
|
+
if (dismiss) {
|
|
276
|
+
// it will surface naturally when the push sheet is closed.
|
|
277
|
+
if (activeBehavior !== "push") {
|
|
278
|
+
PrivateManager.history.push({
|
|
279
|
+
id: sheetId,
|
|
280
|
+
context: currentCtx,
|
|
281
|
+
behavior: activeBehavior,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
} else if (hasHistory) {
|
|
285
|
+
const otherSheetsStillOpen = PrivateManager.stack().some(
|
|
286
|
+
(s) => !(s.id === sheetId && s.context === currentCtx),
|
|
287
|
+
);
|
|
288
|
+
if (!otherSheetsStillOpen) {
|
|
289
|
+
const prev = PrivateManager.history.pop()!;
|
|
290
|
+
eventManager.publish(
|
|
291
|
+
`show_wrap_${prev.id}`,
|
|
292
|
+
undefined,
|
|
293
|
+
prev.context,
|
|
294
|
+
true,
|
|
295
|
+
prev.behavior,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
225
299
|
}
|
|
300
|
+
|
|
301
|
+
PrivateManager.remove(sheetId, currentCtx);
|
|
226
302
|
}
|
|
227
|
-
|
|
303
|
+
|
|
304
|
+
if (fromManager) valueRef.current = data;
|
|
228
305
|
},
|
|
229
|
-
[sheetId, currentCtx, onClose],
|
|
306
|
+
[sheetId, currentCtx, onClose, currentStackBehavior],
|
|
230
307
|
);
|
|
308
|
+
|
|
309
|
+
React.useEffect(() => {
|
|
310
|
+
hideSheetRef.current = hideSheet;
|
|
311
|
+
}, [hideSheet]);
|
|
312
|
+
|
|
231
313
|
const getInstance = React.useCallback(
|
|
232
314
|
(): BottomSheetInstance => ({
|
|
233
315
|
close(options = {}): void {
|
|
@@ -252,9 +334,7 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
252
334
|
|
|
253
335
|
React.useEffect(() => {
|
|
254
336
|
if (sheetId) {
|
|
255
|
-
PrivateManager.registerRef(sheetId, currentCtx, {
|
|
256
|
-
current: getInstance(),
|
|
257
|
-
} as React.RefObject<BottomSheetInstance>);
|
|
337
|
+
PrivateManager.registerRef(sheetId, currentCtx, { current: getInstance() });
|
|
258
338
|
}
|
|
259
339
|
currentSheetRef.current = getInstance();
|
|
260
340
|
}, [currentCtx, getInstance, sheetId, currentSheetRef]);
|
|
@@ -264,7 +344,9 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
264
344
|
hardwareBackPressEvent.current = BackHandler.addEventListener(
|
|
265
345
|
"hardwareBackPress",
|
|
266
346
|
() => {
|
|
267
|
-
|
|
347
|
+
// Go through hideSheet so internal state (PrivateManager, events,
|
|
348
|
+
// history) is updated correctly — not just the visual sheet.
|
|
349
|
+
hideSheetRef.current(undefined, true, false);
|
|
268
350
|
return true;
|
|
269
351
|
},
|
|
270
352
|
);
|
|
@@ -275,44 +357,43 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
275
357
|
|
|
276
358
|
React.useImperativeHandle(ref, getInstance, [getInstance]);
|
|
277
359
|
|
|
360
|
+
const zIndex = React.useMemo(
|
|
361
|
+
() => (isPushed && sheetId ? PrivateManager.zIndex(sheetId, currentCtx) : 0),
|
|
362
|
+
[sheetId, isPushed, currentCtx],
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const backdropOpacity = React.useMemo(() => {
|
|
366
|
+
if (isPushed && stackContext.previousSheetId) {
|
|
367
|
+
return (opacity || 0.45) * 0.6;
|
|
368
|
+
}
|
|
369
|
+
return opacity || 0.45;
|
|
370
|
+
}, [isPushed, stackContext.previousSheetId, opacity]);
|
|
371
|
+
|
|
278
372
|
return (
|
|
279
|
-
<View
|
|
280
|
-
pointerEvents="box-none"
|
|
281
|
-
style={[
|
|
282
|
-
StyleSheet.absoluteFill,
|
|
283
|
-
{
|
|
284
|
-
zIndex:
|
|
285
|
-
sheetId && stackBehavior === "push"
|
|
286
|
-
? PrivateManager.zIndex(sheetId, currentCtx)
|
|
287
|
-
: 0,
|
|
288
|
-
},
|
|
289
|
-
]}
|
|
290
|
-
>
|
|
373
|
+
<View pointerEvents="box-none" style={[StyleSheet.absoluteFill, { zIndex }]}>
|
|
291
374
|
<RNBottomSheet
|
|
292
375
|
enableDynamicSizing={enableDynamicSizing}
|
|
293
|
-
|
|
294
|
-
backdropComponent={(props) => (
|
|
376
|
+
backdropComponent={(backdropProps) => (
|
|
295
377
|
<BottomSheetBackdrop
|
|
296
|
-
enableTouchThrough={!!
|
|
297
|
-
opacity={
|
|
378
|
+
enableTouchThrough={!!passThrough}
|
|
379
|
+
opacity={backdropOpacity}
|
|
298
380
|
disappearsOnIndex={-1}
|
|
299
381
|
appearsOnIndex={0}
|
|
300
|
-
{...
|
|
382
|
+
{...backdropProps}
|
|
301
383
|
/>
|
|
302
384
|
)}
|
|
385
|
+
topInset={0}
|
|
386
|
+
bottomInset={0}
|
|
303
387
|
{...props}
|
|
304
388
|
ref={bottomSheetRef}
|
|
305
389
|
onClose={hideSheet}
|
|
390
|
+
onAnimate={onAnimate}
|
|
306
391
|
animatedIndex={animatedIndex}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
snapPoints={enableDynamicSizing ? undefined : (snapPoints ?? ["66%"])}
|
|
313
|
-
handleIndicatorStyle={[themeHandleIndicatorStyle, handleIndicatorStyle]}
|
|
314
|
-
backgroundStyle={[themeBackgroundStyle, backgroundStyle]}
|
|
315
|
-
handleStyle={[themeBackgroundStyle, handleStyle]}
|
|
392
|
+
style={[defaultStyle, style]}
|
|
393
|
+
snapPoints={enableDynamicSizing ? undefined : snapPoints}
|
|
394
|
+
handleIndicatorStyle={handleIndicatorStyle}
|
|
395
|
+
backgroundStyle={backgroundStyle}
|
|
396
|
+
handleStyle={handleStyle}
|
|
316
397
|
>
|
|
317
398
|
{children}
|
|
318
399
|
</RNBottomSheet>
|
|
@@ -335,17 +416,4 @@ BottomSheet.FooterContainer = BottomSheetFooterContainer;
|
|
|
335
416
|
BottomSheet.Backdrop = BottomSheetBackdrop;
|
|
336
417
|
BottomSheet.TextInput = BottomSheetTextInput;
|
|
337
418
|
|
|
338
|
-
try {
|
|
339
|
-
const { cssInterop } = require("nativewind");
|
|
340
|
-
cssInterop(BottomSheet, {
|
|
341
|
-
handleIndicatorClassName: "handleIndicatorStyle",
|
|
342
|
-
backgroundClassName: "backgroundStyle",
|
|
343
|
-
containerClassName: "containerStyle",
|
|
344
|
-
handleClassName: "handleStyle",
|
|
345
|
-
className: "style",
|
|
346
|
-
});
|
|
347
|
-
} catch (e) {
|
|
348
|
-
// Ignore error
|
|
349
|
-
}
|
|
350
|
-
|
|
351
419
|
export default BottomSheet;
|
package/src/types.ts
CHANGED
|
@@ -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
|
|
|
5
6
|
export interface Sheets {}
|
|
@@ -21,6 +22,37 @@ export interface SheetDefinition<Payload = never, ReturnValue = never> {
|
|
|
21
22
|
returnValue: ReturnValue;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Defines how sheets behave when a new sheet is opened.
|
|
27
|
+
*
|
|
28
|
+
* - `switch`: Closes current sheet and shows new one. Previous sheet is
|
|
29
|
+
* restored when new one closes.
|
|
30
|
+
*
|
|
31
|
+
* - `replace`: Closes current sheet and opens new one. Previous sheet is
|
|
32
|
+
* removed from stack (not restored on close).
|
|
33
|
+
*
|
|
34
|
+
* - `push`: Stacks new sheet on top. Previous sheet remains visible underneath.
|
|
35
|
+
*/
|
|
36
|
+
export type StackBehavior = "switch" | "replace" | "push";
|
|
37
|
+
|
|
38
|
+
export type SheetProviderProps = React.PropsWithChildren<{
|
|
39
|
+
context?: string;
|
|
40
|
+
/** @default default */
|
|
41
|
+
statusBar?: StatusBarStyle;
|
|
42
|
+
scaleConfig?: {
|
|
43
|
+
/** Scale factor when sheet is open (default: 0.92) */
|
|
44
|
+
scale?: number;
|
|
45
|
+
/** Vertical translation when sheet is open (default: 5) */
|
|
46
|
+
translateY?: number;
|
|
47
|
+
/** Border radius when sheet is open (default: 24) */
|
|
48
|
+
borderRadius?: number;
|
|
49
|
+
/** Animation config - timing or spring (default: timing with 300ms duration) */
|
|
50
|
+
animation?:
|
|
51
|
+
| { type: "timing"; config?: WithTimingConfig }
|
|
52
|
+
| { type: "spring"; config?: WithSpringConfig };
|
|
53
|
+
};
|
|
54
|
+
}>;
|
|
55
|
+
|
|
24
56
|
export interface BottomSheetInstance<Id extends SheetIds = SheetIds> {
|
|
25
57
|
/**
|
|
26
58
|
* Close the bottom sheet.
|
|
@@ -81,14 +113,14 @@ export interface BottomSheetInstance<Id extends SheetIds = SheetIds> {
|
|
|
81
113
|
) => void;
|
|
82
114
|
}
|
|
83
115
|
|
|
84
|
-
export type BottomSheetProps = Omit<
|
|
116
|
+
export type BottomSheetProps<Id extends SheetIds = SheetIds> = Omit<
|
|
85
117
|
RNBottomSheetProps,
|
|
86
|
-
"children" | "onClose"
|
|
118
|
+
"children" | "onClose"
|
|
87
119
|
> & {
|
|
88
120
|
/**
|
|
89
121
|
* ID of the `BottomSheet`.
|
|
90
122
|
*/
|
|
91
|
-
id?: SheetID<
|
|
123
|
+
id?: SheetID<Id>;
|
|
92
124
|
|
|
93
125
|
/**
|
|
94
126
|
* Content of the `BottomSheet`.
|
|
@@ -102,25 +134,25 @@ export type BottomSheetProps = Omit<
|
|
|
102
134
|
hardwareBackPressToClose?: boolean;
|
|
103
135
|
|
|
104
136
|
/**
|
|
105
|
-
* Callback when the sheet close
|
|
137
|
+
* Callback when the sheet closes. Return a value to override the close data
|
|
138
|
+
* forwarded to `SheetManager.show()` callers.
|
|
106
139
|
*
|
|
107
|
-
* @
|
|
108
|
-
* @returns The data returned by the sheet to be returned when closed.
|
|
140
|
+
* @returns Optionally return a new value to pass back to the caller.
|
|
109
141
|
*/
|
|
110
|
-
onClose?: (data?:
|
|
142
|
+
onClose?: (data?: SheetReturnValue<Id>) => SheetReturnValue<Id> | void;
|
|
111
143
|
|
|
112
144
|
/**
|
|
113
145
|
* Event called before sheets is visible.
|
|
114
146
|
* @param data Payload of the sheet if any.
|
|
115
147
|
* @type () => void;
|
|
116
148
|
*/
|
|
117
|
-
onBeforeShow?: (data?:
|
|
149
|
+
onBeforeShow?: (data?: SheetPayload<Id>) => void;
|
|
118
150
|
|
|
119
151
|
/**
|
|
120
152
|
* Can click through the sheet to the underlying view.
|
|
121
153
|
* @default false
|
|
122
154
|
*/
|
|
123
|
-
|
|
155
|
+
passThrough?: boolean;
|
|
124
156
|
|
|
125
157
|
/**
|
|
126
158
|
* Opacity of the sheet's overlay.
|
|
@@ -129,26 +161,21 @@ export type BottomSheetProps = Omit<
|
|
|
129
161
|
opacity?: number;
|
|
130
162
|
|
|
131
163
|
/**
|
|
132
|
-
* Defines the stack behavior when
|
|
164
|
+
* Defines the stack behavior when sheets are opened.
|
|
165
|
+
*
|
|
166
|
+
* - `switch`: (default) Dismisses the current sheet before showing the new one.
|
|
167
|
+
* - `replace`: Swaps the current sheet's content with smooth crossfade animation.
|
|
168
|
+
* - `push`: Pushes new sheet on top, creating a navigable stack.
|
|
169
|
+
*
|
|
133
170
|
* @default "switch"
|
|
134
171
|
*/
|
|
135
|
-
stackBehavior?:
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Whether the bottom sheet edge to edge.
|
|
139
|
-
* @default false
|
|
140
|
-
*/
|
|
141
|
-
fullScreen?: boolean;
|
|
172
|
+
stackBehavior?: StackBehavior;
|
|
142
173
|
|
|
143
174
|
/**
|
|
144
|
-
* Whether the bottom sheet is an iOS modal sheet type of animation.
|
|
175
|
+
* Whether the bottom sheet is an iOS 18 modal sheet type of animation.
|
|
176
|
+
* When enabled at snap point 90%, the content behind the sheet scales down and gets a
|
|
177
|
+
* border radius, similar to iOS 18 system sheets.
|
|
145
178
|
* @default false
|
|
146
179
|
*/
|
|
147
180
|
iosModalSheetTypeOfAnimation?: boolean;
|
|
148
|
-
|
|
149
|
-
className?: string;
|
|
150
|
-
handleIndicatorClassName?: string;
|
|
151
|
-
backgroundClassName?: string;
|
|
152
|
-
containerClassName?: string;
|
|
153
|
-
handleClassName?: string;
|
|
154
181
|
};
|