react-native-bottom-sheet-stack 1.5.2 → 1.6.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/lib/commonjs/BottomSheetBackdrop.js.map +1 -1
- package/lib/commonjs/BottomSheetHost.js +103 -140
- package/lib/commonjs/BottomSheetHost.js.map +1 -1
- package/lib/commonjs/BottomSheetManaged.js +8 -9
- package/lib/commonjs/BottomSheetManaged.js.map +1 -1
- package/lib/commonjs/BottomSheetPortal.js +2 -10
- package/lib/commonjs/BottomSheetPortal.js.map +1 -1
- package/lib/commonjs/BottomSheetScaleView.js +13 -28
- package/lib/commonjs/BottomSheetScaleView.js.map +1 -1
- package/lib/commonjs/useBottomSheetContext.js +18 -11
- package/lib/commonjs/useBottomSheetContext.js.map +1 -1
- package/lib/commonjs/useBottomSheetControl.js.map +1 -1
- package/lib/commonjs/useScaleAnimation.js +25 -12
- package/lib/commonjs/useScaleAnimation.js.map +1 -1
- package/lib/typescript/example/src/components/Badge.d.ts +1 -1
- package/lib/typescript/example/src/components/Badge.d.ts.map +1 -1
- package/lib/typescript/example/src/components/Button.d.ts.map +1 -1
- package/lib/typescript/example/src/components/DemoCard.d.ts.map +1 -1
- package/lib/typescript/example/src/components/Sheet.d.ts.map +1 -1
- package/lib/typescript/example/src/screens/HomeScreen.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/ContextSheets.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/DynamicContentSheet.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/NavigationSheets.d.ts.map +1 -1
- package/lib/typescript/example/src/sheets/NestedScaleSheets.d.ts.map +1 -1
- package/lib/typescript/example/src/styles/theme.d.ts +71 -35
- package/lib/typescript/example/src/styles/theme.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetBackdrop.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetHost.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetManaged.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetPortal.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetScaleView.d.ts.map +1 -1
- package/lib/typescript/src/useBottomSheetContext.d.ts +1 -2
- package/lib/typescript/src/useBottomSheetContext.d.ts.map +1 -1
- package/lib/typescript/src/useBottomSheetControl.d.ts.map +1 -1
- package/lib/typescript/src/useScaleAnimation.d.ts +2 -3
- package/lib/typescript/src/useScaleAnimation.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/BottomSheetBackdrop.tsx +0 -3
- package/src/BottomSheetHost.tsx +17 -31
- package/src/BottomSheetManaged.tsx +3 -9
- package/src/BottomSheetPortal.tsx +4 -6
- package/src/BottomSheetScaleView.tsx +2 -7
- package/src/useBottomSheetContext.ts +13 -11
- package/src/useBottomSheetControl.ts +0 -1
- package/src/useScaleAnimation.ts +4 -10
package/package.json
CHANGED
|
@@ -28,12 +28,9 @@ export function BottomSheetBackdrop({
|
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
const animatedIndex = getAnimatedIndex(sheetId);
|
|
31
|
-
|
|
32
31
|
const isVisible = status === 'opening' || status === 'open';
|
|
33
32
|
|
|
34
33
|
const animatedStyle = useAnimatedStyle(() => {
|
|
35
|
-
// Interpolate opacity based on animatedIndex
|
|
36
|
-
// -1 = closed, 0+ = open at snap point
|
|
37
34
|
const opacity = interpolate(
|
|
38
35
|
animatedIndex.value,
|
|
39
36
|
[-1, 0],
|
package/src/BottomSheetHost.tsx
CHANGED
|
@@ -6,13 +6,13 @@ import { PortalHost } from 'react-native-teleport';
|
|
|
6
6
|
|
|
7
7
|
import { shallow } from 'zustand/shallow';
|
|
8
8
|
import { cleanupAnimatedIndex } from './animatedRegistry';
|
|
9
|
-
import { cleanupSheetRef } from './refsMap';
|
|
10
9
|
import { BottomSheetContext } from './BottomSheet.context';
|
|
11
10
|
import { useBottomSheetStore } from './bottomSheet.store';
|
|
12
11
|
import { BottomSheetBackdrop } from './BottomSheetBackdrop';
|
|
13
12
|
import { initBottomSheetCoordinator } from './bottomSheetCoordinator';
|
|
14
13
|
import { useBottomSheetManagerContext } from './BottomSheetManager.provider';
|
|
15
|
-
import {
|
|
14
|
+
import { cleanupSheetRef } from './refsMap';
|
|
15
|
+
import { useScaleAnimatedStyle } from './useScaleAnimation';
|
|
16
16
|
|
|
17
17
|
function PortalHostWrapper({
|
|
18
18
|
id,
|
|
@@ -23,18 +23,14 @@ function PortalHostWrapper({
|
|
|
23
23
|
width: number;
|
|
24
24
|
height: number;
|
|
25
25
|
}) {
|
|
26
|
-
return
|
|
27
|
-
<View style={{ flex: 1, width, height }} pointerEvents="box-none">
|
|
28
|
-
<PortalHost name={`bottomsheet-${id}`} style={{ width, height }} />
|
|
29
|
-
</View>
|
|
30
|
-
);
|
|
26
|
+
return <PortalHost name={`bottomsheet-${id}`} style={{ width, height }} />;
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
function BottomSheetHostComp() {
|
|
34
30
|
const queueIds = useQueueIds();
|
|
35
31
|
const clearGroup = useBottomSheetStore((store) => store.clearGroup);
|
|
36
32
|
|
|
37
|
-
const { groupId
|
|
33
|
+
const { groupId } = useBottomSheetManagerContext();
|
|
38
34
|
|
|
39
35
|
useEffect(() => {
|
|
40
36
|
const unsubscribe = initBottomSheetCoordinator(groupId);
|
|
@@ -52,36 +48,26 @@ function BottomSheetHostComp() {
|
|
|
52
48
|
return (
|
|
53
49
|
<>
|
|
54
50
|
{queueIds.map((id, index) => (
|
|
55
|
-
<QueueItem
|
|
56
|
-
key={id}
|
|
57
|
-
id={id}
|
|
58
|
-
groupId={groupId}
|
|
59
|
-
scaleConfig={scaleConfig}
|
|
60
|
-
stackIndex={index}
|
|
61
|
-
/>
|
|
51
|
+
<QueueItem key={id} id={id} stackIndex={index} />
|
|
62
52
|
))}
|
|
63
53
|
</>
|
|
64
54
|
);
|
|
65
55
|
}
|
|
66
56
|
|
|
67
|
-
function QueueItem({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
stackIndex: number;
|
|
77
|
-
}) {
|
|
78
|
-
const sheet = useBottomSheetStore((state) => state.sheetsById[id]);
|
|
79
|
-
const startClosing = useBottomSheetStore((state) => state.startClosing);
|
|
57
|
+
function QueueItem({ id, stackIndex }: { id: string; stackIndex: number }) {
|
|
58
|
+
const { content, usePortal, startClosing } = useBottomSheetStore(
|
|
59
|
+
(state) => ({
|
|
60
|
+
content: state.sheetsById[id]?.content,
|
|
61
|
+
usePortal: state.sheetsById[id]?.usePortal,
|
|
62
|
+
startClosing: state.startClosing,
|
|
63
|
+
}),
|
|
64
|
+
shallow
|
|
65
|
+
);
|
|
80
66
|
|
|
81
67
|
const { width, height } = useSafeAreaFrame();
|
|
82
68
|
const value = { id };
|
|
83
69
|
|
|
84
|
-
const scaleStyle = useScaleAnimatedStyle({
|
|
70
|
+
const scaleStyle = useScaleAnimatedStyle({ id });
|
|
85
71
|
|
|
86
72
|
useEffect(() => {
|
|
87
73
|
return () => {
|
|
@@ -108,10 +94,10 @@ function QueueItem({
|
|
|
108
94
|
scaleStyle,
|
|
109
95
|
]}
|
|
110
96
|
>
|
|
111
|
-
{
|
|
97
|
+
{usePortal ? (
|
|
112
98
|
<PortalHostWrapper id={id} width={width} height={height} />
|
|
113
99
|
) : (
|
|
114
|
-
|
|
100
|
+
content
|
|
115
101
|
)}
|
|
116
102
|
</Animated.View>
|
|
117
103
|
</BottomSheetContext.Provider>
|
|
@@ -13,7 +13,6 @@ export interface BottomSheetRef extends BottomSheetMethods {}
|
|
|
13
13
|
|
|
14
14
|
interface BottomSheetManagedProps extends BottomSheetProps {}
|
|
15
15
|
|
|
16
|
-
// Null backdrop - we render our own backdrop separately in BottomSheetHost
|
|
17
16
|
const nullBackdrop = () => null;
|
|
18
17
|
|
|
19
18
|
export const BottomSheetManaged = React.forwardRef<
|
|
@@ -32,15 +31,10 @@ export const BottomSheetManaged = React.forwardRef<
|
|
|
32
31
|
},
|
|
33
32
|
ref
|
|
34
33
|
) => {
|
|
35
|
-
const {
|
|
34
|
+
const { id } = useBottomSheetContext();
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
externalAnimatedIndex ?? getAnimatedIndex(bottomSheetState.id);
|
|
40
|
-
|
|
41
|
-
const { handleAnimate, handleClose } = createSheetEventHandlers(
|
|
42
|
-
bottomSheetState.id
|
|
43
|
-
);
|
|
36
|
+
const animatedIndex = externalAnimatedIndex ?? getAnimatedIndex(id);
|
|
37
|
+
const { handleAnimate, handleClose } = createSheetEventHandlers(id);
|
|
44
38
|
|
|
45
39
|
const wrappedOnAnimate: BottomSheetProps['onAnimate'] = (
|
|
46
40
|
fromIndex: number,
|
|
@@ -14,22 +14,20 @@ interface BottomSheetPortalProps {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function BottomSheetPortal({ id, children }: BottomSheetPortalProps) {
|
|
17
|
-
const
|
|
17
|
+
const usePortal = useBottomSheetStore(
|
|
18
|
+
(state) => state.sheetsById[id]?.usePortal
|
|
19
|
+
);
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
if (!sheetState?.usePortal) {
|
|
21
|
+
if (!usePortal) {
|
|
21
22
|
return null;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
// Get the ref that was created in useBottomSheetControl.open()
|
|
25
25
|
const ref = getSheetRef(id);
|
|
26
26
|
|
|
27
|
-
// Clone the child element to add the ref
|
|
28
27
|
const childWithRef = React.cloneElement(children, {
|
|
29
28
|
ref,
|
|
30
29
|
} as { ref: typeof ref });
|
|
31
30
|
|
|
32
|
-
// Wrap with BottomSheetContext so useBottomSheetContext() works inside portal content
|
|
33
31
|
return (
|
|
34
32
|
<Portal hostName={`bottomsheet-${id}`}>
|
|
35
33
|
<BottomSheetContext.Provider value={{ id }}>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type PropsWithChildren } from 'react';
|
|
2
2
|
import { StyleSheet } from 'react-native';
|
|
3
3
|
import Animated from 'react-native-reanimated';
|
|
4
|
-
import { BottomSheetManagerContext } from './BottomSheetManager.context';
|
|
5
4
|
import { useScaleAnimatedStyle } from './useScaleAnimation';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -20,11 +19,7 @@ import { useScaleAnimatedStyle } from './useScaleAnimation';
|
|
|
20
19
|
* ```
|
|
21
20
|
*/
|
|
22
21
|
export function BottomSheetScaleView({ children }: PropsWithChildren) {
|
|
23
|
-
const
|
|
24
|
-
const groupId = context?.groupId ?? 'default';
|
|
25
|
-
const scaleConfig = context?.scaleConfig;
|
|
26
|
-
|
|
27
|
-
const animatedStyle = useScaleAnimatedStyle({ groupId }, scaleConfig);
|
|
22
|
+
const animatedStyle = useScaleAnimatedStyle();
|
|
28
23
|
|
|
29
24
|
return (
|
|
30
25
|
<Animated.View style={[styles.container, animatedStyle]}>
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import { shallow } from 'zustand/shallow';
|
|
1
2
|
import { useMaybeBottomSheetContext } from './BottomSheet.context';
|
|
2
|
-
import {
|
|
3
|
-
useBottomSheetStore,
|
|
4
|
-
type BottomSheetState,
|
|
5
|
-
} from './bottomSheet.store';
|
|
3
|
+
import { useBottomSheetStore } from './bottomSheet.store';
|
|
6
4
|
import type {
|
|
7
5
|
BottomSheetPortalId,
|
|
8
6
|
BottomSheetPortalParams,
|
|
9
7
|
} from './portal.types';
|
|
10
8
|
|
|
11
9
|
export interface UseBottomSheetContextReturn<TParams> {
|
|
12
|
-
|
|
10
|
+
id: string;
|
|
13
11
|
params: TParams;
|
|
14
12
|
close: () => void;
|
|
15
13
|
/** @deprecated Use `close` instead */
|
|
@@ -27,23 +25,27 @@ export function useBottomSheetContext<
|
|
|
27
25
|
>(): UseBottomSheetContextReturn<BottomSheetPortalParams<T> | unknown> {
|
|
28
26
|
const context = useMaybeBottomSheetContext();
|
|
29
27
|
|
|
30
|
-
const
|
|
31
|
-
(state) =>
|
|
28
|
+
const { id, params } = useBottomSheetStore(
|
|
29
|
+
(state) => ({
|
|
30
|
+
id: state.sheetsById[context?.id!]?.id,
|
|
31
|
+
params: state.sheetsById[context?.id!]?.params,
|
|
32
|
+
}),
|
|
33
|
+
shallow
|
|
32
34
|
);
|
|
33
35
|
|
|
34
36
|
const startClosing = useBottomSheetStore((state) => state.startClosing);
|
|
35
37
|
|
|
36
|
-
if (!
|
|
38
|
+
if (!id) {
|
|
37
39
|
throw new Error(
|
|
38
40
|
'useBottomSheetContext must be used within a BottomSheet component'
|
|
39
41
|
);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
const close = () => startClosing(
|
|
44
|
+
const close = () => startClosing(id);
|
|
43
45
|
|
|
44
46
|
return {
|
|
45
|
-
|
|
46
|
-
params:
|
|
47
|
+
id,
|
|
48
|
+
params: params as BottomSheetPortalParams<T>,
|
|
47
49
|
close,
|
|
48
50
|
closeBottomSheet: close,
|
|
49
51
|
};
|
|
@@ -48,7 +48,6 @@ export function useBottomSheetControl<T extends BottomSheetPortalId>(
|
|
|
48
48
|
const open = (options?: OpenOptions<T>) => {
|
|
49
49
|
const groupId = bottomSheetManagerContext?.groupId || 'default';
|
|
50
50
|
|
|
51
|
-
// Create ref when opening (same pattern as useBottomSheetManager)
|
|
52
51
|
const ref = React.createRef<BottomSheetMethods>();
|
|
53
52
|
setSheetRef(id, ref);
|
|
54
53
|
|
package/src/useScaleAnimation.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
useBottomSheetStore,
|
|
9
9
|
type BottomSheetStore,
|
|
10
10
|
} from './bottomSheet.store';
|
|
11
|
+
import { useBottomSheetManagerContext } from './BottomSheetManager.provider';
|
|
11
12
|
|
|
12
13
|
export interface ScaleConfig {
|
|
13
14
|
/** Scale factor when sheet is open (default: 0.92) */
|
|
@@ -39,12 +40,9 @@ export function useScaleDepth(groupId: string, sheetId?: string): number {
|
|
|
39
40
|
const scaleDepthSelector = (state: BottomSheetStore) => {
|
|
40
41
|
const { stackOrder, sheetsById } = state;
|
|
41
42
|
|
|
42
|
-
// For background: check if ANY scaleBackground sheet is active (binary 0/1)
|
|
43
|
-
// For a sheet: count scaleBackground sheets above it in the stack
|
|
44
43
|
const startIndex = sheetId ? stackOrder.indexOf(sheetId) + 1 : 0;
|
|
45
44
|
|
|
46
45
|
if (sheetId && startIndex === 0) {
|
|
47
|
-
// Sheet not found in stack, return previous value to avoid flicker
|
|
48
46
|
return prevDepthRef.current;
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -59,8 +57,6 @@ export function useScaleDepth(groupId: string, sheetId?: string): number {
|
|
|
59
57
|
sheet.status !== 'closing'
|
|
60
58
|
) {
|
|
61
59
|
depth++;
|
|
62
|
-
// For background wrapper (no sheetId), we only need to know if there's at least one
|
|
63
|
-
// Don't accumulate - background scales once, sheets below scale cumulatively
|
|
64
60
|
if (!sheetId) {
|
|
65
61
|
break;
|
|
66
62
|
}
|
|
@@ -78,10 +74,8 @@ export function useScaleDepth(groupId: string, sheetId?: string): number {
|
|
|
78
74
|
* Returns animated style for scale effect based on depth.
|
|
79
75
|
* Uses power scaling: scale^depth for cascading effect.
|
|
80
76
|
*/
|
|
81
|
-
export function useScaleAnimatedStyle(
|
|
82
|
-
{ groupId,
|
|
83
|
-
config?: ScaleConfig
|
|
84
|
-
) {
|
|
77
|
+
export function useScaleAnimatedStyle({ id }: { id?: string } = {}) {
|
|
78
|
+
const { groupId, scaleConfig } = useBottomSheetManagerContext();
|
|
85
79
|
const scaleDepth = useScaleDepth(groupId, id);
|
|
86
80
|
|
|
87
81
|
const {
|
|
@@ -89,7 +83,7 @@ export function useScaleAnimatedStyle(
|
|
|
89
83
|
translateY = DEFAULT_CONFIG.translateY,
|
|
90
84
|
borderRadius = DEFAULT_CONFIG.borderRadius,
|
|
91
85
|
duration = DEFAULT_CONFIG.duration,
|
|
92
|
-
} =
|
|
86
|
+
} = scaleConfig ?? {};
|
|
93
87
|
|
|
94
88
|
const progress = useDerivedValue(() => {
|
|
95
89
|
return withTiming(scaleDepth, { duration });
|