@swmansion/react-native-bottom-sheet 0.11.0 → 0.12.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/README.md CHANGED
@@ -150,6 +150,31 @@ its color:
150
150
  </ModalBottomSheet>
151
151
  ```
152
152
 
153
+ By default, the scrim fades in as the sheet opens and then holds at full
154
+ opacity, so detents above the first share the same scrim. Use `scrimOpacities`
155
+ to control the opacity at each detent: It takes one value in 0–1 per detent,
156
+ indexed to match `detents`, and interpolates linearly as the sheet is dragged
157
+ between them. A shorter array reuses its last value for any remaining detents.
158
+
159
+ The default maps each detent to 0 when it is closed and 1 otherwise, so the
160
+ scrim is transparent at any closed detent and fully opaque at every open one,
161
+ whatever order the detents are passed in.
162
+
163
+ To keep the scrim deepening across every detent, pass one value per detent:
164
+
165
+ ```tsx
166
+ <ModalBottomSheet
167
+ index={index}
168
+ onIndexChange={setIndex}
169
+ detents={[0, 300, 'content']}
170
+ scrimColor="rgba(0, 0, 0, 0.3)"
171
+ scrimOpacities={[0, 0.5, 1]}
172
+ surface={/* ... */}
173
+ >
174
+ {/* ... */}
175
+ </ModalBottomSheet>
176
+ ```
177
+
153
178
  ### Surface
154
179
 
155
180
  Provide the sheet’s background through the `surface` prop. The library renders
@@ -83,6 +83,9 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
83
83
  private var scrimPressed = false
84
84
  private var scrimTouchActive = false
85
85
  private var scrimColor = Color.TRANSPARENT
86
+ // The JS layer always supplies a per-detent array; the fully-opaque fallback
87
+ // only guards against empty input (indexing requires a non-empty array).
88
+ private var scrimOpacities = listOf(1f)
86
89
  private var scrimProgress = 0f
87
90
  private var suppressScrimForClosingTarget = false
88
91
  private var scrimPinnedFull = false
@@ -255,6 +258,11 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
255
258
  invalidate()
256
259
  }
257
260
 
261
+ fun setScrimOpacities(values: List<Float>) {
262
+ scrimOpacities = if (values.isEmpty()) listOf(1f) else values
263
+ updateScrim()
264
+ }
265
+
258
266
  fun setMaxDetentHeight(maxDetentHeight: Double) {
259
267
  this.maxDetentHeight = (maxDetentHeight * density).toFloat()
260
268
  refreshDetentsFromLayout()
@@ -878,18 +886,55 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
878
886
 
879
887
  // While the sheet is fully open and only its content/detent geometry is
880
888
  // resizing, the position momentarily lags the grown detent height. Keep the
881
- // scrim at full opacity instead of dipping it until the re-anchor settles.
889
+ // scrim pinned to the fully-open opacity instead of dipping it until the
890
+ // re-anchor settles.
882
891
  if (scrimPinnedFull) {
883
- scrimProgress = 1f
892
+ scrimProgress = fullyOpenScrimOpacity()
884
893
  invalidate()
885
894
  return
886
895
  }
887
896
 
888
- val threshold = firstNonZeroDetentHeight
889
- scrimProgress = if (threshold <= 0f) 0f else (position / threshold).coerceIn(0f, 1f)
897
+ scrimProgress = scrimOpacityAt(position)
890
898
  invalidate()
891
899
  }
892
900
 
901
+ /** The opacity at the tallest detent, held while the sheet re-anchors. */
902
+ private fun fullyOpenScrimOpacity(): Float {
903
+ val maxHeight = detentSpecs.maxOfOrNull { it.height } ?: return 1f
904
+ return scrimOpacityAt(maxHeight)
905
+ }
906
+
907
+ /**
908
+ * Interpolates the scrim opacity for a sheet height by bracketing it between adjacent detent
909
+ * heights and lerping each detent index's configured value.
910
+ */
911
+ private fun scrimOpacityAt(position: Float): Float {
912
+ if (detentSpecs.isEmpty()) return 0f
913
+ val pairs =
914
+ detentSpecs.indices
915
+ .map { index ->
916
+ detentSpecs[index].height to
917
+ scrimOpacities[index.coerceAtMost(scrimOpacities.size - 1)].coerceIn(0f, 1f)
918
+ }
919
+ .sortedBy { it.first }
920
+
921
+ val first = pairs.first()
922
+ val last = pairs.last()
923
+ if (position <= first.first) return first.second
924
+ if (position >= last.first) return last.second
925
+
926
+ for (i in 1 until pairs.size) {
927
+ val upper = pairs[i]
928
+ if (position <= upper.first) {
929
+ val lower = pairs[i - 1]
930
+ val span = upper.first - lower.first
931
+ val t = if (span <= 0f) 1f else (position - lower.first) / span
932
+ return lower.second + (upper.second - lower.second) * t
933
+ }
934
+ }
935
+ return last.second
936
+ }
937
+
893
938
  private fun hideScrim() {
894
939
  scrimProgress = 0f
895
940
  invalidate()
@@ -138,6 +138,17 @@ class BottomSheetViewManager :
138
138
  view.setScrimColor(scrimColor)
139
139
  }
140
140
 
141
+ @ReactProp(name = "scrimOpacities")
142
+ override fun setScrimOpacities(view: BottomSheetView, value: ReadableArray?) {
143
+ val opacities = mutableListOf<Float>()
144
+ if (value != null) {
145
+ for (i in 0 until value.size()) {
146
+ opacities.add(value.getDouble(i).toFloat())
147
+ }
148
+ }
149
+ view.setScrimOpacities(opacities)
150
+ }
151
+
141
152
  override fun onDropViewInstance(view: BottomSheetView) {
142
153
  super.onDropViewInstance(view)
143
154
  view.destroy()
@@ -86,6 +86,14 @@ using namespace facebook::react;
86
86
  [_sheetView setScrimColor:RCTUIColorFromSharedColor(newViewProps.scrimColor)];
87
87
  }
88
88
 
89
+ if (newViewProps.scrimOpacities != oldViewProps.scrimOpacities) {
90
+ NSMutableArray<NSNumber *> *opacities = [NSMutableArray new];
91
+ for (const auto &opacity : newViewProps.scrimOpacities) {
92
+ [opacities addObject:@(opacity)];
93
+ }
94
+ [_sheetView setScrimOpacities:opacities];
95
+ }
96
+
89
97
  [super updateProps:props oldProps:oldProps];
90
98
  }
91
99
 
@@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
23
23
  - (void)setMaxDetentHeight:(CGFloat)maxDetentHeight;
24
24
  - (void)setDetentIndex:(NSInteger)newIndex;
25
25
  - (void)setScrimColor:(UIColor *_Nullable)color;
26
+ - (void)setScrimOpacities:(NSArray<NSNumber *> *)opacities;
26
27
  - (CGFloat)currentContentOffsetY;
27
28
  - (void)mountChildComponentView:(UIView *)childView atIndex:(NSInteger)index;
28
29
  - (void)unmountChildComponentView:(UIView *)childView;
@@ -80,6 +80,11 @@
80
80
  _impl.scrimColor = color;
81
81
  }
82
82
 
83
+ - (void)setScrimOpacities:(NSArray<NSNumber *> *)opacities
84
+ {
85
+ [_impl setScrimOpacities:opacities];
86
+ }
87
+
83
88
  - (CGFloat)currentContentOffsetY
84
89
  {
85
90
  return _impl.currentContentOffsetY;
@@ -34,6 +34,19 @@ public final class BottomSheetHostingView: UIView {
34
34
  didSet { scrimView.backgroundColor = scrimColor }
35
35
  }
36
36
 
37
+ /// Scrim opacity per detent index. Linearly interpolated between detents and
38
+ /// clamped to the last value for detents beyond the array. The JS layer always
39
+ /// supplies a per-detent array; the fully-opaque fallback only guards against
40
+ /// empty input (indexing requires a non-empty array).
41
+ private var scrimOpacities: [CGFloat] = [1] {
42
+ didSet { updateScrim() }
43
+ }
44
+
45
+ public func setScrimOpacities(_ values: [NSNumber]) {
46
+ let mapped = values.map { CGFloat(truncating: $0) }
47
+ scrimOpacities = mapped.isEmpty ? [1] : mapped
48
+ }
49
+
37
50
  public var maxDetentHeight: CGFloat = .nan {
38
51
  didSet { refreshDetentsFromLayout() }
39
52
  }
@@ -860,24 +873,55 @@ private extension BottomSheetHostingView {
860
873
 
861
874
  // While the sheet is fully open and only its content/detent geometry is
862
875
  // resizing, the position momentarily lags the grown detent height. Keep the
863
- // scrim at full opacity instead of dipping it until the re-anchor settles.
876
+ // scrim pinned to the fully-open opacity instead of dipping it until the
877
+ // re-anchor settles.
864
878
  if scrimPinnedFull {
865
- scrimView.alpha = 1
866
- scrimView.isHidden = false
879
+ let opacity = fullyOpenScrimOpacity
880
+ scrimView.alpha = opacity
881
+ scrimView.isHidden = opacity <= 0.001
867
882
  return
868
883
  }
869
884
 
870
- let threshold = firstNonZeroDetentHeight
871
- let progress: CGFloat
872
- if threshold <= 0 {
873
- progress = 0
874
- } else {
875
- progress = min(1, max(0, position / threshold))
876
- }
885
+ let progress = scrimOpacity(forPosition: position)
877
886
  scrimView.alpha = progress
878
887
  scrimView.isHidden = progress <= 0.001
879
888
  }
880
889
 
890
+ /// The opacity at the tallest detent, held while the sheet re-anchors.
891
+ private var fullyOpenScrimOpacity: CGFloat {
892
+ guard let maxHeight = detentSpecs.map({ $0.height }).max() else { return 1 }
893
+ return scrimOpacity(forPosition: maxHeight)
894
+ }
895
+
896
+ /// Interpolates the scrim opacity for a sheet height by bracketing it between
897
+ /// adjacent detent heights and lerping each detent index's configured value.
898
+ private func scrimOpacity(forPosition position: CGFloat) -> CGFloat {
899
+ guard !detentSpecs.isEmpty else { return 0 }
900
+ let pairs = detentSpecs.indices
901
+ .map { (
902
+ height: detentSpecs[$0].height,
903
+ opacity: clampOpacity(scrimOpacities[min($0, scrimOpacities.count - 1)])
904
+ ) }
905
+ .sorted { $0.height < $1.height }
906
+
907
+ guard let first = pairs.first, let last = pairs.last else { return 0 }
908
+ if position <= first.height { return first.opacity }
909
+ if position >= last.height { return last.opacity }
910
+
911
+ for i in 1 ..< pairs.count where position <= pairs[i].height {
912
+ let lower = pairs[i - 1]
913
+ let upper = pairs[i]
914
+ let span = upper.height - lower.height
915
+ let t = span <= 0 ? 1 : (position - lower.height) / span
916
+ return lower.opacity + (upper.opacity - lower.opacity) * t
917
+ }
918
+ return last.opacity
919
+ }
920
+
921
+ private func clampOpacity(_ value: CGFloat) -> CGFloat {
922
+ min(1, max(0, value))
923
+ }
924
+
881
925
  func updateInteractionState() {
882
926
  scrimView.isUserInteractionEnabled = modal && (closedIndex != nil) && !scrimView.isHidden
883
927
  }
@@ -25,7 +25,8 @@ export const BottomSheet = ({
25
25
  onPositionChange,
26
26
  modal = false,
27
27
  disableScrollableNegotiation = false,
28
- scrimColor
28
+ scrimColor,
29
+ scrimOpacities
29
30
  }) => {
30
31
  const {
31
32
  height: windowHeight
@@ -51,6 +52,10 @@ export const BottomSheet = ({
51
52
  const clampedIndex = Math.max(0, Math.min(index, nativeDetents.length - 1));
52
53
  const selectedDetentValue = detents[clampedIndex] ? resolveDetentValue(detents[clampedIndex]) : 0;
53
54
  const isCollapsed = selectedDetentValue === 0;
55
+ // Default the scrim opacity per detent: transparent at any closed detent,
56
+ // fully opaque at every open one. Mapping each detent independently keeps
57
+ // this correct regardless of the order detents are passed in.
58
+ const resolvedScrimOpacity = scrimOpacities ?? detents.map(detent => resolveDetentValue(detent) === 0 ? 0 : 1);
54
59
  const handleIndexChange = event => {
55
60
  onIndexChange?.(event.nativeEvent.index);
56
61
  };
@@ -86,6 +91,7 @@ export const BottomSheet = ({
86
91
  modal: modal,
87
92
  disableScrollableNegotiation: disableScrollableNegotiation,
88
93
  scrimColor: scrimColor,
94
+ scrimOpacities: resolvedScrimOpacity,
89
95
  onIndexChange: handleIndexChange,
90
96
  onSettle: handleSettle,
91
97
  onPositionChange: handlePositionChange,
@@ -1 +1 @@
1
- {"version":3,"names":["StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","BottomSheetSurfaceNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","surface","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","modal","disableScrollableNegotiation","scrimColor","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","handleIndexChange","event","nativeEvent","handleSettle","handlePositionChange","position","sheet","absoluteFill","pointerEvents","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["StyleSheet","View","useWindowDimensions","useSafeAreaInsets","BottomSheetNativeComponent","BottomSheetSurfaceNativeComponent","Portal","jsx","_jsx","jsxs","_jsxs","programmatic","BottomSheet","children","surface","style","detents","index","animateIn","onIndexChange","onSettle","onPositionChange","modal","disableScrollableNegotiation","scrimColor","scrimOpacities","height","windowHeight","insets","maxHeight","top","nativeDetents","map","detent","isDetentProgrammatic","value","resolveDetentValue","kind","Math","max","min","clampedIndex","length","selectedDetentValue","isCollapsed","resolvedScrimOpacity","handleIndexChange","event","nativeEvent","handleSettle","handlePositionChange","position","sheet","absoluteFill","pointerEvents","left","right","bottom","maxDetentHeight","collapsable","flex"],"sourceRoot":"../../src","sources":["BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -19,6 +19,7 @@ export interface NativeProps extends ViewProps {
19
19
  modal: boolean;
20
20
  disableScrollableNegotiation?: boolean;
21
21
  scrimColor?: ColorValue;
22
+ scrimOpacities?: ReadonlyArray<CodegenTypes.Double>;
22
23
  onIndexChange?: CodegenTypes.DirectEventHandler<
23
24
  Readonly<{ index: CodegenTypes.Int32 }>
24
25
  >;
@@ -45,7 +45,21 @@ export interface BottomSheetProps {
45
45
  disableScrollableNegotiation?: boolean;
46
46
  /** Scrim color used by `ModalBottomSheet`. */
47
47
  scrimColor?: string;
48
+ /**
49
+ * Scrim opacities per detent, indexed to match `detents`. Each value in 0–1
50
+ * scales the scrim color’s alpha at the detent of the same index, and the
51
+ * opacity is linearly interpolated as the sheet is dragged between detents.
52
+ * A shorter array than `detents` reuses its last value for any remaining
53
+ * detents.
54
+ *
55
+ * The default maps each detent to 0 when it is closed and 1 otherwise,
56
+ * so the scrim is transparent at any closed detent and fully opaque at every
57
+ * open one; e.g., `[0, 'content']` defaults to `[0, 1]`, and all-open detents
58
+ * default to a constant opaque scrim. Pass one value per detent—e.g.,
59
+ * `[0, 0.5, 1]`—to keep the scrim deepening across every detent.
60
+ */
61
+ scrimOpacities?: number[];
48
62
  }
49
63
  /** Native bottom sheet that renders inline within the current screen layout. */
50
- export declare const BottomSheet: ({ children, surface, style, detents, index, animateIn, onIndexChange, onSettle, onPositionChange, modal, disableScrollableNegotiation, scrimColor, }: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
64
+ export declare const BottomSheet: ({ children, surface, style, detents, index, animateIn, onIndexChange, onSettle, onPositionChange, modal, disableScrollableNegotiation, scrimColor, scrimOpacities, }: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
51
65
  //# sourceMappingURL=BottomSheet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gFAAgF;AAChF,eAAO,MAAM,WAAW,GAAI,sJAazB,gBAAgB,4CAiGlB,CAAC"}
1
+ {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,gFAAgF;AAChF,eAAO,MAAM,WAAW,GAAI,sKAczB,gBAAgB,4CAwGlB,CAAC"}
@@ -12,6 +12,7 @@ export interface NativeProps extends ViewProps {
12
12
  modal: boolean;
13
13
  disableScrollableNegotiation?: boolean;
14
14
  scrimColor?: ColorValue;
15
+ scrimOpacities?: ReadonlyArray<CodegenTypes.Double>;
15
16
  onIndexChange?: CodegenTypes.DirectEventHandler<Readonly<{
16
17
  index: CodegenTypes.Int32;
17
18
  }>>;
@@ -1 +1 @@
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,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,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,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,eAAe,EAAE,YAAY,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;IAC1B,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC7C,QAAQ,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAA;KAAE,CAAC,CACxC,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,CAAC,kBAAkB,CACxC,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/react-native-bottom-sheet",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
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",
@@ -52,6 +52,20 @@ export interface BottomSheetProps {
52
52
  disableScrollableNegotiation?: boolean;
53
53
  /** Scrim color used by `ModalBottomSheet`. */
54
54
  scrimColor?: string;
55
+ /**
56
+ * Scrim opacities per detent, indexed to match `detents`. Each value in 0–1
57
+ * scales the scrim color’s alpha at the detent of the same index, and the
58
+ * opacity is linearly interpolated as the sheet is dragged between detents.
59
+ * A shorter array than `detents` reuses its last value for any remaining
60
+ * detents.
61
+ *
62
+ * The default maps each detent to 0 when it is closed and 1 otherwise,
63
+ * so the scrim is transparent at any closed detent and fully opaque at every
64
+ * open one; e.g., `[0, 'content']` defaults to `[0, 1]`, and all-open detents
65
+ * default to a constant opaque scrim. Pass one value per detent—e.g.,
66
+ * `[0, 0.5, 1]`—to keep the scrim deepening across every detent.
67
+ */
68
+ scrimOpacities?: number[];
55
69
  }
56
70
 
57
71
  /** Native bottom sheet that renders inline within the current screen layout. */
@@ -68,6 +82,7 @@ export const BottomSheet = ({
68
82
  modal = false,
69
83
  disableScrollableNegotiation = false,
70
84
  scrimColor,
85
+ scrimOpacities,
71
86
  }: BottomSheetProps) => {
72
87
  const { height: windowHeight } = useWindowDimensions();
73
88
  const insets = useSafeAreaInsets();
@@ -96,6 +111,12 @@ export const BottomSheet = ({
96
111
  ? resolveDetentValue(detents[clampedIndex])
97
112
  : 0;
98
113
  const isCollapsed = selectedDetentValue === 0;
114
+ // Default the scrim opacity per detent: transparent at any closed detent,
115
+ // fully opaque at every open one. Mapping each detent independently keeps
116
+ // this correct regardless of the order detents are passed in.
117
+ const resolvedScrimOpacity =
118
+ scrimOpacities ??
119
+ detents.map((detent) => (resolveDetentValue(detent) === 0 ? 0 : 1));
99
120
  const handleIndexChange = (event: { nativeEvent: { index: number } }) => {
100
121
  onIndexChange?.(event.nativeEvent.index);
101
122
  };
@@ -138,6 +159,7 @@ export const BottomSheet = ({
138
159
  modal={modal}
139
160
  disableScrollableNegotiation={disableScrollableNegotiation}
140
161
  scrimColor={scrimColor}
162
+ scrimOpacities={resolvedScrimOpacity}
141
163
  onIndexChange={handleIndexChange}
142
164
  onSettle={handleSettle}
143
165
  onPositionChange={handlePositionChange}
@@ -19,6 +19,7 @@ export interface NativeProps extends ViewProps {
19
19
  modal: boolean;
20
20
  disableScrollableNegotiation?: boolean;
21
21
  scrimColor?: ColorValue;
22
+ scrimOpacities?: ReadonlyArray<CodegenTypes.Double>;
22
23
  onIndexChange?: CodegenTypes.DirectEventHandler<
23
24
  Readonly<{ index: CodegenTypes.Int32 }>
24
25
  >;