@swmansion/react-native-bottom-sheet 0.15.0-next.5 → 0.15.0-next.7

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.
@@ -89,19 +89,28 @@ export interface BottomSheetProps {
89
89
  wrapNativeView?: (
90
90
  component: ComponentType<NativeProps>
91
91
  ) => ComponentType<NativeProps>;
92
- /** Internal flag used by `ModalBottomSheet`. */
93
- modal?: boolean;
94
92
  /**
95
93
  * Escape hatch that disables sheet/list gesture negotiation.
96
94
  * If a gesture starts inside a nested scrollable, that scrollable keeps it
97
95
  * even when it cannot scroll any further.
98
96
  */
99
97
  disableScrollableNegotiation?: boolean;
98
+ }
99
+
100
+ type ModalOnlyBottomSheetProps = {
101
+ /** Internal flag used by `ModalBottomSheet`. */
102
+ modal?: boolean;
103
+ /**
104
+ * Internal flag used by `ModalBottomSheet`. When set, the sheet is presented
105
+ * in a native overlay above everything (including native modal screens)
106
+ * instead of the `BottomSheetProvider` portal.
107
+ */
108
+ nativeOverlay?: boolean;
100
109
  /** Scrim color used by `ModalBottomSheet`. */
101
110
  scrimColor?: string;
102
111
  /**
103
- * Scrim opacities per detent, indexed to match `detents`. Each value in 01
104
- * scales the scrim colors alpha at the detent of the same index, and the
112
+ * Scrim opacities per detent, indexed to match `detents`. Each value in 0-1
113
+ * scales the scrim color's alpha at the detent of the same index, and the
105
114
  * opacity is linearly interpolated as the sheet is dragged between detents.
106
115
  * A shorter array than `detents` reuses its last value for any remaining
107
116
  * detents.
@@ -109,29 +118,34 @@ export interface BottomSheetProps {
109
118
  * The default maps each detent to 0 when it is closed and 1 otherwise,
110
119
  * so the scrim is transparent at any closed detent and fully opaque at every
111
120
  * open one; e.g., `[0, 'content']` defaults to `[0, 1]`, and all-open detents
112
- * default to a constant opaque scrim. Pass one value per detente.g.,
113
- * `[0, 0.5, 1]`—to keep the scrim deepening across every detent.
121
+ * default to a constant opaque scrim. Pass one value per detent, e.g.
122
+ * `[0, 0.5, 1]`, to keep the scrim deepening across every detent.
114
123
  */
115
124
  scrimOpacities?: number[];
116
- }
125
+ };
126
+
127
+ export type BottomSheetInternalProps = BottomSheetProps &
128
+ ModalOnlyBottomSheetProps;
117
129
 
118
130
  /** Native bottom sheet that renders inline within the current screen layout. */
119
- export const BottomSheet = ({
120
- children,
121
- surface,
122
- style,
123
- detents = [0, 'content'],
124
- index,
125
- animateIn = true,
126
- onIndexChange,
127
- onSettle,
128
- onPositionChange,
129
- wrapNativeView,
130
- modal = false,
131
- disableScrollableNegotiation = false,
132
- scrimColor,
133
- scrimOpacities,
134
- }: BottomSheetProps) => {
131
+ export const BottomSheet = (props: BottomSheetProps) => {
132
+ const {
133
+ children,
134
+ surface,
135
+ style,
136
+ detents = [0, 'content'],
137
+ index,
138
+ animateIn = true,
139
+ onIndexChange,
140
+ onSettle,
141
+ onPositionChange,
142
+ wrapNativeView,
143
+ modal = false,
144
+ nativeOverlay = false,
145
+ disableScrollableNegotiation = false,
146
+ scrimColor,
147
+ scrimOpacities,
148
+ } = props as BottomSheetInternalProps;
135
149
  const { height: windowHeight } = useSafeAreaFrame();
136
150
  const insets = useSafeAreaInsets();
137
151
  const maxHeight = windowHeight - insets.top;
@@ -165,6 +179,7 @@ export const BottomSheet = ({
165
179
  const resolvedScrimOpacity =
166
180
  scrimOpacities ??
167
181
  detents.map((detent) => (resolveDetentValue(detent) === 0 ? 0 : 1));
182
+ const usesNativeOverlay = modal && nativeOverlay;
168
183
  const handleIndexChange = (event: { nativeEvent: { index: number } }) => {
169
184
  onIndexChange?.(event.nativeEvent.index);
170
185
  };
@@ -213,6 +228,7 @@ export const BottomSheet = ({
213
228
  index={index}
214
229
  animateIn={animateIn}
215
230
  modal={modal}
231
+ nativeOverlay={usesNativeOverlay}
216
232
  disableScrollableNegotiation={disableScrollableNegotiation}
217
233
  scrimColor={scrimColor}
218
234
  scrimOpacities={resolvedScrimOpacity}
@@ -239,6 +255,12 @@ export const BottomSheet = ({
239
255
  );
240
256
 
241
257
  if (modal) {
258
+ // In native-overlay mode the sheet is rendered inline; the native layer
259
+ // reparents it into a full-screen overlay above everything (including
260
+ // native modal screens), so it bypasses the provider portal entirely.
261
+ if (usesNativeOverlay) {
262
+ return sheet;
263
+ }
242
264
  return <Portal>{sheet}</Portal>;
243
265
  }
244
266
 
@@ -17,6 +17,7 @@ export interface NativeProps extends ViewProps {
17
17
  index: CodegenTypes.Int32;
18
18
  animateIn?: CodegenTypes.WithDefault<boolean, true>;
19
19
  modal: boolean;
20
+ nativeOverlay?: boolean;
20
21
  disableScrollableNegotiation?: boolean;
21
22
  scrimColor?: ColorValue;
22
23
  scrimOpacities?: ReadonlyArray<CodegenTypes.Double>;
@@ -1,12 +1,54 @@
1
- import { BottomSheet, type BottomSheetProps } from './BottomSheet';
1
+ import { createElement } from 'react';
2
+
3
+ import {
4
+ BottomSheet,
5
+ type BottomSheetInternalProps,
6
+ type BottomSheetProps,
7
+ } from './BottomSheet';
2
8
 
3
9
  /** Props for the modal bottom-sheet variant rendered through the provider portal. */
4
- export interface ModalBottomSheetProps extends Omit<
5
- BottomSheetProps,
6
- 'modal'
7
- > {}
10
+ export interface ModalBottomSheetProps extends BottomSheetProps {
11
+ /**
12
+ * Present the sheet in a native overlay above everything—including native
13
+ * modal screens (e.g. a React Navigation native-stack `presentation: "modal"`)
14
+ * —instead of the `BottomSheetProvider` portal.
15
+ *
16
+ * The portal renders into the provider's React tree, so a sheet opened from
17
+ * within a native modal screen is trapped inside that screen and cannot cover
18
+ * the full window. With `nativeOverlay`, the sheet is reparented natively into
19
+ * a window-level overlay (a `UIWindow`-attached container on iOS, a
20
+ * full-screen transparent dialog on Android) that floats above the modal.
21
+ *
22
+ * No `BottomSheetProvider` is required in this mode. The sheet sizes relative
23
+ * to its nearest full-size ancestor, so render it at the top level of a screen
24
+ * as you normally would.
25
+ *
26
+ * @default false
27
+ */
28
+ nativeOverlay?: boolean;
29
+ /** Scrim color shown behind the modal sheet. */
30
+ scrimColor?: string;
31
+ /**
32
+ * Scrim opacities per detent, indexed to match `detents`. Each value in 0-1
33
+ * scales the scrim color's alpha at the detent of the same index, and the
34
+ * opacity is linearly interpolated as the sheet is dragged between detents.
35
+ * A shorter array than `detents` reuses its last value for any remaining
36
+ * detents.
37
+ *
38
+ * The default maps each detent to 0 when it is closed and 1 otherwise,
39
+ * so the scrim is transparent at any closed detent and fully opaque at every
40
+ * open one; e.g., `[0, 'content']` defaults to `[0, 1]`, and all-open detents
41
+ * default to a constant opaque scrim. Pass one value per detent, e.g.
42
+ * `[0, 0.5, 1]`, to keep the scrim deepening across every detent.
43
+ */
44
+ scrimOpacities?: number[];
45
+ }
8
46
 
9
47
  /** Bottom sheet presented above the current UI with a scrim. */
10
- export const ModalBottomSheet = (props: ModalBottomSheetProps) => (
11
- <BottomSheet {...props} modal />
12
- );
48
+ export const ModalBottomSheet = (props: ModalBottomSheetProps) => {
49
+ // `modal` lives on the internal prop set (it is hidden from the public
50
+ // `BottomSheet` type), so type the merged object as the internal shape rather
51
+ // than casting it away.
52
+ const internalProps: BottomSheetInternalProps = { ...props, modal: true };
53
+ return createElement(BottomSheet, internalProps);
54
+ };