@jobber/components-native 0.98.5 → 0.100.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.
Files changed (72) hide show
  1. package/dist/package.json +3 -6
  2. package/dist/src/AtlantisOverlayProvider/AtlantisOverlayProvider.js +5 -0
  3. package/dist/src/AtlantisOverlayProvider/index.js +1 -0
  4. package/dist/src/BottomSheet/BottomSheet.js +9 -11
  5. package/dist/src/BottomSheet/hooks/useBottomSheetBackHandler.js +2 -2
  6. package/dist/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.js +9 -11
  7. package/dist/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.js +19 -0
  8. package/dist/src/ContentOverlay/ContentOverlay.js +143 -107
  9. package/dist/src/ContentOverlay/ContentOverlay.style.js +8 -12
  10. package/dist/src/ContentOverlay/computeContentOverlayBehavior.js +76 -0
  11. package/dist/src/ContentOverlay/constants.js +1 -0
  12. package/dist/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.js +25 -0
  13. package/dist/src/ContentOverlay/index.js +1 -1
  14. package/dist/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.js +7 -9
  15. package/dist/src/InputText/InputText.js +44 -1
  16. package/dist/src/index.js +1 -0
  17. package/dist/src/utils/meta/meta.json +1 -0
  18. package/dist/tsconfig.build.tsbuildinfo +1 -1
  19. package/dist/types/src/AtlantisOverlayProvider/AtlantisOverlayProvider.d.ts +6 -0
  20. package/dist/types/src/AtlantisOverlayProvider/index.d.ts +1 -0
  21. package/dist/types/src/BottomSheet/hooks/useBottomSheetBackHandler.d.ts +3 -3
  22. package/dist/types/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.d.ts +11 -0
  23. package/dist/types/src/ContentOverlay/ContentOverlay.d.ts +2 -5
  24. package/dist/types/src/ContentOverlay/ContentOverlay.style.d.ts +11 -10
  25. package/dist/types/src/ContentOverlay/computeContentOverlayBehavior.d.ts +32 -0
  26. package/dist/types/src/ContentOverlay/constants.d.ts +1 -0
  27. package/dist/types/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.d.ts +7 -0
  28. package/dist/types/src/ContentOverlay/index.d.ts +1 -1
  29. package/dist/types/src/ContentOverlay/types.d.ts +5 -12
  30. package/dist/types/src/index.d.ts +1 -0
  31. package/jestSetup.js +2 -0
  32. package/package.json +3 -6
  33. package/src/AtlantisOverlayProvider/AtlantisOverlayProvider.tsx +12 -0
  34. package/src/AtlantisOverlayProvider/index.ts +1 -0
  35. package/src/BottomSheet/BottomSheet.tsx +13 -13
  36. package/src/BottomSheet/hooks/useBottomSheetBackHandler.test.ts +10 -10
  37. package/src/BottomSheet/hooks/useBottomSheetBackHandler.ts +4 -4
  38. package/src/ButtonGroup/ButtonGroup.stories.tsx +10 -8
  39. package/src/ButtonGroup/ButtonGroup.test.tsx +7 -10
  40. package/src/ButtonGroup/components/SecondaryActionSheet/SecondaryActionSheet.tsx +26 -29
  41. package/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.tsx +36 -0
  42. package/src/ContentOverlay/ContentOverlay.stories.tsx +32 -36
  43. package/src/ContentOverlay/ContentOverlay.style.ts +12 -12
  44. package/src/ContentOverlay/ContentOverlay.test.tsx +157 -79
  45. package/src/ContentOverlay/ContentOverlay.tsx +247 -205
  46. package/src/ContentOverlay/computeContentOverlayBehavior.test.ts +276 -0
  47. package/src/ContentOverlay/computeContentOverlayBehavior.ts +119 -0
  48. package/src/ContentOverlay/constants.ts +1 -0
  49. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.test.ts +81 -0
  50. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.ts +36 -0
  51. package/src/ContentOverlay/index.ts +4 -1
  52. package/src/ContentOverlay/types.ts +5 -13
  53. package/src/Form/Form.stories.tsx +8 -4
  54. package/src/Form/Form.test.tsx +51 -54
  55. package/src/Form/components/FormSaveButton/FormSaveButton.test.tsx +7 -10
  56. package/src/FormatFile/FormatFile.stories.tsx +3 -4
  57. package/src/FormatFile/FormatFile.test.tsx +11 -14
  58. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.tsx +6 -9
  59. package/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.tsx +21 -24
  60. package/src/InputDate/InputDate.test.tsx +5 -8
  61. package/src/InputText/InputText.test.tsx +122 -0
  62. package/src/InputText/InputText.tsx +62 -2
  63. package/src/InputTime/InputTime.stories.tsx +8 -4
  64. package/src/InputTime/InputTime.test.tsx +5 -8
  65. package/src/ThumbnailList/ThumbnailList.stories.tsx +6 -4
  66. package/src/ThumbnailList/ThumbnailList.test.tsx +5 -8
  67. package/src/ThumbnailList/__snapshots__/ThumbnailList.test.tsx.snap +101 -150
  68. package/src/index.ts +1 -0
  69. package/src/utils/meta/meta.json +2 -1
  70. package/dist/src/ContentOverlay/UNSAFE_WrappedModalize.js +0 -23
  71. package/dist/types/src/ContentOverlay/UNSAFE_WrappedModalize.d.ts +0 -3
  72. package/src/ContentOverlay/UNSAFE_WrappedModalize.tsx +0 -41
@@ -1,228 +1,230 @@
1
- import type { Ref } from "react";
2
1
  import React, {
3
- forwardRef,
4
- useCallback,
2
+ createContext,
3
+ useContext,
5
4
  useImperativeHandle,
6
5
  useMemo,
7
6
  useRef,
8
7
  useState,
9
8
  } from "react";
10
- import type { Modalize } from "react-native-modalize";
11
- import { useSafeAreaInsets } from "react-native-safe-area-context";
12
- import type { NativeScrollEvent, NativeSyntheticEvent } from "react-native";
13
9
  import {
14
10
  AccessibilityInfo,
15
- Platform,
16
11
  View,
17
12
  findNodeHandle,
18
13
  useWindowDimensions,
19
14
  } from "react-native";
20
- import { Portal } from "react-native-portalize";
21
- import { useKeyboardVisibility } from "./hooks/useKeyboardVisibility";
22
- import { useStyles } from "./ContentOverlay.style";
23
- import { useViewLayoutHeight } from "./hooks/useViewLayoutHeight";
15
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
16
+ import {
17
+ BottomSheetBackdrop,
18
+ BottomSheetModal,
19
+ BottomSheetView,
20
+ } from "@gorhom/bottom-sheet";
24
21
  import type {
25
- ContentOverlayProps,
26
- ContentOverlayRef,
27
- ModalBackgroundColor,
28
- } from "./types";
29
- import { UNSAFE_WrappedModalize } from "./UNSAFE_WrappedModalize";
22
+ BottomSheetBackdropProps,
23
+ BottomSheetModal as BottomSheetModalType,
24
+ BottomSheetScrollViewMethods,
25
+ } from "@gorhom/bottom-sheet";
26
+ import { BottomSheetKeyboardAwareScrollView } from "./BottomSheetKeyboardAwareScrollView";
27
+ import type { ContentOverlayProps, ModalBackgroundColor } from "./types";
28
+ import { useStyles } from "./ContentOverlay.style";
29
+ import { useBottomSheetModalBackHandler } from "./hooks/useBottomSheetModalBackHandler";
30
+ import { computeContentOverlayBehavior } from "./computeContentOverlayBehavior";
31
+ import { KEYBOARD_TOP_PADDING_AUTO_SCROLL } from "./constants";
30
32
  import { useIsScreenReaderEnabled } from "../hooks";
31
33
  import { IconButton } from "../IconButton";
32
34
  import { Heading } from "../Heading";
33
35
  import { useAtlantisI18n } from "../hooks/useAtlantisI18n";
34
36
  import { useAtlantisTheme } from "../AtlantisThemeContext";
35
37
 
36
- export const ContentOverlay = forwardRef(ContentOverlayPortal);
37
- const ContentOverlayModal = forwardRef(ContentOverlayInternal);
38
+ /**
39
+ * Signals whether keyboard handling inside a ContentOverlay is delegated to
40
+ * a keyboard-aware scroll view (e.g. BottomSheetKeyboardAwareScrollView).
41
+ *
42
+ * When `true`, InputText skips registering with the bottom-sheet's internal
43
+ * keyboard state so that only the scroll view manages keyboard offset —
44
+ * preventing double-counted spacing.
45
+ */
46
+ const ContentOverlayKeyboardContext = createContext(false);
38
47
 
39
- // eslint-disable-next-line max-statements
40
- function ContentOverlayInternal(
41
- {
42
- children,
43
- title,
44
- accessibilityLabel,
45
- fullScreen = false,
46
- showDismiss = false,
47
- isDraggable = true,
48
- adjustToContentHeight = false,
49
- keyboardShouldPersistTaps = false,
50
- keyboardAvoidingBehavior,
51
- scrollEnabled = false,
52
- modalBackgroundColor = "surface",
53
- onClose,
54
- onOpen,
55
- onBeforeExit,
56
- loading = false,
57
- avoidKeyboardLikeIOS,
58
- }: ContentOverlayProps,
59
- ref: Ref<ContentOverlayRef>,
48
+ export function useIsKeyboardHandledByScrollView() {
49
+ return useContext(ContentOverlayKeyboardContext);
50
+ }
51
+
52
+ const LARGE_SCREEN_BREAKPOINT = 640;
53
+
54
+ function getModalBackgroundColor(
55
+ variation: ModalBackgroundColor,
56
+ tokens: ReturnType<typeof useAtlantisTheme>["tokens"],
60
57
  ) {
61
- isDraggable = onBeforeExit ? false : isDraggable;
62
- const isCloseableOnOverlayTap = onBeforeExit ? false : true;
58
+ switch (variation) {
59
+ case "surface":
60
+ return tokens["color-surface"];
61
+ case "background":
62
+ return tokens["color-surface--background"];
63
+ }
64
+ }
65
+
66
+ // eslint-disable-next-line max-statements
67
+ export function ContentOverlay({
68
+ children,
69
+ title,
70
+ accessibilityLabel,
71
+ fullScreen = false,
72
+ showDismiss = false,
73
+ isDraggable = true,
74
+ adjustToContentHeight = false,
75
+ keyboardShouldPersistTaps = false,
76
+ scrollEnabled = false,
77
+ modalBackgroundColor = "surface",
78
+ onClose,
79
+ onOpen,
80
+ onBeforeExit,
81
+ loading = false,
82
+ ref,
83
+ }: ContentOverlayProps) {
84
+ const insets = useSafeAreaInsets();
85
+ const { width: windowWidth } = useWindowDimensions();
86
+ const bottomSheetModalRef = useRef<BottomSheetModalType>(null);
87
+ const previousIndexRef = useRef(-1);
88
+ const [currentPosition, setCurrentPosition] = useState<number>(-1);
89
+
90
+ const styles = useStyles();
63
91
  const { t } = useAtlantisI18n();
64
92
  const { tokens } = useAtlantisTheme();
65
- const { width: windowWidth, height: windowHeight } = useWindowDimensions();
66
- const insets = useSafeAreaInsets();
67
- const [position, setPosition] = useState<"top" | "initial">("initial");
68
93
  const isScreenReaderEnabled = useIsScreenReaderEnabled();
69
- const isFullScreenOrTopPosition =
70
- fullScreen || (!adjustToContentHeight && position === "top");
71
- const shouldShowDismiss =
72
- showDismiss || isScreenReaderEnabled || isFullScreenOrTopPosition;
94
+
95
+ const behavior = computeContentOverlayBehavior(
96
+ {
97
+ fullScreen,
98
+ adjustToContentHeight,
99
+ isDraggable,
100
+ hasOnBeforeExit: onBeforeExit !== undefined,
101
+ showDismiss,
102
+ },
103
+ {
104
+ isScreenReaderEnabled,
105
+ position: currentPosition,
106
+ },
107
+ );
108
+
109
+ const effectiveIsDraggable = behavior.isDraggable;
110
+ const shouldShowDismiss = behavior.showDismiss;
111
+ const isCloseableOnOverlayTap = onBeforeExit === undefined;
112
+
113
+ // Prevent the Overlay from being flush with the top of the screen, even if we are "100%" or "fullscreen"
114
+ const topInset = insets.top || tokens["space-larger"];
115
+
73
116
  const [showHeaderShadow, setShowHeaderShadow] = useState<boolean>(false);
74
117
  const overlayHeader = useRef<View>(null);
118
+ const scrollViewRef = useRef<
119
+ BottomSheetScrollViewMethods & { scrollTop?: number }
120
+ >(null);
75
121
 
76
- const internalRef = useRef<Modalize>(null);
77
- const [modalizeMethods, setModalizeMethods] = useState<ContentOverlayRef>();
78
- const callbackInternalRef = useCallback((instance: Modalize) => {
79
- if (instance && !internalRef.current) {
80
- internalRef.current = instance;
81
- setModalizeMethods(instance);
82
- }
122
+ // enableDynamicSizing will add another snap point of the content height
123
+ const snapPoints = useMemo(() => {
124
+ // There is a bug with "restore" behavior after keyboard is dismissed.
125
+ // https://github.com/gorhom/react-native-bottom-sheet/issues/2465
126
+ // providing a 100% snap point "fixes" it for now, but there is an approved PR to fix it
127
+ // that just needs to be merged and released: https://github.com/gorhom/react-native-bottom-sheet/pull/2511
128
+ return ["100%"];
83
129
  }, []);
84
130
 
85
- const refMethods = useMemo(() => {
86
- if (!modalizeMethods?.open || !modalizeMethods?.close) {
87
- return {};
131
+ const onCloseController = () => {
132
+ if (!onBeforeExit) {
133
+ bottomSheetModalRef.current?.dismiss();
134
+ } else {
135
+ onBeforeExit();
88
136
  }
137
+ };
89
138
 
90
- return {
91
- open: modalizeMethods?.open,
92
- close: modalizeMethods?.close,
93
- };
94
- }, [modalizeMethods]);
95
-
96
- const { keyboardHeight } = useKeyboardVisibility();
97
- useImperativeHandle(ref, () => refMethods, [refMethods]);
98
-
99
- const {
100
- handleLayout: handleChildrenLayout,
101
- height: childrenHeight,
102
- heightKnown: childrenHeightKnown,
103
- } = useViewLayoutHeight();
104
- const {
105
- handleLayout: handleHeaderLayout,
106
- height: headerHeight,
107
- heightKnown: headerHeightKnown,
108
- } = useViewLayoutHeight();
109
-
110
- const snapPoint = useMemo(() => {
111
- if (fullScreen || !isDraggable || adjustToContentHeight) {
112
- return undefined;
113
- }
114
- const overlayHeight = headerHeight + childrenHeight;
139
+ const { handleSheetPositionChange } =
140
+ useBottomSheetModalBackHandler(onCloseController);
115
141
 
116
- if (overlayHeight >= windowHeight) {
117
- return undefined;
118
- }
142
+ useImperativeHandle(
143
+ ref,
144
+ () => ({
145
+ open: () => {
146
+ bottomSheetModalRef.current?.present();
147
+ },
148
+ close: () => {
149
+ bottomSheetModalRef.current?.dismiss();
150
+ },
151
+ }),
152
+ [],
153
+ );
119
154
 
120
- return overlayHeight;
121
- }, [
122
- fullScreen,
123
- isDraggable,
124
- adjustToContentHeight,
125
- headerHeight,
126
- childrenHeight,
127
- windowHeight,
128
- ]);
155
+ const handleChange = (index: number, position: number) => {
156
+ const previousIndex = previousIndexRef.current;
129
157
 
130
- const styles = useStyles();
158
+ setCurrentPosition(position);
159
+ handleSheetPositionChange(index);
131
160
 
132
- const modalStyle = [
133
- styles.modal,
134
- windowWidth > 640 ? styles.modalForLargeScreens : undefined,
135
- { backgroundColor: getModalBackgroundColor(modalBackgroundColor) },
136
- keyboardHeight > 0 && { marginBottom: 0 },
137
- ];
161
+ if (previousIndex === -1 && index >= 0) {
162
+ // Transitioned from closed to open
163
+ onOpen?.();
138
164
 
139
- const renderedChildren = renderChildren();
140
- const renderedHeader = renderHeader();
165
+ // Set accessibility focus on header when opened
166
+ if (overlayHeader.current) {
167
+ const reactTag = findNodeHandle(overlayHeader.current);
141
168
 
142
- const onCloseController = () => {
143
- if (!onBeforeExit) {
144
- internalRef.current?.close();
169
+ if (reactTag) {
170
+ AccessibilityInfo.setAccessibilityFocus(reactTag);
171
+ }
172
+ }
173
+ }
145
174
 
146
- return true;
147
- } else {
148
- onBeforeExit();
175
+ previousIndexRef.current = index;
176
+ };
149
177
 
150
- return false;
151
- }
178
+ const handleOnScroll = () => {
179
+ const scrollTop = scrollViewRef.current?.scrollTop || 0;
180
+ setShowHeaderShadow(scrollTop > 0);
152
181
  };
153
182
 
154
- return (
155
- <>
156
- {headerHeightKnown && childrenHeightKnown && (
157
- <UNSAFE_WrappedModalize
158
- ref={callbackInternalRef}
159
- overlayStyle={styles.overlay}
160
- handleStyle={styles.handle}
161
- handlePosition="inside"
162
- modalStyle={modalStyle}
163
- modalTopOffset={tokens["space-larger"]}
164
- snapPoint={snapPoint}
165
- closeSnapPointStraightEnabled={false}
166
- withHandle={isDraggable}
167
- panGestureEnabled={isDraggable}
168
- adjustToContentHeight={adjustToContentHeight}
169
- disableScrollIfPossible={!adjustToContentHeight} // workaround for scroll not working on Android when content fills the screen with adjustToContentHeight
170
- onClose={onClose}
171
- onOpen={onOpen}
172
- keyboardAvoidingBehavior={keyboardAvoidingBehavior}
173
- avoidKeyboardLikeIOS={avoidKeyboardLikeIOS}
174
- childrenStyle={styles.childrenStyle}
175
- onBackButtonPress={onCloseController}
176
- closeOnOverlayTap={isCloseableOnOverlayTap}
177
- onOpened={() => {
178
- if (overlayHeader.current) {
179
- const reactTag = findNodeHandle(overlayHeader.current);
180
-
181
- if (reactTag) {
182
- AccessibilityInfo.setAccessibilityFocus(reactTag);
183
- }
184
- }
185
- }}
186
- scrollViewProps={{
187
- scrollEnabled,
188
- showsVerticalScrollIndicator: false,
189
- stickyHeaderIndices: Platform.OS === "android" ? [0] : undefined,
190
- onScroll: handleOnScroll,
191
- keyboardShouldPersistTaps: keyboardShouldPersistTaps
192
- ? "handled"
193
- : "never",
194
- }}
195
- HeaderComponent={Platform.OS === "ios" ? renderedHeader : undefined}
196
- onPositionChange={setPosition}
197
- >
198
- {Platform.OS === "android" ? renderedHeader : undefined}
199
- {renderedChildren}
200
- </UNSAFE_WrappedModalize>
201
- )}
202
- {!childrenHeightKnown && (
203
- <View style={[styles.hiddenContent, modalStyle]}>
204
- {renderedChildren}
205
- </View>
206
- )}
207
- {!headerHeightKnown && (
208
- <View style={[styles.hiddenContent, modalStyle]}>{renderedHeader}</View>
209
- )}
210
- </>
183
+ const sheetStyle = useMemo(
184
+ () =>
185
+ windowWidth > LARGE_SCREEN_BREAKPOINT
186
+ ? {
187
+ width: LARGE_SCREEN_BREAKPOINT,
188
+ marginLeft: (windowWidth - LARGE_SCREEN_BREAKPOINT) / 2,
189
+ }
190
+ : undefined,
191
+ [windowWidth],
211
192
  );
212
193
 
213
- function renderHeader() {
194
+ const backgroundStyle = [
195
+ styles.background,
196
+ { backgroundColor: getModalBackgroundColor(modalBackgroundColor, tokens) },
197
+ ];
198
+
199
+ const handleIndicatorStyles = [
200
+ styles.handle,
201
+ !effectiveIsDraggable && {
202
+ opacity: 0,
203
+ },
204
+ ];
205
+
206
+ const renderHeader = () => {
214
207
  const closeOverlayA11YLabel = t("ContentOverlay.close", {
215
208
  title: title,
216
209
  });
217
210
 
218
211
  const headerStyles = [
219
212
  styles.header,
213
+ {
214
+ // Background color is necessary for scrollable modals as the content flows behind the header.
215
+ backgroundColor: getModalBackgroundColor(modalBackgroundColor, tokens),
216
+ },
217
+ ];
218
+
219
+ const headerShadowStyles = [
220
220
  showHeaderShadow && styles.headerShadow,
221
- { backgroundColor: getModalBackgroundColor(modalBackgroundColor) },
221
+ {
222
+ backgroundColor: getModalBackgroundColor(modalBackgroundColor, tokens),
223
+ },
222
224
  ];
223
225
 
224
226
  return (
225
- <View onLayout={handleHeaderLayout} testID="ATL-Overlay-Header">
227
+ <View testID="ATL-Overlay-Header">
226
228
  <View style={headerStyles}>
227
229
  <View
228
230
  style={[
@@ -260,45 +262,85 @@ function ContentOverlayInternal(
260
262
  </View>
261
263
  )}
262
264
  </View>
265
+ <View>
266
+ <View style={headerShadowStyles} />
267
+ </View>
263
268
  </View>
264
269
  );
265
- }
266
-
267
- function renderChildren() {
268
- return (
269
- <View
270
- style={{ paddingBottom: insets.bottom }}
271
- onLayout={handleChildrenLayout}
272
- testID="ATL-Overlay-Children"
273
- >
274
- {children}
275
- </View>
276
- );
277
- }
278
-
279
- function handleOnScroll({
280
- nativeEvent,
281
- }: NativeSyntheticEvent<NativeScrollEvent>) {
282
- setShowHeaderShadow(nativeEvent.contentOffset.y > 0);
283
- }
270
+ };
284
271
 
285
- function getModalBackgroundColor(variation: ModalBackgroundColor) {
286
- switch (variation) {
287
- case "surface":
288
- return tokens["color-surface"];
289
- case "background":
290
- return tokens["color-surface--background"];
291
- }
292
- }
272
+ return (
273
+ <BottomSheetModal
274
+ ref={bottomSheetModalRef}
275
+ onChange={handleChange}
276
+ style={sheetStyle}
277
+ backgroundStyle={backgroundStyle}
278
+ handleStyle={styles.handleWrapper}
279
+ handleIndicatorStyle={handleIndicatorStyles}
280
+ backdropComponent={props => (
281
+ <Backdrop
282
+ {...props}
283
+ pressBehavior={isCloseableOnOverlayTap ? "close" : "none"}
284
+ />
285
+ )}
286
+ snapPoints={snapPoints}
287
+ enablePanDownToClose={effectiveIsDraggable}
288
+ enableContentPanningGesture={effectiveIsDraggable}
289
+ enableHandlePanningGesture={effectiveIsDraggable}
290
+ enableDynamicSizing={behavior.initialHeight === "contentHeight"}
291
+ keyboardBehavior="interactive"
292
+ keyboardBlurBehavior="restore"
293
+ topInset={topInset}
294
+ onDismiss={() => onClose?.()}
295
+ >
296
+ <ContentOverlayKeyboardContext.Provider value={scrollEnabled}>
297
+ {scrollEnabled ? (
298
+ <BottomSheetKeyboardAwareScrollView
299
+ ref={scrollViewRef}
300
+ contentContainerStyle={{ paddingBottom: insets.bottom }}
301
+ keyboardShouldPersistTaps={
302
+ keyboardShouldPersistTaps ? "handled" : "never"
303
+ }
304
+ showsVerticalScrollIndicator={false}
305
+ onScroll={handleOnScroll}
306
+ stickyHeaderIndices={[0]}
307
+ bottomOffset={KEYBOARD_TOP_PADDING_AUTO_SCROLL}
308
+ >
309
+ {renderHeader()}
310
+ <View testID="ATL-Overlay-Children">{children}</View>
311
+ </BottomSheetKeyboardAwareScrollView>
312
+ ) : (
313
+ <BottomSheetView>
314
+ {renderHeader()}
315
+ <View
316
+ style={{ paddingBottom: insets.bottom }}
317
+ testID="ATL-Overlay-Children"
318
+ >
319
+ {children}
320
+ </View>
321
+ </BottomSheetView>
322
+ )}
323
+ </ContentOverlayKeyboardContext.Provider>
324
+ </BottomSheetModal>
325
+ );
293
326
  }
294
327
 
295
- function ContentOverlayPortal(
296
- modalProps: ContentOverlayProps,
297
- ref: Ref<ContentOverlayRef>,
328
+ function Backdrop(
329
+ bottomSheetBackdropProps: BottomSheetBackdropProps & {
330
+ pressBehavior: "none" | "close";
331
+ },
298
332
  ) {
333
+ const styles = useStyles();
334
+ const { pressBehavior, ...props } = bottomSheetBackdropProps;
335
+
299
336
  return (
300
- <Portal>
301
- <ContentOverlayModal ref={ref} {...modalProps} />
302
- </Portal>
337
+ <BottomSheetBackdrop
338
+ {...props}
339
+ appearsOnIndex={0}
340
+ disappearsOnIndex={-1}
341
+ style={styles.backdrop}
342
+ opacity={1}
343
+ pressBehavior={pressBehavior}
344
+ />
303
345
  );
304
346
  }