react-native-bottom-sheet-stack 1.6.0 → 1.7.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 +9 -7
- package/lib/commonjs/BottomSheet.context.js +1 -2
- package/lib/commonjs/BottomSheet.context.js.map +1 -1
- package/lib/commonjs/BottomSheetBackdrop.js +23 -32
- package/lib/commonjs/BottomSheetBackdrop.js.map +1 -1
- package/lib/commonjs/BottomSheetHost.js +17 -254
- package/lib/commonjs/BottomSheetHost.js.map +1 -1
- package/lib/commonjs/BottomSheetManaged.js +87 -54
- package/lib/commonjs/BottomSheetManaged.js.map +1 -1
- package/lib/commonjs/BottomSheetPersistent.js +113 -0
- package/lib/commonjs/BottomSheetPersistent.js.map +1 -0
- package/lib/commonjs/BottomSheetPortal.js +4 -3
- package/lib/commonjs/BottomSheetPortal.js.map +1 -1
- package/lib/commonjs/BottomSheetRef.context.js +17 -0
- package/lib/commonjs/BottomSheetRef.context.js.map +1 -0
- package/lib/commonjs/QueueItem.js +167 -0
- package/lib/commonjs/QueueItem.js.map +1 -0
- package/lib/commonjs/animatedRegistry.js +9 -0
- package/lib/commonjs/animatedRegistry.js.map +1 -1
- package/lib/commonjs/bottomSheet.store.js +11 -133
- package/lib/commonjs/bottomSheet.store.js.map +1 -1
- package/lib/commonjs/bottomSheetCoordinator.js +9 -10
- package/lib/commonjs/bottomSheetCoordinator.js.map +1 -1
- package/lib/commonjs/index.js +28 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/portalSessionRegistry.js +32 -0
- package/lib/commonjs/portalSessionRegistry.js.map +1 -0
- package/lib/commonjs/refsMap.js +9 -0
- package/lib/commonjs/refsMap.js.map +1 -1
- package/lib/commonjs/store/helpers.js +59 -0
- package/lib/commonjs/store/helpers.js.map +1 -0
- package/lib/commonjs/store/hooks.js +176 -0
- package/lib/commonjs/store/hooks.js.map +1 -0
- package/lib/commonjs/store/index.js +52 -0
- package/lib/commonjs/store/index.js.map +1 -0
- package/lib/commonjs/store/store.js +140 -0
- package/lib/commonjs/store/store.js.map +1 -0
- package/lib/commonjs/store/types.js +6 -0
- package/lib/commonjs/store/types.js.map +1 -0
- package/lib/commonjs/useBottomSheetContext.js +24 -42
- package/lib/commonjs/useBottomSheetContext.js.map +1 -1
- package/lib/commonjs/useBottomSheetControl.js +8 -14
- package/lib/commonjs/useBottomSheetControl.js.map +1 -1
- package/lib/commonjs/useBottomSheetManager.js +3 -13
- package/lib/commonjs/useBottomSheetManager.js.map +1 -1
- package/lib/commonjs/useBottomSheetStatus.js +9 -17
- package/lib/commonjs/useBottomSheetStatus.js.map +1 -1
- package/lib/commonjs/useEvent.js +39 -0
- package/lib/commonjs/useEvent.js.map +1 -0
- package/lib/commonjs/useScaleAnimation.js +53 -30
- package/lib/commonjs/useScaleAnimation.js.map +1 -1
- package/lib/commonjs/useSheetRenderData.js +62 -0
- package/lib/commonjs/useSheetRenderData.js.map +1 -0
- package/lib/typescript/example/src/App.d.ts.map +1 -1
- package/lib/typescript/example/src/screens/HomeScreen.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/NavigationSheets.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/ScannerNestedSheets.d.ts +4 -0
- package/lib/typescript/example/src/sheets/ScannerNestedSheets.d.ts.map +1 -0
- package/lib/typescript/example/src/sheets/ScannerSheet.d.ts +3 -0
- package/lib/typescript/example/src/sheets/ScannerSheet.d.ts.map +1 -0
- package/lib/typescript/example/src/sheets/index.d.ts +1 -0
- package/lib/typescript/example/src/sheets/index.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheet.context.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetBackdrop.d.ts +0 -5
- package/lib/typescript/src/BottomSheetBackdrop.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetHost.d.ts +1 -3
- package/lib/typescript/src/BottomSheetHost.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetManaged.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetPersistent.d.ts +9 -0
- package/lib/typescript/src/BottomSheetPersistent.d.ts.map +1 -0
- package/lib/typescript/src/BottomSheetPortal.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetRef.context.d.ts +11 -0
- package/lib/typescript/src/BottomSheetRef.context.d.ts.map +1 -0
- package/lib/typescript/src/QueueItem.d.ts +8 -0
- package/lib/typescript/src/QueueItem.d.ts.map +1 -0
- package/lib/typescript/src/animatedRegistry.d.ts +5 -0
- package/lib/typescript/src/animatedRegistry.d.ts.map +1 -1
- package/lib/typescript/src/bottomSheet.store.d.ts +1 -37
- package/lib/typescript/src/bottomSheet.store.d.ts.map +1 -1
- package/lib/typescript/src/bottomSheetCoordinator.d.ts +2 -1
- package/lib/typescript/src/bottomSheetCoordinator.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +5 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/portalSessionRegistry.d.ts +8 -0
- package/lib/typescript/src/portalSessionRegistry.d.ts.map +1 -0
- package/lib/typescript/src/refsMap.d.ts +5 -0
- package/lib/typescript/src/refsMap.d.ts.map +1 -1
- package/lib/typescript/src/store/helpers.d.ts +11 -0
- package/lib/typescript/src/store/helpers.d.ts.map +1 -0
- package/lib/typescript/src/store/hooks.d.ts +16 -0
- package/lib/typescript/src/store/hooks.d.ts.map +1 -0
- package/lib/typescript/src/store/index.d.ts +5 -0
- package/lib/typescript/src/store/index.d.ts.map +1 -0
- package/lib/typescript/src/store/store.d.ts +11 -0
- package/lib/typescript/src/store/store.d.ts.map +1 -0
- package/lib/typescript/src/store/types.d.ts +37 -0
- package/lib/typescript/src/store/types.d.ts.map +1 -0
- package/lib/typescript/src/useBottomSheetContext.d.ts.map +1 -1
- package/lib/typescript/src/useBottomSheetControl.d.ts.map +1 -1
- package/lib/typescript/src/useBottomSheetManager.d.ts.map +1 -1
- package/lib/typescript/src/useBottomSheetStatus.d.ts +1 -2
- package/lib/typescript/src/useBottomSheetStatus.d.ts.map +1 -1
- package/lib/typescript/src/useEvent.d.ts +4 -0
- package/lib/typescript/src/useEvent.d.ts.map +1 -0
- package/lib/typescript/src/useScaleAnimation.d.ts +10 -13
- package/lib/typescript/src/useScaleAnimation.d.ts.map +1 -1
- package/lib/typescript/src/useSheetRenderData.d.ts +17 -0
- package/lib/typescript/src/useSheetRenderData.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/BottomSheet.context.ts +1 -3
- package/src/BottomSheetBackdrop.tsx +10 -19
- package/src/BottomSheetHost.tsx +13 -99
- package/src/BottomSheetManaged.tsx +24 -2
- package/src/BottomSheetPersistent.tsx +57 -0
- package/src/BottomSheetPortal.tsx +5 -7
- package/src/BottomSheetRef.context.ts +14 -0
- package/src/QueueItem.tsx +83 -0
- package/src/animatedRegistry.ts +8 -0
- package/src/bottomSheet.store.ts +1 -173
- package/src/bottomSheetCoordinator.ts +10 -8
- package/src/index.tsx +7 -1
- package/src/portalSessionRegistry.ts +25 -0
- package/src/refsMap.ts +8 -0
- package/src/store/helpers.ts +65 -0
- package/src/store/hooks.ts +50 -0
- package/src/store/index.ts +4 -0
- package/src/store/store.ts +168 -0
- package/src/store/types.ts +42 -0
- package/src/useBottomSheetContext.ts +6 -15
- package/src/useBottomSheetControl.ts +16 -7
- package/src/useBottomSheetManager.tsx +9 -10
- package/src/useBottomSheetStatus.ts +4 -14
- package/src/useEvent.ts +17 -0
- package/src/useScaleAnimation.ts +67 -35
- package/src/useSheetRenderData.ts +74 -0
package/src/useScaleAnimation.ts
CHANGED
|
@@ -2,14 +2,18 @@ import { useRef } from 'react';
|
|
|
2
2
|
import {
|
|
3
3
|
useAnimatedStyle,
|
|
4
4
|
useDerivedValue,
|
|
5
|
+
withSpring,
|
|
5
6
|
withTiming,
|
|
7
|
+
type WithSpringConfig,
|
|
8
|
+
type WithTimingConfig,
|
|
6
9
|
} from 'react-native-reanimated';
|
|
7
|
-
import {
|
|
8
|
-
useBottomSheetStore,
|
|
9
|
-
type BottomSheetStore,
|
|
10
|
-
} from './bottomSheet.store';
|
|
10
|
+
import { useBottomSheetStore } from './bottomSheet.store';
|
|
11
11
|
import { useBottomSheetManagerContext } from './BottomSheetManager.provider';
|
|
12
12
|
|
|
13
|
+
export type ScaleAnimationConfig =
|
|
14
|
+
| { type: 'timing'; config?: WithTimingConfig }
|
|
15
|
+
| { type: 'spring'; config?: WithSpringConfig };
|
|
16
|
+
|
|
13
17
|
export interface ScaleConfig {
|
|
14
18
|
/** Scale factor when sheet is open (default: 0.92) */
|
|
15
19
|
scale?: number;
|
|
@@ -17,76 +21,104 @@ export interface ScaleConfig {
|
|
|
17
21
|
translateY?: number;
|
|
18
22
|
/** Border radius when sheet is open (default: 12) */
|
|
19
23
|
borderRadius?: number;
|
|
20
|
-
/** Animation
|
|
21
|
-
|
|
24
|
+
/** Animation config - timing or spring (default: timing with 300ms duration) */
|
|
25
|
+
animation?: ScaleAnimationConfig;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
const
|
|
28
|
+
const DEFAULT_ANIMATION: ScaleAnimationConfig = {
|
|
29
|
+
type: 'timing',
|
|
30
|
+
config: { duration: 300 },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const DEFAULT_CONFIG = {
|
|
25
34
|
scale: 0.92,
|
|
26
35
|
translateY: 10,
|
|
27
36
|
borderRadius: 12,
|
|
28
|
-
|
|
29
|
-
}
|
|
37
|
+
animation: DEFAULT_ANIMATION,
|
|
38
|
+
} satisfies Required<ScaleConfig>;
|
|
39
|
+
|
|
40
|
+
function useBackgroundScaleDepth(groupId: string): number {
|
|
41
|
+
return useBottomSheetStore((state) => {
|
|
42
|
+
const { stackOrder, sheetsById } = state;
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < stackOrder.length; i++) {
|
|
45
|
+
const id = stackOrder[i]!;
|
|
46
|
+
const sheet = sheetsById[id];
|
|
47
|
+
if (
|
|
48
|
+
sheet &&
|
|
49
|
+
sheet.groupId === groupId &&
|
|
50
|
+
sheet.scaleBackground &&
|
|
51
|
+
sheet.status !== 'closing' &&
|
|
52
|
+
sheet.status !== 'hidden'
|
|
53
|
+
) {
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return 0;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
30
60
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* Uses shallow comparison internally for optimal re-renders.
|
|
36
|
-
*/
|
|
37
|
-
export function useScaleDepth(groupId: string, sheetId?: string): number {
|
|
61
|
+
function useSheetScaleDepth(
|
|
62
|
+
groupId: string,
|
|
63
|
+
sheetId: string | undefined
|
|
64
|
+
): number {
|
|
38
65
|
const prevDepthRef = useRef(0);
|
|
39
66
|
|
|
40
|
-
|
|
41
|
-
|
|
67
|
+
return useBottomSheetStore((state) => {
|
|
68
|
+
if (!sheetId) {
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
42
71
|
|
|
43
|
-
const
|
|
72
|
+
const { stackOrder, sheetsById } = state;
|
|
73
|
+
const sheetIndex = stackOrder.indexOf(sheetId);
|
|
44
74
|
|
|
45
|
-
if (
|
|
75
|
+
if (sheetIndex === -1) {
|
|
46
76
|
return prevDepthRef.current;
|
|
47
77
|
}
|
|
48
78
|
|
|
49
79
|
let depth = 0;
|
|
50
|
-
for (let i =
|
|
80
|
+
for (let i = sheetIndex + 1; i < stackOrder.length; i++) {
|
|
51
81
|
const id = stackOrder[i]!;
|
|
52
82
|
const sheet = sheetsById[id];
|
|
53
83
|
if (
|
|
54
84
|
sheet &&
|
|
55
85
|
sheet.groupId === groupId &&
|
|
56
86
|
sheet.scaleBackground &&
|
|
57
|
-
sheet.status !== 'closing'
|
|
87
|
+
sheet.status !== 'closing' &&
|
|
88
|
+
sheet.status !== 'hidden'
|
|
58
89
|
) {
|
|
59
90
|
depth++;
|
|
60
|
-
if (!sheetId) {
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
91
|
}
|
|
64
92
|
}
|
|
65
93
|
|
|
66
94
|
prevDepthRef.current = depth;
|
|
67
95
|
return depth;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
return useBottomSheetStore(scaleDepthSelector);
|
|
96
|
+
});
|
|
71
97
|
}
|
|
72
98
|
|
|
73
|
-
/**
|
|
74
|
-
* Returns animated style for scale effect based on depth.
|
|
75
|
-
* Uses power scaling: scale^depth for cascading effect.
|
|
76
|
-
*/
|
|
77
99
|
export function useScaleAnimatedStyle({ id }: { id?: string } = {}) {
|
|
78
100
|
const { groupId, scaleConfig } = useBottomSheetManagerContext();
|
|
79
|
-
const scaleDepth = useScaleDepth(groupId, id);
|
|
80
101
|
|
|
81
102
|
const {
|
|
82
103
|
scale = DEFAULT_CONFIG.scale,
|
|
83
104
|
translateY = DEFAULT_CONFIG.translateY,
|
|
84
105
|
borderRadius = DEFAULT_CONFIG.borderRadius,
|
|
85
|
-
|
|
106
|
+
animation = DEFAULT_CONFIG.animation,
|
|
86
107
|
} = scaleConfig ?? {};
|
|
87
108
|
|
|
109
|
+
const isBackground = id === undefined;
|
|
110
|
+
|
|
111
|
+
const backgroundDepth = useBackgroundScaleDepth(groupId);
|
|
112
|
+
const sheetDepth = useSheetScaleDepth(groupId, id);
|
|
113
|
+
|
|
114
|
+
const scaleDepth = isBackground ? backgroundDepth : sheetDepth;
|
|
115
|
+
|
|
116
|
+
// Animate the depth change
|
|
88
117
|
const progress = useDerivedValue(() => {
|
|
89
|
-
|
|
118
|
+
if (animation.type === 'spring') {
|
|
119
|
+
return withSpring(scaleDepth, animation.config);
|
|
120
|
+
}
|
|
121
|
+
return withTiming(scaleDepth, animation.config);
|
|
90
122
|
});
|
|
91
123
|
|
|
92
124
|
return useAnimatedStyle(() => {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { shallow } from 'zustand/shallow';
|
|
2
|
+
import {
|
|
3
|
+
useBottomSheetStore,
|
|
4
|
+
type BottomSheetState,
|
|
5
|
+
} from './bottomSheet.store';
|
|
6
|
+
import { useBottomSheetManagerContext } from './BottomSheetManager.provider';
|
|
7
|
+
|
|
8
|
+
export interface SheetRenderItem {
|
|
9
|
+
id: string;
|
|
10
|
+
stackIndex: number;
|
|
11
|
+
isActive: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns a flat list of sheets to render.
|
|
16
|
+
*
|
|
17
|
+
* Each sheet appears exactly once - this prevents React from
|
|
18
|
+
* unmounting/remounting when a sheet transitions between states.
|
|
19
|
+
*
|
|
20
|
+
* Render order:
|
|
21
|
+
* 1. Hidden persistent sheets (keepMounted=true, not in stack)
|
|
22
|
+
* 2. Active sheets (in stackOrder)
|
|
23
|
+
*/
|
|
24
|
+
export function useSheetRenderData(): SheetRenderItem[] {
|
|
25
|
+
const { groupId } = useBottomSheetManagerContext();
|
|
26
|
+
|
|
27
|
+
return useBottomSheetStore((state) => {
|
|
28
|
+
const hiddenPersistent = getHiddenPersistentSheets(state, groupId);
|
|
29
|
+
const active = getActiveSheets(state, groupId);
|
|
30
|
+
|
|
31
|
+
return [...hiddenPersistent, ...active];
|
|
32
|
+
}, shallow);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getHiddenPersistentSheets(
|
|
36
|
+
state: { sheetsById: Record<string, BottomSheetState>; stackOrder: string[] },
|
|
37
|
+
groupId: string
|
|
38
|
+
): SheetRenderItem[] {
|
|
39
|
+
const inStack = new Set(state.stackOrder);
|
|
40
|
+
|
|
41
|
+
return Object.values(state.sheetsById)
|
|
42
|
+
.filter((sheet) => isHiddenPersistent(sheet, groupId, inStack))
|
|
43
|
+
.map((sheet) => ({
|
|
44
|
+
id: sheet.id,
|
|
45
|
+
stackIndex: -1,
|
|
46
|
+
isActive: false,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isHiddenPersistent(
|
|
51
|
+
sheet: BottomSheetState,
|
|
52
|
+
groupId: string,
|
|
53
|
+
inStack: Set<string>
|
|
54
|
+
): boolean {
|
|
55
|
+
const belongsToGroup = sheet.groupId === groupId;
|
|
56
|
+
const isPersistent = sheet.keepMounted === true;
|
|
57
|
+
const isHidden = sheet.status === 'hidden';
|
|
58
|
+
const isNotInStack = !inStack.has(sheet.id);
|
|
59
|
+
|
|
60
|
+
return belongsToGroup && isPersistent && isHidden && isNotInStack;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getActiveSheets(
|
|
64
|
+
state: { sheetsById: Record<string, BottomSheetState>; stackOrder: string[] },
|
|
65
|
+
groupId: string
|
|
66
|
+
): SheetRenderItem[] {
|
|
67
|
+
return state.stackOrder
|
|
68
|
+
.filter((id) => state.sheetsById[id]?.groupId === groupId)
|
|
69
|
+
.map((id, index) => ({
|
|
70
|
+
id,
|
|
71
|
+
stackIndex: index,
|
|
72
|
+
isActive: true,
|
|
73
|
+
}));
|
|
74
|
+
}
|