@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.
- package/Application/BottomSheet.hooks.ts +25 -45
- package/Application/BottomSheet.parts.tsx +79 -153
- package/Application/BottomSheet.styles.ts +7 -23
- package/Application/BottomSheet.tsx +86 -268
- package/Application/BottomTab/ActiveIndicator.tsx +15 -14
- package/Application/BottomTab/BottomTabBar.styles.ts +65 -0
- package/Application/BottomTab/BottomTabBar.tsx +53 -134
- package/Application/BottomTab/BottomTabInset.tsx +8 -4
- package/Application/BottomTab/CurvedContainer.tsx +14 -12
- package/Application/BottomTab/CustomBottomTabItem.tsx +13 -13
- package/Application/BottomTab/DuoBarCompression.tsx +13 -19
- package/Application/BottomTab/DuoRailTabBar.tsx +223 -0
- package/Application/BottomTab/DuoTabBar.styles.ts +81 -0
- package/Application/BottomTab/DuoTabBar.tsx +20 -315
- package/Application/BottomTab/TabBarIcon.tsx +15 -29
- package/Application/BottomTab/TabScreen.tsx +160 -0
- package/Application/BottomTab/index.tsx +40 -194
- package/Application/BottomTab/metrics.ts +23 -23
- package/Application/BottomTab/tabItems.ts +1 -1
- package/Application/BottomTab/usePressLift.ts +2 -2
- package/Application/Components/BackgroundImageView.tsx +4 -0
- package/Application/Components/DuoGlassBackground.tsx +5 -4
- package/Application/Components/HeaderAnimated.tsx +40 -12
- package/Application/Components/HeaderBackground.tsx +19 -2
- package/Application/Components/HeaderExtendHeader.tsx +56 -34
- package/Application/Components/HeaderLeft.tsx +4 -2
- package/Application/Components/HeaderRight.styles.ts +15 -9
- package/Application/Components/HeaderRight.tsx +2 -1
- package/Application/Components/HeaderTitle.shared.ts +19 -12
- package/Application/Components/HeaderTitle.tsx +4 -3
- package/Application/Components/HeaderToolkitAction.tsx +28 -22
- package/Application/Components/NavigationButton.tsx +10 -6
- package/Application/Components/SearchHeader.tsx +41 -15
- package/Application/Components/TitleJourney.tsx +2 -2
- package/Application/Components/TitleLocation.tsx +2 -2
- package/Application/Components/TitleUser.tsx +2 -2
- package/Application/Components/useToolkitActions.tsx +17 -32
- package/Application/Localize.ts +7 -0
- package/Application/ModalScreen.tsx +10 -4
- package/Application/Navigation.ts +14 -16
- package/Application/NavigationContainer.tsx +19 -16
- package/Application/Navigator.ts +20 -48
- package/Application/ScaleSizeProvider.tsx +13 -6
- package/Application/StackScreen.tracking.ts +11 -26
- package/Application/StackScreen.tsx +17 -35
- package/Application/TooltipPortal.tsx +12 -5
- package/Application/WidgetContainer.tsx +10 -4
- package/Application/headerLayout.ts +158 -0
- package/Application/index.ts +17 -3
- package/Application/modalLayout.ts +15 -19
- package/Application/navigationOptions.tsx +27 -32
- package/Application/types.header.ts +7 -2
- package/Application/types.tabs.ts +5 -0
- package/Application/types.ts +17 -245
- package/Application/utils.ts +0 -36
- package/Badge/Badge.tsx +5 -0
- package/Badge/BadgeDot.tsx +1 -0
- package/Badge/BadgeDotAnimation.tsx +15 -7
- package/Badge/BadgeRibbon.tsx +46 -38
- package/Badge/Shape.tsx +2 -0
- package/Badge/types.ts +2 -2
- package/Button/index.tsx +5 -16
- package/Button/utils.ts +9 -15
- package/CheckBox/index.tsx +4 -0
- package/Consts/theme.ts +10 -10
- package/Context/index.ts +5 -1
- package/Divider/DashDivider.tsx +1 -0
- package/Divider/index.tsx +4 -0
- package/FoundationList/index.tsx +4 -0
- package/Icon/index.tsx +6 -6
- package/Icon/types.ts +1 -1
- package/IconButton/index.tsx +4 -12
- package/Image/index.tsx +9 -7
- package/Input/Input.tsx +8 -9
- package/Input/InputDropDown.tsx +10 -12
- package/Input/InputMoney.tsx +12 -8
- package/Input/InputMoneyView.tsx +14 -7
- package/Input/InputOTP.tsx +35 -33
- package/Input/InputPhoneNumber.tsx +8 -9
- package/Input/InputSearch.tsx +22 -8
- package/Input/InputTextArea.tsx +4 -0
- package/Input/SearchTextTyping.tsx +4 -0
- package/Input/SystemTextInput.tsx +7 -2
- package/Input/TextTyping.tsx +4 -0
- package/Input/common.tsx +26 -12
- package/Input/index.tsx +24 -21
- package/Input/moneyUtils.ts +10 -4
- package/Input/styles.ts +0 -5
- package/Input/utils.ts +14 -12
- package/Layout/Card.tsx +7 -4
- package/Layout/FloatingButton.tsx +4 -0
- package/Layout/Item.tsx +6 -2
- package/Layout/ItemList.tsx +9 -7
- package/Layout/ItemSectionList.tsx +2 -1
- package/Layout/ReservedRegions.tsx +25 -25
- package/Layout/Screen.tsx +112 -696
- package/Layout/Section.tsx +8 -5
- package/Layout/TrackingScope.tsx +1 -0
- package/Layout/index.ts +8 -3
- package/Layout/screenContent.tsx +92 -0
- package/Layout/screenFooter.tsx +63 -0
- package/Layout/screenHeader.tsx +321 -0
- package/Layout/screenQuickReturn.tsx +64 -0
- package/Layout/screenScroll.ts +107 -0
- package/Layout/screenTypes.ts +143 -0
- package/Layout/types.ts +2 -4
- package/Layout/utils.ts +31 -37
- package/Loader/DotLoader.tsx +4 -0
- package/Loader/Loader.tsx +4 -0
- package/Loader/ProgressBar.tsx +1 -0
- package/Loader/Spinner.tsx +4 -0
- package/Loader/utils.ts +11 -7
- package/Pagination/Dot.tsx +4 -0
- package/Pagination/PaginationDot.tsx +1 -0
- package/Pagination/PaginationNumber.tsx +5 -3
- package/Pagination/PaginationScroll.tsx +5 -0
- package/Pagination/PaginationWhiteDot.tsx +1 -0
- package/Pagination/index.tsx +4 -0
- package/Pagination/types.ts +2 -2
- package/Popup/PopupNotify.tsx +44 -48
- package/Popup/PopupPromotion.tsx +4 -7
- package/Popup/types.ts +4 -4
- package/Popup/utils.ts +4 -0
- package/Radio/index.tsx +4 -0
- package/Skeleton/index.tsx +8 -0
- package/Switch/index.tsx +1 -0
- package/Tag/index.tsx +5 -1
- package/Tag/types.ts +3 -3
- package/Text/index.tsx +14 -3
- package/Text/styles.ts +1 -1
- package/Text/types.ts +1 -6
- package/Text/utils.ts +20 -4
- package/Title/index.tsx +41 -32
- package/ViewBoundary/index.tsx +4 -2
- package/index.ts +0 -6
- package/package.json +7 -7
- package/Application/__tests__/modalLayout.test.ts +0 -128
- 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 {
|
|
24
|
-
import {
|
|
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
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
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 {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
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
|
|
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
|
-
}:
|
|
54
|
-
|
|
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
|
-
{
|
|
77
|
-
<TouchableOpacity style={styles.iconButton} onPress={onPressBack}>
|
|
78
|
-
<Icon source={iconBack} />
|
|
79
|
-
</TouchableOpacity>
|
|
80
|
-
) : null}
|
|
75
|
+
{backButton}
|
|
81
76
|
|
|
82
|
-
{
|
|
83
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
topGap,
|
|
130
|
+
isFoldable,
|
|
131
|
+
placement,
|
|
132
|
+
sheet,
|
|
202
133
|
keyboardLift,
|
|
203
|
-
sideColumn,
|
|
204
|
-
sideColumnHeight,
|
|
205
|
-
insets,
|
|
206
134
|
showBaseLineDebug,
|
|
207
|
-
}: SheetStyleParams) =>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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 {
|
|
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:
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
});
|