@jobber/components-native 0.95.4-improve-co-ca924fd.14 → 0.95.4

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 (41) hide show
  1. package/dist/package.json +5 -3
  2. package/dist/src/ContentOverlay/ContentOverlay.js +107 -128
  3. package/dist/src/ContentOverlay/ContentOverlay.style.js +12 -8
  4. package/dist/src/ContentOverlay/UNSAFE_WrappedModalize.js +23 -0
  5. package/dist/src/ContentOverlay/index.js +0 -1
  6. package/dist/src/InputFieldWrapper/InputFieldWrapper.js +12 -2
  7. package/dist/src/InputText/InputText.js +2 -36
  8. package/dist/src/utils/meta/meta.json +0 -1
  9. package/dist/tsconfig.build.tsbuildinfo +1 -1
  10. package/dist/types/src/ContentOverlay/ContentOverlay.d.ts +5 -1
  11. package/dist/types/src/ContentOverlay/ContentOverlay.style.d.ts +10 -11
  12. package/dist/types/src/ContentOverlay/UNSAFE_WrappedModalize.d.ts +3 -0
  13. package/dist/types/src/ContentOverlay/index.d.ts +0 -1
  14. package/dist/types/src/ContentOverlay/types.d.ts +12 -5
  15. package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +5 -1
  16. package/jestSetup.js +0 -2
  17. package/package.json +5 -3
  18. package/src/ContentOverlay/ContentOverlay.style.ts +12 -12
  19. package/src/ContentOverlay/ContentOverlay.test.tsx +79 -157
  20. package/src/ContentOverlay/ContentOverlay.tsx +210 -223
  21. package/src/ContentOverlay/UNSAFE_WrappedModalize.tsx +41 -0
  22. package/src/ContentOverlay/index.ts +0 -1
  23. package/src/ContentOverlay/types.ts +13 -5
  24. package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +47 -0
  25. package/src/InputFieldWrapper/InputFieldWrapper.tsx +19 -1
  26. package/src/InputText/InputText.test.tsx +0 -122
  27. package/src/InputText/InputText.tsx +3 -52
  28. package/src/ThumbnailList/__snapshots__/ThumbnailList.test.tsx.snap +20 -0
  29. package/src/utils/meta/meta.json +0 -1
  30. package/dist/src/ContentOverlay/ContentOverlayProvider.js +0 -5
  31. package/dist/src/ContentOverlay/computeContentOverlayBehavior.js +0 -76
  32. package/dist/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.js +0 -25
  33. package/dist/types/src/ContentOverlay/ContentOverlayProvider.d.ts +0 -6
  34. package/dist/types/src/ContentOverlay/computeContentOverlayBehavior.d.ts +0 -32
  35. package/dist/types/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.d.ts +0 -7
  36. package/src/ContentOverlay/ContentOverlay.stories.tsx +0 -59
  37. package/src/ContentOverlay/ContentOverlayProvider.tsx +0 -12
  38. package/src/ContentOverlay/computeContentOverlayBehavior.test.ts +0 -276
  39. package/src/ContentOverlay/computeContentOverlayBehavior.ts +0 -119
  40. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.test.ts +0 -81
  41. package/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.ts +0 -36
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { StyleProp, TextStyle, ViewStyle } from "react-native";
3
- import { Text as RNText, View } from "react-native";
3
+ import { PixelRatio, Platform, Text as RNText, View } from "react-native";
4
4
  import type { FieldError } from "react-hook-form";
5
5
  import type { IconNames } from "@jobber/design";
6
6
  import { useStyles } from "./InputFieldWrapper.style";
@@ -112,6 +112,11 @@ export interface InputFieldWrapperProps {
112
112
  * Change the type of loading indicator to spinner or glimmer.
113
113
  */
114
114
  readonly loadingType?: "spinner" | "glimmer";
115
+
116
+ /**
117
+ * Whether the input is a multiline input.
118
+ */
119
+ readonly multiline?: boolean;
115
120
  }
116
121
 
117
122
  export const INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID =
@@ -138,6 +143,7 @@ export function InputFieldWrapper({
138
143
  toolbarVisibility = "while-editing",
139
144
  loading = false,
140
145
  loadingType = "spinner",
146
+ multiline = false,
141
147
  }: InputFieldWrapperProps) {
142
148
  fieldAffixRequiredPropsCheck([prefix, suffix]);
143
149
  const handleClear = onClear ?? noopClear;
@@ -163,6 +169,9 @@ export function InputFieldWrapper({
163
169
  (Boolean(invalid) || error) && styles.inputInvalid,
164
170
  disabled && styles.disabled,
165
171
  styleOverride?.container,
172
+ shouldApplyScrollTrapWorkaround(multiline) && {
173
+ maxWidth: "90%",
174
+ },
166
175
  ]}
167
176
  >
168
177
  <View style={styles.field}>
@@ -283,6 +292,15 @@ export function InputFieldWrapper({
283
292
  );
284
293
  }
285
294
 
295
+ function shouldApplyScrollTrapWorkaround(isMultiline: boolean): boolean {
296
+ const isCustomFontScale = PixelRatio.getFontScale() !== 1;
297
+
298
+ // On iOS, when the OS font scale is not default, it causes multiline inputs to become scroll-trapped
299
+ // which prevents the user from scrolling the parent form view. For now, we're working around this
300
+ // by limiting the width of the input field, thus providing a gap so the user can scroll more easily.
301
+ return isMultiline && Platform.OS === "ios" && isCustomFontScale;
302
+ }
303
+
286
304
  function getLabelVariation(
287
305
  error?: FieldError,
288
306
  invalid?: boolean | string,
@@ -836,126 +836,4 @@ describe("Transform", () => {
836
836
  });
837
837
  });
838
838
  });
839
-
840
- describe("Bottom Sheet keyboard handling integration", () => {
841
- beforeEach(() => {
842
- jest.clearAllMocks();
843
- });
844
-
845
- // eslint-disable-next-line max-statements
846
- it("updates animatedKeyboardState on focus when inside ContentOverlay", () => {
847
- const mockSet = jest.fn();
848
- const mockGet = jest.fn(() => ({ target: undefined }));
849
- const mockKeyboardState = {
850
- value: { target: undefined },
851
- set: mockSet,
852
- get: mockGet,
853
- };
854
-
855
- const mockTextInputNodesRef = { current: new Set<number>() };
856
-
857
- // Mock the useBottomSheetInternal hook to simulate being inside ContentOverlay
858
- jest
859
- .spyOn(require("@gorhom/bottom-sheet"), "useBottomSheetInternal")
860
- .mockReturnValue({
861
- animatedKeyboardState: mockKeyboardState,
862
- textInputNodesRef: mockTextInputNodesRef,
863
- });
864
-
865
- const a11yLabel = "Test InputText";
866
- const { getByLabelText } = render(
867
- <InputText accessibilityLabel={a11yLabel} />,
868
- );
869
-
870
- const input = getByLabelText(a11yLabel);
871
-
872
- fireEvent(input, "onFocus", {
873
- nativeEvent: { target: 123 },
874
- });
875
-
876
- expect(mockSet).toHaveBeenCalledWith(expect.any(Function));
877
- // Verify the set callback updates the state correctly
878
- const setCallback = mockSet.mock.calls[0][0];
879
- const newState = setCallback({ target: undefined });
880
- expect(newState).toEqual({ target: 123 });
881
- });
882
-
883
- // eslint-disable-next-line max-statements
884
- it("consumer onFocus and onBlur callbacks still fire when inside ContentOverlay", () => {
885
- const focusCallback = jest.fn();
886
- const blurCallback = jest.fn();
887
- const mockSet = jest.fn();
888
- const mockGet = jest.fn(() => ({ target: undefined }));
889
- const mockKeyboardState = {
890
- value: { target: undefined },
891
- set: mockSet,
892
- get: mockGet,
893
- };
894
-
895
- const mockTextInputNodesRef = { current: new Set<number>() };
896
-
897
- jest
898
- .spyOn(require("@gorhom/bottom-sheet"), "useBottomSheetInternal")
899
- .mockReturnValue({
900
- animatedKeyboardState: mockKeyboardState,
901
- textInputNodesRef: mockTextInputNodesRef,
902
- });
903
-
904
- const a11yLabel = "Test InputText";
905
- const { getByLabelText } = render(
906
- <InputText
907
- onFocus={focusCallback}
908
- onBlur={blurCallback}
909
- accessibilityLabel={a11yLabel}
910
- />,
911
- );
912
-
913
- const input = getByLabelText(a11yLabel);
914
-
915
- fireEvent(input, "onFocus", {
916
- nativeEvent: { target: 123 },
917
- });
918
- expect(focusCallback).toHaveBeenCalled();
919
-
920
- fireEvent(input, "onBlur", {
921
- nativeEvent: { target: 123 },
922
- });
923
- expect(blurCallback).toHaveBeenCalled();
924
- });
925
-
926
- it("handles value changes when inside ContentOverlay", () => {
927
- const mockSet = jest.fn();
928
- const mockGet = jest.fn(() => ({ target: undefined }));
929
- const mockKeyboardState = {
930
- value: { target: undefined },
931
- set: mockSet,
932
- get: mockGet,
933
- };
934
-
935
- const mockTextInputNodesRef = { current: new Set<number>() };
936
- const changeCallback = jest.fn();
937
-
938
- jest
939
- .spyOn(require("@gorhom/bottom-sheet"), "useBottomSheetInternal")
940
- .mockReturnValue({
941
- animatedKeyboardState: mockKeyboardState,
942
- textInputNodesRef: mockTextInputNodesRef,
943
- });
944
-
945
- const a11yLabel = "Test InputText";
946
- const { getByLabelText } = render(
947
- <InputText
948
- onChangeText={changeCallback}
949
- accessibilityLabel={a11yLabel}
950
- />,
951
- );
952
-
953
- const input = getByLabelText(a11yLabel);
954
-
955
- fireEvent.changeText(input, "New value");
956
-
957
- // Value changes should work normally
958
- expect(changeCallback).toHaveBeenCalledWith("New value");
959
- });
960
- });
961
839
  });
@@ -14,8 +14,7 @@ import type {
14
14
  TextInputProps,
15
15
  TextStyle,
16
16
  } from "react-native";
17
- import { Platform, TextInput, findNodeHandle } from "react-native";
18
- import { useBottomSheetInternal } from "@gorhom/bottom-sheet";
17
+ import { Platform, TextInput } from "react-native";
19
18
  import type { RegisterOptions } from "react-hook-form";
20
19
  import type { IconNames } from "@jobber/design";
21
20
  import identity from "lodash/identity";
@@ -316,11 +315,6 @@ function InputTextInternal(
316
315
  disabled,
317
316
  });
318
317
 
319
- // Bottom sheet keyboard handling - detect if we're inside a ContentOverlay
320
- const bottomSheetContext = useBottomSheetInternal(true);
321
- const animatedKeyboardState = bottomSheetContext?.animatedKeyboardState;
322
- const textInputNodesRef = bottomSheetContext?.textInputNodesRef;
323
-
324
318
  // Android doesn't have an accessibility label like iOS does. By adding
325
319
  // it as a placeholder it readds it like a label. However we don't want to
326
320
  // add a placeholder on iOS.
@@ -398,6 +392,7 @@ function InputTextInternal(
398
392
  toolbarVisibility={toolbarVisibility}
399
393
  loading={loading}
400
394
  loadingType={loadingType}
395
+ multiline={multiline}
401
396
  >
402
397
  <TextInput
403
398
  inputAccessoryViewID={inputAccessoryID || undefined}
@@ -444,13 +439,11 @@ function InputTextInternal(
444
439
  secureTextEntry={secureTextEntry}
445
440
  {...androidA11yProps}
446
441
  onFocus={event => {
447
- handleBottomSheetFocus(event);
448
442
  _name && setFocusedInput(_name);
449
443
  setFocused(true);
450
444
  onFocus?.(event);
451
445
  }}
452
446
  onBlur={event => {
453
- handleBottomSheetBlur(event);
454
447
  _name && setFocusedInput("");
455
448
  setFocused(false);
456
449
  onBlur?.(event);
@@ -477,48 +470,6 @@ function InputTextInternal(
477
470
  updateFormAndState(removedIOSCharValue);
478
471
  }
479
472
 
480
- function handleBottomSheetFocus(event?: FocusEvent) {
481
- if (!animatedKeyboardState || !textInputNodesRef || !event?.nativeEvent) {
482
- return;
483
- }
484
-
485
- animatedKeyboardState.set(state => ({
486
- ...state,
487
- target: event.nativeEvent.target,
488
- }));
489
- }
490
-
491
- function handleBottomSheetBlur(event?: FocusEvent) {
492
- if (!animatedKeyboardState || !textInputNodesRef || !event?.nativeEvent) {
493
- return;
494
- }
495
- const keyboardState = animatedKeyboardState.get();
496
- const currentlyFocusedInput = TextInput.State.currentlyFocusedInput();
497
- const currentFocusedInput =
498
- currentlyFocusedInput !== null
499
- ? findNodeHandle(
500
- // @ts-expect-error - TextInput.State.currentlyFocusedInput() returns NativeMethods
501
- // which is not directly assignable to findNodeHandle's expected type,
502
- // but it works at runtime. This is a known type limitation in React Native.
503
- currentlyFocusedInput,
504
- )
505
- : null;
506
-
507
- // Only remove the target if it belongs to the current component
508
- // and if the currently focused input is not in the targets set
509
- const shouldRemoveCurrentTarget =
510
- keyboardState.target === event.nativeEvent.target;
511
- const shouldIgnoreBlurEvent =
512
- currentFocusedInput && textInputNodesRef.current.has(currentFocusedInput);
513
-
514
- if (shouldRemoveCurrentTarget && !shouldIgnoreBlurEvent) {
515
- animatedKeyboardState.set(state => ({
516
- ...state,
517
- target: undefined,
518
- }));
519
- }
520
- }
521
-
522
473
  function handleClear() {
523
474
  handleChangeText("");
524
475
  }
@@ -565,7 +516,7 @@ interface UseTextInputRefProps {
565
516
  }
566
517
 
567
518
  function useTextInputRef({ ref, onClear }: UseTextInputRefProps) {
568
- const textInputRef = useRef<TextInput | null>(null);
519
+ const textInputRef = useRef<InputTextRef | null>(null);
569
520
 
570
521
  useImperativeHandle(
571
522
  ref,
@@ -152,6 +152,20 @@ exports[`renders a thumbnail component with attachments 1`] = `
152
152
  }
153
153
  >
154
154
  <View
155
+ backdropComponent={[Function]}
156
+ backgroundStyle={
157
+ {
158
+ "borderTopLeftRadius": 24,
159
+ "borderTopRightRadius": 24,
160
+ }
161
+ }
162
+ enablePanDownToClose={true}
163
+ handleStyle={
164
+ {
165
+ "display": "none",
166
+ }
167
+ }
168
+ keyboardBlurBehavior="restore"
155
169
  style={
156
170
  {
157
171
  "display": "none",
@@ -160,6 +174,12 @@ exports[`renders a thumbnail component with attachments 1`] = `
160
174
  testID="bottom-sheet-mock"
161
175
  >
162
176
  <View
177
+ style={
178
+ {
179
+ "paddingBottom": 8,
180
+ "paddingTop": 8,
181
+ }
182
+ }
163
183
  testID="bottom-sheet-view"
164
184
  >
165
185
  <View
@@ -23,7 +23,6 @@
23
23
  "Chip",
24
24
  "Content",
25
25
  "ContentOverlay",
26
- "ContentOverlayProvider",
27
26
  "Disclosure",
28
27
  "Divider",
29
28
  "EmptyState",
@@ -1,5 +0,0 @@
1
- import React from "react";
2
- import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
3
- export function ContentOverlayProvider({ children, }) {
4
- return React.createElement(BottomSheetModalProvider, null, children);
5
- }
@@ -1,76 +0,0 @@
1
- /**
2
- * Computes the abstract behavior of ContentOverlay from its props and state.
3
- *
4
- * This pure function documents and centralizes the complex logic that determines:
5
- * - Initial height mode (fullScreen vs contentHeight)
6
- * - Whether the overlay is draggable
7
- * - Whether the dismiss button should be shown
8
- *
9
- * The logic accounts for legacy behavior where:
10
- * - `onBeforeExit` silently overrides `isDraggable` to false
11
- * - Default props (neither fullScreen nor adjustToContentHeight) are treated
12
- * as contentHeight for the new implementation
13
- * - Dismiss button visibility depends on multiple factors including position state
14
- */
15
- export function computeContentOverlayBehavior(config, state) {
16
- const isDraggable = computeIsDraggable(config);
17
- const initialHeight = computeInitialHeight(config, isDraggable);
18
- const showDismiss = computeShowDismiss(config, state);
19
- return {
20
- initialHeight,
21
- isDraggable,
22
- showDismiss,
23
- };
24
- }
25
- /**
26
- * Order is important to maintain legacy behavior, despite the questionable logic.
27
- * A non draggable overlay wants to be fullscreen, so as to have the dismiss button be visible.
28
- * There is an invalid combination here with adjustToContentHeight and onBeforeExit which in turn overrides isDraggable to false.
29
- * This requires an explicit showDismiss=true or else it will not be possible to dismiss the overlay.
30
- */
31
- function computeInitialHeight(config, isDraggable) {
32
- if (config.adjustToContentHeight) {
33
- return "contentHeight";
34
- }
35
- if (config.fullScreen) {
36
- return "fullScreen";
37
- }
38
- if (!isDraggable) {
39
- return "fullScreen";
40
- }
41
- return "contentHeight";
42
- }
43
- /**
44
- * Draggability determination:
45
- * - hasOnBeforeExit: true → false (silent override, regardless of isDraggable prop)
46
- * - Otherwise → use isDraggable prop value
47
- *
48
- * This silent override exists because onBeforeExit needs to intercept close attempts,
49
- * and dragging would bypass that interception.
50
- */
51
- function computeIsDraggable(config) {
52
- if (config.hasOnBeforeExit) {
53
- return false;
54
- }
55
- return config.isDraggable;
56
- }
57
- /**
58
- * Dismiss button visibility:
59
- * The idea behind fullscreen having it is that there may be little room to tap the background to dismiss.
60
- * While this logic is redundant with the position, it's a relic of the legacy behavior where position didn't update in time.
61
- */
62
- function computeShowDismiss(config, state) {
63
- if (config.showDismiss) {
64
- return true;
65
- }
66
- if (state.isScreenReaderEnabled) {
67
- return true;
68
- }
69
- if (config.fullScreen) {
70
- return true;
71
- }
72
- if (!config.adjustToContentHeight && state.position === 0) {
73
- return true;
74
- }
75
- return false;
76
- }
@@ -1,25 +0,0 @@
1
- import { useCallback, useRef } from "react";
2
- import { BackHandler } from "react-native";
3
- /**
4
- * Hook that dismisses the bottom sheet on the hardware back button press if it is visible
5
- * @param bottomSheetModalRef ref to the bottom sheet modal component
6
- */
7
- export function useBottomSheetModalBackHandler(onCloseController) {
8
- const backHandlerSubscriptionRef = useRef(null);
9
- const handleSheetPositionChange = useCallback((index) => {
10
- var _a;
11
- const isBottomSheetModalVisible = index >= 0;
12
- if (isBottomSheetModalVisible && !backHandlerSubscriptionRef.current) {
13
- // Setup the back handler if the bottom sheet is right in front of the user
14
- backHandlerSubscriptionRef.current = BackHandler.addEventListener("hardwareBackPress", () => {
15
- onCloseController();
16
- return true;
17
- });
18
- }
19
- else if (!isBottomSheetModalVisible) {
20
- (_a = backHandlerSubscriptionRef.current) === null || _a === void 0 ? void 0 : _a.remove();
21
- backHandlerSubscriptionRef.current = null;
22
- }
23
- }, [onCloseController]);
24
- return { handleSheetPositionChange };
25
- }
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- interface ContentOverlayProviderProps {
3
- readonly children: React.ReactNode;
4
- }
5
- export declare function ContentOverlayProvider({ children, }: ContentOverlayProviderProps): React.JSX.Element;
6
- export {};
@@ -1,32 +0,0 @@
1
- export interface ContentOverlayConfig {
2
- fullScreen: boolean;
3
- adjustToContentHeight: boolean;
4
- isDraggable: boolean;
5
- hasOnBeforeExit: boolean;
6
- showDismiss: boolean;
7
- }
8
- export interface ContentOverlayState {
9
- isScreenReaderEnabled: boolean;
10
- position: number;
11
- }
12
- export type InitialHeight = "fullScreen" | "contentHeight";
13
- export interface ContentOverlayBehavior {
14
- initialHeight: InitialHeight;
15
- isDraggable: boolean;
16
- showDismiss: boolean;
17
- }
18
- /**
19
- * Computes the abstract behavior of ContentOverlay from its props and state.
20
- *
21
- * This pure function documents and centralizes the complex logic that determines:
22
- * - Initial height mode (fullScreen vs contentHeight)
23
- * - Whether the overlay is draggable
24
- * - Whether the dismiss button should be shown
25
- *
26
- * The logic accounts for legacy behavior where:
27
- * - `onBeforeExit` silently overrides `isDraggable` to false
28
- * - Default props (neither fullScreen nor adjustToContentHeight) are treated
29
- * as contentHeight for the new implementation
30
- * - Dismiss button visibility depends on multiple factors including position state
31
- */
32
- export declare function computeContentOverlayBehavior(config: ContentOverlayConfig, state: ContentOverlayState): ContentOverlayBehavior;
@@ -1,7 +0,0 @@
1
- /**
2
- * Hook that dismisses the bottom sheet on the hardware back button press if it is visible
3
- * @param bottomSheetModalRef ref to the bottom sheet modal component
4
- */
5
- export declare function useBottomSheetModalBackHandler(onCloseController: () => void): {
6
- handleSheetPositionChange: (index: number) => void;
7
- };
@@ -1,59 +0,0 @@
1
- import React, { useRef } from "react";
2
- import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
3
- import { View } from "react-native";
4
- import { SafeAreaProvider } from "react-native-safe-area-context";
5
- import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
6
- import { Button, Heading, Text } from "@jobber/components-native";
7
- import { ContentOverlay } from "./ContentOverlay";
8
- import type { ContentOverlayRef } from "./types";
9
-
10
- const meta = {
11
- title: "Components/Overlays/ContentOverlay",
12
- component: ContentOverlay,
13
- } satisfies Meta<typeof ContentOverlay>;
14
-
15
- export default meta;
16
- type Story = StoryObj<typeof meta>;
17
-
18
- const BasicTemplate = () => {
19
- const contentOverlayRef = useRef<ContentOverlayRef>(null);
20
-
21
- const openContentOverlay = () => {
22
- contentOverlayRef.current?.open?.();
23
- };
24
-
25
- const closeContentOverlay = () => {
26
- contentOverlayRef.current?.close?.();
27
- };
28
-
29
- return (
30
- <SafeAreaProvider>
31
- <BottomSheetModalProvider>
32
- <View style={{ display: "flex", flexDirection: "column", gap: 16 }}>
33
- <Heading>Basic ContentOverlay</Heading>
34
- <Text>
35
- Note that due to the differences between React Native Web and React
36
- Native, this does not render 100% properly
37
- </Text>
38
- <Button label="Open Content Overlay" onPress={openContentOverlay} />
39
- <Button label="Close Content Overlay" onPress={closeContentOverlay} />
40
- </View>
41
- <ContentOverlay
42
- ref={contentOverlayRef}
43
- title="Content Overlay Title"
44
- onClose={() => console.log("closed content overlay")}
45
- onOpen={() => console.log("opened content overlay")}
46
- >
47
- <View style={{ padding: 16 }}>
48
- <Text>This is the content inside the overlay.</Text>
49
- </View>
50
- </ContentOverlay>
51
- </BottomSheetModalProvider>
52
- </SafeAreaProvider>
53
- );
54
- };
55
-
56
- export const Basic: Story = {
57
- render: BasicTemplate,
58
- args: {} as Story["args"],
59
- };
@@ -1,12 +0,0 @@
1
- import React from "react";
2
- import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
3
-
4
- interface ContentOverlayProviderProps {
5
- readonly children: React.ReactNode;
6
- }
7
-
8
- export function ContentOverlayProvider({
9
- children,
10
- }: ContentOverlayProviderProps) {
11
- return <BottomSheetModalProvider>{children}</BottomSheetModalProvider>;
12
- }