@swmansion/react-native-bottom-sheet 0.7.0 → 0.7.2
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 +36 -55
- package/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetView.kt +37 -13
- package/ios/RNSBottomSheetHostingView.swift +53 -20
- package/lib/module/BottomSheet.js +1 -3
- package/lib/module/BottomSheet.js.map +1 -1
- package/lib/typescript/src/BottomSheet.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/BottomSheet.tsx +2 -7
package/README.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
React Native Bottom Sheet provides bottom‍-‍sheet components for
|
|
8
8
|
React Native.
|
|
9
9
|
|
|
10
|
+
## Highlights
|
|
11
|
+
|
|
12
|
+
- Native implementation for optimal performance.
|
|
13
|
+
- Bring your own sheet surface.
|
|
14
|
+
- Dynamic, content‍-‍based sizing out of the box.
|
|
15
|
+
- Automatic handling of vertically scrollable children.
|
|
16
|
+
- Position tracking for driving UI tied to sheets.
|
|
17
|
+
- Programmatic‍-‍only detents for snap points unreachable
|
|
18
|
+
by dragging.
|
|
19
|
+
|
|
10
20
|
## Getting started
|
|
11
21
|
|
|
12
22
|
1. Install React Native Bottom Sheet:
|
|
@@ -15,20 +25,16 @@ React Native.
|
|
|
15
25
|
npm i @swmansion/react-native-bottom-sheet
|
|
16
26
|
```
|
|
17
27
|
|
|
18
|
-
2. Ensure the peer
|
|
28
|
+
2. Ensure the peer dependency is installed:
|
|
19
29
|
|
|
20
30
|
```sh
|
|
21
|
-
npm i react-native-
|
|
31
|
+
npm i react-native-safe-area-context@^4.0.0
|
|
22
32
|
```
|
|
23
33
|
|
|
24
|
-
3. Wrap your app with
|
|
34
|
+
3. Wrap your app with `BottomSheetProvider`:
|
|
25
35
|
|
|
26
36
|
```tsx
|
|
27
|
-
const App = () =>
|
|
28
|
-
<GestureHandlerRootView>
|
|
29
|
-
<BottomSheetProvider>{/* ... */}</BottomSheetProvider>
|
|
30
|
-
</GestureHandlerRootView>
|
|
31
|
-
);
|
|
37
|
+
const App = () => <BottomSheetProvider>{/* ... */}</BottomSheetProvider>;
|
|
32
38
|
```
|
|
33
39
|
|
|
34
40
|
## Usage
|
|
@@ -86,22 +92,14 @@ const insets = useSafeAreaInsets();
|
|
|
86
92
|
|
|
87
93
|
#### Scrim
|
|
88
94
|
|
|
89
|
-
Tapping the scrim collapses the sheet.
|
|
90
|
-
|
|
91
|
-
1 when the first nonzero detent is reached:
|
|
95
|
+
Tapping the scrim collapses the sheet. Use `scrimColor` to customize
|
|
96
|
+
its color:
|
|
92
97
|
|
|
93
98
|
```tsx
|
|
94
99
|
<ModalBottomSheet
|
|
95
100
|
index={index}
|
|
96
101
|
onIndexChange={setIndex}
|
|
97
|
-
|
|
98
|
-
<Animated.View
|
|
99
|
-
style={useAnimatedStyle(() => ({
|
|
100
|
-
backgroundColor: `rgba(0, 0, 255, ${0.3 * progress.value})`,
|
|
101
|
-
flex: 1,
|
|
102
|
-
}))}
|
|
103
|
-
/>
|
|
104
|
-
)}
|
|
102
|
+
scrimColor="rgba(0, 0, 0, 0.3)"
|
|
105
103
|
>
|
|
106
104
|
{/* ... */}
|
|
107
105
|
</ModalBottomSheet>
|
|
@@ -115,8 +113,8 @@ available screen height). The default detents are `[0, 'max']`.
|
|
|
115
113
|
|
|
116
114
|
The `index` prop is a zero‍-‍based index into the `detents` array.
|
|
117
115
|
`onIndexChange` is called when the sheet snaps to a different detent after
|
|
118
|
-
a
|
|
119
|
-
state.
|
|
116
|
+
a drag. You can also control the sheet externally by updating the
|
|
117
|
+
index state.
|
|
120
118
|
|
|
121
119
|
```tsx
|
|
122
120
|
const [index, setIndex] = useState(0);
|
|
@@ -150,55 +148,38 @@ drag snapping but can still be targeted via `index` updates.
|
|
|
150
148
|
|
|
151
149
|
### Position tracking
|
|
152
150
|
|
|
153
|
-
|
|
154
|
-
the
|
|
155
|
-
screen to the top of the sheet). Use it to drive animations tied to the
|
|
156
|
-
sheet position.
|
|
157
|
-
|
|
158
|
-
```tsx
|
|
159
|
-
const position = useSharedValue(0);
|
|
160
|
-
```
|
|
151
|
+
Use `onPositionChange` to observe the sheet’s current position (the distance in
|
|
152
|
+
pixels from the bottom of the screen to the top of the sheet).
|
|
161
153
|
|
|
162
154
|
```tsx
|
|
163
155
|
<BottomSheet // Or `ModalBottomSheet`.
|
|
164
156
|
index={index}
|
|
165
157
|
onIndexChange={setIndex}
|
|
166
|
-
|
|
158
|
+
onPositionChange={(position) => {
|
|
159
|
+
console.log(position);
|
|
160
|
+
}}
|
|
167
161
|
>
|
|
168
162
|
{/* ... */}
|
|
169
163
|
</BottomSheet>
|
|
170
164
|
```
|
|
171
165
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Use the `openAnimationConfig` and `closeAnimationConfig` props to tweak the
|
|
175
|
-
spring parameters for opening and closing.
|
|
176
|
-
|
|
177
|
-
### Scrollable content
|
|
178
|
-
|
|
179
|
-
For scrollable sheet content, use `BottomSheetScrollView` or
|
|
180
|
-
`BottomSheetFlatList` instead of the standard React Native components. These
|
|
181
|
-
integrate scrolling with the sheet’s drag gesture so that dragging down while
|
|
182
|
-
scrolled to the top collapses the sheet.
|
|
183
|
-
|
|
184
|
-
If you need a custom scrollable (for example, a `FlashList`), wrap it with
|
|
185
|
-
`bottomSheetScrollable`. The returned component forwards the underlying
|
|
186
|
-
scrollable ref, so you can call any imperative methods supported by the
|
|
187
|
-
wrapped component.
|
|
166
|
+
If you want to keep the latest position in a Reanimated shared value, update it
|
|
167
|
+
from the callback:
|
|
188
168
|
|
|
189
169
|
```tsx
|
|
190
|
-
const
|
|
191
|
-
FlashListProps<string>,
|
|
192
|
-
FlashListRef<string>
|
|
193
|
-
>(FlashList);
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
```tsx
|
|
197
|
-
const listRef = useRef<FlashListRef<string>>(null);
|
|
170
|
+
const position = useSharedValue(0);
|
|
198
171
|
```
|
|
199
172
|
|
|
200
173
|
```tsx
|
|
201
|
-
<
|
|
174
|
+
<BottomSheet
|
|
175
|
+
index={index}
|
|
176
|
+
onIndexChange={setIndex}
|
|
177
|
+
onPositionChange={(nextPosition) => {
|
|
178
|
+
position.value = nextPosition;
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
{/* ... */}
|
|
182
|
+
</BottomSheet>
|
|
202
183
|
```
|
|
203
184
|
|
|
204
185
|
## By [Software Mansion](https://swmansion.com)
|
|
@@ -15,6 +15,7 @@ import com.facebook.react.bridge.Arguments
|
|
|
15
15
|
import com.facebook.react.uimanager.PointerEvents
|
|
16
16
|
import com.facebook.react.uimanager.StateWrapper
|
|
17
17
|
import com.facebook.react.views.view.ReactViewGroup
|
|
18
|
+
import com.facebook.react.uimanager.events.NativeGestureUtil
|
|
18
19
|
import kotlin.math.abs
|
|
19
20
|
|
|
20
21
|
private data class DetentSpec(val height: Float, val programmatic: Boolean)
|
|
@@ -58,6 +59,10 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
58
59
|
init {
|
|
59
60
|
clipChildren = false
|
|
60
61
|
clipToPadding = false
|
|
62
|
+
// Set directly rather than via the JSX prop because Fabric doesn't forward
|
|
63
|
+
// pointerEvents to the native view on Android. Without BOX_NONE the view
|
|
64
|
+
// itself becomes a touch target and its onTouchEvent would claim gestures
|
|
65
|
+
// that should go to children.
|
|
61
66
|
pointerEvents = PointerEvents.BOX_NONE
|
|
62
67
|
sheetContainer.clipChildren = false
|
|
63
68
|
sheetContainer.clipToPadding = false
|
|
@@ -322,21 +327,28 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
322
327
|
val dx = x - initialTouchX
|
|
323
328
|
val dy = y - initialTouchY
|
|
324
329
|
|
|
325
|
-
if (abs(dy) > touchSlop && abs(dy) > abs(dx)) {
|
|
330
|
+
if (abs(dy) > touchSlop && abs(dy) > abs(dx) && draggableMinTy < draggableMaxTy) {
|
|
326
331
|
if (!isAtMaxDraggable) {
|
|
327
332
|
lastTouchY = y
|
|
328
333
|
requestDisallowInterceptTouchEvent(false)
|
|
334
|
+
// Cancel in-flight JS touches. React Native's JSTouchDispatcher
|
|
335
|
+
// processes events at the root view level before onInterceptTouchEvent
|
|
336
|
+
// runs, so without this the JS side never sees a cancel and Pressable
|
|
337
|
+
// would still fire onPress.
|
|
338
|
+
NativeGestureUtil.notifyNativeGestureStarted(this, ev)
|
|
329
339
|
return true
|
|
330
340
|
}
|
|
331
341
|
if (dy > 0 && isScrollViewAtTop()) {
|
|
332
342
|
lastTouchY = y
|
|
333
343
|
requestDisallowInterceptTouchEvent(false)
|
|
344
|
+
NativeGestureUtil.notifyNativeGestureStarted(this, ev)
|
|
334
345
|
return true
|
|
335
346
|
}
|
|
336
347
|
}
|
|
337
348
|
}
|
|
338
349
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
|
339
350
|
initialTouchX = 0f
|
|
351
|
+
initialTouchY = 0f
|
|
340
352
|
activePointerId = MotionEvent.INVALID_POINTER_ID
|
|
341
353
|
}
|
|
342
354
|
}
|
|
@@ -344,16 +356,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
344
356
|
}
|
|
345
357
|
|
|
346
358
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
347
|
-
val sheetTop = sheetContainer.top + sheetContainer.translationY
|
|
348
|
-
if (event.actionMasked == MotionEvent.ACTION_DOWN && event.y < sheetTop) {
|
|
349
|
-
return false
|
|
350
|
-
}
|
|
351
|
-
|
|
352
359
|
when (event.actionMasked) {
|
|
353
|
-
MotionEvent.ACTION_DOWN -> {
|
|
354
|
-
beginPan(event)
|
|
355
|
-
return true
|
|
356
|
-
}
|
|
357
360
|
MotionEvent.ACTION_MOVE -> {
|
|
358
361
|
if (!isPanning) beginPan(event)
|
|
359
362
|
val pointerIndex = event.findPointerIndex(activePointerId)
|
|
@@ -387,9 +390,10 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
387
390
|
MotionEvent.ACTION_POINTER_UP -> {
|
|
388
391
|
val actionIndex = event.actionIndex
|
|
389
392
|
if (event.getPointerId(actionIndex) == activePointerId) {
|
|
390
|
-
val
|
|
391
|
-
activePointerId = event.getPointerId(
|
|
392
|
-
lastTouchY = event.getY(
|
|
393
|
+
val newPointerIndex = if (actionIndex == 0) 1 else 0
|
|
394
|
+
activePointerId = event.getPointerId(newPointerIndex)
|
|
395
|
+
lastTouchY = event.getY(newPointerIndex)
|
|
396
|
+
velocityTracker?.clear()
|
|
393
397
|
}
|
|
394
398
|
return true
|
|
395
399
|
}
|
|
@@ -412,12 +416,32 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
|
|
|
412
416
|
}
|
|
413
417
|
|
|
414
418
|
// MARK: - Scroll view helpers
|
|
419
|
+
//
|
|
420
|
+
// Explicit scroll-view detection is required because Android's touch dispatch
|
|
421
|
+
// doesn't support mid-gesture handoff. Once a ScrollView claims a gesture it
|
|
422
|
+
// keeps it for the entire sequence, and it always claims (returns true from
|
|
423
|
+
// onTouchEvent) even when at the scroll boundary. Without this check the sheet
|
|
424
|
+
// could never collapse by dragging down when a ScrollView is at the top.
|
|
415
425
|
|
|
416
426
|
private fun isScrollViewAtTop(): Boolean {
|
|
417
427
|
val scrollView = findScrollView(sheetContainer) ?: return true
|
|
428
|
+
if (!isTouchInsideView(scrollView)) return true
|
|
418
429
|
return !scrollView.canScrollVertically(-1)
|
|
419
430
|
}
|
|
420
431
|
|
|
432
|
+
private fun isTouchInsideView(target: View): Boolean {
|
|
433
|
+
val targetLocation = IntArray(2)
|
|
434
|
+
target.getLocationOnScreen(targetLocation)
|
|
435
|
+
val myLocation = IntArray(2)
|
|
436
|
+
getLocationOnScreen(myLocation)
|
|
437
|
+
val touchScreenX = myLocation[0] + initialTouchX
|
|
438
|
+
val touchScreenY = myLocation[1] + initialTouchY
|
|
439
|
+
return touchScreenX >= targetLocation[0] &&
|
|
440
|
+
touchScreenX < targetLocation[0] + target.width &&
|
|
441
|
+
touchScreenY >= targetLocation[1] &&
|
|
442
|
+
touchScreenY < targetLocation[1] + target.height
|
|
443
|
+
}
|
|
444
|
+
|
|
421
445
|
private fun findScrollView(view: View): View? {
|
|
422
446
|
if (view.canScrollVertically(1) || view.canScrollVertically(-1)) return view
|
|
423
447
|
if (view is ViewGroup) {
|
|
@@ -42,8 +42,10 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
42
42
|
panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
|
|
43
43
|
panGesture.delegate = self
|
|
44
44
|
panGesture.cancelsTouchesInView = true
|
|
45
|
+
// Delay touch delivery to views so that Pressable doesn't flash its pressed
|
|
46
|
+
// state while the pan gesture is still being disambiguated.
|
|
45
47
|
panGesture.delaysTouchesBegan = true
|
|
46
|
-
panGesture.delaysTouchesEnded =
|
|
48
|
+
panGesture.delaysTouchesEnded = false
|
|
47
49
|
sheetContainer.addGestureRecognizer(panGesture)
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -51,6 +53,30 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
51
53
|
fatalError("init(coder:) has not been implemented")
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
// RCTSurfaceTouchHandler dispatches touch events to JS independently of the
|
|
57
|
+
// pan gesture (it fires in touchesBegan: regardless of its recognizer state).
|
|
58
|
+
// We cache it here and toggle isEnabled in handlePan(.began) to force a
|
|
59
|
+
// touchesCancelled dispatch to JS, preventing Pressable from firing onPress
|
|
60
|
+
// during a sheet drag. This is the iOS equivalent of Android's
|
|
61
|
+
// NativeGestureUtil.notifyNativeGestureStarted.
|
|
62
|
+
private weak var surfaceTouchHandler: UIGestureRecognizer?
|
|
63
|
+
|
|
64
|
+
public override func didMoveToWindow() {
|
|
65
|
+
super.didMoveToWindow()
|
|
66
|
+
surfaceTouchHandler = nil
|
|
67
|
+
guard window != nil else { return }
|
|
68
|
+
var current: UIView? = superview
|
|
69
|
+
while let view = current {
|
|
70
|
+
for gr in view.gestureRecognizers ?? [] {
|
|
71
|
+
if NSStringFromClass(type(of: gr)).contains("TouchHandler") {
|
|
72
|
+
surfaceTouchHandler = gr
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
current = view.superview
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
54
80
|
public override func layoutSubviews() {
|
|
55
81
|
super.layoutSubviews()
|
|
56
82
|
guard bounds.width > 0, bounds.height > 0 else { return }
|
|
@@ -240,6 +266,10 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
240
266
|
case .began:
|
|
241
267
|
isPanning = true
|
|
242
268
|
setContentInteractionEnabled(false)
|
|
269
|
+
if let handler = surfaceTouchHandler {
|
|
270
|
+
handler.isEnabled = false
|
|
271
|
+
handler.isEnabled = true
|
|
272
|
+
}
|
|
243
273
|
gesture.setTranslation(.zero, in: self)
|
|
244
274
|
if let animator = activeAnimator {
|
|
245
275
|
stopDisplayLink()
|
|
@@ -258,13 +288,21 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
258
288
|
sheetContainer.transform = CGAffineTransform(translationX: 0, y: newTy)
|
|
259
289
|
emitPosition()
|
|
260
290
|
|
|
261
|
-
case .ended
|
|
291
|
+
case .ended:
|
|
262
292
|
isPanning = false
|
|
263
293
|
let velocity = gesture.velocity(in: self).y
|
|
264
294
|
let currentHeight = maxHeight - sheetContainer.transform.ty
|
|
265
295
|
let index = bestSnapIndex(for: currentHeight, velocity: velocity)
|
|
266
296
|
snapToIndex(index, velocity: velocity)
|
|
267
297
|
|
|
298
|
+
case .cancelled:
|
|
299
|
+
isPanning = false
|
|
300
|
+
setContentInteractionEnabled(true)
|
|
301
|
+
let cancelVelocity = gesture.velocity(in: self).y
|
|
302
|
+
let cancelHeight = maxHeight - sheetContainer.transform.ty
|
|
303
|
+
let cancelIndex = bestSnapIndex(for: cancelHeight, velocity: cancelVelocity)
|
|
304
|
+
snapToIndex(cancelIndex, velocity: cancelVelocity)
|
|
305
|
+
|
|
268
306
|
case .failed:
|
|
269
307
|
isPanning = false
|
|
270
308
|
setContentInteractionEnabled(true)
|
|
@@ -312,37 +350,32 @@ public final class RNSBottomSheetHostingView: UIView {
|
|
|
312
350
|
let velocity = panGesture.velocity(in: self)
|
|
313
351
|
guard abs(velocity.y) > abs(velocity.x) else { return false }
|
|
314
352
|
|
|
315
|
-
let
|
|
316
|
-
guard
|
|
353
|
+
let draggable = detentSpecs.enumerated().filter { !$0.element.programmatic }
|
|
354
|
+
guard draggable.count > 1 else { return false }
|
|
317
355
|
|
|
356
|
+
let maxDraggableIndex = draggable.last?.offset ?? 0
|
|
357
|
+
// Below max: allow drag in either direction to reach other detents.
|
|
358
|
+
guard targetIndex >= maxDraggableIndex else { return true }
|
|
359
|
+
// At max: only allow downward drag, and only when the scroll view (if any)
|
|
360
|
+
// is at its top edge — otherwise the scroll view should handle the gesture.
|
|
318
361
|
if velocity.y < 0 {
|
|
319
362
|
return false
|
|
320
363
|
}
|
|
321
364
|
|
|
322
|
-
let
|
|
323
|
-
|
|
365
|
+
guard let scrollView = firstScrollView(in: sheetContainer) else { return true }
|
|
366
|
+
let locationInScroll = panGesture.location(in: scrollView)
|
|
367
|
+
guard scrollView.bounds.contains(locationInScroll) else { return true }
|
|
368
|
+
return scrollView.contentOffset.y <= 0
|
|
324
369
|
}
|
|
325
370
|
}
|
|
326
371
|
|
|
327
372
|
extension RNSBottomSheetHostingView: UIGestureRecognizerDelegate {
|
|
328
|
-
public func gestureRecognizer(
|
|
329
|
-
_ gestureRecognizer: UIGestureRecognizer,
|
|
330
|
-
shouldRequireFailureOf other: UIGestureRecognizer
|
|
331
|
-
) -> Bool {
|
|
332
|
-
guard gestureRecognizer === panGesture else { return false }
|
|
333
|
-
|
|
334
|
-
if other is UITapGestureRecognizer {
|
|
335
|
-
return true
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return false
|
|
339
|
-
}
|
|
340
|
-
|
|
341
373
|
public func gestureRecognizer(
|
|
342
374
|
_ gestureRecognizer: UIGestureRecognizer,
|
|
343
375
|
shouldBeRequiredToFailBy other: UIGestureRecognizer
|
|
344
376
|
) -> Bool {
|
|
345
|
-
|
|
377
|
+
guard gestureRecognizer === panGesture else { return false }
|
|
378
|
+
return other is UIPanGestureRecognizer || other is UITapGestureRecognizer
|
|
346
379
|
}
|
|
347
380
|
|
|
348
381
|
public func gestureRecognizer(
|
|
@@ -52,7 +52,6 @@ export const BottomSheet = ({
|
|
|
52
52
|
};
|
|
53
53
|
const clampedIndex = Math.max(0, Math.min(index, resolvedDetents.length - 1));
|
|
54
54
|
const isCollapsed = (resolvedDetents[clampedIndex]?.height ?? 0) === 0;
|
|
55
|
-
const sheetPointerEvents = isCollapsed ? 'none' : 'box-none';
|
|
56
55
|
const scrimPressEnabledRef = useRef(!modal || isCollapsed);
|
|
57
56
|
const previousIsCollapsedRef = useRef(isCollapsed);
|
|
58
57
|
const firstNonzeroDetent = resolvedDetents.find(detent => detent.height > 0)?.height ?? 0;
|
|
@@ -113,7 +112,7 @@ export const BottomSheet = ({
|
|
|
113
112
|
opacity: sheetOpacity
|
|
114
113
|
}],
|
|
115
114
|
children: /*#__PURE__*/_jsx(BottomSheetNativeComponent, {
|
|
116
|
-
pointerEvents:
|
|
115
|
+
pointerEvents: "box-none",
|
|
117
116
|
style: [{
|
|
118
117
|
position: 'absolute',
|
|
119
118
|
left: 0,
|
|
@@ -131,7 +130,6 @@ export const BottomSheet = ({
|
|
|
131
130
|
style: {
|
|
132
131
|
flex: 1
|
|
133
132
|
},
|
|
134
|
-
pointerEvents: "box-none",
|
|
135
133
|
children: [children, /*#__PURE__*/_jsx(View, {
|
|
136
134
|
onLayout: handleSentinelLayout,
|
|
137
135
|
pointerEvents: "none"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","useState","Animated","Pressable","StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","Portal","resolveDetent","jsx","_jsx","jsxs","_jsxs","programmatic","DefaultScrim","progress","color","style","absoluteFill","flex","backgroundColor","opacity","BottomSheet","children","detents","index","animateIn","onIndexChange","onPositionChange","modal","scrimColor","height","screenHeight","insets","maxHeight","top","contentHeight","setContentHeight","currentPositionRef","scrimProgress","Value","current","sheetOpacity","resolvedDetents","map","detent","value","Math","max","min","isDetentProgrammatic","handleSentinelLayout","event","nativeEvent","layout","y","clampedIndex","length","isCollapsed","
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","useState","Animated","Pressable","StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","Portal","resolveDetent","jsx","_jsx","jsxs","_jsxs","programmatic","DefaultScrim","progress","color","style","absoluteFill","flex","backgroundColor","opacity","BottomSheet","children","detents","index","animateIn","onIndexChange","onPositionChange","modal","scrimColor","height","screenHeight","insets","maxHeight","top","contentHeight","setContentHeight","currentPositionRef","scrimProgress","Value","current","sheetOpacity","resolvedDetents","map","detent","value","Math","max","min","isDetentProgrammatic","handleSentinelLayout","event","nativeEvent","layout","y","clampedIndex","length","isCollapsed","scrimPressEnabledRef","previousIsCollapsedRef","firstNonzeroDetent","find","setValue","undefined","frame","requestAnimationFrame","cancelAnimationFrame","handleIndexChange","handlePositionChange","position","closedIndex","findIndex","handleScrimPress","scrimElement","sheet","pointerEvents","onPress","left","right","bottom","collapsable","onLayout"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAqB,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAY5E,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAmBlD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,GAAI,qGAUzB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAqB,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAY5E,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAmBlD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,GAAI,qGAUzB,gBAAgB,4CAiJlB,CAAC"}
|
package/package.json
CHANGED
package/src/BottomSheet.tsx
CHANGED
|
@@ -77,7 +77,6 @@ export const BottomSheet = ({
|
|
|
77
77
|
|
|
78
78
|
const clampedIndex = Math.max(0, Math.min(index, resolvedDetents.length - 1));
|
|
79
79
|
const isCollapsed = (resolvedDetents[clampedIndex]?.height ?? 0) === 0;
|
|
80
|
-
const sheetPointerEvents = isCollapsed ? 'none' : 'box-none';
|
|
81
80
|
const scrimPressEnabledRef = useRef(!modal || isCollapsed);
|
|
82
81
|
const previousIsCollapsedRef = useRef(isCollapsed);
|
|
83
82
|
const firstNonzeroDetent =
|
|
@@ -169,7 +168,7 @@ export const BottomSheet = ({
|
|
|
169
168
|
style={[StyleSheet.absoluteFill, { opacity: sheetOpacity }]}
|
|
170
169
|
>
|
|
171
170
|
<BottomSheetNativeComponent
|
|
172
|
-
pointerEvents=
|
|
171
|
+
pointerEvents="box-none"
|
|
173
172
|
style={[
|
|
174
173
|
{
|
|
175
174
|
position: 'absolute',
|
|
@@ -186,11 +185,7 @@ export const BottomSheet = ({
|
|
|
186
185
|
onIndexChange={handleIndexChange}
|
|
187
186
|
onPositionChange={handlePositionChange}
|
|
188
187
|
>
|
|
189
|
-
<View
|
|
190
|
-
collapsable={false}
|
|
191
|
-
style={{ flex: 1 }}
|
|
192
|
-
pointerEvents="box-none"
|
|
193
|
-
>
|
|
188
|
+
<View collapsable={false} style={{ flex: 1 }}>
|
|
194
189
|
{children}
|
|
195
190
|
<View onLayout={handleSentinelLayout} pointerEvents="none" />
|
|
196
191
|
</View>
|