@swmansion/react-native-bottom-sheet 0.7.3 → 0.8.0-next.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.
@@ -1,6 +1,9 @@
1
1
  package com.swmansion.reactnativebottomsheet
2
2
 
3
3
  import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.graphics.Color
6
+ import android.graphics.Paint
4
7
  import android.view.Choreographer
5
8
  import android.view.MotionEvent
6
9
  import android.view.VelocityTracker
@@ -37,6 +40,12 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
37
40
  private var detentSpecs: List<DetentSpec> = emptyList()
38
41
  private var targetIndex: Int = 0
39
42
  var animateIn: Boolean = true
43
+ var modal: Boolean = false
44
+ set(value) {
45
+ field = value
46
+ updateInteractionState()
47
+ updateScrim()
48
+ }
40
49
  private var pendingIndex: Int? = null
41
50
  private var hasLaidOut = false
42
51
  private var isPanning = false
@@ -44,6 +53,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
44
53
  // MARK: - Internal
45
54
 
46
55
  private val sheetContainer = FrameLayout(context)
56
+ private val scrimPaint = Paint(Paint.ANTI_ALIAS_FLAG)
47
57
  private var activeAnimation: SpringAnimation? = null
48
58
  private var velocityTracker: VelocityTracker? = null
49
59
  private var choreographerCallback: Choreographer.FrameCallback? = null
@@ -55,6 +65,9 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
55
65
  private var initialTouchX = 0f
56
66
  private var lastTouchY = 0f
57
67
  private var activePointerId = MotionEvent.INVALID_POINTER_ID
68
+ private var scrimPressed = false
69
+ private var scrimColor = Color.argb(128, 0, 0, 0)
70
+ private var scrimProgress = 0f
58
71
 
59
72
  init {
60
73
  clipChildren = false
@@ -141,6 +154,11 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
141
154
  updateShadowState(sheetContainer.translationY)
142
155
  }
143
156
 
157
+ override fun dispatchDraw(canvas: Canvas) {
158
+ drawScrim(canvas)
159
+ super.dispatchDraw(canvas)
160
+ }
161
+
144
162
  private fun layoutSheetChildren() {
145
163
  for (i in 0 until sheetContainer.childCount) {
146
164
  val child = sheetContainer.getChildAt(i)
@@ -175,6 +193,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
175
193
  }
176
194
 
177
195
  requestLayout()
196
+ updateScrim()
178
197
  }
179
198
 
180
199
  fun setIndex(newIndex: Int) {
@@ -190,6 +209,11 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
190
209
  snapToIndex(newIndex, 0f)
191
210
  }
192
211
 
212
+ fun setScrimColor(color: Int?) {
213
+ scrimColor = color ?: Color.argb(128, 0, 0, 0)
214
+ invalidate()
215
+ }
216
+
193
217
  // MARK: - Snap logic
194
218
 
195
219
  private fun translationY(index: Int): Float {
@@ -198,6 +222,12 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
198
222
  return maxHeight - snapHeight
199
223
  }
200
224
 
225
+ private val closedIndex: Int?
226
+ get() = detentSpecs.indexOfFirst { it.height == 0f }.takeIf { it >= 0 }
227
+
228
+ private val firstNonZeroDetentHeight: Float
229
+ get() = detentSpecs.firstOrNull { it.height > 0f }?.height ?: 0f
230
+
201
231
  private val draggableMinTy: Float
202
232
  get() {
203
233
  val highestIndex = detentSpecs.indices.lastOrNull { !detentSpecs[it].programmatic } ?: 0
@@ -216,7 +246,10 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
216
246
  private fun emitPosition() {
217
247
  val maxHeight = detentSpecs.lastOrNull()?.height ?: height.toFloat()
218
248
  val ty = sheetContainer.translationY
219
- listener?.onPositionChange(((maxHeight - ty) / density).toDouble())
249
+ val position = maxHeight - ty
250
+ updateScrim(position)
251
+ updateInteractionState()
252
+ listener?.onPositionChange((position / density).toDouble())
220
253
  updateShadowState(ty)
221
254
  }
222
255
 
@@ -276,6 +309,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
276
309
  stopChoreographer()
277
310
  emitPosition()
278
311
  activeAnimation = null
312
+ updateInteractionState()
279
313
  listener?.onIndexChange(index)
280
314
  }
281
315
  }
@@ -308,6 +342,13 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
308
342
  override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
309
343
  val sheetTop = sheetContainer.top + sheetContainer.translationY
310
344
  if (ev.actionMasked == MotionEvent.ACTION_DOWN && ev.y < sheetTop) {
345
+ if (isScrimVisible()) {
346
+ initialTouchX = ev.x
347
+ initialTouchY = ev.y
348
+ lastTouchY = ev.y
349
+ scrimPressed = true
350
+ return true
351
+ }
311
352
  return false
312
353
  }
313
354
 
@@ -350,12 +391,37 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
350
391
  initialTouchX = 0f
351
392
  initialTouchY = 0f
352
393
  activePointerId = MotionEvent.INVALID_POINTER_ID
394
+ scrimPressed = false
353
395
  }
354
396
  }
355
397
  return false
356
398
  }
357
399
 
358
400
  override fun onTouchEvent(event: MotionEvent): Boolean {
401
+ if (scrimPressed) {
402
+ when (event.actionMasked) {
403
+ MotionEvent.ACTION_MOVE -> {
404
+ val sheetTop = sheetContainer.top + sheetContainer.translationY
405
+ if (event.y >= sheetTop || abs(event.y - initialTouchY) > touchSlop) {
406
+ scrimPressed = false
407
+ }
408
+ return true
409
+ }
410
+ MotionEvent.ACTION_UP -> {
411
+ val closeIndex = closedIndex
412
+ scrimPressed = false
413
+ if (closeIndex != null && isScrimVisible()) {
414
+ snapToIndex(closeIndex, 0f)
415
+ }
416
+ return true
417
+ }
418
+ MotionEvent.ACTION_CANCEL -> {
419
+ scrimPressed = false
420
+ return true
421
+ }
422
+ }
423
+ }
424
+
359
425
  when (event.actionMasked) {
360
426
  MotionEvent.ACTION_MOVE -> {
361
427
  if (!isPanning) beginPan(event)
@@ -480,9 +546,51 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
480
546
  initialTouchX = 0f
481
547
  lastTouchY = 0f
482
548
  activePointerId = MotionEvent.INVALID_POINTER_ID
549
+ scrimPressed = false
483
550
  sheetContainer.translationY = 0f
551
+ scrimProgress = 0f
484
552
  sheetContainer.removeAllViews()
485
553
  stateWrapper = null
486
554
  lastShadowOffsetY = Float.NaN
487
555
  }
556
+
557
+ private fun updateScrim(position: Float = currentSheetHeight()) {
558
+ if (!modal) {
559
+ scrimProgress = 0f
560
+ invalidate()
561
+ return
562
+ }
563
+
564
+ val threshold = firstNonZeroDetentHeight
565
+ scrimProgress =
566
+ if (threshold <= 0f) 0f else (position / threshold).coerceIn(0f, 1f)
567
+ invalidate()
568
+ }
569
+
570
+ private fun updateInteractionState() {
571
+ pointerEvents =
572
+ if (modal && (activeAnimation != null || isPanning || isScrimVisible())) {
573
+ PointerEvents.AUTO
574
+ } else {
575
+ PointerEvents.BOX_NONE
576
+ }
577
+ }
578
+
579
+ private fun currentSheetHeight(): Float {
580
+ val maxHeight = detentSpecs.lastOrNull()?.height ?: height.toFloat()
581
+ return maxHeight - sheetContainer.translationY
582
+ }
583
+
584
+ private fun isScrimVisible(): Boolean = modal && currentSheetHeight() > 1f
585
+
586
+ private fun drawScrim(canvas: Canvas) {
587
+ if (!modal || scrimProgress <= 0.001f) {
588
+ return
589
+ }
590
+
591
+ val alpha = (Color.alpha(scrimColor) * scrimProgress).toInt().coerceIn(0, 255)
592
+ scrimPaint.color =
593
+ Color.argb(alpha, Color.red(scrimColor), Color.green(scrimColor), Color.blue(scrimColor))
594
+ canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), scrimPaint)
595
+ }
488
596
  }
@@ -109,6 +109,16 @@ class BottomSheetViewManager :
109
109
  view.animateIn = animateIn
110
110
  }
111
111
 
112
+ @ReactProp(name = "modal")
113
+ override fun setModal(view: BottomSheetView, modal: Boolean) {
114
+ view.modal = modal
115
+ }
116
+
117
+ @ReactProp(name = "scrimColor", customType = "Color")
118
+ override fun setScrimColor(view: BottomSheetView, scrimColor: Int?) {
119
+ view.setScrimColor(scrimColor)
120
+ }
121
+
112
122
  override fun onDropViewInstance(view: BottomSheetView) {
113
123
  super.onDropViewInstance(view)
114
124
  view.destroy()
@@ -64,6 +64,14 @@ using namespace facebook::react;
64
64
  _sheetView.animateIn = newViewProps.animateIn;
65
65
  }
66
66
 
67
+ if (newViewProps.modal != oldViewProps.modal) {
68
+ _sheetView.modal = newViewProps.modal;
69
+ }
70
+
71
+ if (newViewProps.scrimColor != oldViewProps.scrimColor) {
72
+ [_sheetView setScrimColor:RCTUIColorFromSharedColor(newViewProps.scrimColor)];
73
+ }
74
+
67
75
  [super updateProps:props oldProps:oldProps];
68
76
  }
69
77
 
@@ -13,10 +13,12 @@ NS_ASSUME_NONNULL_BEGIN
13
13
 
14
14
  @property (nonatomic, weak, nullable) id<BottomSheetContentViewDelegate> delegate;
15
15
  @property (nonatomic) BOOL animateIn;
16
+ @property (nonatomic) BOOL modal;
16
17
  @property (nonatomic, readonly) UIView *sheetContainer;
17
18
 
18
19
  - (void)setDetents:(NSArray<NSDictionary *> *)raw;
19
20
  - (void)setDetentIndex:(NSInteger)newIndex;
21
+ - (void)setScrimColor:(UIColor *_Nullable)color;
20
22
  - (void)mountChildComponentView:(UIView *)childView atIndex:(NSInteger)index;
21
23
  - (void)unmountChildComponentView:(UIView *)childView;
22
24
  - (void)resetSheetState;
@@ -40,6 +40,16 @@
40
40
  return _impl.sheetContainer;
41
41
  }
42
42
 
43
+ - (BOOL)modal
44
+ {
45
+ return _impl.modal;
46
+ }
47
+
48
+ - (void)setModal:(BOOL)modal
49
+ {
50
+ _impl.modal = modal;
51
+ }
52
+
43
53
  - (void)setDetents:(NSArray<NSDictionary *> *)raw
44
54
  {
45
55
  [_impl setDetents:raw];
@@ -50,6 +60,11 @@
50
60
  [_impl setDetentIndex:newIndex];
51
61
  }
52
62
 
63
+ - (void)setScrimColor:(UIColor *)color
64
+ {
65
+ _impl.scrimColor = color;
66
+ }
67
+
53
68
  - (void)mountChildComponentView:(UIView *)childView atIndex:(NSInteger)index
54
69
  {
55
70
  [_impl mountChildComponentView:childView atIndex:index];
@@ -13,15 +13,25 @@ private struct DetentSpec {
13
13
  @objcMembers
14
14
  public final class RNSBottomSheetHostingView: UIView {
15
15
  public weak var eventDelegate: RNSBottomSheetHostingViewDelegate?
16
+ public var modal: Bool = false {
17
+ didSet { updateScrim() }
18
+ }
19
+ public var scrimColor: UIColor? = UIColor.black.withAlphaComponent(0.5) {
20
+ didSet { scrimView.backgroundColor = scrimColor }
21
+ }
16
22
 
17
23
  private var detentSpecs: [DetentSpec] = [] {
18
- didSet { setNeedsLayout() }
24
+ didSet {
25
+ setNeedsLayout()
26
+ updateScrim()
27
+ }
19
28
  }
20
29
 
21
30
  private var targetIndex: Int = 0
22
31
  public var animateIn: Bool = true
23
32
 
24
33
  public let sheetContainer = UIView()
34
+ private let scrimView = UIControl()
25
35
  private var panGesture: UIPanGestureRecognizer!
26
36
  private var activeAnimator: UIViewPropertyAnimator?
27
37
  private var displayLink: CADisplayLink?
@@ -35,6 +45,12 @@ public final class RNSBottomSheetHostingView: UIView {
35
45
  backgroundColor = .clear
36
46
  clipsToBounds = false
37
47
 
48
+ scrimView.backgroundColor = scrimColor
49
+ scrimView.alpha = 0
50
+ scrimView.isHidden = true
51
+ scrimView.addTarget(self, action: #selector(handleScrimPress), for: .touchUpInside)
52
+ addSubview(scrimView)
53
+
38
54
  sheetContainer.backgroundColor = .clear
39
55
  sheetContainer.clipsToBounds = false
40
56
  addSubview(sheetContainer)
@@ -81,6 +97,7 @@ public final class RNSBottomSheetHostingView: UIView {
81
97
  super.layoutSubviews()
82
98
  guard bounds.width > 0, bounds.height > 0 else { return }
83
99
 
100
+ scrimView.frame = bounds
84
101
  let maxHeight = detentSpecs.last?.height ?? bounds.height
85
102
  sheetContainer.bounds = CGRect(x: 0, y: 0, width: bounds.width, height: maxHeight)
86
103
  sheetContainer.center = CGPoint(x: bounds.width / 2, y: bounds.height - maxHeight / 2)
@@ -106,6 +123,7 @@ public final class RNSBottomSheetHostingView: UIView {
106
123
 
107
124
  if activeAnimator != nil || isPanning { return }
108
125
  sheetContainer.transform = CGAffineTransform(translationX: 0, y: translationY(for: targetIndex))
126
+ updateScrim()
109
127
  }
110
128
 
111
129
  private var presentedSheetFrame: CGRect {
@@ -116,12 +134,21 @@ public final class RNSBottomSheetHostingView: UIView {
116
134
  }
117
135
 
118
136
  public override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
119
- presentedSheetFrame.contains(point)
137
+ if presentedSheetFrame.contains(point) {
138
+ return true
139
+ }
140
+
141
+ return isScrimVisible && bounds.contains(point)
120
142
  }
121
143
 
122
144
  public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
123
145
  guard self.point(inside: point, with: event) else { return nil }
124
146
 
147
+ if isScrimVisible && !presentedSheetFrame.contains(point) {
148
+ let scrimPoint = convert(point, to: scrimView)
149
+ return scrimView.hitTest(scrimPoint, with: event)
150
+ }
151
+
125
152
  let containerPoint = convert(point, to: sheetContainer)
126
153
  guard sheetContainer.bounds.contains(containerPoint) else { return nil }
127
154
  return sheetContainer.hitTest(containerPoint, with: event)
@@ -169,6 +196,8 @@ public final class RNSBottomSheetHostingView: UIView {
169
196
  isPanning = false
170
197
  setContentInteractionEnabled(true)
171
198
  sheetContainer.transform = .identity
199
+ scrimView.alpha = 0
200
+ scrimView.isHidden = true
172
201
  for subview in sheetContainer.subviews {
173
202
  subview.removeFromSuperview()
174
203
  }
@@ -194,10 +223,31 @@ public final class RNSBottomSheetHostingView: UIView {
194
223
  return (minTy: translationY(for: highestIndex), maxTy: translationY(for: lowestIndex))
195
224
  }
196
225
 
226
+ private var closedIndex: Int? {
227
+ detentSpecs.firstIndex(where: { $0.height == 0 })
228
+ }
229
+
230
+ private var firstNonZeroDetentHeight: CGFloat {
231
+ detentSpecs.first(where: { $0.height > 0 })?.height ?? 0
232
+ }
233
+
234
+ private var currentSheetHeight: CGFloat {
235
+ let maxHeight = detentSpecs.last?.height ?? bounds.height
236
+ let ty = sheetContainer.layer.presentation()?.affineTransform().ty ?? sheetContainer.transform.ty
237
+ return maxHeight - ty
238
+ }
239
+
240
+ private var isScrimVisible: Bool {
241
+ modal && currentSheetHeight > 0.5
242
+ }
243
+
197
244
  private func emitPosition() {
198
245
  let maxHeight = detentSpecs.last?.height ?? bounds.height
199
246
  let ty = sheetContainer.layer.presentation()?.affineTransform().ty ?? sheetContainer.transform.ty
200
- eventDelegate?.bottomSheetHostingView(self, didChangePosition: maxHeight - ty)
247
+ let position = maxHeight - ty
248
+ updateScrim(forPosition: position)
249
+ updateInteractionState()
250
+ eventDelegate?.bottomSheetHostingView(self, didChangePosition: position)
201
251
  }
202
252
 
203
253
  private func startDisplayLink() {
@@ -227,6 +277,19 @@ public final class RNSBottomSheetHostingView: UIView {
227
277
  emitPosition()
228
278
  }
229
279
 
280
+ @objc private func handleScrimPress() {
281
+ guard
282
+ modal,
283
+ let closedIndex,
284
+ targetIndex != closedIndex,
285
+ activeAnimator == nil || currentSheetHeight > 0.5
286
+ else {
287
+ return
288
+ }
289
+
290
+ snapToIndex(closedIndex, velocity: 0)
291
+ }
292
+
230
293
  private func snapToIndex(_ index: Int, velocity: CGFloat) {
231
294
  guard index >= 0, index < detentSpecs.count else { return }
232
295
  targetIndex = index
@@ -252,6 +315,7 @@ public final class RNSBottomSheetHostingView: UIView {
252
315
  self.emitPosition()
253
316
  self.activeAnimator = nil
254
317
  self.setContentInteractionEnabled(true)
318
+ self.updateInteractionState()
255
319
  self.eventDelegate?.bottomSheetHostingView(self, didChangeIndex: index)
256
320
  }
257
321
  animator.startAnimation()
@@ -399,3 +463,32 @@ extension RNSBottomSheetHostingView: UIGestureRecognizerDelegate {
399
463
  return false
400
464
  }
401
465
  }
466
+
467
+ private extension RNSBottomSheetHostingView {
468
+ func updateScrim() {
469
+ updateScrim(forPosition: currentSheetHeight)
470
+ updateInteractionState()
471
+ }
472
+
473
+ func updateScrim(forPosition position: CGFloat) {
474
+ guard modal else {
475
+ scrimView.alpha = 0
476
+ scrimView.isHidden = true
477
+ return
478
+ }
479
+
480
+ let threshold = firstNonZeroDetentHeight
481
+ let progress: CGFloat
482
+ if threshold <= 0 {
483
+ progress = 0
484
+ } else {
485
+ progress = min(1, max(0, position / threshold))
486
+ }
487
+ scrimView.alpha = progress
488
+ scrimView.isHidden = progress <= 0.001
489
+ }
490
+
491
+ func updateInteractionState() {
492
+ scrimView.isUserInteractionEnabled = modal && (closedIndex != nil) && !scrimView.isHidden
493
+ }
494
+ }
@@ -1,29 +1,17 @@
1
1
  "use strict";
2
2
 
3
- import { useEffect, useRef, useState } from 'react';
4
- import { Animated, Pressable, StyleSheet, View, useWindowDimensions } from 'react-native';
3
+ import { useRef, useState } from 'react';
4
+ import { Animated, StyleSheet, View, useWindowDimensions } from 'react-native';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import BottomSheetNativeComponent from './BottomSheetNativeComponent';
7
7
  import { Portal } from "./BottomSheetProvider.js";
8
8
  import { resolveDetent } from "./bottomSheetUtils.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  export { programmatic } from "./bottomSheetUtils.js";
11
- const DefaultScrim = ({
12
- progress,
13
- color
14
- }) => {
15
- return /*#__PURE__*/_jsx(Animated.View, {
16
- style: [StyleSheet.absoluteFill, {
17
- flex: 1,
18
- backgroundColor: color,
19
- opacity: progress
20
- }]
21
- });
22
- };
23
11
  export const BottomSheet = ({
24
12
  children,
25
13
  style,
26
- detents = [0, 'max'],
14
+ detents = [0, 'content'],
27
15
  index,
28
16
  animateIn = true,
29
17
  onIndexChange,
@@ -32,13 +20,11 @@ export const BottomSheet = ({
32
20
  scrimColor = 'rgba(0, 0, 0, 0.5)'
33
21
  }) => {
34
22
  const {
35
- height: screenHeight
23
+ height: windowHeight
36
24
  } = useWindowDimensions();
37
25
  const insets = useSafeAreaInsets();
38
- const maxHeight = screenHeight - insets.top;
26
+ const maxHeight = windowHeight - insets.top;
39
27
  const [contentHeight, setContentHeight] = useState(0);
40
- const currentPositionRef = useRef(0);
41
- const scrimProgress = useRef(new Animated.Value(0)).current;
42
28
  const sheetOpacity = useRef(new Animated.Value(0)).current;
43
29
  const resolvedDetents = detents.map(detent => {
44
30
  const value = resolveDetent(detent, contentHeight, maxHeight);
@@ -52,61 +38,18 @@ export const BottomSheet = ({
52
38
  };
53
39
  const clampedIndex = Math.max(0, Math.min(index, resolvedDetents.length - 1));
54
40
  const isCollapsed = (resolvedDetents[clampedIndex]?.height ?? 0) === 0;
55
- const scrimPressEnabledRef = useRef(!modal || isCollapsed);
56
- const previousIsCollapsedRef = useRef(isCollapsed);
57
- const firstNonzeroDetent = resolvedDetents.find(detent => detent.height > 0)?.height ?? 0;
58
- useEffect(() => {
59
- const progress = firstNonzeroDetent <= 0 ? 0 : Math.min(1, Math.max(0, currentPositionRef.current / firstNonzeroDetent));
60
- scrimProgress.setValue(progress);
61
- }, [firstNonzeroDetent, scrimProgress]);
62
- useEffect(() => {
63
- if (!modal) {
64
- scrimPressEnabledRef.current = true;
65
- previousIsCollapsedRef.current = isCollapsed;
66
- return undefined;
67
- }
68
- if (previousIsCollapsedRef.current && !isCollapsed) {
69
- scrimPressEnabledRef.current = false;
70
- previousIsCollapsedRef.current = isCollapsed;
71
- const frame = requestAnimationFrame(() => {
72
- scrimPressEnabledRef.current = true;
73
- });
74
- return () => cancelAnimationFrame(frame);
75
- }
76
- scrimPressEnabledRef.current = !isCollapsed;
77
- previousIsCollapsedRef.current = isCollapsed;
78
- return undefined;
79
- }, [isCollapsed, modal]);
80
41
  const handleIndexChange = event => {
81
42
  onIndexChange?.(event.nativeEvent.index);
82
43
  };
83
44
  const handlePositionChange = event => {
84
45
  const height = event.nativeEvent.position;
85
- currentPositionRef.current = height;
86
- const progress = firstNonzeroDetent <= 0 ? 0 : Math.min(1, Math.max(0, height / firstNonzeroDetent));
87
- scrimProgress.setValue(progress);
88
46
  sheetOpacity.setValue(height === 0 ? 0 : 1);
89
47
  onPositionChange?.(height);
90
48
  };
91
- const closedIndex = resolvedDetents.findIndex(detent => detent.height === 0);
92
- const handleScrimPress = () => {
93
- if (closedIndex === -1 || clampedIndex === closedIndex || !scrimPressEnabledRef.current) {
94
- return;
95
- }
96
- onIndexChange?.(closedIndex);
97
- };
98
- const scrimElement = modal ? /*#__PURE__*/_jsx(DefaultScrim, {
99
- progress: scrimProgress,
100
- color: scrimColor
101
- }) : null;
102
- const sheet = /*#__PURE__*/_jsxs(Animated.View, {
49
+ const sheet = /*#__PURE__*/_jsx(Animated.View, {
103
50
  style: StyleSheet.absoluteFill,
104
51
  pointerEvents: modal ? isCollapsed ? 'none' : 'auto' : 'box-none',
105
- children: [modal && scrimElement !== null ? /*#__PURE__*/_jsx(Pressable, {
106
- style: StyleSheet.absoluteFill,
107
- onPress: handleScrimPress,
108
- children: scrimElement
109
- }) : null, /*#__PURE__*/_jsx(Animated.View, {
52
+ children: /*#__PURE__*/_jsx(Animated.View, {
110
53
  pointerEvents: "box-none",
111
54
  style: [StyleSheet.absoluteFill, {
112
55
  opacity: sheetOpacity
@@ -118,17 +61,23 @@ export const BottomSheet = ({
118
61
  left: 0,
119
62
  right: 0,
120
63
  bottom: 0,
121
- height: maxHeight
64
+ // The native host always spans the full height of its container.
65
+ // Detents are still capped to `maxHeight`, so the sheet itself
66
+ // never extends under the status bar.
67
+ height: windowHeight
122
68
  }, style],
123
69
  detents: resolvedDetents,
124
70
  index: index,
125
71
  animateIn: animateIn,
72
+ modal: modal,
73
+ scrimColor: scrimColor,
126
74
  onIndexChange: handleIndexChange,
127
75
  onPositionChange: handlePositionChange,
128
76
  children: /*#__PURE__*/_jsxs(View, {
129
77
  collapsable: false,
130
78
  style: {
131
- flex: 1
79
+ flex: 1,
80
+ maxHeight
132
81
  },
133
82
  children: [children, /*#__PURE__*/_jsx(View, {
134
83
  onLayout: handleSentinelLayout,
@@ -136,7 +85,7 @@ export const BottomSheet = ({
136
85
  })]
137
86
  })
138
87
  })
139
- })]
88
+ })
140
89
  });
141
90
  if (modal) {
142
91
  return /*#__PURE__*/_jsx(Portal, {
@@ -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","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
+ {"version":3,"names":["useRef","useState","Animated","StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","Portal","resolveDetent","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","style","detents","index","animateIn","onIndexChange","onPositionChange","modal","scrimColor","height","windowHeight","insets","maxHeight","top","contentHeight","setContentHeight","sheetOpacity","Value","current","resolvedDetents","map","detent","value","Math","max","min","isDetentProgrammatic","handleSentinelLayout","event","nativeEvent","layout","y","clampedIndex","length","isCollapsed","handleIndexChange","handlePositionChange","position","setValue","sheet","absoluteFill","pointerEvents","opacity","left","right","bottom","collapsable","flex","onLayout"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  codegenNativeComponent,
3
3
  type CodegenTypes,
4
+ type ColorValue,
4
5
  type ViewProps,
5
6
  } from 'react-native';
6
7
 
@@ -13,6 +14,8 @@ export interface NativeProps extends ViewProps {
13
14
  detents: ReadonlyArray<NativeDetent>;
14
15
  index: CodegenTypes.Int32;
15
16
  animateIn: boolean;
17
+ modal: boolean;
18
+ scrimColor: ColorValue;
16
19
  onIndexChange?: CodegenTypes.DirectEventHandler<
17
20
  Readonly<{ index: CodegenTypes.Int32 }>
18
21
  >;
@@ -41,7 +41,7 @@ export const findSnapTarget = (currentTranslate, velocityY, currentIndex, allPos
41
41
  export const resolveDetent = (detent, contentHeight, maxHeight) => {
42
42
  const detentValueInput = detentValue(detent);
43
43
  if (typeof detentValueInput === 'number') return detentValueInput;
44
- if (detentValueInput === 'max') {
44
+ if (detentValueInput === 'content') {
45
45
  return contentHeight > 0 ? Math.min(contentHeight, maxHeight) : maxHeight;
46
46
  }
47
47
  throw new Error(`Invalid detent: \`${detentValueInput}\`.`);
@@ -1 +1 @@
1
- {"version":3,"names":["programmatic","value","detentValue","detent","isDetentProgrammatic","VELOCITY_THRESHOLD","findSnapTarget","currentTranslate","velocityY","currentIndex","allPositions","draggablePositions","filter","position","isDraggable","effectivePositions","length","targetIndex","minDistance","Infinity","distance","Math","abs","translateY","index","lowerPosition","sort","a","b","undefined","upperPosition","resolveDetent","contentHeight","maxHeight","detentValueInput","min","Error","clampIndex","detentCount","max"],"sourceRoot":"../../src","sources":["bottomSheetUtils.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["programmatic","value","detentValue","detent","isDetentProgrammatic","VELOCITY_THRESHOLD","findSnapTarget","currentTranslate","velocityY","currentIndex","allPositions","draggablePositions","filter","position","isDraggable","effectivePositions","length","targetIndex","minDistance","Infinity","distance","Math","abs","translateY","index","lowerPosition","sort","a","b","undefined","upperPosition","resolveDetent","contentHeight","maxHeight","detentValueInput","min","Error","clampIndex","detentCount","max"],"sourceRoot":"../../src","sources":["bottomSheetUtils.ts"],"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,4CAiJlB,CAAC"}
1
+ {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAqB,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAM5E,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;AAElD,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,4CA+ElB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type CodegenTypes, type ViewProps } from 'react-native';
1
+ import { type CodegenTypes, type ColorValue, type ViewProps } from 'react-native';
2
2
  type NativeDetent = Readonly<{
3
3
  height: CodegenTypes.Double;
4
4
  programmatic: boolean;
@@ -7,6 +7,8 @@ export interface NativeProps extends ViewProps {
7
7
  detents: ReadonlyArray<NativeDetent>;
8
8
  index: CodegenTypes.Int32;
9
9
  animateIn: boolean;
10
+ modal: boolean;
11
+ scrimColor: ColorValue;
10
12
  onIndexChange?: CodegenTypes.DirectEventHandler<Readonly<{
11
13
  index: CodegenTypes.Int32;
12
14
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CAC5C,CAAC;CACH;;AAED,wBAAsE"}
1
+ {"version":3,"file":"BottomSheetNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/BottomSheetNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAChD,QAAQ,CAAC;QAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CAC5C,CAAC;CACH;;AAED,wBAAsE"}
@@ -1,4 +1,4 @@
1
- export type DetentValue = number | 'max';
1
+ export type DetentValue = number | 'content';
2
2
  export type Detent = DetentValue | {
3
3
  value: DetentValue;
4
4
  programmatic?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"bottomSheetUtils.d.ts","sourceRoot":"","sources":["../../../src/bottomSheetUtils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,CAAC;AAEzC,MAAM,MAAM,MAAM,GACd,WAAW,GACX;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,KAAG,MAGhD,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,WAG5C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,OAKrD,CAAC;AAIF,eAAO,MAAM,cAAc,GACzB,kBAAkB,MAAM,EACxB,WAAW,MAAM,EACjB,cAAc,MAAM,EACpB,cAAc;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAAE,WAiC5E,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,WAAW,MAAM,WAQlB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,aAAa,MAAM,WAG5D,CAAC"}
1
+ {"version":3,"file":"bottomSheetUtils.d.ts","sourceRoot":"","sources":["../../../src/bottomSheetUtils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7C,MAAM,MAAM,MAAM,GACd,WAAW,GACX;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,KAAG,MAGhD,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,WAG5C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,OAKrD,CAAC;AAIF,eAAO,MAAM,cAAc,GACzB,kBAAkB,MAAM,EACxB,WAAW,MAAM,EACjB,cAAc,MAAM,EACpB,cAAc;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAAE,WAiC5E,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,WAAW,MAAM,WAQlB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,aAAa,MAAM,WAG5D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/react-native-bottom-sheet",
3
- "version": "0.7.3",
3
+ "version": "0.8.0-next.2",
4
4
  "description": "Provides bottom-sheet components for React Native.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -1,12 +1,6 @@
1
- import { useEffect, useRef, useState, type ReactNode } from 'react';
1
+ import { useRef, useState, type ReactNode } from 'react';
2
2
  import type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
3
- import {
4
- Animated,
5
- Pressable,
6
- StyleSheet,
7
- View,
8
- useWindowDimensions,
9
- } from 'react-native';
3
+ import { Animated, StyleSheet, View, useWindowDimensions } from 'react-native';
10
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
11
5
 
12
6
  import BottomSheetNativeComponent from './BottomSheetNativeComponent';
@@ -15,23 +9,6 @@ import { type Detent, resolveDetent } from './bottomSheetUtils';
15
9
  export type { Detent, DetentValue } from './bottomSheetUtils';
16
10
  export { programmatic } from './bottomSheetUtils';
17
11
 
18
- const DefaultScrim = ({
19
- progress,
20
- color,
21
- }: {
22
- progress: Animated.Value;
23
- color: string;
24
- }) => {
25
- return (
26
- <Animated.View
27
- style={[
28
- StyleSheet.absoluteFill,
29
- { flex: 1, backgroundColor: color, opacity: progress },
30
- ]}
31
- />
32
- );
33
- };
34
-
35
12
  export interface BottomSheetProps {
36
13
  children: ReactNode;
37
14
  style?: StyleProp<ViewStyle>;
@@ -47,7 +24,7 @@ export interface BottomSheetProps {
47
24
  export const BottomSheet = ({
48
25
  children,
49
26
  style,
50
- detents = [0, 'max'],
27
+ detents = [0, 'content'],
51
28
  index,
52
29
  animateIn = true,
53
30
  onIndexChange,
@@ -55,12 +32,10 @@ export const BottomSheet = ({
55
32
  modal = false,
56
33
  scrimColor = 'rgba(0, 0, 0, 0.5)',
57
34
  }: BottomSheetProps) => {
58
- const { height: screenHeight } = useWindowDimensions();
35
+ const { height: windowHeight } = useWindowDimensions();
59
36
  const insets = useSafeAreaInsets();
60
- const maxHeight = screenHeight - insets.top;
37
+ const maxHeight = windowHeight - insets.top;
61
38
  const [contentHeight, setContentHeight] = useState(0);
62
- const currentPositionRef = useRef(0);
63
- const scrimProgress = useRef(new Animated.Value(0)).current;
64
39
  const sheetOpacity = useRef(new Animated.Value(0)).current;
65
40
 
66
41
  const resolvedDetents = detents.map((detent) => {
@@ -77,45 +52,6 @@ export const BottomSheet = ({
77
52
 
78
53
  const clampedIndex = Math.max(0, Math.min(index, resolvedDetents.length - 1));
79
54
  const isCollapsed = (resolvedDetents[clampedIndex]?.height ?? 0) === 0;
80
- const scrimPressEnabledRef = useRef(!modal || isCollapsed);
81
- const previousIsCollapsedRef = useRef(isCollapsed);
82
- const firstNonzeroDetent =
83
- resolvedDetents.find((detent) => detent.height > 0)?.height ?? 0;
84
-
85
- useEffect(() => {
86
- const progress =
87
- firstNonzeroDetent <= 0
88
- ? 0
89
- : Math.min(
90
- 1,
91
- Math.max(0, currentPositionRef.current / firstNonzeroDetent)
92
- );
93
- scrimProgress.setValue(progress);
94
- }, [firstNonzeroDetent, scrimProgress]);
95
-
96
- useEffect(() => {
97
- if (!modal) {
98
- scrimPressEnabledRef.current = true;
99
- previousIsCollapsedRef.current = isCollapsed;
100
- return undefined;
101
- }
102
-
103
- if (previousIsCollapsedRef.current && !isCollapsed) {
104
- scrimPressEnabledRef.current = false;
105
- previousIsCollapsedRef.current = isCollapsed;
106
-
107
- const frame = requestAnimationFrame(() => {
108
- scrimPressEnabledRef.current = true;
109
- });
110
-
111
- return () => cancelAnimationFrame(frame);
112
- }
113
-
114
- scrimPressEnabledRef.current = !isCollapsed;
115
- previousIsCollapsedRef.current = isCollapsed;
116
- return undefined;
117
- }, [isCollapsed, modal]);
118
-
119
55
  const handleIndexChange = (event: { nativeEvent: { index: number } }) => {
120
56
  onIndexChange?.(event.nativeEvent.index);
121
57
  };
@@ -124,45 +60,15 @@ export const BottomSheet = ({
124
60
  nativeEvent: { position: number };
125
61
  }) => {
126
62
  const height = event.nativeEvent.position;
127
- currentPositionRef.current = height;
128
- const progress =
129
- firstNonzeroDetent <= 0
130
- ? 0
131
- : Math.min(1, Math.max(0, height / firstNonzeroDetent));
132
- scrimProgress.setValue(progress);
133
63
  sheetOpacity.setValue(height === 0 ? 0 : 1);
134
64
  onPositionChange?.(height);
135
65
  };
136
66
 
137
- const closedIndex = resolvedDetents.findIndex(
138
- (detent) => detent.height === 0
139
- );
140
- const handleScrimPress = () => {
141
- if (
142
- closedIndex === -1 ||
143
- clampedIndex === closedIndex ||
144
- !scrimPressEnabledRef.current
145
- ) {
146
- return;
147
- }
148
-
149
- onIndexChange?.(closedIndex);
150
- };
151
-
152
- const scrimElement = modal ? (
153
- <DefaultScrim progress={scrimProgress} color={scrimColor} />
154
- ) : null;
155
-
156
67
  const sheet = (
157
68
  <Animated.View
158
69
  style={StyleSheet.absoluteFill}
159
70
  pointerEvents={modal ? (isCollapsed ? 'none' : 'auto') : 'box-none'}
160
71
  >
161
- {modal && scrimElement !== null ? (
162
- <Pressable style={StyleSheet.absoluteFill} onPress={handleScrimPress}>
163
- {scrimElement}
164
- </Pressable>
165
- ) : null}
166
72
  <Animated.View
167
73
  pointerEvents="box-none"
168
74
  style={[StyleSheet.absoluteFill, { opacity: sheetOpacity }]}
@@ -175,17 +81,22 @@ export const BottomSheet = ({
175
81
  left: 0,
176
82
  right: 0,
177
83
  bottom: 0,
178
- height: maxHeight,
84
+ // The native host always spans the full height of its container.
85
+ // Detents are still capped to `maxHeight`, so the sheet itself
86
+ // never extends under the status bar.
87
+ height: windowHeight,
179
88
  },
180
89
  style,
181
90
  ]}
182
91
  detents={resolvedDetents}
183
92
  index={index}
184
93
  animateIn={animateIn}
94
+ modal={modal}
95
+ scrimColor={scrimColor}
185
96
  onIndexChange={handleIndexChange}
186
97
  onPositionChange={handlePositionChange}
187
98
  >
188
- <View collapsable={false} style={{ flex: 1 }}>
99
+ <View collapsable={false} style={{ flex: 1, maxHeight }}>
189
100
  {children}
190
101
  <View onLayout={handleSentinelLayout} pointerEvents="none" />
191
102
  </View>
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  codegenNativeComponent,
3
3
  type CodegenTypes,
4
+ type ColorValue,
4
5
  type ViewProps,
5
6
  } from 'react-native';
6
7
 
@@ -13,6 +14,8 @@ export interface NativeProps extends ViewProps {
13
14
  detents: ReadonlyArray<NativeDetent>;
14
15
  index: CodegenTypes.Int32;
15
16
  animateIn: boolean;
17
+ modal: boolean;
18
+ scrimColor: ColorValue;
16
19
  onIndexChange?: CodegenTypes.DirectEventHandler<
17
20
  Readonly<{ index: CodegenTypes.Int32 }>
18
21
  >;
@@ -1,4 +1,4 @@
1
- export type DetentValue = number | 'max';
1
+ export type DetentValue = number | 'content';
2
2
 
3
3
  export type Detent =
4
4
  | DetentValue
@@ -69,7 +69,7 @@ export const resolveDetent = (
69
69
  ) => {
70
70
  const detentValueInput = detentValue(detent);
71
71
  if (typeof detentValueInput === 'number') return detentValueInput;
72
- if (detentValueInput === 'max') {
72
+ if (detentValueInput === 'content') {
73
73
  return contentHeight > 0 ? Math.min(contentHeight, maxHeight) : maxHeight;
74
74
  }
75
75
  throw new Error(`Invalid detent: \`${detentValueInput}\`.`);