react-native-bottom-sheet-stack 1.7.5 → 1.8.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/BottomSheetManaged.js +5 -172
- package/lib/commonjs/BottomSheetManaged.js.map +1 -1
- package/lib/commonjs/BottomSheetPersistent.js.map +1 -1
- package/lib/commonjs/BottomSheetRef.context.js.map +1 -1
- package/lib/commonjs/QueueItem.js +2 -2
- package/lib/commonjs/QueueItem.js.map +1 -1
- package/lib/commonjs/adapter.types.js +6 -0
- package/lib/commonjs/adapter.types.js.map +1 -0
- package/lib/commonjs/adapters/actions-sheet/ActionsSheetAdapter.js +137 -0
- package/lib/commonjs/adapters/actions-sheet/ActionsSheetAdapter.js.map +1 -0
- package/lib/commonjs/adapters/actions-sheet/index.js +13 -0
- package/lib/commonjs/adapters/actions-sheet/index.js.map +1 -0
- package/lib/commonjs/adapters/custom-modal/CustomModalAdapter.js +157 -0
- package/lib/commonjs/adapters/custom-modal/CustomModalAdapter.js.map +1 -0
- package/lib/commonjs/adapters/custom-modal/index.js +19 -0
- package/lib/commonjs/adapters/custom-modal/index.js.map +1 -0
- package/lib/commonjs/adapters/gorhom-sheet/GorhomSheetAdapter.js +187 -0
- package/lib/commonjs/adapters/gorhom-sheet/GorhomSheetAdapter.js.map +1 -0
- package/lib/commonjs/adapters/gorhom-sheet/index.js +13 -0
- package/lib/commonjs/adapters/gorhom-sheet/index.js.map +1 -0
- package/lib/commonjs/adapters/index.js +40 -0
- package/lib/commonjs/adapters/index.js.map +1 -0
- package/lib/commonjs/adapters/react-native-modal/ReactNativeModalAdapter.js +119 -0
- package/lib/commonjs/adapters/react-native-modal/ReactNativeModalAdapter.js.map +1 -0
- package/lib/commonjs/adapters/react-native-modal/index.js +13 -0
- package/lib/commonjs/adapters/react-native-modal/index.js.map +1 -0
- package/lib/commonjs/animatedRegistry.js +11 -1
- package/lib/commonjs/animatedRegistry.js.map +1 -1
- package/lib/commonjs/bottomSheetCoordinator.js +29 -22
- package/lib/commonjs/bottomSheetCoordinator.js.map +1 -1
- package/lib/commonjs/index.js +68 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/refsMap.js.map +1 -1
- package/lib/commonjs/useAdapterRef.js +29 -0
- package/lib/commonjs/useAdapterRef.js.map +1 -0
- package/lib/commonjs/useAnimatedIndex.js +47 -0
- package/lib/commonjs/useAnimatedIndex.js.map +1 -0
- package/lib/commonjs/useBottomSheetControl.js.map +1 -1
- package/lib/commonjs/useBottomSheetManager.js.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/ModalSheets.d.ts +8 -0
- package/lib/typescript/example/src/sheets/ModalSheets.d.ts.map +1 -0
- package/lib/typescript/example/src/sheets/ThirdPartyAdapterSheets.d.ts +17 -0
- package/lib/typescript/example/src/sheets/ThirdPartyAdapterSheets.d.ts.map +1 -0
- package/lib/typescript/example/src/sheets/index.d.ts +2 -0
- package/lib/typescript/example/src/sheets/index.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetManaged.d.ts +10 -9
- package/lib/typescript/src/BottomSheetManaged.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetPersistent.d.ts.map +1 -1
- package/lib/typescript/src/BottomSheetRef.context.d.ts +1 -4
- package/lib/typescript/src/BottomSheetRef.context.d.ts.map +1 -1
- package/lib/typescript/src/QueueItem.d.ts.map +1 -1
- package/lib/typescript/src/adapter.types.d.ts +33 -0
- package/lib/typescript/src/adapter.types.d.ts.map +1 -0
- package/lib/typescript/src/adapters/actions-sheet/ActionsSheetAdapter.d.ts +23 -0
- package/lib/typescript/src/adapters/actions-sheet/ActionsSheetAdapter.d.ts.map +1 -0
- package/lib/typescript/src/adapters/actions-sheet/index.d.ts +2 -0
- package/lib/typescript/src/adapters/actions-sheet/index.d.ts.map +1 -0
- package/lib/typescript/src/adapters/custom-modal/CustomModalAdapter.d.ts +9 -0
- package/lib/typescript/src/adapters/custom-modal/CustomModalAdapter.d.ts.map +1 -0
- package/lib/typescript/src/adapters/custom-modal/index.d.ts +4 -0
- package/lib/typescript/src/adapters/custom-modal/index.d.ts.map +1 -0
- package/lib/typescript/src/adapters/gorhom-sheet/GorhomSheetAdapter.d.ts +7 -0
- package/lib/typescript/src/adapters/gorhom-sheet/GorhomSheetAdapter.d.ts.map +1 -0
- package/lib/typescript/src/adapters/gorhom-sheet/index.d.ts +2 -0
- package/lib/typescript/src/adapters/gorhom-sheet/index.d.ts.map +1 -0
- package/lib/typescript/src/adapters/index.d.ts +5 -0
- package/lib/typescript/src/adapters/index.d.ts.map +1 -0
- package/lib/typescript/src/adapters/react-native-modal/ReactNativeModalAdapter.d.ts +22 -0
- package/lib/typescript/src/adapters/react-native-modal/ReactNativeModalAdapter.d.ts.map +1 -0
- package/lib/typescript/src/adapters/react-native-modal/index.d.ts +2 -0
- package/lib/typescript/src/adapters/react-native-modal/index.d.ts.map +1 -0
- package/lib/typescript/src/animatedRegistry.d.ts +4 -0
- package/lib/typescript/src/animatedRegistry.d.ts.map +1 -1
- package/lib/typescript/src/bottomSheetCoordinator.d.ts +13 -7
- package/lib/typescript/src/bottomSheetCoordinator.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +11 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/refsMap.d.ts +1 -4
- package/lib/typescript/src/refsMap.d.ts.map +1 -1
- package/lib/typescript/src/useAdapterRef.d.ts +21 -0
- package/lib/typescript/src/useAdapterRef.d.ts.map +1 -0
- package/lib/typescript/src/useAnimatedIndex.d.ts +25 -0
- package/lib/typescript/src/useAnimatedIndex.d.ts.map +1 -0
- package/package.json +33 -2
- package/src/BottomSheetManaged.tsx +14 -106
- package/src/BottomSheetPersistent.tsx +2 -2
- package/src/BottomSheetRef.context.ts +2 -4
- package/src/QueueItem.tsx +4 -2
- package/src/adapter.types.ts +35 -0
- package/src/adapters/actions-sheet/ActionsSheetAdapter.tsx +83 -0
- package/src/adapters/actions-sheet/index.ts +4 -0
- package/src/adapters/custom-modal/CustomModalAdapter.tsx +131 -0
- package/src/adapters/custom-modal/index.ts +7 -0
- package/src/adapters/gorhom-sheet/GorhomSheetAdapter.tsx +118 -0
- package/src/adapters/gorhom-sheet/index.ts +4 -0
- package/src/adapters/index.ts +17 -0
- package/src/adapters/react-native-modal/ReactNativeModalAdapter.tsx +81 -0
- package/src/adapters/react-native-modal/index.ts +4 -0
- package/src/animatedRegistry.ts +10 -1
- package/src/bottomSheetCoordinator.ts +32 -24
- package/src/index.tsx +33 -0
- package/src/refsMap.ts +1 -4
- package/src/useAdapterRef.ts +28 -0
- package/src/useAnimatedIndex.ts +31 -0
- package/src/useBottomSheetControl.ts +2 -2
- package/src/useBottomSheetManager.tsx +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-bottom-sheet-stack",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Bottom Sheet Stack Manager",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "lib/commonjs/index.js",
|
|
@@ -73,12 +73,29 @@
|
|
|
73
73
|
"@gorhom/bottom-sheet": ">=5.0.0",
|
|
74
74
|
"react": "*",
|
|
75
75
|
"react-native": "*",
|
|
76
|
+
"react-native-actions-sheet": ">=0.9.0",
|
|
76
77
|
"react-native-gesture-handler": ">=2.0.0",
|
|
78
|
+
"react-native-modal": ">=11.0.0",
|
|
77
79
|
"react-native-reanimated": ">=3.0.0",
|
|
78
80
|
"react-native-safe-area-context": ">=5.0.0",
|
|
79
81
|
"react-native-teleport": ">=0.5.0",
|
|
82
|
+
"react-native-worklets": ">=0.7.0",
|
|
80
83
|
"zustand": ">=5.0.0"
|
|
81
84
|
},
|
|
85
|
+
"peerDependenciesMeta": {
|
|
86
|
+
"@gorhom/bottom-sheet": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"react-native-actions-sheet": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"react-native-gesture-handler": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"react-native-modal": {
|
|
96
|
+
"optional": true
|
|
97
|
+
}
|
|
98
|
+
},
|
|
82
99
|
"workspaces": [
|
|
83
100
|
"example"
|
|
84
101
|
],
|
|
@@ -109,7 +126,21 @@
|
|
|
109
126
|
"plugins": {
|
|
110
127
|
"@release-it/conventional-changelog": {
|
|
111
128
|
"preset": {
|
|
112
|
-
"name": "
|
|
129
|
+
"name": "conventionalcommits",
|
|
130
|
+
"types": [
|
|
131
|
+
{
|
|
132
|
+
"type": "feat",
|
|
133
|
+
"section": "Features"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"type": "fix",
|
|
137
|
+
"section": "Bug Fixes"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"type": "perf",
|
|
141
|
+
"section": "Performance"
|
|
142
|
+
}
|
|
143
|
+
]
|
|
113
144
|
}
|
|
114
145
|
}
|
|
115
146
|
}
|
|
@@ -1,106 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export interface BottomSheetRef extends BottomSheetMethods {}
|
|
16
|
-
|
|
17
|
-
interface BottomSheetManagedProps extends BottomSheetProps {}
|
|
18
|
-
|
|
19
|
-
const nullBackdrop = () => null;
|
|
20
|
-
|
|
21
|
-
export const BottomSheetManaged = React.forwardRef<
|
|
22
|
-
BottomSheetRef,
|
|
23
|
-
BottomSheetManagedProps
|
|
24
|
-
>(
|
|
25
|
-
(
|
|
26
|
-
{
|
|
27
|
-
children,
|
|
28
|
-
onAnimate,
|
|
29
|
-
onChange,
|
|
30
|
-
onClose,
|
|
31
|
-
enablePanDownToClose = true,
|
|
32
|
-
backdropComponent = nullBackdrop,
|
|
33
|
-
animatedIndex: externalAnimatedIndex,
|
|
34
|
-
...props
|
|
35
|
-
},
|
|
36
|
-
forwardedRef
|
|
37
|
-
) => {
|
|
38
|
-
const { id } = useBottomSheetContext();
|
|
39
|
-
const contextRef = useBottomSheetRefContext();
|
|
40
|
-
const ref = contextRef ?? forwardedRef;
|
|
41
|
-
|
|
42
|
-
const defaultIndex = useBottomSheetDefaultIndex();
|
|
43
|
-
const contextAnimatedIndex = getAnimatedIndex(id);
|
|
44
|
-
|
|
45
|
-
if (!contextAnimatedIndex) {
|
|
46
|
-
throw new Error('animatedIndex must be defined in BottomSheetManaged');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
useAnimatedReaction(
|
|
50
|
-
() => contextAnimatedIndex.value,
|
|
51
|
-
(value) => {
|
|
52
|
-
externalAnimatedIndex?.set(value);
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const { handleAnimate, handleChange, handleClose } =
|
|
57
|
-
createSheetEventHandlers(id);
|
|
58
|
-
|
|
59
|
-
const wrappedOnAnimate: BottomSheetProps['onAnimate'] = (
|
|
60
|
-
fromIndex,
|
|
61
|
-
toIndex,
|
|
62
|
-
fromPosition,
|
|
63
|
-
toPosition
|
|
64
|
-
) => {
|
|
65
|
-
handleAnimate(fromIndex, toIndex);
|
|
66
|
-
onAnimate?.(fromIndex, toIndex, fromPosition, toPosition);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const wrappedOnChange: BottomSheetProps['onChange'] = (
|
|
70
|
-
index,
|
|
71
|
-
position,
|
|
72
|
-
type
|
|
73
|
-
) => {
|
|
74
|
-
handleChange(index);
|
|
75
|
-
onChange?.(index, position, type);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const wrappedOnClose = () => {
|
|
79
|
-
onClose?.();
|
|
80
|
-
handleClose();
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const config = useBottomSheetSpringConfigs({
|
|
84
|
-
stiffness: 400,
|
|
85
|
-
damping: 80,
|
|
86
|
-
mass: 0.7,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<BottomSheetOriginal
|
|
91
|
-
animationConfigs={config}
|
|
92
|
-
ref={ref}
|
|
93
|
-
{...props}
|
|
94
|
-
index={defaultIndex}
|
|
95
|
-
animatedIndex={contextAnimatedIndex}
|
|
96
|
-
onChange={wrappedOnChange}
|
|
97
|
-
onClose={wrappedOnClose}
|
|
98
|
-
onAnimate={wrappedOnAnimate}
|
|
99
|
-
backdropComponent={backdropComponent}
|
|
100
|
-
enablePanDownToClose={enablePanDownToClose}
|
|
101
|
-
>
|
|
102
|
-
{children}
|
|
103
|
-
</BottomSheetOriginal>
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
);
|
|
1
|
+
/**
|
|
2
|
+
* Backward-compatible re-export of GorhomSheetAdapter.
|
|
3
|
+
*
|
|
4
|
+
* Existing users can continue importing `BottomSheetManaged` and `BottomSheetRef`
|
|
5
|
+
* without any changes. For new code, prefer importing `GorhomSheetAdapter` directly
|
|
6
|
+
* from 'react-native-bottom-sheet-stack/adapters/gorhom' or use the `ModalAdapter`
|
|
7
|
+
* for modal-based sheets.
|
|
8
|
+
*/
|
|
9
|
+
export {
|
|
10
|
+
GorhomSheetAdapter as BottomSheetManaged,
|
|
11
|
+
type GorhomSheetAdapterProps as BottomSheetManagedProps,
|
|
12
|
+
} from './adapters/gorhom-sheet';
|
|
13
|
+
|
|
14
|
+
export type { SheetAdapterRef as BottomSheetRef } from './adapter.types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BottomSheetMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
2
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import type { SheetAdapterRef } from './adapter.types';
|
|
3
3
|
|
|
4
4
|
import { Portal } from 'react-native-teleport';
|
|
5
5
|
import { BottomSheetContext } from './BottomSheet.context';
|
|
@@ -30,7 +30,7 @@ export function BottomSheetPersistent({
|
|
|
30
30
|
const unmount = useUnmount();
|
|
31
31
|
const sheetExists = useSheetExists(id);
|
|
32
32
|
const portalSession = useSheetPortalSession(id);
|
|
33
|
-
const sheetRef = useRef<
|
|
33
|
+
const sheetRef = useRef<SheetAdapterRef>(null);
|
|
34
34
|
const groupId = bottomSheetManagerContext?.groupId || 'default';
|
|
35
35
|
|
|
36
36
|
const mountSheet = useEvent(() => {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { createContext, useContext
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
type SheetRef = RefObject<BottomSheetMethods | null>;
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import type { SheetRef } from './adapter.types';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Context for passing sheet ref from BottomSheetPersistent/BottomSheetPortal
|
package/src/QueueItem.tsx
CHANGED
|
@@ -43,8 +43,10 @@ export const QueueItem = memo(function QueueItem({
|
|
|
43
43
|
};
|
|
44
44
|
}, [id, keepMounted]);
|
|
45
45
|
|
|
46
|
-
const
|
|
47
|
-
|
|
46
|
+
const baseZIndex = 100_000_000;
|
|
47
|
+
|
|
48
|
+
const backdropZIndex = baseZIndex + stackIndex * 2;
|
|
49
|
+
const contentZIndex = baseZIndex + stackIndex * 2 + 1;
|
|
48
50
|
|
|
49
51
|
if (!animatedIndex) {
|
|
50
52
|
return null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Minimal ref interface for controlling a sheet/modal/overlay.
|
|
5
|
+
* Every adapter must implement these two methods.
|
|
6
|
+
*
|
|
7
|
+
* The coordinator calls:
|
|
8
|
+
* - `expand()` when status transitions to 'opening'
|
|
9
|
+
* - `close()` when status transitions to 'closing' or 'hidden'
|
|
10
|
+
*/
|
|
11
|
+
export interface SheetAdapterRef {
|
|
12
|
+
expand(): void;
|
|
13
|
+
close(): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Event handlers that adapters MUST call to sync UI state back to the store.
|
|
18
|
+
* Returned by `createSheetEventHandlers(sheetId)`.
|
|
19
|
+
*
|
|
20
|
+
* Lifecycle:
|
|
21
|
+
* 1. Coordinator calls `ref.expand()` → adapter shows UI
|
|
22
|
+
* 2. Adapter calls `handleOpened()` when show animation completes
|
|
23
|
+
* 3. User dismisses (swipe/backdrop/back) → adapter calls `handleDismiss()`
|
|
24
|
+
* 4. Adapter calls `handleClosed()` when hide animation completes
|
|
25
|
+
*/
|
|
26
|
+
export interface SheetAdapterEvents {
|
|
27
|
+
/** User-initiated dismiss (swipe down, backdrop tap, hardware back button) */
|
|
28
|
+
handleDismiss(): void;
|
|
29
|
+
/** Show animation completed — sheet is fully visible and interactive */
|
|
30
|
+
handleOpened(): void;
|
|
31
|
+
/** Hide animation completed — sheet is fully hidden */
|
|
32
|
+
handleClosed(): void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type SheetRef = RefObject<SheetAdapterRef | null>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useImperativeHandle, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { SheetAdapterRef } from '../../adapter.types';
|
|
4
|
+
import { createSheetEventHandlers } from '../../bottomSheetCoordinator';
|
|
5
|
+
import { useAdapterRef } from '../../useAdapterRef';
|
|
6
|
+
import { useAnimatedIndex } from '../../useAnimatedIndex';
|
|
7
|
+
import { useBottomSheetContext } from '../../useBottomSheetContext';
|
|
8
|
+
|
|
9
|
+
const ActionSheet = require('react-native-actions-sheet').default;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Adapter for `react-native-actions-sheet` — a zero-dependency action sheet
|
|
13
|
+
* with snap points and gesture controls.
|
|
14
|
+
*
|
|
15
|
+
* All ActionSheet props are accepted via spread and forwarded to the
|
|
16
|
+
* underlying component. Uses `isModal={false}` internally — the stack
|
|
17
|
+
* manager handles the overlay lifecycle.
|
|
18
|
+
*
|
|
19
|
+
* Requires `react-native-actions-sheet` as a peer dependency:
|
|
20
|
+
* ```
|
|
21
|
+
* npm install react-native-actions-sheet
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @see https://github.com/ammarahm-ed/react-native-actions-sheet
|
|
25
|
+
*/
|
|
26
|
+
export interface ActionsSheetAdapterProps {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const ActionsSheetAdapter = React.forwardRef<
|
|
32
|
+
SheetAdapterRef,
|
|
33
|
+
ActionsSheetAdapterProps
|
|
34
|
+
>(({ children, ...sheetProps }, forwardedRef) => {
|
|
35
|
+
const { id } = useBottomSheetContext();
|
|
36
|
+
const ref = useAdapterRef(forwardedRef);
|
|
37
|
+
const animatedIndex = useAnimatedIndex();
|
|
38
|
+
|
|
39
|
+
const actionSheetRef = useRef<any>(null);
|
|
40
|
+
|
|
41
|
+
const { handleDismiss, handleOpened, handleClosed } =
|
|
42
|
+
createSheetEventHandlers(id);
|
|
43
|
+
|
|
44
|
+
useImperativeHandle(
|
|
45
|
+
ref,
|
|
46
|
+
() => ({
|
|
47
|
+
expand: () => actionSheetRef.current?.show(),
|
|
48
|
+
close: () => actionSheetRef.current?.hide(),
|
|
49
|
+
}),
|
|
50
|
+
[]
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const onOpen = () => {
|
|
54
|
+
animatedIndex.set(0);
|
|
55
|
+
handleOpened();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const onClose = () => {
|
|
59
|
+
animatedIndex.set(-1);
|
|
60
|
+
handleClosed();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<ActionSheet
|
|
65
|
+
// Adapter defaults (overridable via spread)
|
|
66
|
+
gestureEnabled
|
|
67
|
+
closeOnTouchBackdrop
|
|
68
|
+
closeOnPressBack
|
|
69
|
+
keyboardHandlerEnabled
|
|
70
|
+
{...sheetProps}
|
|
71
|
+
// Managed by adapter (not overridable)
|
|
72
|
+
ref={actionSheetRef}
|
|
73
|
+
isModal={false}
|
|
74
|
+
onOpen={onOpen}
|
|
75
|
+
onClose={onClose}
|
|
76
|
+
onBeforeClose={handleDismiss}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</ActionSheet>
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
ActionsSheetAdapter.displayName = 'ActionsSheetAdapter';
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React, { useEffect, useImperativeHandle, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
BackHandler,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
type ViewStyle,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import Animated, {
|
|
9
|
+
useAnimatedReaction,
|
|
10
|
+
useAnimatedStyle,
|
|
11
|
+
useSharedValue,
|
|
12
|
+
withTiming,
|
|
13
|
+
} from 'react-native-reanimated';
|
|
14
|
+
import { scheduleOnRN } from 'react-native-worklets';
|
|
15
|
+
|
|
16
|
+
import type { SheetAdapterRef } from '../../adapter.types';
|
|
17
|
+
import { createSheetEventHandlers } from '../../bottomSheetCoordinator';
|
|
18
|
+
import { useAdapterRef } from '../../useAdapterRef';
|
|
19
|
+
import { useAnimatedIndex } from '../../useAnimatedIndex';
|
|
20
|
+
import { useBottomSheetContext } from '../../useBottomSheetContext';
|
|
21
|
+
|
|
22
|
+
const ANIMATION_DURATION = 300;
|
|
23
|
+
|
|
24
|
+
const ZOOM_INITIAL_SCALE = 0.85;
|
|
25
|
+
|
|
26
|
+
export interface ModalAdapterProps {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const CustomModalAdapter = React.forwardRef<
|
|
32
|
+
SheetAdapterRef,
|
|
33
|
+
ModalAdapterProps
|
|
34
|
+
>(({ children, contentContainerStyle }, forwardedRef) => {
|
|
35
|
+
const { id } = useBottomSheetContext();
|
|
36
|
+
const ref = useAdapterRef(forwardedRef);
|
|
37
|
+
const animatedIndex = useAnimatedIndex();
|
|
38
|
+
const [rendered, setRendered] = useState(false);
|
|
39
|
+
const [open, setOpen] = useState(false);
|
|
40
|
+
|
|
41
|
+
const progress = useSharedValue(0);
|
|
42
|
+
|
|
43
|
+
const { handleDismiss, handleOpened, handleClosed } =
|
|
44
|
+
createSheetEventHandlers(id);
|
|
45
|
+
|
|
46
|
+
useImperativeHandle(
|
|
47
|
+
ref,
|
|
48
|
+
() => ({
|
|
49
|
+
expand: () => {
|
|
50
|
+
setRendered(true);
|
|
51
|
+
setOpen(true);
|
|
52
|
+
animatedIndex.set(0);
|
|
53
|
+
},
|
|
54
|
+
close: () => {
|
|
55
|
+
setOpen(false);
|
|
56
|
+
animatedIndex.set(-1);
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
[animatedIndex]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const onAnimationEnd = (value: boolean) => {
|
|
63
|
+
'worklet';
|
|
64
|
+
if (value) {
|
|
65
|
+
scheduleOnRN(handleOpened);
|
|
66
|
+
} else {
|
|
67
|
+
scheduleOnRN(setRendered, false);
|
|
68
|
+
scheduleOnRN(handleClosed);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
useAnimatedReaction(
|
|
73
|
+
() => open,
|
|
74
|
+
(value, prevValue) => {
|
|
75
|
+
if (prevValue === null || value === prevValue) return;
|
|
76
|
+
progress.value = withTiming(
|
|
77
|
+
value ? 1 : 0,
|
|
78
|
+
{ duration: ANIMATION_DURATION },
|
|
79
|
+
(finished) => {
|
|
80
|
+
if (!finished) return;
|
|
81
|
+
onAnimationEnd(value);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (!rendered) return;
|
|
89
|
+
const subscription = BackHandler.addEventListener(
|
|
90
|
+
'hardwareBackPress',
|
|
91
|
+
() => {
|
|
92
|
+
handleDismiss();
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
return () => subscription.remove();
|
|
97
|
+
}, [rendered, handleDismiss]);
|
|
98
|
+
|
|
99
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
100
|
+
return {
|
|
101
|
+
opacity: progress.value,
|
|
102
|
+
transform: [
|
|
103
|
+
{
|
|
104
|
+
scale: ZOOM_INITIAL_SCALE + progress.value * (1 - ZOOM_INITIAL_SCALE),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (!rendered) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Animated.View
|
|
116
|
+
style={[styles.container, contentContainerStyle, animatedStyle]}
|
|
117
|
+
>
|
|
118
|
+
{children}
|
|
119
|
+
</Animated.View>
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
CustomModalAdapter.displayName = 'CustomModalAdapter';
|
|
124
|
+
|
|
125
|
+
const styles = StyleSheet.create({
|
|
126
|
+
container: {
|
|
127
|
+
...StyleSheet.absoluteFillObject,
|
|
128
|
+
justifyContent: 'center',
|
|
129
|
+
alignItems: 'center',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import BottomSheetOriginal, {
|
|
2
|
+
useBottomSheetSpringConfigs,
|
|
3
|
+
type BottomSheetProps,
|
|
4
|
+
} from '@gorhom/bottom-sheet';
|
|
5
|
+
import React, { useImperativeHandle, useRef } from 'react';
|
|
6
|
+
import { useAnimatedReaction } from 'react-native-reanimated';
|
|
7
|
+
|
|
8
|
+
import type { SheetAdapterRef } from '../../adapter.types';
|
|
9
|
+
import { createSheetEventHandlers } from '../../bottomSheetCoordinator';
|
|
10
|
+
import { useBottomSheetDefaultIndex } from '../../BottomSheetDefaultIndex.context';
|
|
11
|
+
import { useAdapterRef } from '../../useAdapterRef';
|
|
12
|
+
import { useAnimatedIndex } from '../../useAnimatedIndex';
|
|
13
|
+
import { useBottomSheetContext } from '../../useBottomSheetContext';
|
|
14
|
+
import type { BottomSheetMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
15
|
+
|
|
16
|
+
export interface GorhomSheetAdapterProps extends BottomSheetProps {}
|
|
17
|
+
|
|
18
|
+
const nullBackdrop = () => null;
|
|
19
|
+
|
|
20
|
+
export const GorhomSheetAdapter = React.forwardRef<
|
|
21
|
+
SheetAdapterRef,
|
|
22
|
+
GorhomSheetAdapterProps
|
|
23
|
+
>(
|
|
24
|
+
(
|
|
25
|
+
{
|
|
26
|
+
children,
|
|
27
|
+
onAnimate,
|
|
28
|
+
onChange,
|
|
29
|
+
onClose,
|
|
30
|
+
enablePanDownToClose = true,
|
|
31
|
+
backdropComponent = nullBackdrop,
|
|
32
|
+
animatedIndex: externalAnimatedIndex,
|
|
33
|
+
...props
|
|
34
|
+
},
|
|
35
|
+
forwardedRef
|
|
36
|
+
) => {
|
|
37
|
+
const { id } = useBottomSheetContext();
|
|
38
|
+
const ref = useAdapterRef(forwardedRef);
|
|
39
|
+
const contextAnimatedIndex = useAnimatedIndex();
|
|
40
|
+
const defaultIndex = useBottomSheetDefaultIndex();
|
|
41
|
+
|
|
42
|
+
const gorhomRef = useRef<BottomSheetMethods | null>(null);
|
|
43
|
+
|
|
44
|
+
useImperativeHandle(
|
|
45
|
+
ref,
|
|
46
|
+
() => ({
|
|
47
|
+
expand: () => gorhomRef.current?.expand(),
|
|
48
|
+
close: () => gorhomRef.current?.close(),
|
|
49
|
+
}),
|
|
50
|
+
[]
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
useAnimatedReaction(
|
|
54
|
+
() => contextAnimatedIndex.value,
|
|
55
|
+
(value) => {
|
|
56
|
+
externalAnimatedIndex?.set(value);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const { handleDismiss, handleOpened, handleClosed } =
|
|
61
|
+
createSheetEventHandlers(id);
|
|
62
|
+
|
|
63
|
+
const wrappedOnAnimate: BottomSheetProps['onAnimate'] = (
|
|
64
|
+
fromIndex,
|
|
65
|
+
toIndex,
|
|
66
|
+
fromPosition,
|
|
67
|
+
toPosition
|
|
68
|
+
) => {
|
|
69
|
+
// toIndex === -1 means gorhom is animating toward closed state
|
|
70
|
+
if (toIndex === -1) {
|
|
71
|
+
handleDismiss();
|
|
72
|
+
}
|
|
73
|
+
onAnimate?.(fromIndex, toIndex, fromPosition, toPosition);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const wrappedOnChange: BottomSheetProps['onChange'] = (
|
|
77
|
+
index,
|
|
78
|
+
position,
|
|
79
|
+
type
|
|
80
|
+
) => {
|
|
81
|
+
// index >= 0 means sheet reached a valid snap point (opened)
|
|
82
|
+
if (index >= 0) {
|
|
83
|
+
handleOpened();
|
|
84
|
+
}
|
|
85
|
+
onChange?.(index, position, type);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const wrappedOnClose = () => {
|
|
89
|
+
onClose?.();
|
|
90
|
+
handleClosed();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const config = useBottomSheetSpringConfigs({
|
|
94
|
+
stiffness: 400,
|
|
95
|
+
damping: 80,
|
|
96
|
+
mass: 0.7,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<BottomSheetOriginal
|
|
101
|
+
animationConfigs={config}
|
|
102
|
+
ref={gorhomRef}
|
|
103
|
+
{...props}
|
|
104
|
+
index={defaultIndex}
|
|
105
|
+
animatedIndex={contextAnimatedIndex}
|
|
106
|
+
onChange={wrappedOnChange}
|
|
107
|
+
onClose={wrappedOnClose}
|
|
108
|
+
onAnimate={wrappedOnAnimate}
|
|
109
|
+
backdropComponent={backdropComponent}
|
|
110
|
+
enablePanDownToClose={enablePanDownToClose}
|
|
111
|
+
>
|
|
112
|
+
{children}
|
|
113
|
+
</BottomSheetOriginal>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
GorhomSheetAdapter.displayName = 'GorhomSheetAdapter';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export {
|
|
2
|
+
GorhomSheetAdapter,
|
|
3
|
+
type GorhomSheetAdapterProps,
|
|
4
|
+
} from './gorhom-sheet';
|
|
5
|
+
export {
|
|
6
|
+
CustomModalAdapter,
|
|
7
|
+
ModalAdapter,
|
|
8
|
+
type ModalAdapterProps,
|
|
9
|
+
} from './custom-modal';
|
|
10
|
+
export {
|
|
11
|
+
ReactNativeModalAdapter,
|
|
12
|
+
type ReactNativeModalAdapterProps,
|
|
13
|
+
} from './react-native-modal';
|
|
14
|
+
export {
|
|
15
|
+
ActionsSheetAdapter,
|
|
16
|
+
type ActionsSheetAdapterProps,
|
|
17
|
+
} from './actions-sheet';
|