@momo-kits/foundation 0.168.1-beta.36 → 0.168.1-beta.38

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 (138) hide show
  1. package/Application/BottomSheet.hooks.ts +25 -45
  2. package/Application/BottomSheet.parts.tsx +79 -153
  3. package/Application/BottomSheet.styles.ts +7 -23
  4. package/Application/BottomSheet.tsx +86 -268
  5. package/Application/BottomTab/ActiveIndicator.tsx +15 -14
  6. package/Application/BottomTab/BottomTabBar.styles.ts +65 -0
  7. package/Application/BottomTab/BottomTabBar.tsx +53 -134
  8. package/Application/BottomTab/BottomTabInset.tsx +8 -4
  9. package/Application/BottomTab/CurvedContainer.tsx +14 -12
  10. package/Application/BottomTab/CustomBottomTabItem.tsx +13 -13
  11. package/Application/BottomTab/DuoBarCompression.tsx +13 -19
  12. package/Application/BottomTab/DuoRailTabBar.tsx +223 -0
  13. package/Application/BottomTab/DuoTabBar.styles.ts +81 -0
  14. package/Application/BottomTab/DuoTabBar.tsx +20 -315
  15. package/Application/BottomTab/TabBarIcon.tsx +15 -29
  16. package/Application/BottomTab/TabScreen.tsx +160 -0
  17. package/Application/BottomTab/index.tsx +40 -194
  18. package/Application/BottomTab/metrics.ts +23 -23
  19. package/Application/BottomTab/tabItems.ts +1 -1
  20. package/Application/BottomTab/usePressLift.ts +2 -2
  21. package/Application/Components/BackgroundImageView.tsx +4 -0
  22. package/Application/Components/DuoGlassBackground.tsx +5 -4
  23. package/Application/Components/HeaderAnimated.tsx +40 -12
  24. package/Application/Components/HeaderBackground.tsx +19 -2
  25. package/Application/Components/HeaderExtendHeader.tsx +56 -34
  26. package/Application/Components/HeaderLeft.tsx +4 -2
  27. package/Application/Components/HeaderRight.styles.ts +15 -9
  28. package/Application/Components/HeaderRight.tsx +2 -1
  29. package/Application/Components/HeaderTitle.shared.ts +19 -12
  30. package/Application/Components/HeaderTitle.tsx +4 -3
  31. package/Application/Components/HeaderToolkitAction.tsx +28 -22
  32. package/Application/Components/NavigationButton.tsx +10 -6
  33. package/Application/Components/SearchHeader.tsx +41 -15
  34. package/Application/Components/TitleJourney.tsx +2 -2
  35. package/Application/Components/TitleLocation.tsx +2 -2
  36. package/Application/Components/TitleUser.tsx +2 -2
  37. package/Application/Components/useToolkitActions.tsx +17 -32
  38. package/Application/Localize.ts +7 -0
  39. package/Application/ModalScreen.tsx +10 -4
  40. package/Application/Navigation.ts +14 -16
  41. package/Application/NavigationContainer.tsx +19 -16
  42. package/Application/Navigator.ts +20 -48
  43. package/Application/ScaleSizeProvider.tsx +13 -6
  44. package/Application/StackScreen.tracking.ts +11 -26
  45. package/Application/StackScreen.tsx +17 -35
  46. package/Application/TooltipPortal.tsx +12 -5
  47. package/Application/WidgetContainer.tsx +10 -4
  48. package/Application/headerLayout.ts +158 -0
  49. package/Application/index.ts +17 -3
  50. package/Application/modalLayout.ts +15 -19
  51. package/Application/navigationOptions.tsx +27 -32
  52. package/Application/types.header.ts +7 -2
  53. package/Application/types.tabs.ts +5 -0
  54. package/Application/types.ts +17 -245
  55. package/Application/utils.ts +0 -36
  56. package/Badge/Badge.tsx +5 -0
  57. package/Badge/BadgeDot.tsx +1 -0
  58. package/Badge/BadgeDotAnimation.tsx +15 -7
  59. package/Badge/BadgeRibbon.tsx +46 -38
  60. package/Badge/Shape.tsx +2 -0
  61. package/Badge/types.ts +2 -2
  62. package/Button/index.tsx +5 -16
  63. package/Button/utils.ts +9 -15
  64. package/CheckBox/index.tsx +4 -0
  65. package/Consts/theme.ts +10 -10
  66. package/Context/index.ts +5 -1
  67. package/Divider/DashDivider.tsx +1 -0
  68. package/Divider/index.tsx +4 -0
  69. package/FoundationList/index.tsx +4 -0
  70. package/Icon/index.tsx +6 -6
  71. package/Icon/types.ts +1 -1
  72. package/IconButton/index.tsx +4 -12
  73. package/Image/index.tsx +9 -7
  74. package/Input/Input.tsx +8 -9
  75. package/Input/InputDropDown.tsx +10 -12
  76. package/Input/InputMoney.tsx +12 -8
  77. package/Input/InputMoneyView.tsx +14 -7
  78. package/Input/InputOTP.tsx +35 -33
  79. package/Input/InputPhoneNumber.tsx +8 -9
  80. package/Input/InputSearch.tsx +22 -8
  81. package/Input/InputTextArea.tsx +4 -0
  82. package/Input/SearchTextTyping.tsx +4 -0
  83. package/Input/SystemTextInput.tsx +7 -2
  84. package/Input/TextTyping.tsx +4 -0
  85. package/Input/common.tsx +26 -12
  86. package/Input/index.tsx +24 -21
  87. package/Input/moneyUtils.ts +10 -4
  88. package/Input/styles.ts +0 -5
  89. package/Input/utils.ts +14 -12
  90. package/Layout/Card.tsx +7 -4
  91. package/Layout/FloatingButton.tsx +4 -0
  92. package/Layout/Item.tsx +6 -2
  93. package/Layout/ItemList.tsx +9 -7
  94. package/Layout/ItemSectionList.tsx +2 -1
  95. package/Layout/ReservedRegions.tsx +25 -25
  96. package/Layout/Screen.tsx +112 -696
  97. package/Layout/Section.tsx +8 -5
  98. package/Layout/TrackingScope.tsx +1 -0
  99. package/Layout/index.ts +8 -3
  100. package/Layout/screenContent.tsx +92 -0
  101. package/Layout/screenFooter.tsx +63 -0
  102. package/Layout/screenHeader.tsx +321 -0
  103. package/Layout/screenQuickReturn.tsx +64 -0
  104. package/Layout/screenScroll.ts +107 -0
  105. package/Layout/screenTypes.ts +143 -0
  106. package/Layout/types.ts +2 -4
  107. package/Layout/utils.ts +31 -37
  108. package/Loader/DotLoader.tsx +4 -0
  109. package/Loader/Loader.tsx +4 -0
  110. package/Loader/ProgressBar.tsx +1 -0
  111. package/Loader/Spinner.tsx +4 -0
  112. package/Loader/utils.ts +11 -7
  113. package/Pagination/Dot.tsx +4 -0
  114. package/Pagination/PaginationDot.tsx +1 -0
  115. package/Pagination/PaginationNumber.tsx +5 -3
  116. package/Pagination/PaginationScroll.tsx +5 -0
  117. package/Pagination/PaginationWhiteDot.tsx +1 -0
  118. package/Pagination/index.tsx +4 -0
  119. package/Pagination/types.ts +2 -2
  120. package/Popup/PopupNotify.tsx +44 -48
  121. package/Popup/PopupPromotion.tsx +4 -7
  122. package/Popup/types.ts +4 -4
  123. package/Popup/utils.ts +4 -0
  124. package/Radio/index.tsx +4 -0
  125. package/Skeleton/index.tsx +8 -0
  126. package/Switch/index.tsx +1 -0
  127. package/Tag/index.tsx +5 -1
  128. package/Tag/types.ts +3 -3
  129. package/Text/index.tsx +14 -3
  130. package/Text/styles.ts +1 -1
  131. package/Text/types.ts +1 -6
  132. package/Text/utils.ts +20 -4
  133. package/Title/index.tsx +41 -32
  134. package/ViewBoundary/index.tsx +4 -2
  135. package/index.ts +0 -6
  136. package/package.json +7 -7
  137. package/Application/__tests__/modalLayout.test.ts +0 -128
  138. package/Application/device.ts +0 -21
@@ -16,43 +16,24 @@ import {
16
16
  } from 'react-native';
17
17
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
18
18
  import { useHeaderHeight } from '@react-navigation/elements';
19
- import { Spacing } from '../Consts';
20
- import { DuoMetrics, useScreenLayout } from '../Layout/utils';
21
19
  import { scheduleOnRN } from 'react-native-worklets';
22
20
  import { BottomSheetParams, NavigatorProps } from './types';
23
- import { getDuoTopInset, isIPhoneDuo } from './utils';
24
- import { DUO_REGULAR_MIN_WIDTH, getSideInset } from './BottomSheet.styles';
21
+ import { isIPhoneDuo } from './utils';
22
+ import { useModalLayout } from './modalLayout';
25
23
 
24
+ /**
25
+ * Sheet geometry for the current window: foldable placement and size from
26
+ * `useModalLayout`, plus the insets and offsets the keyboard handling needs.
27
+ */
26
28
  export const useBottomSheetLayout = () => {
27
29
  const windowSize = useWindowDimensions();
28
30
  const isDuo = isIPhoneDuo();
29
- const isDuoCentered =
30
- isDuo &&
31
- Math.min(windowSize.width, windowSize.height) >= DUO_REGULAR_MIN_WIDTH;
32
- const isDuoFloating = isDuo && !isDuoCentered;
33
- const { sideBar } = useScreenLayout();
34
- const sideColumnWidth = (sideBar?.width ?? 0) - Spacing.M;
35
- const sideColumn =
36
- isDuoFloating &&
37
- sideColumnWidth >= DuoMetrics.controlSize + Spacing.M &&
38
- sideBar
39
- ? sideBar
40
- : undefined;
41
- const hasSideColumn = !!sideColumn;
31
+ const { isFoldable, placement, sheet, scrimOpacity } = useModalLayout();
42
32
  // 'screen' is the outer display on iPhone Duo, even when unfolded
43
33
  const screenHeight = Dimensions.get('screen').height;
44
34
  const heightDevice = isDuo ? windowSize.height : screenHeight;
45
35
  const insets = useSafeAreaInsets();
46
36
  const heightHeader = useHeaderHeight();
47
- const topGap = Math.max(
48
- sideColumn
49
- ? insets.top
50
- : getDuoTopInset(insets, windowSize.width, windowSize.height),
51
- Spacing.XL,
52
- );
53
- const sideInsetLeft = isDuoFloating ? getSideInset(insets.left) : 0;
54
- const sideInsetRight = isDuoFloating ? getSideInset(insets.right) : 0;
55
- const indicatorShift = (sideInsetRight - sideInsetLeft) / 2;
56
37
  const isIOS = Platform.OS === 'ios';
57
38
  const bottomInset = isIOS ? Math.min(insets.bottom, 21) : insets.bottom;
58
39
  const keyboardOffset = heightHeader - bottomInset;
@@ -60,24 +41,20 @@ export const useBottomSheetLayout = () => {
60
41
  return {
61
42
  windowSize,
62
43
  isDuo,
63
- isDuoCentered,
64
- isDuoFloating,
65
- sideColumn,
66
- sideColumnWidth,
67
- hasSideColumn,
44
+ isFoldable,
45
+ placement,
46
+ sheet,
47
+ scrimOpacity,
68
48
  heightDevice,
69
- insets,
70
- topGap,
71
- sideInsetLeft,
72
- sideInsetRight,
73
- indicatorShift,
74
49
  bottomInset,
75
50
  keyboardOffset,
76
51
  };
77
52
  };
78
53
 
79
- // KeyboardAvoidingView lifts the whole sheet past the top on iPhone Duo,
80
- // so lift it here and shrink maxHeight by the same amount instead
54
+ /**
55
+ * Keyboard lift of the sheet on iPhone Duo, where KeyboardAvoidingView pushes
56
+ * the whole sheet past the top; the sheet lifts by it and shrinks its maxHeight.
57
+ */
81
58
  export const useDuoKeyboardLift = (
82
59
  isDuo: boolean,
83
60
  useKeyboardAvoidingView: boolean,
@@ -124,9 +101,14 @@ export const useDuoKeyboardLift = (
124
101
  return keyboardLift;
125
102
  };
126
103
 
104
+ /**
105
+ * Slide of the sheet and fade of the scrim behind it, up to the
106
+ * `scrimOpacity` of the modal spec (lighter on foldables).
107
+ */
127
108
  export const useSheetAnimatedStyles = (
128
109
  translateY: SharedValue<number>,
129
110
  heightDevice: number,
111
+ scrimOpacity: number,
130
112
  ) => {
131
113
  const animatedStyle = useAnimatedStyle(() => {
132
114
  return {
@@ -139,7 +121,7 @@ export const useSheetAnimatedStyles = (
139
121
  opacity: interpolate(
140
122
  translateY.value,
141
123
  [0, heightDevice],
142
- [1, 0],
124
+ [scrimOpacity, 0],
143
125
  Extrapolation.CLAMP,
144
126
  ),
145
127
  };
@@ -156,6 +138,10 @@ type SheetDismissParams = {
156
138
  action: MutableRefObject<undefined | string>;
157
139
  };
158
140
 
141
+ /**
142
+ * Close handlers of a bottom sheet. A non-forced dismiss (scrim tap, hardware
143
+ * back) is ignored while `barrierDismissible` is set.
144
+ */
159
145
  export const useSheetDismiss = ({
160
146
  barrierDismissible,
161
147
  closeAnimation,
@@ -163,9 +149,6 @@ export const useSheetDismiss = ({
163
149
  leftOptions,
164
150
  action,
165
151
  }: SheetDismissParams) => {
166
- /**
167
- * handler dismiss
168
- */
169
152
  const onDismiss = useCallback(
170
153
  (force = false, callback?: () => void) => {
171
154
  if (barrierDismissible && !force) {
@@ -181,9 +164,6 @@ export const useSheetDismiss = ({
181
164
  [barrierDismissible, closeAnimation, navigator],
182
165
  );
183
166
 
184
- /**
185
- * on request close
186
- */
187
167
  const onRequestClose = useCallback(
188
168
  (callback?: () => void) => {
189
169
  onDismiss(true, callback);
@@ -1,68 +1,67 @@
1
1
  import React from 'react';
2
- import {
3
- PanResponderInstance,
4
- ScaledSize,
5
- TouchableOpacity,
6
- View,
7
- } from 'react-native';
8
- import type { EdgeInsets } from 'react-native-safe-area-context';
9
- import { Radius, Spacing, Styles } from '../Consts';
2
+ import { PanResponderInstance, View, ViewStyle } from 'react-native';
3
+ import { Spacing, Styles } from '../Consts';
10
4
  import layoutStyles from '../Layout/styles';
11
5
  import { Text } from '../Text';
12
- import { Icon } from '../Icon';
13
- import { InnerEdgeStyles, type SideBarLayout } from '../Layout/utils';
14
- import { SideBarButton } from './Components/SideBarButton';
15
- import {
16
- INDICATOR_HEIGHT,
17
- SIDE_COLUMN_OFFSET,
18
- styles,
19
- } from './BottomSheet.styles';
6
+ import { INDICATOR_HEIGHT, styles } from './BottomSheet.styles';
7
+ import { ModalIconButton } from './ModalIconButton';
8
+ import { type ModalLayout } from './modalLayout';
20
9
  import { BottomSheetParams, Theme } from './types';
21
10
 
22
- type SheetPartsParams = {
11
+ type SheetHeaderParams = {
23
12
  panHandlers: PanResponderInstance['panHandlers'];
24
- indicatorShift: number;
25
13
  useDivider: boolean;
26
14
  theme: Theme;
27
- hasSideColumn: boolean;
28
15
  showBack: boolean;
29
16
  onPressBack: () => void;
30
17
  onPressClose: () => void;
31
18
  iconBack: string;
32
19
  options: BottomSheetParams['options'];
33
20
  leftOptions: BottomSheetParams['leftOptions'];
34
- sideColumn?: SideBarLayout;
35
- windowHeight: number;
36
- sheetTop: number;
37
- sideColumnHeight: number;
38
- sideColumnWidth: number;
39
21
  };
40
22
 
23
+ /**
24
+ * Drag handle and header row: back, title (or a custom header) and close, with
25
+ * the 32 modal icon buttons on every device.
26
+ */
41
27
  export const renderSheetHeader = ({
42
28
  panHandlers,
43
- indicatorShift,
44
29
  useDivider,
45
30
  theme,
46
- hasSideColumn,
47
31
  showBack,
48
32
  onPressBack,
49
33
  onPressClose,
50
34
  iconBack,
51
35
  options,
52
36
  leftOptions,
53
- }: SheetPartsParams) => {
54
- const showButtons = !hasSideColumn;
37
+ }: SheetHeaderParams) => {
38
+ let backButton: React.ReactNode = null;
39
+ if (showBack) {
40
+ backButton = <ModalIconButton icon={iconBack} onPress={onPressBack} />;
41
+ }
42
+
43
+ let headerContent: React.ReactNode;
44
+ if (options.header) {
45
+ headerContent = <View style={Styles.flex}>{options.header}</View>;
46
+ } else {
47
+ headerContent = (
48
+ <>
49
+ {!leftOptions ? <View style={styles.iconButtonSpace} /> : null}
50
+ <Text
51
+ style={[Styles.flex, styles.title]}
52
+ numberOfLines={1}
53
+ typography="header_default_bold"
54
+ >
55
+ {options.title ?? ''}
56
+ </Text>
57
+ </>
58
+ );
59
+ }
60
+
55
61
  return (
56
62
  <View {...panHandlers}>
57
63
  <View style={{ height: INDICATOR_HEIGHT }}>
58
- <View
59
- style={[
60
- styles.indicator,
61
- indicatorShift !== 0 && {
62
- transform: [{ translateX: indicatorShift }],
63
- },
64
- ]}
65
- />
64
+ <View style={styles.indicator} />
66
65
  </View>
67
66
  <View
68
67
  style={[
@@ -73,97 +72,29 @@ export const renderSheetHeader = ({
73
72
  },
74
73
  ]}
75
74
  >
76
- {showButtons && showBack ? (
77
- <TouchableOpacity style={styles.iconButton} onPress={onPressBack}>
78
- <Icon source={iconBack} />
79
- </TouchableOpacity>
80
- ) : null}
75
+ {backButton}
81
76
 
82
- {options.header ? (
83
- <View style={Styles.flex}>{options.header}</View>
84
- ) : (
85
- <>
86
- {showButtons && !leftOptions ? (
87
- <View style={styles.iconButton} />
88
- ) : null}
89
- <Text
90
- style={[
91
- Styles.flex,
92
- styles.title,
93
- !showButtons && styles.titleInset,
94
- ]}
95
- numberOfLines={1}
96
- typography="header_default_bold"
97
- >
98
- {options.title ?? ''}
99
- </Text>
100
- </>
101
- )}
102
- {showButtons ? (
103
- <TouchableOpacity style={styles.iconButton} onPress={onPressClose}>
104
- <Icon source="navigation_close" />
105
- </TouchableOpacity>
106
- ) : null}
77
+ {headerContent}
78
+ <ModalIconButton icon="navigation_close" onPress={onPressClose} />
107
79
  </View>
108
80
  </View>
109
81
  );
110
82
  };
111
83
 
112
84
  /**
113
- * iPhone Duo folded: back and close move to the side bar column, drawn on
114
- * the part of the sheet under the side safe area. They line up with the
115
- * header row, stay below the status bar cluster on a tall sheet and above a
116
- * camera at the bottom end of the strip.
85
+ * Footer pinned under the sheet content, `null` when the sheet has none.
117
86
  */
118
- export const renderSheetSideColumn = ({
119
- sideColumn,
120
- windowHeight,
121
- sheetTop,
122
- sideColumnHeight,
123
- sideColumnWidth,
124
- showBack,
125
- iconBack,
126
- onPressBack,
127
- onPressClose,
128
- }: SheetPartsParams) => {
129
- if (!sideColumn) {
130
- return null;
131
- }
132
- const lowestTop =
133
- windowHeight - sideColumn.bottom - sideColumnHeight - sheetTop;
134
- const top = Math.min(
135
- Math.max(sideColumn.top - sheetTop, SIDE_COLUMN_OFFSET),
136
- lowestTop,
137
- );
138
-
139
- return (
140
- <View
141
- pointerEvents={'box-none'}
142
- style={[
143
- styles.sideColumn,
144
- sideColumn.edge === 'right' ? styles.alignRight : styles.alignLeft,
145
- InnerEdgeStyles[sideColumn.edge],
146
- { top, width: sideColumnWidth },
147
- ]}
148
- >
149
- {showBack ? (
150
- <SideBarButton icon={iconBack} onPress={onPressBack} />
151
- ) : null}
152
- <SideBarButton icon="navigation_close" onPress={onPressClose} />
153
- </View>
154
- );
155
- };
156
-
157
87
  export const renderSheetFooter = ({
158
88
  footerComponent,
159
89
  theme,
160
- sideInsetStyle,
161
90
  }: {
162
91
  footerComponent: BottomSheetParams['footerComponent'];
163
92
  theme: Theme;
164
- sideInsetStyle: any;
165
- }) =>
166
- footerComponent && (
93
+ }) => {
94
+ if (!footerComponent) {
95
+ return null;
96
+ }
97
+ return (
167
98
  <View
168
99
  style={[
169
100
  layoutStyles.shadow,
@@ -171,61 +102,56 @@ export const renderSheetFooter = ({
171
102
  paddingBottom: Spacing.S,
172
103
  backgroundColor: theme.colors.background.surface,
173
104
  },
174
- sideInsetStyle,
175
105
  ]}
176
106
  >
177
107
  {footerComponent}
178
108
  </View>
179
109
  );
110
+ };
180
111
 
181
112
  type SheetStyleParams = {
182
113
  backgroundColor: string;
183
114
  isDuo: boolean;
184
- isDuoFloating: boolean;
185
- isDuoCentered: boolean;
186
- windowSize: ScaledSize;
187
- topGap: number;
115
+ isFoldable: boolean;
116
+ placement: ModalLayout['placement'];
117
+ sheet: ModalLayout['sheet'];
188
118
  keyboardLift: number;
189
- sideColumn?: SideBarLayout;
190
- sideColumnHeight: number;
191
- insets: EdgeInsets;
192
119
  showBaseLineDebug: boolean;
193
120
  };
194
121
 
122
+ /**
123
+ * Sheet container style. On foldables the sheet is centered in the placement
124
+ * area, clear of the iPhone Duo control column and on the right half when half
125
+ * folded; the keyboard lift comes off its max height.
126
+ */
195
127
  export const getSheetStyle = ({
196
128
  backgroundColor,
197
129
  isDuo,
198
- isDuoFloating,
199
- isDuoCentered,
200
- windowSize,
201
- topGap,
130
+ isFoldable,
131
+ placement,
132
+ sheet,
202
133
  keyboardLift,
203
- sideColumn,
204
- sideColumnHeight,
205
- insets,
206
134
  showBaseLineDebug,
207
- }: SheetStyleParams) => [
208
- styles.sheetContainer,
209
- {
210
- backgroundColor,
211
- borderTopLeftRadius: isDuo ? Radius.XL : Radius.M,
212
- borderTopRightRadius: isDuo ? Radius.XL : Radius.M,
213
- },
214
- isDuo && {
215
- maxHeight: windowSize.height - topGap - keyboardLift,
216
- marginBottom: keyboardLift,
217
- },
218
- isDuoFloating && { marginHorizontal: Spacing.M },
219
- sideColumn && {
220
- minHeight: SIDE_COLUMN_OFFSET + sideColumnHeight + sideColumn.bottom,
221
- },
222
- isDuoCentered && styles.centered,
223
- isDuoCentered && {
224
- // keeps the portrait width in landscape, like system sheets
225
- width: Math.min(
226
- Math.min(windowSize.width, windowSize.height) - Spacing.L * 2,
227
- windowSize.width - Math.max(insets.left, insets.right, Spacing.L) * 2,
228
- ),
229
- },
230
- showBaseLineDebug && styles.debugBaseLine,
231
- ];
135
+ }: SheetStyleParams) => {
136
+ const { width, maxHeight } = sheet;
137
+ let foldableStyle: ViewStyle | undefined;
138
+ if (isFoldable && width !== undefined && maxHeight !== undefined) {
139
+ foldableStyle = {
140
+ width,
141
+ marginLeft: placement.x + (placement.width - width) / 2,
142
+ maxHeight: maxHeight - keyboardLift,
143
+ minHeight: sheet.minHeight,
144
+ };
145
+ }
146
+ return [
147
+ styles.sheetContainer,
148
+ {
149
+ backgroundColor,
150
+ borderTopLeftRadius: sheet.radius,
151
+ borderTopRightRadius: sheet.radius,
152
+ },
153
+ isDuo && { marginBottom: keyboardLift },
154
+ foldableStyle,
155
+ showBaseLineDebug && styles.debugBaseLine,
156
+ ];
157
+ };
@@ -1,17 +1,10 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
  import { Colors, Radius, Spacing } from '../Consts';
3
- import { DuoMetrics } from '../Layout/utils';
4
-
5
- // iPhone Duo inner display: center the sheet instead of spanning the width
6
- export const DUO_REGULAR_MIN_WIDTH = 600;
3
+ import { MODAL_ICON_BUTTON_SIZE } from './ModalIconButton';
7
4
 
8
5
  export const INDICATOR_HEIGHT = 16;
9
6
  export const HEADER_HEIGHT = 56;
10
7
  export const DUO_ORIENTATIONS = ['portrait', 'landscape'];
11
- export const SIDE_COLUMN_OFFSET =
12
- INDICATOR_HEIGHT + (HEADER_HEIGHT - DuoMetrics.controlSize) / 2;
13
-
14
- export const getSideInset = (inset: number) => Math.max(inset - Spacing.M, 0);
15
8
 
16
9
  export const styles = StyleSheet.create({
17
10
  container: {
@@ -20,7 +13,7 @@ export const styles = StyleSheet.create({
20
13
  },
21
14
  overlay: {
22
15
  flex: 1,
23
- backgroundColor: 'rgba(0, 0, 0, 0.6)',
16
+ backgroundColor: Colors.black_20,
24
17
  },
25
18
  indicator: {
26
19
  width: 40,
@@ -35,25 +28,16 @@ export const styles = StyleSheet.create({
35
28
  height: HEADER_HEIGHT,
36
29
  flexDirection: 'row',
37
30
  alignItems: 'center',
31
+ paddingHorizontal: Spacing.M,
32
+ gap: Spacing.S,
38
33
  },
39
34
  title: { textAlign: 'center' },
40
- titleInset: { paddingHorizontal: Spacing.M },
41
- iconButton: {
42
- width: 24,
43
- height: 24,
44
- alignItems: 'center',
45
- justifyContent: 'center',
46
- marginHorizontal: Spacing.M,
35
+ iconButtonSpace: {
36
+ width: MODAL_ICON_BUTTON_SIZE,
37
+ height: MODAL_ICON_BUTTON_SIZE,
47
38
  },
48
39
  shrink: { flexShrink: 1 },
49
- sideColumn: {
50
- position: 'absolute',
51
- gap: Spacing.M,
52
- },
53
- alignRight: { right: 0 },
54
- alignLeft: { left: 0 },
55
40
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
56
41
  headerDivider: { borderBottomWidth: 1 },
57
42
  sheetContainer: { overflow: 'hidden' },
58
- centered: { alignSelf: 'center' },
59
43
  });