insyd-bottom-sheet 0.1.0 → 0.2.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/package.json +1 -1
- package/src/SmoothSheet.tsx +64 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "insyd-bottom-sheet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A smooth, physics-based bottom sheet for React Native — by Ishan Gupta. Works with Expo Go, bare workflow, and React Native CLI.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
package/src/SmoothSheet.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Dimensions,
|
|
4
4
|
KeyboardAvoidingView,
|
|
5
|
+
Modal,
|
|
5
6
|
Platform,
|
|
6
7
|
Pressable,
|
|
7
8
|
StyleSheet,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
import {
|
|
11
12
|
Gesture,
|
|
12
13
|
GestureDetector,
|
|
14
|
+
GestureHandlerRootView,
|
|
13
15
|
} from "react-native-gesture-handler";
|
|
14
16
|
import Animated, {
|
|
15
17
|
runOnJS,
|
|
@@ -101,27 +103,28 @@ export function SmoothSheet({
|
|
|
101
103
|
|
|
102
104
|
const translateY = useSharedValue(SCREEN_HEIGHT);
|
|
103
105
|
const backdropOpacity = useSharedValue(0);
|
|
106
|
+
// Keep Modal mounted during the closing animation so the sheet can slide out
|
|
107
|
+
const [modalVisible, setModalVisible] = useState(isVisible);
|
|
104
108
|
|
|
105
109
|
useEffect(() => {
|
|
106
110
|
if (isVisible) {
|
|
111
|
+
setModalVisible(true);
|
|
107
112
|
translateY.value = withSpring(0, spring);
|
|
108
113
|
backdropOpacity.value = withTiming(1, { duration: 250 });
|
|
109
114
|
} else {
|
|
110
115
|
translateY.value = withSpring(SCREEN_HEIGHT, spring);
|
|
111
|
-
backdropOpacity.value = withTiming(0, { duration: 200 })
|
|
116
|
+
backdropOpacity.value = withTiming(0, { duration: 200 }, () => {
|
|
117
|
+
runOnJS(setModalVisible)(false);
|
|
118
|
+
});
|
|
112
119
|
}
|
|
113
120
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
114
121
|
}, [isVisible]);
|
|
115
122
|
|
|
116
123
|
function dismiss() {
|
|
117
124
|
translateY.value = withSpring(SCREEN_HEIGHT, spring);
|
|
118
|
-
backdropOpacity.value = withTiming(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
() => {
|
|
122
|
-
runOnJS(onDismiss)();
|
|
123
|
-
},
|
|
124
|
-
);
|
|
125
|
+
backdropOpacity.value = withTiming(0, { duration: 200 }, () => {
|
|
126
|
+
runOnJS(onDismiss)();
|
|
127
|
+
});
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
const panGesture = Gesture.Pan()
|
|
@@ -149,57 +152,60 @@ export function SmoothSheet({
|
|
|
149
152
|
opacity: backdropOpacity.value,
|
|
150
153
|
}));
|
|
151
154
|
|
|
152
|
-
if (!isVisible && translateY.value === SCREEN_HEIGHT) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
155
|
return (
|
|
157
|
-
<
|
|
158
|
-
{
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
/>
|
|
191
|
-
</View>
|
|
192
|
-
</GestureDetector>
|
|
193
|
-
|
|
194
|
-
{/* Content */}
|
|
195
|
-
<KeyboardAvoidingView
|
|
196
|
-
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
197
|
-
style={styles.content}
|
|
156
|
+
<Modal
|
|
157
|
+
visible={modalVisible}
|
|
158
|
+
transparent
|
|
159
|
+
animationType="none"
|
|
160
|
+
statusBarTranslucent
|
|
161
|
+
onRequestClose={dismiss}
|
|
162
|
+
>
|
|
163
|
+
<GestureHandlerRootView style={StyleSheet.absoluteFill}>
|
|
164
|
+
{/* Backdrop */}
|
|
165
|
+
<Animated.View
|
|
166
|
+
style={[
|
|
167
|
+
StyleSheet.absoluteFill,
|
|
168
|
+
{ backgroundColor: backdropColor },
|
|
169
|
+
backdropStyle,
|
|
170
|
+
]}
|
|
171
|
+
>
|
|
172
|
+
<Pressable style={StyleSheet.absoluteFill} onPress={dismiss} />
|
|
173
|
+
</Animated.View>
|
|
174
|
+
|
|
175
|
+
{/* Sheet */}
|
|
176
|
+
<Animated.View
|
|
177
|
+
style={[
|
|
178
|
+
styles.sheet,
|
|
179
|
+
{
|
|
180
|
+
borderTopLeftRadius: borderRadius,
|
|
181
|
+
borderTopRightRadius: borderRadius,
|
|
182
|
+
backgroundColor,
|
|
183
|
+
minHeight: SCREEN_HEIGHT * minHeightFraction,
|
|
184
|
+
maxHeight: SCREEN_HEIGHT * maxHeightFraction,
|
|
185
|
+
},
|
|
186
|
+
sheetStyle,
|
|
187
|
+
]}
|
|
188
|
+
pointerEvents="box-none"
|
|
198
189
|
>
|
|
199
|
-
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
190
|
+
{/* Drag handle */}
|
|
191
|
+
<GestureDetector gesture={panGesture}>
|
|
192
|
+
<View style={styles.handleArea}>
|
|
193
|
+
<View
|
|
194
|
+
style={[styles.handle, { backgroundColor: handleColor }]}
|
|
195
|
+
/>
|
|
196
|
+
</View>
|
|
197
|
+
</GestureDetector>
|
|
198
|
+
|
|
199
|
+
{/* Content */}
|
|
200
|
+
<KeyboardAvoidingView
|
|
201
|
+
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
202
|
+
style={styles.content}
|
|
203
|
+
>
|
|
204
|
+
{children}
|
|
205
|
+
</KeyboardAvoidingView>
|
|
206
|
+
</Animated.View>
|
|
207
|
+
</GestureHandlerRootView>
|
|
208
|
+
</Modal>
|
|
203
209
|
);
|
|
204
210
|
}
|
|
205
211
|
|