@niibase/bottom-sheet-manager 1.1.0 → 1.3.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 +372 -38
- package/lib/commonjs/events.js +100 -15
- package/lib/commonjs/events.js.map +1 -1
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/manager.js +107 -29
- package/lib/commonjs/manager.js.map +1 -1
- package/lib/commonjs/provider.js +69 -28
- package/lib/commonjs/provider.js.map +1 -1
- package/lib/commonjs/router/index.js +50 -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 +194 -84
- package/lib/commonjs/router/view.js.map +1 -1
- package/lib/commonjs/sheet.js +125 -76
- 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 +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/manager.js +108 -29
- package/lib/module/manager.js.map +1 -1
- package/lib/module/provider.js +65 -25
- package/lib/module/provider.js.map +1 -1
- package/lib/module/router/index.js +34 -18
- 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 +194 -84
- package/lib/module/router/view.js.map +1 -1
- package/lib/module/sheet.js +127 -78
- 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 +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/manager.d.ts +57 -7
- package/lib/typescript/manager.d.ts.map +1 -1
- package/lib/typescript/provider.d.ts +22 -3
- package/lib/typescript/provider.d.ts.map +1 -1
- package/lib/typescript/router/index.d.ts +33 -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 +113 -17
- package/lib/typescript/router/types.d.ts.map +1 -1
- package/lib/typescript/router/view.d.ts +1 -1
- package/lib/typescript/router/view.d.ts.map +1 -1
- package/lib/typescript/sheet.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +27 -12
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/events.ts +118 -27
- package/src/index.ts +6 -5
- package/src/manager.ts +156 -33
- package/src/provider.tsx +98 -44
- package/src/router/index.tsx +38 -31
- package/src/router/router.ts +184 -15
- package/src/router/types.ts +119 -22
- package/src/router/view.tsx +252 -132
- package/src/sheet.tsx +176 -95
- package/src/types.ts +144 -129
package/src/sheet.tsx
CHANGED
|
@@ -20,9 +20,9 @@ import {
|
|
|
20
20
|
} from "react-native";
|
|
21
21
|
import {
|
|
22
22
|
Easing,
|
|
23
|
-
interpolate,
|
|
24
23
|
useAnimatedReaction,
|
|
25
24
|
useSharedValue,
|
|
25
|
+
withTiming,
|
|
26
26
|
} from "react-native-reanimated";
|
|
27
27
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
28
28
|
import { useTheme } from "@react-navigation/native";
|
|
@@ -33,8 +33,9 @@ import {
|
|
|
33
33
|
useSheetAnimationContext,
|
|
34
34
|
useSheetIDContext,
|
|
35
35
|
useSheetRef,
|
|
36
|
+
useStackBehaviorContext,
|
|
36
37
|
} from "./provider";
|
|
37
|
-
import { BottomSheetInstance, BottomSheetProps, SheetIds } from "./types";
|
|
38
|
+
import { BottomSheetInstance, BottomSheetProps, SheetIds, StackBehavior } from "./types";
|
|
38
39
|
import { PrivateManager } from "./manager";
|
|
39
40
|
import { eventManager } from "./events";
|
|
40
41
|
|
|
@@ -64,34 +65,42 @@ const useSheetManager = ({
|
|
|
64
65
|
onContextUpdate,
|
|
65
66
|
}: {
|
|
66
67
|
id?: string;
|
|
67
|
-
onHide: (data?:
|
|
68
|
-
onBeforeShow?: (data?:
|
|
68
|
+
onHide: (data?: unknown, dismiss?: boolean, behavior?: StackBehavior) => void;
|
|
69
|
+
onBeforeShow?: (data?: unknown, behavior?: StackBehavior) => void;
|
|
69
70
|
onContextUpdate: () => void;
|
|
70
71
|
}) => {
|
|
71
|
-
const [visible, setVisible] = React.useState(false);
|
|
72
72
|
const currentContext = useProviderContext();
|
|
73
|
+
const hasShownRef = React.useRef(false);
|
|
73
74
|
|
|
74
75
|
React.useEffect(() => {
|
|
75
76
|
if (!id) return undefined;
|
|
76
77
|
|
|
77
78
|
const subscriptions = [
|
|
78
|
-
eventManager.subscribe(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
eventManager.subscribe(
|
|
80
|
+
`show_${id}`,
|
|
81
|
+
(data: unknown, context?: string, behavior?: StackBehavior) => {
|
|
82
|
+
if (currentContext !== context) return;
|
|
83
|
+
if (!hasShownRef.current) {
|
|
84
|
+
hasShownRef.current = true;
|
|
85
|
+
onContextUpdate?.();
|
|
86
|
+
onBeforeShow?.(data, behavior);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
),
|
|
90
|
+
eventManager.subscribe(
|
|
91
|
+
`hide_${id}`,
|
|
92
|
+
(data: unknown, context: string, dismiss?: boolean, behavior?: StackBehavior) => {
|
|
93
|
+
if (currentContext !== context) return;
|
|
94
|
+
hasShownRef.current = false;
|
|
95
|
+
onHide?.(data, dismiss, behavior);
|
|
96
|
+
},
|
|
97
|
+
),
|
|
88
98
|
];
|
|
89
99
|
return () => {
|
|
100
|
+
hasShownRef.current = false;
|
|
90
101
|
subscriptions.forEach((s) => s?.unsubscribe?.());
|
|
91
102
|
};
|
|
92
103
|
}, [id, onHide, onBeforeShow, onContextUpdate, currentContext]);
|
|
93
|
-
|
|
94
|
-
return { visible, setVisible };
|
|
95
104
|
};
|
|
96
105
|
|
|
97
106
|
const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetProps>(
|
|
@@ -106,10 +115,12 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
106
115
|
enableDynamicSizing = false,
|
|
107
116
|
handleIndicatorStyle,
|
|
108
117
|
iosModalSheetTypeOfAnimation: pageAnimation,
|
|
118
|
+
animatedIndex: defaultAnimatedIndex,
|
|
109
119
|
backgroundStyle,
|
|
120
|
+
onAnimate,
|
|
110
121
|
handleStyle,
|
|
122
|
+
style,
|
|
111
123
|
clickThrough,
|
|
112
|
-
fullScreen,
|
|
113
124
|
opacity,
|
|
114
125
|
|
|
115
126
|
...props
|
|
@@ -118,14 +129,27 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
118
129
|
) => {
|
|
119
130
|
const currentSheetRef = useSheetRef();
|
|
120
131
|
const currentCtx = useProviderContext();
|
|
132
|
+
const stackContext = useStackBehaviorContext();
|
|
121
133
|
|
|
122
|
-
const { isFullScreen, iosModalSheetTypeOfAnimation } =
|
|
134
|
+
const { isFullScreen, iosModalSheetTypeOfAnimation, duration } =
|
|
135
|
+
useSheetAnimationContext();
|
|
123
136
|
const animatedIndex = useSharedValue(0);
|
|
137
|
+
const previousIndex = useSharedValue(-1);
|
|
138
|
+
|
|
139
|
+
const [currentStackBehavior, setCurrentStackBehavior] =
|
|
140
|
+
React.useState<StackBehavior>(stackBehavior);
|
|
141
|
+
const isPushed = currentStackBehavior === "push";
|
|
124
142
|
|
|
125
143
|
const { colors } = useTheme();
|
|
126
|
-
const {
|
|
144
|
+
const { bottom, left, right } = useSafeAreaInsets();
|
|
145
|
+
|
|
127
146
|
const themeBackgroundStyle = React.useMemo(
|
|
128
|
-
() => ({
|
|
147
|
+
() => ({
|
|
148
|
+
borderCurve: "continuous" as unknown as undefined,
|
|
149
|
+
backgroundColor: colors.card,
|
|
150
|
+
borderTopLeftRadius: 20,
|
|
151
|
+
borderTopRightRadius: 20,
|
|
152
|
+
}),
|
|
129
153
|
[colors.card],
|
|
130
154
|
);
|
|
131
155
|
const themeHandleIndicatorStyle = React.useMemo(
|
|
@@ -137,6 +161,15 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
137
161
|
[colors.border],
|
|
138
162
|
);
|
|
139
163
|
|
|
164
|
+
const defaultStyle = React.useMemo(
|
|
165
|
+
() => ({
|
|
166
|
+
paddingBottom: bottom,
|
|
167
|
+
paddingLeft: left,
|
|
168
|
+
paddingRight: right,
|
|
169
|
+
}),
|
|
170
|
+
[bottom, left, right],
|
|
171
|
+
);
|
|
172
|
+
|
|
140
173
|
const valueRef = React.useRef<unknown>(null);
|
|
141
174
|
const bottomSheetRef = React.useRef<BottomSheetModal>(null);
|
|
142
175
|
const hardwareBackPressEvent = React.useRef<NativeEventSubscription>(
|
|
@@ -145,10 +178,15 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
145
178
|
|
|
146
179
|
const id = useSheetIDContext();
|
|
147
180
|
const sheetId = props.id || id;
|
|
181
|
+
|
|
148
182
|
useSheetManager({
|
|
149
183
|
id: sheetId,
|
|
150
|
-
onHide: (data, dismiss) =>
|
|
151
|
-
|
|
184
|
+
onHide: (data, dismiss, behavior) => {
|
|
185
|
+
if (behavior) setCurrentStackBehavior(behavior);
|
|
186
|
+
hideSheet(data, true, dismiss);
|
|
187
|
+
},
|
|
188
|
+
onBeforeShow: (data, behavior) => {
|
|
189
|
+
if (behavior) setCurrentStackBehavior(behavior);
|
|
152
190
|
onBeforeShow?.(data);
|
|
153
191
|
valueRef.current = undefined;
|
|
154
192
|
currentSheetRef.current = getInstance();
|
|
@@ -164,69 +202,111 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
164
202
|
});
|
|
165
203
|
|
|
166
204
|
useAnimatedReaction(
|
|
167
|
-
() =>
|
|
168
|
-
if (!!iosModalSheetTypeOfAnimation || !!pageAnimation) {
|
|
169
|
-
isFullScreen.value = 0;
|
|
170
|
-
}
|
|
171
|
-
return animatedIndex.value;
|
|
172
|
-
},
|
|
205
|
+
() => animatedIndex.value,
|
|
173
206
|
(index) => {
|
|
174
|
-
"worklet";
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
207
|
+
("worklet");
|
|
208
|
+
if (defaultAnimatedIndex) {
|
|
209
|
+
defaultAnimatedIndex.set(index);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!iosModalSheetTypeOfAnimation && !pageAnimation) {
|
|
213
|
+
if (isFullScreen.value > 0) isFullScreen.set(0);
|
|
214
|
+
previousIndex.set(index);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (isFullScreen.value < 0) {
|
|
219
|
+
isFullScreen.set(0);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const isClosing =
|
|
223
|
+
index < 0 || (previousIndex.value >= 0 && index < previousIndex.value - 0.05);
|
|
224
|
+
previousIndex.set(index);
|
|
225
|
+
|
|
226
|
+
if (isClosing) {
|
|
227
|
+
if (isFullScreen.value > 0.01) {
|
|
228
|
+
isFullScreen.set(
|
|
229
|
+
withTiming(0, {
|
|
230
|
+
duration: duration * 0.85,
|
|
231
|
+
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
232
|
+
}),
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const points: (string | number)[] = ["%90", "90%"];
|
|
239
|
+
const fullScreenIndex =
|
|
240
|
+
snapPoints instanceof Array
|
|
179
241
|
? snapPoints.findIndex((p) => points.includes(p))
|
|
180
242
|
: snapPoints?.value?.findIndex((p) => points.includes(p)) || -1;
|
|
181
243
|
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
isFullScreen.value = interpolate(
|
|
187
|
-
index,
|
|
188
|
-
[checkFullScreen - 1, checkFullScreen],
|
|
189
|
-
[0, 1],
|
|
190
|
-
);
|
|
244
|
+
if (index >= fullScreenIndex - 0.5 && index <= fullScreenIndex + 0.5) {
|
|
245
|
+
isFullScreen.set(1);
|
|
246
|
+
} else if (index >= 0) {
|
|
247
|
+
isFullScreen.set(0);
|
|
191
248
|
}
|
|
192
249
|
},
|
|
193
|
-
[snapPoints],
|
|
250
|
+
[snapPoints, iosModalSheetTypeOfAnimation, pageAnimation, duration],
|
|
194
251
|
);
|
|
195
252
|
|
|
196
253
|
const hideSheet = React.useCallback(
|
|
197
|
-
(data?:
|
|
198
|
-
|
|
254
|
+
(data?: unknown, fromManager?: boolean, dismiss?: boolean) => {
|
|
255
|
+
let value = data ?? valueRef.current;
|
|
256
|
+
|
|
257
|
+
hardwareBackPressEvent.current?.remove();
|
|
199
258
|
|
|
200
|
-
|
|
201
|
-
|
|
259
|
+
const closeValue = onClose?.(value);
|
|
260
|
+
if (closeValue !== undefined) value = closeValue;
|
|
261
|
+
|
|
262
|
+
if (dismiss && currentStackBehavior === "push") {
|
|
263
|
+
if (fromManager) valueRef.current = data;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (currentStackBehavior !== "replace" || !dismiss) {
|
|
202
268
|
bottomSheetRef.current?.close();
|
|
203
|
-
onClose?.(value);
|
|
204
269
|
}
|
|
205
270
|
|
|
206
271
|
if (sheetId) {
|
|
207
|
-
PrivateManager.
|
|
208
|
-
|
|
272
|
+
const hasHistory = PrivateManager.history.length > 0;
|
|
273
|
+
const shouldRestorePrevious = currentStackBehavior !== "replace";
|
|
209
274
|
|
|
210
|
-
const history = PrivateManager.history.length >= 1;
|
|
211
275
|
eventManager.publish(
|
|
212
276
|
`onclose_${sheetId}`,
|
|
213
277
|
value,
|
|
214
278
|
currentCtx,
|
|
215
|
-
|
|
279
|
+
hasHistory || !!dismiss,
|
|
280
|
+
currentStackBehavior,
|
|
216
281
|
);
|
|
217
282
|
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
283
|
+
if (shouldRestorePrevious) {
|
|
284
|
+
if (dismiss) {
|
|
285
|
+
PrivateManager.history.push({
|
|
286
|
+
id: sheetId,
|
|
287
|
+
context: currentCtx,
|
|
288
|
+
behavior: currentStackBehavior,
|
|
289
|
+
});
|
|
290
|
+
} else if (hasHistory) {
|
|
291
|
+
const prev = PrivateManager.history.pop()!;
|
|
292
|
+
eventManager.publish(
|
|
293
|
+
`show_wrap_${prev.id}`,
|
|
294
|
+
undefined,
|
|
295
|
+
prev.context,
|
|
296
|
+
true,
|
|
297
|
+
prev.behavior,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
224
300
|
}
|
|
301
|
+
|
|
302
|
+
PrivateManager.remove(sheetId, currentCtx);
|
|
225
303
|
}
|
|
226
|
-
|
|
304
|
+
|
|
305
|
+
if (fromManager) valueRef.current = data;
|
|
227
306
|
},
|
|
228
|
-
[sheetId, currentCtx, onClose],
|
|
307
|
+
[sheetId, currentCtx, onClose, currentStackBehavior],
|
|
229
308
|
);
|
|
309
|
+
|
|
230
310
|
const getInstance = React.useCallback(
|
|
231
311
|
(): BottomSheetInstance => ({
|
|
232
312
|
close(options = {}): void {
|
|
@@ -274,40 +354,54 @@ const BottomSheetComponent = React.forwardRef<BottomSheetInstance, BottomSheetPr
|
|
|
274
354
|
|
|
275
355
|
React.useImperativeHandle(ref, getInstance, [getInstance]);
|
|
276
356
|
|
|
357
|
+
const zIndex = React.useMemo(() => {
|
|
358
|
+
if (!sheetId) return 0;
|
|
359
|
+
if (isPushed) {
|
|
360
|
+
return PrivateManager.zIndex(sheetId, currentCtx);
|
|
361
|
+
}
|
|
362
|
+
return 0;
|
|
363
|
+
}, [sheetId, isPushed, currentCtx]);
|
|
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
|
+
|
|
277
372
|
return (
|
|
278
|
-
<View
|
|
279
|
-
pointerEvents="box-none"
|
|
280
|
-
style={[
|
|
281
|
-
StyleSheet.absoluteFill,
|
|
282
|
-
{
|
|
283
|
-
zIndex:
|
|
284
|
-
sheetId && stackBehavior === "push"
|
|
285
|
-
? PrivateManager.zIndex(sheetId, currentCtx)
|
|
286
|
-
: 0,
|
|
287
|
-
},
|
|
288
|
-
]}
|
|
289
|
-
>
|
|
373
|
+
<View pointerEvents="box-none" style={[StyleSheet.absoluteFill, { zIndex }]}>
|
|
290
374
|
<RNBottomSheet
|
|
291
375
|
enableDynamicSizing={enableDynamicSizing}
|
|
292
|
-
|
|
293
|
-
backdropComponent={(props) => (
|
|
376
|
+
backdropComponent={(backdropProps) => (
|
|
294
377
|
<BottomSheetBackdrop
|
|
295
378
|
enableTouchThrough={!!clickThrough}
|
|
296
|
-
opacity={
|
|
379
|
+
opacity={backdropOpacity}
|
|
297
380
|
disappearsOnIndex={-1}
|
|
298
381
|
appearsOnIndex={0}
|
|
299
|
-
{...
|
|
382
|
+
{...backdropProps}
|
|
300
383
|
/>
|
|
301
384
|
)}
|
|
385
|
+
onAnimate={(from, to, ...args) => {
|
|
386
|
+
const snapPointLen = Array.isArray(snapPoints)
|
|
387
|
+
? snapPoints.length
|
|
388
|
+
: (snapPoints?.value?.length ?? 0);
|
|
389
|
+
|
|
390
|
+
if (to >= isFullScreen.value && to > snapPointLen - 1) {
|
|
391
|
+
isFullScreen.set(0);
|
|
392
|
+
} else if (to > 0 && to === previousIndex.value && isFullScreen.value === 0) {
|
|
393
|
+
isFullScreen.set(1);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
onAnimate?.(from, to, ...args);
|
|
397
|
+
}}
|
|
398
|
+
topInset={0}
|
|
399
|
+
bottomInset={0}
|
|
302
400
|
{...props}
|
|
303
401
|
ref={bottomSheetRef}
|
|
304
402
|
onClose={hideSheet}
|
|
305
403
|
animatedIndex={animatedIndex}
|
|
306
|
-
|
|
307
|
-
fullScreen
|
|
308
|
-
? 0
|
|
309
|
-
: top + (iosModalSheetTypeOfAnimation || pageAnimation ? 20 : 5)
|
|
310
|
-
}
|
|
404
|
+
style={[defaultStyle, style]}
|
|
311
405
|
snapPoints={enableDynamicSizing ? undefined : (snapPoints ?? ["66%"])}
|
|
312
406
|
handleIndicatorStyle={[themeHandleIndicatorStyle, handleIndicatorStyle]}
|
|
313
407
|
backgroundStyle={[themeBackgroundStyle, backgroundStyle]}
|
|
@@ -334,17 +428,4 @@ BottomSheet.FooterContainer = BottomSheetFooterContainer;
|
|
|
334
428
|
BottomSheet.Backdrop = BottomSheetBackdrop;
|
|
335
429
|
BottomSheet.TextInput = BottomSheetTextInput;
|
|
336
430
|
|
|
337
|
-
try {
|
|
338
|
-
const { cssInterop } = require("nativewind");
|
|
339
|
-
cssInterop(BottomSheet, {
|
|
340
|
-
handleIndicatorClassName: "handleIndicatorStyle",
|
|
341
|
-
backgroundClassName: "backgroundStyle",
|
|
342
|
-
containerClassName: "containerStyle",
|
|
343
|
-
handleClassName: "handleStyle",
|
|
344
|
-
className: "style",
|
|
345
|
-
});
|
|
346
|
-
} catch (e) {
|
|
347
|
-
// Ignore error
|
|
348
|
-
}
|
|
349
|
-
|
|
350
431
|
export default BottomSheet;
|