@utilitywarehouse/hearth-react-native 0.29.0 → 0.29.2

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 (33) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +13 -13
  3. package/CHANGELOG.md +42 -0
  4. package/build/components/BottomSheet/BottomSheet.context.d.ts +1 -0
  5. package/build/components/BottomSheet/BottomSheet.context.js +3 -1
  6. package/build/components/BottomSheet/BottomSheet.js +5 -1
  7. package/build/components/BottomSheet/BottomSheetFlatList.js +16 -2
  8. package/build/components/BottomSheet/BottomSheetModal.js +5 -1
  9. package/build/components/BottomSheet/BottomSheetModalProvider.d.ts +9 -0
  10. package/build/components/BottomSheet/BottomSheetModalProvider.js +14 -0
  11. package/build/components/BottomSheet/BottomSheetScrollView.js +16 -2
  12. package/build/components/BottomSheet/BottomSheetView.js +16 -2
  13. package/build/components/BottomSheet/index.d.ts +3 -1
  14. package/build/components/BottomSheet/index.js +2 -1
  15. package/build/components/Combobox/Combobox.js +3 -1
  16. package/build/components/Modal/Modal.js +54 -8
  17. package/build/components/NavModal/NavModal.js +3 -3
  18. package/build/components/Select/Select.js +3 -1
  19. package/package.json +1 -1
  20. package/src/components/BottomSheet/BottomSheet.context.ts +4 -1
  21. package/src/components/BottomSheet/BottomSheet.docs.mdx +20 -0
  22. package/src/components/BottomSheet/BottomSheet.tsx +8 -1
  23. package/src/components/BottomSheet/BottomSheetFlatList.tsx +16 -2
  24. package/src/components/BottomSheet/BottomSheetModal.tsx +8 -1
  25. package/src/components/BottomSheet/BottomSheetModalProvider.tsx +33 -0
  26. package/src/components/BottomSheet/BottomSheetScrollView.tsx +16 -2
  27. package/src/components/BottomSheet/BottomSheetView.tsx +17 -2
  28. package/src/components/BottomSheet/index.ts +2 -1
  29. package/src/components/Combobox/Combobox.tsx +3 -1
  30. package/src/components/Modal/Modal.docs.mdx +14 -0
  31. package/src/components/Modal/Modal.tsx +54 -8
  32. package/src/components/NavModal/NavModal.tsx +3 -3
  33. package/src/components/Select/Select.tsx +3 -1
@@ -1,4 +1,4 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.29.0 build /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.29.2 build /home/runner/work/hearth/hearth/packages/react-native
3
3
  > tsc
4
4
 
@@ -1,5 +1,5 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.29.0 lint /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.29.2 lint /home/runner/work/hearth/hearth/packages/react-native
3
3
  > TIMING=1 eslint .
4
4
 
5
5
 
@@ -51,15 +51,15 @@
51
51
 
52
52
  ✖ 22 problems (0 errors, 22 warnings)
53
53
 
54
- Rule | Time (ms) | Relative
55
- :-----------------------------------------|----------:|--------:
56
- @typescript-eslint/no-unused-vars | 1560.145 | 62.1%
57
- react-hooks/exhaustive-deps | 117.093 | 4.7%
58
- no-global-assign | 95.045 | 3.8%
59
- react-hooks/rules-of-hooks | 70.847 | 2.8%
60
- no-misleading-character-class | 41.174 | 1.6%
61
- @typescript-eslint/ban-ts-comment | 40.449 | 1.6%
62
- no-unexpected-multiline | 38.671 | 1.5%
63
- no-useless-escape | 35.996 | 1.4%
64
- @typescript-eslint/no-unused-expressions | 34.583 | 1.4%
65
- @typescript-eslint/triple-slash-reference | 33.557 | 1.3%
54
+ Rule | Time (ms) | Relative
55
+ :----------------------------------------|----------:|--------:
56
+ @typescript-eslint/no-unused-vars | 1520.806 | 60.5%
57
+ react-hooks/exhaustive-deps | 119.554 | 4.8%
58
+ no-global-assign | 82.827 | 3.3%
59
+ react-hooks/rules-of-hooks | 73.620 | 2.9%
60
+ no-loss-of-precision | 46.636 | 1.9%
61
+ no-unexpected-multiline | 38.241 | 1.5%
62
+ no-misleading-character-class | 37.413 | 1.5%
63
+ @typescript-eslint/no-unused-expressions | 31.682 | 1.3%
64
+ no-useless-escape | 28.666 | 1.1%
65
+ @typescript-eslint/ban-ts-comment | 27.948 | 1.1%
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @utilitywarehouse/hearth-react-native
2
2
 
3
+ ## 0.29.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1067](https://github.com/utilitywarehouse/hearth/pull/1067) [`893cbfd`](https://github.com/utilitywarehouse/hearth/commit/893cbfd1bf090b8b75df6f58f2babaf8ba1e0033) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add a `useSafeAreaInsets` prop to `BottomSheetModalProvider` to control Hearth's bottom-sheet safe-area spacing.
8
+
9
+ Bottom-sheet wrappers such as `BottomSheetView`, `BottomSheetScrollView`, `BottomSheetFlatList`, and components that render `SafeAreaView` inside a bottom sheet now respect `BottomSheetModalProvider` configuration.
10
+
11
+ **Components affected**:
12
+ - `BottomSheetModalProvider`
13
+ - `BottomSheetView`
14
+ - `BottomSheetScrollView`
15
+ - `BottomSheetFlatList`
16
+ - `Modal`
17
+ - `Select`
18
+ - `Combobox`
19
+
20
+ **Developer changes**:
21
+
22
+ No changes are required if you want the current behaviour. If your app already applies its own safe-area padding around bottom-sheet content, opt out like this:
23
+
24
+ ```tsx
25
+ <BottomSheetModalProvider useSafeAreaInsets={false}>
26
+ {/* Your app content */}
27
+ </BottomSheetModalProvider>
28
+ ```
29
+
30
+ ## 0.29.1
31
+
32
+ ### Patch Changes
33
+
34
+ - [#1062](https://github.com/utilitywarehouse/hearth/pull/1062) [`0da3ffe`](https://github.com/utilitywarehouse/hearth/commit/0da3ffe12691a4287694ae9fcb2290d459e3c041) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Respect the selected `NavModal` background style
35
+
36
+ Fixed an issue where `NavModal` always rendered its inner content with the default surface background, which prevented the `background="brand"` treatment from being applied correctly.
37
+
38
+ **Components affected**:
39
+ - `NavModal`
40
+
41
+ **Developer changes**:
42
+
43
+ No changes are required.
44
+
3
45
  ## 0.29.0
4
46
 
5
47
  ### Minor Changes
@@ -1,5 +1,6 @@
1
1
  interface BottomSheetContextProps {
2
2
  handle?: boolean;
3
+ useSafeAreaInsets: boolean;
3
4
  }
4
5
  export declare const BottomSheetContext: import("react").Context<BottomSheetContextProps>;
5
6
  export declare const useBottomSheetContext: () => BottomSheetContextProps;
@@ -1,5 +1,7 @@
1
1
  import { createContext, useContext } from 'react';
2
- export const BottomSheetContext = createContext({});
2
+ export const BottomSheetContext = createContext({
3
+ useSafeAreaInsets: true,
4
+ });
3
5
  export const useBottomSheetContext = () => {
4
6
  const context = useContext(BottomSheetContext);
5
7
  return context;
@@ -7,6 +7,7 @@ import useBottomSheetLogic from './useBottomSheetLogic';
7
7
  const StyledBottomSheetCore = withUnistyles(BottomSheetCore);
8
8
  const BottomSheet = ({ children, containerStyle, handleStyle, backdrop = true, showHandle = true, ref, ...rest }) => {
9
9
  const bottomSheetRef = React.useRef(null);
10
+ const parentContext = React.useContext(BottomSheetContext);
10
11
  const { renderBackdrop, renderHandle } = useBottomSheetLogic({
11
12
  ref,
12
13
  bottomSheetRef,
@@ -14,7 +15,10 @@ const BottomSheet = ({ children, containerStyle, handleStyle, backdrop = true, s
14
15
  showHandle,
15
16
  handleStyle,
16
17
  });
17
- const value = useMemo(() => ({ handle: showHandle }), [showHandle]);
18
+ const value = useMemo(() => ({
19
+ ...parentContext,
20
+ handle: showHandle,
21
+ }), [parentContext, showHandle]);
18
22
  return (_jsx(StyledBottomSheetCore, { ref: bottomSheetRef, index: -1, backdropComponent: renderBackdrop, handleComponent: renderHandle, style: [styles.container, containerStyle], backgroundStyle: styles.background, ...rest, children: _jsx(BottomSheetContext.Provider, { value: value, children: children }) }));
19
23
  };
20
24
  const styles = StyleSheet.create(theme => ({
@@ -4,10 +4,11 @@ import { StyleSheet, withUnistyles } from 'react-native-unistyles';
4
4
  import { useBottomSheetContext } from './BottomSheet.context';
5
5
  const StyledBottomSheetFlatList = withUnistyles(FlatList);
6
6
  const BottomSheetFlatList = ({ style, contentContainerStyle, isModal = true, ...props }) => {
7
- const { handle } = useBottomSheetContext();
7
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
8
8
  styles.useVariants({
9
9
  isModal,
10
10
  handle,
11
+ useSafeAreaInsets,
11
12
  });
12
13
  return (_jsx(StyledBottomSheetFlatList, { style: [styles.container, style], contentContainerStyle: [styles.contentContainer, contentContainerStyle], ...props }));
13
14
  };
@@ -19,7 +20,7 @@ const styles = StyleSheet.create((theme, rt) => ({
19
20
  variants: {
20
21
  isModal: {
21
22
  true: {
22
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
23
+ paddingBottom: theme.components.bottomSheet.padding,
23
24
  },
24
25
  },
25
26
  handle: {
@@ -27,7 +28,20 @@ const styles = StyleSheet.create((theme, rt) => ({
27
28
  paddingTop: theme.components.bottomSheet.padding,
28
29
  },
29
30
  },
31
+ useSafeAreaInsets: {
32
+ true: {},
33
+ false: {},
34
+ },
30
35
  },
36
+ compoundVariants: [
37
+ {
38
+ isModal: true,
39
+ useSafeAreaInsets: true,
40
+ styles: {
41
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
42
+ },
43
+ },
44
+ ],
31
45
  },
32
46
  }));
33
47
  BottomSheetFlatList.displayName = 'BottomSheetFlatList';
@@ -7,6 +7,7 @@ import useBottomSheetLogic from './useBottomSheetLogic';
7
7
  const StyledBottomSheetModalCore = withUnistyles(BottomSheetModalCore);
8
8
  const BottomSheetModal = ({ children, containerStyle, handleStyle, backdrop = true, showHandle = true, ref, ...rest }) => {
9
9
  const bottomSheetRef = React.useRef(null);
10
+ const parentContext = React.useContext(BottomSheetContext);
10
11
  const { renderBackdrop, renderHandle } = useBottomSheetLogic({
11
12
  // @ts-expect-error - ref
12
13
  ref,
@@ -15,7 +16,10 @@ const BottomSheetModal = ({ children, containerStyle, handleStyle, backdrop = tr
15
16
  showHandle,
16
17
  handleStyle,
17
18
  });
18
- const value = useMemo(() => ({ handle: showHandle }), [showHandle]);
19
+ const value = useMemo(() => ({
20
+ ...parentContext,
21
+ handle: showHandle,
22
+ }), [parentContext, showHandle]);
19
23
  return (_jsx(StyledBottomSheetModalCore, { ref: bottomSheetRef, backdropComponent: renderBackdrop, handleComponent: renderHandle, style: [styles.container, containerStyle], backgroundStyle: styles.background, ...rest, children: _jsx(BottomSheetContext.Provider, { value: value, children: children }) }));
20
24
  };
21
25
  const styles = StyleSheet.create(theme => ({
@@ -0,0 +1,9 @@
1
+ import type { BottomSheetModalProviderProps as GorhomBottomSheetModalProviderProps } from '@gorhom/bottom-sheet/lib/typescript/components/bottomSheetModalProvider/types';
2
+ export interface BottomSheetModalProviderProps extends GorhomBottomSheetModalProviderProps {
3
+ useSafeAreaInsets?: boolean;
4
+ }
5
+ declare const BottomSheetModalProvider: {
6
+ ({ children, useSafeAreaInsets, ...props }: BottomSheetModalProviderProps): import("react/jsx-runtime").JSX.Element;
7
+ displayName: string;
8
+ };
9
+ export default BottomSheetModalProvider;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BottomSheetModalProvider as GorhomBottomSheetModalProvider } from '@gorhom/bottom-sheet';
3
+ import { useMemo } from 'react';
4
+ import { BottomSheetContext, useBottomSheetContext } from './BottomSheet.context';
5
+ const BottomSheetModalProvider = ({ children, useSafeAreaInsets = true, ...props }) => {
6
+ const parentContext = useBottomSheetContext();
7
+ const value = useMemo(() => ({
8
+ ...parentContext,
9
+ useSafeAreaInsets,
10
+ }), [parentContext, useSafeAreaInsets]);
11
+ return (_jsx(GorhomBottomSheetModalProvider, { ...props, children: _jsx(BottomSheetContext.Provider, { value: value, children: children }) }));
12
+ };
13
+ BottomSheetModalProvider.displayName = 'BottomSheetModalProvider';
14
+ export default BottomSheetModalProvider;
@@ -4,10 +4,11 @@ import { StyleSheet, withUnistyles } from 'react-native-unistyles';
4
4
  import { useBottomSheetContext } from './BottomSheet.context';
5
5
  const StyledBottomSheetScrollView = withUnistyles(ScrollView);
6
6
  const BottomSheetScrollView = ({ children, style, contentContainerStyle, isModal = true, ...props }) => {
7
- const { handle } = useBottomSheetContext();
7
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
8
8
  styles.useVariants({
9
9
  isModal,
10
10
  handle,
11
+ useSafeAreaInsets,
11
12
  });
12
13
  return (_jsx(StyledBottomSheetScrollView, { style: [styles.container, style], contentContainerStyle: [styles.contentContainer, contentContainerStyle], ...props, children: children }));
13
14
  };
@@ -23,7 +24,7 @@ const styles = StyleSheet.create((theme, rt) => ({
23
24
  variants: {
24
25
  isModal: {
25
26
  true: {
26
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
27
+ paddingBottom: theme.components.bottomSheet.padding,
27
28
  },
28
29
  },
29
30
  handle: {
@@ -31,7 +32,20 @@ const styles = StyleSheet.create((theme, rt) => ({
31
32
  paddingTop: theme.components.bottomSheet.padding,
32
33
  },
33
34
  },
35
+ useSafeAreaInsets: {
36
+ true: {},
37
+ false: {},
38
+ },
34
39
  },
40
+ compoundVariants: [
41
+ {
42
+ isModal: true,
43
+ useSafeAreaInsets: true,
44
+ styles: {
45
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
46
+ },
47
+ },
48
+ ],
35
49
  },
36
50
  }));
37
51
  BottomSheetScrollView.displayName = 'BottomSheetScrollView';
@@ -4,10 +4,11 @@ import { StyleSheet, withUnistyles } from 'react-native-unistyles';
4
4
  import { useBottomSheetContext } from './BottomSheet.context';
5
5
  const StyledBottomSheetView = withUnistyles(View);
6
6
  const BottomSheetView = ({ children, style, isModal = true, ...props }) => {
7
- const { handle } = useBottomSheetContext();
7
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
8
8
  styles.useVariants({
9
9
  isModal,
10
10
  handle,
11
+ useSafeAreaInsets,
11
12
  });
12
13
  return (_jsx(StyledBottomSheetView, { style: [styles.contentContainer, style], ...props, children: children }));
13
14
  };
@@ -21,7 +22,7 @@ const styles = StyleSheet.create((theme, rt) => ({
21
22
  variants: {
22
23
  isModal: {
23
24
  true: {
24
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
25
+ paddingBottom: theme.components.bottomSheet.padding,
25
26
  },
26
27
  },
27
28
  handle: {
@@ -29,7 +30,20 @@ const styles = StyleSheet.create((theme, rt) => ({
29
30
  paddingTop: theme.components.bottomSheet.padding,
30
31
  },
31
32
  },
33
+ useSafeAreaInsets: {
34
+ true: {},
35
+ false: {},
36
+ },
32
37
  },
38
+ compoundVariants: [
39
+ {
40
+ isModal: true,
41
+ useSafeAreaInsets: true,
42
+ styles: {
43
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
44
+ },
45
+ },
46
+ ],
33
47
  },
34
48
  }));
35
49
  BottomSheetView.displayName = 'BottomSheetView';
@@ -1,7 +1,9 @@
1
- export { BottomSheetFlashList, BottomSheetFooter, BottomSheetModalProvider, BottomSheetSectionList, BottomSheetVirtualizedList, useBottomSheet, useBottomSheetModal, type BottomSheetBackdropProps, type BottomSheetBackgroundProps, type BottomSheetHandleProps, type BottomSheetModalProps, } from '@gorhom/bottom-sheet';
1
+ export { BottomSheetFlashList, BottomSheetFooter, BottomSheetSectionList, BottomSheetVirtualizedList, useBottomSheet, useBottomSheetModal, type BottomSheetBackdropProps, type BottomSheetBackgroundProps, type BottomSheetHandleProps, type BottomSheetModalProps, } from '@gorhom/bottom-sheet';
2
2
  export { default as BottomSheet } from './BottomSheet';
3
3
  export type { default as BottomSheetProps } from './BottomSheet.props';
4
4
  export { default as BottomSheetFlatList } from './BottomSheetFlatList';
5
5
  export { default as BottomSheetModal } from './BottomSheetModal';
6
+ export { default as BottomSheetModalProvider } from './BottomSheetModalProvider';
7
+ export type { BottomSheetModalProviderProps } from './BottomSheetModalProvider';
6
8
  export { default as BottomSheetScrollView } from './BottomSheetScrollView';
7
9
  export { default as BottomSheetView } from './BottomSheetView';
@@ -1,6 +1,7 @@
1
- export { BottomSheetFlashList, BottomSheetFooter, BottomSheetModalProvider, BottomSheetSectionList, BottomSheetVirtualizedList, useBottomSheet, useBottomSheetModal, } from '@gorhom/bottom-sheet';
1
+ export { BottomSheetFlashList, BottomSheetFooter, BottomSheetSectionList, BottomSheetVirtualizedList, useBottomSheet, useBottomSheetModal, } from '@gorhom/bottom-sheet';
2
2
  export { default as BottomSheet } from './BottomSheet';
3
3
  export { default as BottomSheetFlatList } from './BottomSheetFlatList';
4
4
  export { default as BottomSheetModal } from './BottomSheetModal';
5
+ export { default as BottomSheetModalProvider } from './BottomSheetModalProvider';
5
6
  export { default as BottomSheetScrollView } from './BottomSheetScrollView';
6
7
  export { default as BottomSheetView } from './BottomSheetView';
@@ -7,6 +7,7 @@ import { StyleSheet } from 'react-native-unistyles';
7
7
  import { useTheme } from '../../hooks';
8
8
  import { BodyText } from '../BodyText';
9
9
  import { BottomSheetFlatList, BottomSheetModal, BottomSheetView } from '../BottomSheet';
10
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
10
11
  import { DetailText } from '../DetailText';
11
12
  import { FormField, useFormFieldContext } from '../FormField';
12
13
  import { Icon } from '../Icon';
@@ -23,6 +24,7 @@ const Combobox = ({ options = [], value, onValueChange, inputValue, onInputValue
23
24
  const isDisabled = formFieldContext?.disabled ?? disabled;
24
25
  const isReadonly = formFieldContext?.readonly ?? readonly;
25
26
  const { color } = useTheme();
27
+ const { useSafeAreaInsets } = useBottomSheetContext();
26
28
  const bottomSheetModalRef = useRef(null);
27
29
  const searchInputRef = useRef(null);
28
30
  const focusTimeoutRef = useRef(null);
@@ -162,7 +164,7 @@ const Combobox = ({ options = [], value, onValueChange, inputValue, onInputValue
162
164
  selectedValue: value,
163
165
  selectOption,
164
166
  setSearch,
165
- }, children: [_jsxs(SafeAreaView, { edges: ['top'], children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), _jsx(View, { style: styles.searchContainer, children: _jsx(Input, { ref: searchInputRef, placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search", clearable: true, onClear: handleClear, loading: loading }) })] }), customContent || (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, ...listProps }))] }) })] }));
167
+ }, children: [_jsxs(SafeAreaView, { edges: useSafeAreaInsets ? ['top'] : [], children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), _jsx(View, { style: styles.searchContainer, children: _jsx(Input, { ref: searchInputRef, placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search", clearable: true, onClear: handleClear, loading: loading }) })] }), customContent || (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, ...listProps }))] }) })] }));
166
168
  };
167
169
  const styles = StyleSheet.create(theme => ({
168
170
  container: {
@@ -6,6 +6,7 @@ import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native'
6
6
  import { StyleSheet } from 'react-native-unistyles';
7
7
  import { BodyText } from '../BodyText';
8
8
  import { BottomSheetModal, BottomSheetScrollView } from '../BottomSheet';
9
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
9
10
  import { Button } from '../Button';
10
11
  import { Heading } from '../Heading';
11
12
  import { Spinner } from '../Spinner';
@@ -14,6 +15,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
14
15
  const bottomSheetModalRef = useRef(null);
15
16
  const viewRef = useRef(null);
16
17
  const scrollViewRef = useRef(null);
18
+ const { useSafeAreaInsets } = useBottomSheetContext();
17
19
  useImperativeHandle(ref, () => ({
18
20
  ...bottomSheetModalRef.current,
19
21
  }));
@@ -64,6 +66,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
64
66
  noButtons,
65
67
  stickyFooter,
66
68
  showHandle: props.showHandle,
69
+ useSafeAreaInsets,
67
70
  });
68
71
  const footer = useMemo(() => (_jsxs(View, { style: styles.footer, children: [onPressPrimaryButton && primaryButtonText ? (_jsx(Button, { onPress: handlePrimaryButtonPress, text: primaryButtonText, ...primaryButtonProps, variant: primaryButtonProps?.variant ?? 'solid', colorScheme: primaryButtonProps?.colorScheme ?? 'highlight' })) : null, onPressSecondaryButton && secondaryButtonText ? (_jsx(Button, { onPress: handleSecondaryButtonPress, text: secondaryButtonText, ...secondaryButtonProps, variant: secondaryButtonProps?.variant ?? 'outline', colorScheme: secondaryButtonProps?.colorScheme ?? 'functional' })) : null] })), [
69
72
  handlePrimaryButtonPress,
@@ -99,34 +102,68 @@ const styles = StyleSheet.create((theme, rt) => ({
99
102
  variants: {
100
103
  bothButtons: {
101
104
  true: {
105
+ paddingBottom: 166,
106
+ },
107
+ false: {
108
+ paddingBottom: 102,
109
+ },
110
+ },
111
+ noButtons: {
112
+ true: {
113
+ paddingBottom: theme.components.modal.padding,
114
+ },
115
+ },
116
+ stickyFooter: {
117
+ true: {},
118
+ false: {
119
+ paddingBottom: theme.components.modal.padding + theme.components.bottomSheet.padding,
120
+ },
121
+ },
122
+ useSafeAreaInsets: {
123
+ true: {},
124
+ false: {},
125
+ },
126
+ },
127
+ compoundVariants: [
128
+ {
129
+ bothButtons: true,
130
+ useSafeAreaInsets: true,
131
+ styles: {
102
132
  paddingBottom: 166 +
103
133
  rt.insets.bottom -
104
134
  theme.components.modal.padding +
105
135
  theme.components.bottomSheet.padding,
106
136
  },
107
- false: {
137
+ },
138
+ {
139
+ bothButtons: false,
140
+ useSafeAreaInsets: true,
141
+ styles: {
108
142
  paddingBottom: 102 +
109
143
  rt.insets.bottom -
110
144
  theme.components.modal.padding +
111
145
  theme.components.bottomSheet.padding,
112
146
  },
113
147
  },
114
- noButtons: {
115
- true: {
148
+ {
149
+ noButtons: true,
150
+ useSafeAreaInsets: true,
151
+ styles: {
116
152
  paddingBottom: rt.insets.bottom +
117
153
  theme.components.modal.padding +
118
154
  theme.components.bottomSheet.padding,
119
155
  },
120
156
  },
121
- stickyFooter: {
122
- true: {},
123
- false: {
157
+ {
158
+ useSafeAreaInsets: true,
159
+ stickyFooter: false,
160
+ styles: {
124
161
  paddingBottom: rt.insets.bottom +
125
162
  theme.components.modal.padding +
126
163
  theme.components.bottomSheet.padding,
127
164
  },
128
165
  },
129
- },
166
+ ],
130
167
  },
131
168
  header: {
132
169
  flexDirection: 'row',
@@ -172,7 +209,16 @@ const styles = StyleSheet.create((theme, rt) => ({
172
209
  footerWrap: {
173
210
  backgroundColor: theme.color.surface.neutral.strong,
174
211
  paddingHorizontal: theme.components.bottomSheet.padding,
175
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
212
+ variants: {
213
+ useSafeAreaInsets: {
214
+ true: {
215
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
216
+ },
217
+ false: {
218
+ paddingBottom: theme.components.bottomSheet.padding,
219
+ },
220
+ },
221
+ },
176
222
  },
177
223
  }));
178
224
  export default Modal;
@@ -152,7 +152,9 @@ const styles = StyleSheet.create((theme, rt) => ({
152
152
  flex: 1,
153
153
  variants: {
154
154
  background: {
155
- primary: {},
155
+ primary: {
156
+ backgroundColor: theme.color.surface.neutral.strong,
157
+ },
156
158
  brand: {
157
159
  backgroundColor: theme.color.background.brand,
158
160
  },
@@ -161,11 +163,9 @@ const styles = StyleSheet.create((theme, rt) => ({
161
163
  modal: {
162
164
  borderTopLeftRadius: theme.components.modal.borderRadius,
163
165
  borderTopRightRadius: theme.components.modal.borderRadius,
164
- backgroundColor: theme.color.surface.neutral.strong,
165
166
  padding: theme.components.bottomSheet.padding,
166
167
  },
167
168
  fullScreen: {
168
- backgroundColor: theme.color.surface.neutral.strong,
169
169
  padding: theme.components.bottomSheet.padding,
170
170
  },
171
171
  },
@@ -6,6 +6,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
6
6
  import { StyleSheet } from 'react-native-unistyles';
7
7
  import { BodyText } from '../BodyText';
8
8
  import { BottomSheetFlatList, BottomSheetModal, BottomSheetScrollView, BottomSheetView, } from '../BottomSheet';
9
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
9
10
  import { DetailText } from '../DetailText';
10
11
  import { FormField, useFormFieldContext } from '../FormField';
11
12
  import { Icon } from '../Icon';
@@ -18,6 +19,7 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
18
19
  const isRequired = formFieldContext?.required ?? required;
19
20
  const isDisabled = formFieldContext?.disabled ?? disabled;
20
21
  const isReadonly = formFieldContext?.readonly ?? readonly;
22
+ const { useSafeAreaInsets } = useBottomSheetContext();
21
23
  const bottomSheetModalRef = useRef(null);
22
24
  const [search, setSearch] = useState('');
23
25
  const [isOpen, setIsOpen] = useState(false);
@@ -77,7 +79,7 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
77
79
  selectedValue: value,
78
80
  onValueChange,
79
81
  close: closeBottomSheet,
80
- }, children: _jsxs(SafeAreaView, { edges: ['top'], style: { flex: 1 }, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search", testID: testID ? `${testID}-search` : undefined }) })), children ? (_jsx(BottomSheetScrollView, { testID: testID ? `${testID}-options` : undefined, children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, testID: testID ? `${testID}-options` : undefined, ...listProps }))] }) }) })] }));
82
+ }, children: _jsxs(SafeAreaView, { edges: useSafeAreaInsets ? ['top'] : [], style: { flex: 1 }, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search", testID: testID ? `${testID}-search` : undefined }) })), children ? (_jsx(BottomSheetScrollView, { testID: testID ? `${testID}-options` : undefined, children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, testID: testID ? `${testID}-options` : undefined, ...listProps }))] }) }) })] }));
81
83
  };
82
84
  const styles = StyleSheet.create(theme => ({
83
85
  container: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.29.0",
3
+ "version": "0.29.2",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -2,9 +2,12 @@ import { createContext, useContext } from 'react';
2
2
 
3
3
  interface BottomSheetContextProps {
4
4
  handle?: boolean;
5
+ useSafeAreaInsets: boolean;
5
6
  }
6
7
 
7
- export const BottomSheetContext = createContext<BottomSheetContextProps>({});
8
+ export const BottomSheetContext = createContext<BottomSheetContextProps>({
9
+ useSafeAreaInsets: true,
10
+ });
8
11
 
9
12
  export const useBottomSheetContext = (): BottomSheetContextProps => {
10
13
  const context = useContext(BottomSheetContext);
@@ -129,6 +129,20 @@ const App = () => {
129
129
  };
130
130
  ```
131
131
 
132
+ `BottomSheetModalProvider` adds Hearth's bottom-sheet safe-area spacing by default. If your app already handles safe-area padding, you can opt out and avoid double spacing:
133
+
134
+ ```tsx
135
+ import { BottomSheetModalProvider } from '@utilitywarehouse/hearth-react-native';
136
+
137
+ const App = () => {
138
+ return (
139
+ <BottomSheetModalProvider useSafeAreaInsets={false}>
140
+ {/* Your app content */}
141
+ </BottomSheetModalProvider>
142
+ );
143
+ };
144
+ ```
145
+
132
146
  ### `BottomSheetScrollView`
133
147
 
134
148
  For scrollable content within a bottom sheet, use the `BottomSheetScrollView` component instead of the standard ScrollView:
@@ -169,6 +183,12 @@ const App = () => {
169
183
  };
170
184
  ```
171
185
 
186
+ Use the `useSafeAreaInsets` prop to control whether Hearth applies bottom-sheet safe-area spacing for modal content, list wrappers, and the top `SafeAreaView` used by components such as `Select` and `Combobox`.
187
+
188
+ | Property | Type | Description | Default |
189
+ | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
190
+ | `useSafeAreaInsets` | `boolean` | Applies Hearth's safe-area insets inside bottom sheets. Set to `false` when your app already manages safe-area padding around bottom-sheet content. | `true` |
191
+
172
192
  ### `Input` in Bottom Sheets
173
193
 
174
194
  When using the `Input` component inside a `BottomSheet` or `BottomSheetModal`, you need to pass the `inBottomSheet` prop to ensure proper behavior with the keyboard and focus management.
@@ -22,6 +22,7 @@ const BottomSheet = ({
22
22
  ...rest
23
23
  }: BottomSheetProps) => {
24
24
  const bottomSheetRef = React.useRef<BottomSheet>(null);
25
+ const parentContext = React.useContext(BottomSheetContext);
25
26
 
26
27
  const { renderBackdrop, renderHandle } = useBottomSheetLogic<BottomSheet>({
27
28
  ref,
@@ -31,7 +32,13 @@ const BottomSheet = ({
31
32
  handleStyle,
32
33
  });
33
34
 
34
- const value = useMemo(() => ({ handle: showHandle }), [showHandle]);
35
+ const value = useMemo(
36
+ () => ({
37
+ ...parentContext,
38
+ handle: showHandle,
39
+ }),
40
+ [parentContext, showHandle]
41
+ );
35
42
 
36
43
  return (
37
44
  <StyledBottomSheetCore
@@ -11,10 +11,11 @@ const BottomSheetFlatList = ({
11
11
  isModal = true,
12
12
  ...props
13
13
  }: BottomSheetFlatListProps<any> & { isModal?: boolean }) => {
14
- const { handle } = useBottomSheetContext();
14
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
15
15
  styles.useVariants({
16
16
  isModal,
17
17
  handle,
18
+ useSafeAreaInsets,
18
19
  });
19
20
 
20
21
  return (
@@ -34,7 +35,7 @@ const styles = StyleSheet.create((theme, rt) => ({
34
35
  variants: {
35
36
  isModal: {
36
37
  true: {
37
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
38
+ paddingBottom: theme.components.bottomSheet.padding,
38
39
  },
39
40
  },
40
41
  handle: {
@@ -42,7 +43,20 @@ const styles = StyleSheet.create((theme, rt) => ({
42
43
  paddingTop: theme.components.bottomSheet.padding,
43
44
  },
44
45
  },
46
+ useSafeAreaInsets: {
47
+ true: {},
48
+ false: {},
49
+ },
45
50
  },
51
+ compoundVariants: [
52
+ {
53
+ isModal: true,
54
+ useSafeAreaInsets: true,
55
+ styles: {
56
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
57
+ },
58
+ },
59
+ ],
46
60
  },
47
61
  }));
48
62
 
@@ -20,6 +20,7 @@ const BottomSheetModal = ({
20
20
  ...rest
21
21
  }: BottomSheetProps) => {
22
22
  const bottomSheetRef = React.useRef<BottomSheetModalMethods<any>>(null);
23
+ const parentContext = React.useContext(BottomSheetContext);
23
24
 
24
25
  const { renderBackdrop, renderHandle } = useBottomSheetLogic<BottomSheetModal>({
25
26
  // @ts-expect-error - ref
@@ -30,7 +31,13 @@ const BottomSheetModal = ({
30
31
  handleStyle,
31
32
  });
32
33
 
33
- const value = useMemo(() => ({ handle: showHandle }), [showHandle]);
34
+ const value = useMemo(
35
+ () => ({
36
+ ...parentContext,
37
+ handle: showHandle,
38
+ }),
39
+ [parentContext, showHandle]
40
+ );
34
41
 
35
42
  return (
36
43
  <StyledBottomSheetModalCore
@@ -0,0 +1,33 @@
1
+ import { BottomSheetModalProvider as GorhomBottomSheetModalProvider } from '@gorhom/bottom-sheet';
2
+ import type { BottomSheetModalProviderProps as GorhomBottomSheetModalProviderProps } from '@gorhom/bottom-sheet/lib/typescript/components/bottomSheetModalProvider/types';
3
+ import { useMemo } from 'react';
4
+ import { BottomSheetContext, useBottomSheetContext } from './BottomSheet.context';
5
+
6
+ export interface BottomSheetModalProviderProps extends GorhomBottomSheetModalProviderProps {
7
+ useSafeAreaInsets?: boolean;
8
+ }
9
+
10
+ const BottomSheetModalProvider = ({
11
+ children,
12
+ useSafeAreaInsets = true,
13
+ ...props
14
+ }: BottomSheetModalProviderProps) => {
15
+ const parentContext = useBottomSheetContext();
16
+ const value = useMemo(
17
+ () => ({
18
+ ...parentContext,
19
+ useSafeAreaInsets,
20
+ }),
21
+ [parentContext, useSafeAreaInsets]
22
+ );
23
+
24
+ return (
25
+ <GorhomBottomSheetModalProvider {...props}>
26
+ <BottomSheetContext.Provider value={value}>{children}</BottomSheetContext.Provider>
27
+ </GorhomBottomSheetModalProvider>
28
+ );
29
+ };
30
+
31
+ BottomSheetModalProvider.displayName = 'BottomSheetModalProvider';
32
+
33
+ export default BottomSheetModalProvider;
@@ -14,10 +14,11 @@ const BottomSheetScrollView = ({
14
14
  isModal = true,
15
15
  ...props
16
16
  }: BottomSheetScrollViewProps & { isModal?: boolean }) => {
17
- const { handle } = useBottomSheetContext();
17
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
18
18
  styles.useVariants({
19
19
  isModal,
20
20
  handle,
21
+ useSafeAreaInsets,
21
22
  });
22
23
 
23
24
  return (
@@ -43,7 +44,7 @@ const styles = StyleSheet.create((theme, rt) => ({
43
44
  variants: {
44
45
  isModal: {
45
46
  true: {
46
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
47
+ paddingBottom: theme.components.bottomSheet.padding,
47
48
  },
48
49
  },
49
50
  handle: {
@@ -51,7 +52,20 @@ const styles = StyleSheet.create((theme, rt) => ({
51
52
  paddingTop: theme.components.bottomSheet.padding,
52
53
  },
53
54
  },
55
+ useSafeAreaInsets: {
56
+ true: {},
57
+ false: {},
58
+ },
54
59
  },
60
+ compoundVariants: [
61
+ {
62
+ isModal: true,
63
+ useSafeAreaInsets: true,
64
+ styles: {
65
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
66
+ },
67
+ },
68
+ ],
55
69
  },
56
70
  }));
57
71
 
@@ -13,11 +13,13 @@ const BottomSheetView = ({
13
13
  isModal = true,
14
14
  ...props
15
15
  }: BottomSheetViewProps & { isModal?: boolean }) => {
16
- const { handle } = useBottomSheetContext();
16
+ const { handle, useSafeAreaInsets } = useBottomSheetContext();
17
17
  styles.useVariants({
18
18
  isModal,
19
19
  handle,
20
+ useSafeAreaInsets,
20
21
  });
22
+
21
23
  return (
22
24
  <StyledBottomSheetView style={[styles.contentContainer, style]} {...props}>
23
25
  {children}
@@ -35,7 +37,7 @@ const styles = StyleSheet.create((theme, rt) => ({
35
37
  variants: {
36
38
  isModal: {
37
39
  true: {
38
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
40
+ paddingBottom: theme.components.bottomSheet.padding,
39
41
  },
40
42
  },
41
43
  handle: {
@@ -43,7 +45,20 @@ const styles = StyleSheet.create((theme, rt) => ({
43
45
  paddingTop: theme.components.bottomSheet.padding,
44
46
  },
45
47
  },
48
+ useSafeAreaInsets: {
49
+ true: {},
50
+ false: {},
51
+ },
46
52
  },
53
+ compoundVariants: [
54
+ {
55
+ isModal: true,
56
+ useSafeAreaInsets: true,
57
+ styles: {
58
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
59
+ },
60
+ },
61
+ ],
47
62
  },
48
63
  }));
49
64
 
@@ -1,7 +1,6 @@
1
1
  export {
2
2
  BottomSheetFlashList,
3
3
  BottomSheetFooter,
4
- BottomSheetModalProvider,
5
4
  BottomSheetSectionList,
6
5
  BottomSheetVirtualizedList,
7
6
  useBottomSheet,
@@ -15,5 +14,7 @@ export { default as BottomSheet } from './BottomSheet';
15
14
  export type { default as BottomSheetProps } from './BottomSheet.props';
16
15
  export { default as BottomSheetFlatList } from './BottomSheetFlatList';
17
16
  export { default as BottomSheetModal } from './BottomSheetModal';
17
+ export { default as BottomSheetModalProvider } from './BottomSheetModalProvider';
18
+ export type { BottomSheetModalProviderProps } from './BottomSheetModalProvider';
18
19
  export { default as BottomSheetScrollView } from './BottomSheetScrollView';
19
20
  export { default as BottomSheetView } from './BottomSheetView';
@@ -6,6 +6,7 @@ import { StyleSheet } from 'react-native-unistyles';
6
6
  import { useTheme } from '../../hooks';
7
7
  import { BodyText } from '../BodyText';
8
8
  import { BottomSheetFlatList, BottomSheetModal, BottomSheetView } from '../BottomSheet';
9
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
9
10
  import { DetailText } from '../DetailText';
10
11
  import { FormField, useFormFieldContext } from '../FormField';
11
12
  import { Icon } from '../Icon';
@@ -55,6 +56,7 @@ const Combobox = ({
55
56
  const isDisabled = formFieldContext?.disabled ?? disabled;
56
57
  const isReadonly = formFieldContext?.readonly ?? readonly;
57
58
  const { color } = useTheme();
59
+ const { useSafeAreaInsets } = useBottomSheetContext();
58
60
 
59
61
  const bottomSheetModalRef = useRef<BottomSheetModal>(null);
60
62
  const searchInputRef = useRef<TextInput>(null);
@@ -325,7 +327,7 @@ const Combobox = ({
325
327
  setSearch,
326
328
  }}
327
329
  >
328
- <SafeAreaView edges={['top']}>
330
+ <SafeAreaView edges={useSafeAreaInsets ? ['top'] : []}>
329
331
  {menuHeading && (
330
332
  <View style={styles.headingContainer}>
331
333
  <DetailText size="lg">{menuHeading}</DetailText>
@@ -476,6 +476,20 @@ const App = () => {
476
476
  };
477
477
  ```
478
478
 
479
+ If your app already handles safe-area padding around modal content, you can disable Hearth's bottom-sheet safe-area spacing:
480
+
481
+ ```tsx
482
+ import { BottomSheetModalProvider } from '@utilitywarehouse/hearth-react-native';
483
+
484
+ const App = () => {
485
+ return (
486
+ <BottomSheetModalProvider useSafeAreaInsets={false}>
487
+ {/* Your app content */}
488
+ </BottomSheetModalProvider>
489
+ );
490
+ };
491
+ ```
492
+
479
493
  ### Ref Usage
480
494
 
481
495
  The Modal component forwards its ref to the underlying `BottomSheetModal`, giving you access to methods like:
@@ -11,6 +11,7 @@ import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native'
11
11
  import { StyleSheet } from 'react-native-unistyles';
12
12
  import { BodyText } from '../BodyText';
13
13
  import { BottomSheetModal, BottomSheetScrollView } from '../BottomSheet';
14
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
14
15
  import { Button } from '../Button';
15
16
  import { Heading } from '../Heading';
16
17
  import { Spinner } from '../Spinner';
@@ -45,6 +46,7 @@ const Modal = ({
45
46
  const bottomSheetModalRef = useRef<BottomSheetModal>(null);
46
47
  const viewRef = useRef<View>(null);
47
48
  const scrollViewRef = useRef<BottomSheetScrollViewMethods>(null);
49
+ const { useSafeAreaInsets } = useBottomSheetContext();
48
50
 
49
51
  useImperativeHandle(ref, () => ({
50
52
  ...(bottomSheetModalRef.current as BottomSheetModal),
@@ -105,6 +107,7 @@ const Modal = ({
105
107
  noButtons,
106
108
  stickyFooter,
107
109
  showHandle: props.showHandle,
110
+ useSafeAreaInsets,
108
111
  });
109
112
 
110
113
  const footer = useMemo(
@@ -256,13 +259,44 @@ const styles = StyleSheet.create((theme, rt) => ({
256
259
  variants: {
257
260
  bothButtons: {
258
261
  true: {
262
+ paddingBottom: 166,
263
+ },
264
+ false: {
265
+ paddingBottom: 102,
266
+ },
267
+ },
268
+ noButtons: {
269
+ true: {
270
+ paddingBottom: theme.components.modal.padding,
271
+ },
272
+ },
273
+ stickyFooter: {
274
+ true: {},
275
+ false: {
276
+ paddingBottom: theme.components.modal.padding + theme.components.bottomSheet.padding,
277
+ },
278
+ },
279
+ useSafeAreaInsets: {
280
+ true: {},
281
+ false: {},
282
+ },
283
+ },
284
+ compoundVariants: [
285
+ {
286
+ bothButtons: true,
287
+ useSafeAreaInsets: true,
288
+ styles: {
259
289
  paddingBottom:
260
290
  166 +
261
291
  rt.insets.bottom -
262
292
  theme.components.modal.padding +
263
293
  theme.components.bottomSheet.padding,
264
294
  },
265
- false: {
295
+ },
296
+ {
297
+ bothButtons: false,
298
+ useSafeAreaInsets: true,
299
+ styles: {
266
300
  paddingBottom:
267
301
  102 +
268
302
  rt.insets.bottom -
@@ -270,24 +304,27 @@ const styles = StyleSheet.create((theme, rt) => ({
270
304
  theme.components.bottomSheet.padding,
271
305
  },
272
306
  },
273
- noButtons: {
274
- true: {
307
+ {
308
+ noButtons: true,
309
+ useSafeAreaInsets: true,
310
+ styles: {
275
311
  paddingBottom:
276
312
  rt.insets.bottom +
277
313
  theme.components.modal.padding +
278
314
  theme.components.bottomSheet.padding,
279
315
  },
280
316
  },
281
- stickyFooter: {
282
- true: {},
283
- false: {
317
+ {
318
+ useSafeAreaInsets: true,
319
+ stickyFooter: false,
320
+ styles: {
284
321
  paddingBottom:
285
322
  rt.insets.bottom +
286
323
  theme.components.modal.padding +
287
324
  theme.components.bottomSheet.padding,
288
325
  },
289
326
  },
290
- },
327
+ ],
291
328
  },
292
329
  header: {
293
330
  flexDirection: 'row',
@@ -333,7 +370,16 @@ const styles = StyleSheet.create((theme, rt) => ({
333
370
  footerWrap: {
334
371
  backgroundColor: theme.color.surface.neutral.strong,
335
372
  paddingHorizontal: theme.components.bottomSheet.padding,
336
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
373
+ variants: {
374
+ useSafeAreaInsets: {
375
+ true: {
376
+ paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
377
+ },
378
+ false: {
379
+ paddingBottom: theme.components.bottomSheet.padding,
380
+ },
381
+ },
382
+ },
337
383
  },
338
384
  }));
339
385
 
@@ -336,7 +336,9 @@ const styles = StyleSheet.create((theme, rt) => ({
336
336
  flex: 1,
337
337
  variants: {
338
338
  background: {
339
- primary: {},
339
+ primary: {
340
+ backgroundColor: theme.color.surface.neutral.strong,
341
+ },
340
342
  brand: {
341
343
  backgroundColor: theme.color.background.brand,
342
344
  },
@@ -345,11 +347,9 @@ const styles = StyleSheet.create((theme, rt) => ({
345
347
  modal: {
346
348
  borderTopLeftRadius: theme.components.modal.borderRadius,
347
349
  borderTopRightRadius: theme.components.modal.borderRadius,
348
- backgroundColor: theme.color.surface.neutral.strong,
349
350
  padding: theme.components.bottomSheet.padding,
350
351
  },
351
352
  fullScreen: {
352
- backgroundColor: theme.color.surface.neutral.strong,
353
353
  padding: theme.components.bottomSheet.padding,
354
354
  },
355
355
  },
@@ -10,6 +10,7 @@ import {
10
10
  BottomSheetScrollView,
11
11
  BottomSheetView,
12
12
  } from '../BottomSheet';
13
+ import { useBottomSheetContext } from '../BottomSheet/BottomSheet.context';
13
14
  import { DetailText } from '../DetailText';
14
15
  import { FormField, useFormFieldContext } from '../FormField';
15
16
  import { Icon } from '../Icon';
@@ -49,6 +50,7 @@ const Select = ({
49
50
  const isRequired = formFieldContext?.required ?? required;
50
51
  const isDisabled = formFieldContext?.disabled ?? disabled;
51
52
  const isReadonly = formFieldContext?.readonly ?? readonly;
53
+ const { useSafeAreaInsets } = useBottomSheetContext();
52
54
 
53
55
  const bottomSheetModalRef = useRef<BottomSheetModal>(null);
54
56
  const [search, setSearch] = useState('');
@@ -183,7 +185,7 @@ const Select = ({
183
185
  close: closeBottomSheet,
184
186
  }}
185
187
  >
186
- <SafeAreaView edges={['top']} style={{ flex: 1 }}>
188
+ <SafeAreaView edges={useSafeAreaInsets ? ['top'] : []} style={{ flex: 1 }}>
187
189
  {menuHeading && (
188
190
  <View style={styles.headingContainer}>
189
191
  <DetailText size="lg">{menuHeading}</DetailText>