@swmansion/react-native-bottom-sheet 0.8.1-next.1 → 0.8.2-next.1

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 CHANGED
@@ -42,7 +42,8 @@ React Native.
42
42
  The library provides two components: `BottomSheet` (inline) and
43
43
  `ModalBottomSheet` (modal). Both render their children as the sheet content
44
44
  (including any background) and are controlled via `detents`, `index`,
45
- and `onIndexChange`.
45
+ and `onIndexChange`. Use `onSettle` for
46
+ post‍-‍snap observability.
46
47
 
47
48
  ### Inline
48
49
 
@@ -108,13 +109,18 @@ its color:
108
109
  ### Detents and index
109
110
 
110
111
  Detents are the points to which the sheet snaps. Each detent is either a number
111
- (a fixed height in pixels) or `'max'` (the sheet’s content height, capped by the
112
- available screen height). The default detents are `[0, 'max']`.
112
+ (a fixed height in pixels) or `'content'` (the sheet’s content height, capped by
113
+ the available screen height). The default detents are `[0, 'content']`.
113
114
 
114
115
  The `index` prop is a zero‍-‍based index into the `detents` array.
115
- `onIndexChange` is called when the sheet snaps to a different detent after
116
- a drag. You can also control the sheet externally by updating the
117
- index state.
116
+ `onIndexChange` and `onSettle` have different responsibilities:
117
+
118
+ - `onIndexChange` is for user‍-‍triggered snaps. Treat it as the signal
119
+ to update your controlled `index` state.
120
+ - `onSettle` fires when the sheet finishes snapping to a detent, regardless of
121
+ whether that snap was user‍-‍triggered or programmatic. Use it for
122
+ observability or side effects (analytics, reacting to collapse, etc.), not for
123
+ updating the controlled `index` state.
118
124
 
119
125
  ```tsx
120
126
  const [index, setIndex] = useState(0);
@@ -122,9 +128,12 @@ const [index, setIndex] = useState(0);
122
128
 
123
129
  ```tsx
124
130
  <BottomSheet // Or `ModalBottomSheet`.
125
- detents={[0, 300, 'max']} // Collapsed, 300 px, content height.
131
+ detents={[0, 300, 'content']} // Collapsed, 300 px, content height.
126
132
  index={index}
127
- onIndexChange={setIndex}
133
+ onIndexChange={setIndex} // Keep controlled state in sync.
134
+ onSettle={(nextIndex) => {
135
+ if (nextIndex === 0) console.log('Sheet collapsed.');
136
+ }}
128
137
  >
129
138
  {/* ... */}
130
139
  </BottomSheet>
@@ -138,9 +147,12 @@ drag snapping but can still be targeted via `index`&nbsp;updates.
138
147
 
139
148
  ```tsx
140
149
  <BottomSheet
141
- detents={[0, programmatic(300), 'max']}
150
+ detents={[0, programmatic(300), 'content']}
142
151
  index={index}
143
152
  onIndexChange={setIndex}
153
+ onSettle={(nextIndex) => {
154
+ console.log(`Settled at ${nextIndex}.`);
155
+ }}
144
156
  >
145
157
  {/* ... */}
146
158
  </BottomSheet>
@@ -581,6 +581,14 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
581
581
  return
582
582
  }
583
583
 
584
+ // When settled at the closed detent, dynamic content updates can briefly
585
+ // produce stale non-zero positions. Keep scrim hidden in this state.
586
+ if (closedIndex != null && targetIndex == closedIndex && activeAnimation == null && !isPanning) {
587
+ scrimProgress = 0f
588
+ invalidate()
589
+ return
590
+ }
591
+
584
592
  val threshold = firstNonZeroDetentHeight
585
593
  scrimProgress =
586
594
  if (threshold <= 0f) 0f else (position / threshold).coerceIn(0f, 1f)
@@ -601,7 +609,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
601
609
  return maxHeight - sheetContainer.translationY
602
610
  }
603
611
 
604
- private fun isScrimVisible(): Boolean = modal && currentSheetHeight() > 1f
612
+ private fun isScrimVisible(): Boolean = modal && scrimProgress > 0.001f
605
613
 
606
614
  private fun drawScrim(canvas: Canvas) {
607
615
  if (!modal || scrimProgress <= 0.001f) {
@@ -272,7 +272,7 @@ public final class RNSBottomSheetHostingView: UIView {
272
272
  }
273
273
 
274
274
  private var isScrimVisible: Bool {
275
- modal && currentSheetHeight > 0.5
275
+ modal && !scrimView.isHidden
276
276
  }
277
277
 
278
278
  private func emitPosition() {
@@ -523,6 +523,19 @@ private extension RNSBottomSheetHostingView {
523
523
  return
524
524
  }
525
525
 
526
+ // If we're settled on the closed detent, dynamic detent/content updates can
527
+ // momentarily report a stale non-zero position. Keep scrim fully hidden.
528
+ if
529
+ let closedIndex,
530
+ targetIndex == closedIndex,
531
+ activeAnimator == nil,
532
+ !isPanning
533
+ {
534
+ scrimView.alpha = 0
535
+ scrimView.isHidden = true
536
+ return
537
+ }
538
+
526
539
  let threshold = firstNonZeroDetentHeight
527
540
  let progress: CGFloat
528
541
  if threshold <= 0 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/react-native-bottom-sheet",
3
- "version": "0.8.1-next.1",
3
+ "version": "0.8.2-next.1",
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",