@momo-kits/foundation 0.169.9 → 0.169.10-beta.1
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 +17 -27
- package/Application/BottomSheet.tsx +27 -35
- package/Application/BottomTab/BottomTabBar.tsx +6 -6
- package/Application/BottomTab/DuoRailTabBar.tsx +5 -5
- package/Application/BottomTab/TabScreen.tsx +10 -11
- package/Application/BottomTab/index.tsx +5 -5
- package/Application/BottomTab/usePressLift.ts +3 -3
- package/Application/Components/HeaderAnimated.tsx +38 -13
- package/Application/Components/HeaderBackground.tsx +16 -3
- package/Application/Components/HeaderExtendHeader.tsx +41 -28
- package/Application/Components/HeaderLeft.tsx +4 -18
- package/Application/Components/HeaderRight.styles.ts +15 -13
- package/Application/Components/HeaderTitle.shared.ts +10 -11
- package/Application/Components/HeaderToolkitAction.tsx +21 -54
- package/Application/Components/NavigationButton.tsx +9 -6
- package/Application/Components/SearchHeader.tsx +20 -7
- package/Application/Components/useToolkitActions.tsx +21 -22
- package/Application/ModalScreen.tsx +15 -19
- package/Application/StackScreen.tsx +18 -13
- package/Application/headerLayout.ts +165 -0
- package/Application/index.ts +11 -1
- package/Application/modalLayout.ts +0 -1
- package/Application/navigationOptions.tsx +6 -15
- package/Application/types.header.ts +7 -2
- package/Application/types.ts +7 -0
- package/Context/index.ts +1 -3
- package/Image/index.tsx +6 -6
- package/Input/Input.tsx +37 -40
- package/Input/InputDropDown.tsx +10 -13
- package/Input/InputMoney.tsx +17 -17
- package/Input/InputMoneyView.tsx +12 -12
- package/Input/InputOTP.tsx +34 -46
- package/Input/InputPhoneNumber.tsx +43 -48
- package/Input/InputSearch.tsx +39 -26
- package/Input/InputTextArea.tsx +23 -29
- package/Input/common.tsx +257 -0
- package/Input/index.tsx +7 -1
- package/Input/moneyUtils.ts +23 -0
- package/Input/utils.ts +7 -126
- package/Layout/FloatingButton.tsx +24 -38
- package/Layout/Screen.tsx +3 -0
- package/Layout/layoutMetrics.ts +34 -43
- package/Layout/screenHeader.tsx +55 -52
- package/Layout/screenTypes.ts +13 -4
- package/Pagination/PaginationScroll.tsx +3 -5
- package/Pagination/types.ts +5 -3
- package/Popup/PopupNotify.tsx +14 -17
- package/Popup/PopupPromotion.tsx +4 -5
- package/Popup/types.ts +4 -2
- package/Popup/utils.ts +4 -7
- package/Skeleton/index.tsx +12 -15
- package/package.json +1 -1
- package/Input/ErrorView.tsx +0 -59
- package/Input/FloatingView.tsx +0 -101
- package/Input/RenderTrailing.tsx +0 -79
- package/Input/constants.ts +0 -8
|
@@ -17,11 +17,16 @@ import BackgroundImageView from './BackgroundImageView';
|
|
|
17
17
|
import { type AnimatedCompatValue } from '../utils';
|
|
18
18
|
import { useNormalizedSharedValue } from '../hooks';
|
|
19
19
|
import { useScreenLayout } from '../../Layout';
|
|
20
|
-
import {
|
|
20
|
+
import { HeaderMetrics } from '../../Layout/utils';
|
|
21
|
+
import {
|
|
22
|
+
HeaderBarMetrics,
|
|
23
|
+
type HeaderContentLayout,
|
|
24
|
+
useHeaderLayout,
|
|
25
|
+
} from '../headerLayout';
|
|
21
26
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const TOOLKIT_WIDTH =
|
|
27
|
+
const { buttonSize, pillWidth, sidePadding, titleGap } = HeaderBarMetrics;
|
|
28
|
+
const SCREEN_PADDING = sidePadding;
|
|
29
|
+
const TOOLKIT_WIDTH = pillWidth + sidePadding;
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
* Extended header background: a gradient that collapses on scroll and, with
|
|
@@ -38,6 +43,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
38
43
|
useShadowHeader?: boolean;
|
|
39
44
|
gradientColor?: string;
|
|
40
45
|
headerBackground?: string;
|
|
46
|
+
contentLayout?: HeaderContentLayout;
|
|
41
47
|
}> = ({
|
|
42
48
|
headerType = 'default',
|
|
43
49
|
animatedValue,
|
|
@@ -48,6 +54,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
48
54
|
useShadowHeader: useShadowHeaderProp = true,
|
|
49
55
|
gradientColor: customGradientColor,
|
|
50
56
|
headerBackground: customBackground,
|
|
57
|
+
contentLayout,
|
|
51
58
|
}) => {
|
|
52
59
|
const { theme } = useContext(ApplicationContext);
|
|
53
60
|
const context = useContext<any>(MiniAppContext);
|
|
@@ -55,29 +62,32 @@ const HeaderExtendHeader: React.FC<{
|
|
|
55
62
|
const gradientColor = customGradientColor ?? theme.colors.gradient;
|
|
56
63
|
const headerBackground = customBackground ?? theme.assets?.headerBackground;
|
|
57
64
|
const layout = useScreenLayout();
|
|
65
|
+
const headerLayout = useHeaderLayout(contentLayout);
|
|
66
|
+
// the stretch frame pulls the search in from both bar edges
|
|
67
|
+
const frameShift = headerLayout.frameInset - sidePadding;
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const duoToolkitWidth = DuoMetrics.itemPitch * 2 + SCREEN_PADDING;
|
|
62
|
-
const backWidth = isStatusBarRow ? DuoMetrics.controlSize : BACK_WIDTH;
|
|
63
|
-
const toolkitWidth = isStatusBarRow ? duoToolkitWidth : TOOLKIT_WIDTH;
|
|
64
|
-
const defaultLeft = layout.sideBar ? SCREEN_PADDING : backWidth + 20;
|
|
69
|
+
const backLeft = buttonSize + sidePadding + titleGap;
|
|
70
|
+
const defaultLeft = layout.sideBar ? SCREEN_PADDING : backLeft;
|
|
65
71
|
const leftPosition = inputSearchProps?.leftPosition || defaultLeft;
|
|
66
|
-
const defaultRightWidth = layout.sideBar ? 0 :
|
|
72
|
+
const defaultRightWidth = layout.sideBar ? 0 : TOOLKIT_WIDTH;
|
|
67
73
|
const headerRightWidth = customHeaderRightWidth ?? defaultRightWidth;
|
|
68
|
-
const contentLeft = layout.insetLeft + SCREEN_PADDING;
|
|
69
|
-
const contentRight = layout.insetLeft + layout.contentWidth;
|
|
74
|
+
const contentLeft = layout.insetLeft + SCREEN_PADDING + frameShift;
|
|
75
|
+
const contentRight = layout.insetLeft + layout.contentWidth - frameShift;
|
|
70
76
|
// collapsed on the status bar row, the search stays between its clusters
|
|
71
77
|
const clearanceLeft = layout.statusBarClearance?.left ?? 0;
|
|
72
78
|
const clearanceRight = layout.statusBarClearance?.right ?? 0;
|
|
73
|
-
const
|
|
79
|
+
const searchLeft = leftPosition + clearanceLeft + frameShift;
|
|
80
|
+
const collapsedLeft = layout.insetLeft + searchLeft;
|
|
74
81
|
const collapsedRight = contentRight - clearanceRight - headerRightWidth;
|
|
75
|
-
const searchWidth =
|
|
82
|
+
const searchWidth = contentRight - contentLeft - SCREEN_PADDING;
|
|
76
83
|
const collapsedSearchWidth = collapsedRight - collapsedLeft - SCREEN_PADDING;
|
|
77
84
|
// a row taller than barHeight (iPhone Duo) centers the collapsed search on the title
|
|
78
85
|
const titleRowHeight = layout.headerHeight - layout.headerStatusBarHeight;
|
|
79
86
|
const collapsedRaise = (titleRowHeight - HeaderMetrics.barHeight) / 2;
|
|
80
87
|
|
|
88
|
+
// the iPhone Duo side bar keeps the content search size
|
|
89
|
+
const searchSize = layout.sideBar ? 'default' : 'header';
|
|
90
|
+
|
|
81
91
|
let useShadowHeader = useShadowHeaderProp;
|
|
82
92
|
if (inputSearchProps && Platform.OS === 'android') {
|
|
83
93
|
useShadowHeader = false;
|
|
@@ -169,6 +179,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
169
179
|
<Animated.View
|
|
170
180
|
style={[
|
|
171
181
|
styles.extendedHeader,
|
|
182
|
+
headerLayout.isWide && styles.phoneHeight,
|
|
172
183
|
// fade out within the header box, as DuoScrollGradient does
|
|
173
184
|
!!layout.sideBar && styles.fillHeaderBox,
|
|
174
185
|
gradientOpacityStyle,
|
|
@@ -180,7 +191,10 @@ const HeaderExtendHeader: React.FC<{
|
|
|
180
191
|
>
|
|
181
192
|
{!!theme.assets?.headerBackground && (
|
|
182
193
|
<Image
|
|
183
|
-
style={
|
|
194
|
+
style={[
|
|
195
|
+
styles.headerBackground,
|
|
196
|
+
headerLayout.isWide && styles.phoneHeight,
|
|
197
|
+
]}
|
|
184
198
|
source={{ uri: theme.assets?.headerBackground }}
|
|
185
199
|
loading={false}
|
|
186
200
|
/>
|
|
@@ -189,9 +203,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
189
203
|
</Animated.View>
|
|
190
204
|
)}
|
|
191
205
|
</Animated.View>
|
|
192
|
-
<Animated.View
|
|
193
|
-
style={[styles.searchContainer, heightStyle]}
|
|
194
|
-
>
|
|
206
|
+
<Animated.View style={[styles.searchContainer, heightStyle]}>
|
|
195
207
|
<Animated.View
|
|
196
208
|
style={[{ marginVertical: Spacing.S }, searchTranslateStyle]}
|
|
197
209
|
>
|
|
@@ -201,6 +213,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
201
213
|
<InputSearch
|
|
202
214
|
{...inputSearchProps}
|
|
203
215
|
ref={inputSearchRef}
|
|
216
|
+
size={searchSize}
|
|
204
217
|
backgroundColor={'transparent'}
|
|
205
218
|
showButtonText={false}
|
|
206
219
|
/>
|
|
@@ -236,7 +249,10 @@ const HeaderExtendHeader: React.FC<{
|
|
|
236
249
|
>
|
|
237
250
|
{!!headerBackground && (
|
|
238
251
|
<Image
|
|
239
|
-
style={
|
|
252
|
+
style={[
|
|
253
|
+
styles.headerBackground,
|
|
254
|
+
headerLayout.isWide && styles.phoneHeight,
|
|
255
|
+
]}
|
|
240
256
|
source={{ uri: headerBackground }}
|
|
241
257
|
loading={false}
|
|
242
258
|
/>
|
|
@@ -264,6 +280,11 @@ const styles = StyleSheet.create({
|
|
|
264
280
|
position: 'absolute',
|
|
265
281
|
width: '100%',
|
|
266
282
|
},
|
|
283
|
+
// wide windows keep the phone gradient height instead of scaling with the width
|
|
284
|
+
phoneHeight: {
|
|
285
|
+
aspectRatio: undefined,
|
|
286
|
+
height: HeaderBarMetrics.gradientHeight,
|
|
287
|
+
},
|
|
267
288
|
fillHeaderBox: {
|
|
268
289
|
aspectRatio: undefined,
|
|
269
290
|
height: '100%',
|
|
@@ -273,14 +294,6 @@ const styles = StyleSheet.create({
|
|
|
273
294
|
position: 'absolute',
|
|
274
295
|
overflow: 'hidden',
|
|
275
296
|
},
|
|
276
|
-
verifiedDot: {
|
|
277
|
-
width: 4,
|
|
278
|
-
height: 4,
|
|
279
|
-
borderRadius: 2,
|
|
280
|
-
backgroundColor: Colors.green_03,
|
|
281
|
-
position: 'absolute',
|
|
282
|
-
alignSelf: 'center',
|
|
283
|
-
},
|
|
284
297
|
debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
|
|
285
298
|
container: {
|
|
286
299
|
zIndex: 0,
|
|
@@ -6,12 +6,13 @@ import { PopupNotify } from '../../Popup';
|
|
|
6
6
|
import { NavigationButton } from './NavigationButton';
|
|
7
7
|
import { SideBarButton } from './SideBarButton';
|
|
8
8
|
import Animated from 'react-native-reanimated';
|
|
9
|
-
import {
|
|
9
|
+
import { useSideBarItemStyle } from '../../Layout/utils';
|
|
10
10
|
import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
|
|
11
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Header back button, also bound to the Android hardware back. `preventBack`
|
|
14
|
-
* confirms in a popup first; the iPhone Duo
|
|
15
|
+
* confirms in a popup first; the iPhone Duo side bar uses the 48pt side bar button.
|
|
15
16
|
*/
|
|
16
17
|
const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
17
18
|
tintColor,
|
|
@@ -24,7 +25,6 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
24
25
|
const { navigator } = useContext(ApplicationContext);
|
|
25
26
|
const sideBarStyle = useSideBarItemStyle('left', 0);
|
|
26
27
|
const counterStyle = useSideBarCounterStyle();
|
|
27
|
-
const { statusBarClearance } = useScreenLayout();
|
|
28
28
|
|
|
29
29
|
const goBack = useCallback(() => {
|
|
30
30
|
const canGoBack = navigator?.ref?.current?.canGoBack?.();
|
|
@@ -97,20 +97,6 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
97
97
|
);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// on the status bar row the controls keep the side bar size
|
|
101
|
-
if (statusBarClearance) {
|
|
102
|
-
return (
|
|
103
|
-
<View style={styles.headerLeft}>
|
|
104
|
-
<SideBarButton
|
|
105
|
-
accessibilityLabel="btn_navigation_back"
|
|
106
|
-
icon="arrow-back"
|
|
107
|
-
tintColor={tintColor}
|
|
108
|
-
onPress={goBackSafe}
|
|
109
|
-
/>
|
|
110
|
-
</View>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
100
|
return (
|
|
115
101
|
<View style={styles.headerLeft}>
|
|
116
102
|
<NavigationButton
|
|
@@ -125,7 +111,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
125
111
|
|
|
126
112
|
const styles = StyleSheet.create({
|
|
127
113
|
headerLeft: {
|
|
128
|
-
marginLeft:
|
|
114
|
+
marginLeft: HeaderBarMetrics.sidePadding,
|
|
129
115
|
},
|
|
130
116
|
});
|
|
131
117
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { Platform, StyleSheet } from 'react-native';
|
|
2
2
|
import { Colors, Spacing } from '../../Consts';
|
|
3
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
4
|
+
|
|
5
|
+
const { buttonSize, pillWidth, pillHeight, sidePadding } = HeaderBarMetrics;
|
|
3
6
|
|
|
4
7
|
export const styles = StyleSheet.create({
|
|
5
8
|
navigationButton: {
|
|
6
|
-
height:
|
|
7
|
-
width:
|
|
8
|
-
borderRadius:
|
|
9
|
+
height: buttonSize,
|
|
10
|
+
width: buttonSize,
|
|
11
|
+
borderRadius: buttonSize / 2,
|
|
9
12
|
justifyContent: 'center',
|
|
10
13
|
alignItems: 'center',
|
|
11
14
|
backgroundColor: Colors.black_01 + '99',
|
|
@@ -45,11 +48,11 @@ export const styles = StyleSheet.create({
|
|
|
45
48
|
flexDirection: 'row',
|
|
46
49
|
justifyContent: 'center',
|
|
47
50
|
alignItems: 'center',
|
|
48
|
-
paddingRight:
|
|
51
|
+
paddingRight: sidePadding,
|
|
49
52
|
},
|
|
50
53
|
toolkitContainer: {
|
|
51
|
-
height:
|
|
52
|
-
borderRadius:
|
|
54
|
+
height: pillHeight,
|
|
55
|
+
borderRadius: pillHeight / 2,
|
|
53
56
|
justifyContent: 'center',
|
|
54
57
|
alignItems: 'center',
|
|
55
58
|
flexDirection: 'row',
|
|
@@ -59,7 +62,10 @@ export const styles = StyleSheet.create({
|
|
|
59
62
|
marginLeft: Spacing.S,
|
|
60
63
|
},
|
|
61
64
|
toolkitButton: {
|
|
62
|
-
|
|
65
|
+
flex: 1,
|
|
66
|
+
height: '100%',
|
|
67
|
+
justifyContent: 'center',
|
|
68
|
+
alignItems: 'center',
|
|
63
69
|
},
|
|
64
70
|
divider: {
|
|
65
71
|
width: 0.5,
|
|
@@ -68,10 +74,6 @@ export const styles = StyleSheet.create({
|
|
|
68
74
|
sideBarColumn: {
|
|
69
75
|
gap: Spacing.M,
|
|
70
76
|
},
|
|
71
|
-
sideBarRow: {
|
|
72
|
-
flexDirection: 'row',
|
|
73
|
-
gap: Spacing.M,
|
|
74
|
-
},
|
|
75
77
|
headerLeft: {
|
|
76
78
|
marginLeft: 12,
|
|
77
79
|
},
|
|
@@ -136,9 +138,9 @@ export const styles = StyleSheet.create({
|
|
|
136
138
|
marginRight: Spacing.M,
|
|
137
139
|
},
|
|
138
140
|
toolkitWide: {
|
|
139
|
-
width:
|
|
141
|
+
width: pillWidth,
|
|
140
142
|
},
|
|
141
143
|
toolkitNarrow: {
|
|
142
|
-
width:
|
|
144
|
+
width: buttonSize,
|
|
143
145
|
},
|
|
144
146
|
});
|
|
@@ -3,6 +3,9 @@ import { MiniAppContext } from '../../Context';
|
|
|
3
3
|
import { Spacing } from '../../Consts';
|
|
4
4
|
import { isWhiteListDesignSystem } from '../utils';
|
|
5
5
|
import { useScreenLayout } from '../../Layout';
|
|
6
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
7
|
+
|
|
8
|
+
const { sidePadding, buttonSize, titleGap, clusterWidth } = HeaderBarMetrics;
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Header title font: MoMoTrustDisplay for design-system whitelisted mini apps,
|
|
@@ -14,32 +17,28 @@ const useHeaderFontFamily = (): string => {
|
|
|
14
17
|
};
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
|
-
* back button
|
|
18
|
-
|
|
19
|
-
const HEADER_ACTIONS_WIDTH = 172;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* extra width the 48pt back and toolkit take on the iPhone Duo status bar row
|
|
20
|
+
* side paddings, back button, title gaps and right cluster sharing the
|
|
21
|
+
* navigation bar with the title
|
|
23
22
|
*/
|
|
24
|
-
const
|
|
23
|
+
const HEADER_ACTIONS_WIDTH =
|
|
24
|
+
sidePadding * 2 + buttonSize + titleGap * 2 + clusterWidth;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Max header title width. The iPhone Duo side bar takes back and toolkit out of
|
|
28
|
-
* the bar, so the title gets the content width; otherwise it shares the bar with
|
|
28
|
+
* the bar, so the title gets the content width; otherwise it shares the bar with
|
|
29
|
+
* them, minus the status bar clusters on the iPhone Duo inner portrait row.
|
|
29
30
|
*/
|
|
30
31
|
const useTitleMaxWidth = () => {
|
|
31
32
|
const layout = useScreenLayout();
|
|
32
33
|
const { width, contentWidth, sideBar, statusBarClearance } = layout;
|
|
33
34
|
let clearance = 0;
|
|
34
|
-
let rowActionsExtra = 0;
|
|
35
35
|
if (statusBarClearance) {
|
|
36
36
|
clearance = statusBarClearance.left + statusBarClearance.right;
|
|
37
|
-
rowActionsExtra = STATUS_BAR_ROW_ACTIONS_EXTRA;
|
|
38
37
|
}
|
|
39
38
|
if (sideBar) {
|
|
40
39
|
return contentWidth - Spacing.M * 2 - clearance;
|
|
41
40
|
}
|
|
42
|
-
return width - HEADER_ACTIONS_WIDTH -
|
|
41
|
+
return width - HEADER_ACTIONS_WIDTH - clearance;
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
export { useHeaderFontFamily, HEADER_ACTIONS_WIDTH, useTitleMaxWidth };
|
|
@@ -4,18 +4,15 @@ import { NavigationButton } from './NavigationButton';
|
|
|
4
4
|
import { MiniAppContext } from '../../Context';
|
|
5
5
|
import { Colors, Spacing, Styles } from '../../Consts';
|
|
6
6
|
import { Icon } from '../../Icon';
|
|
7
|
-
import { DuoMetrics
|
|
7
|
+
import { DuoMetrics } from '../../Layout/utils';
|
|
8
8
|
import { SideBarButton, SideBarGroup, SideBarGroupItem } from './SideBarButton';
|
|
9
9
|
import { useDuoBarCompression } from '../BottomTab/DuoBarCompression';
|
|
10
10
|
import { styles } from './HeaderRight.styles';
|
|
11
11
|
import { useToolkitActions } from './useToolkitActions';
|
|
12
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
12
13
|
|
|
13
14
|
const CLOSE_ICON = '16_navigation_close_circle';
|
|
14
15
|
const HOME_ICON = '16_basic_home';
|
|
15
|
-
const TOOLKIT_ICON_SIZE = 20;
|
|
16
|
-
// the capsule's two buttons extend their touch area outward only
|
|
17
|
-
const HELP_CENTER_HIT_SLOP = { top: 7, bottom: 7, left: 7, right: 0 };
|
|
18
|
-
const CLOSE_HIT_SLOP = { top: 7, bottom: 7, left: 0, right: 7 };
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Header toolkit: optional shortcut plus the help center / close capsule. When
|
|
@@ -35,14 +32,13 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
35
32
|
const compression = useDuoBarCompression();
|
|
36
33
|
const { toolbarCompressed, toolbarHidden } = compression;
|
|
37
34
|
const { expandToolbar, setToolbarHeight } = compression;
|
|
38
|
-
const { statusBarClearance } = useScreenLayout();
|
|
39
35
|
const {
|
|
40
36
|
isLoading,
|
|
41
37
|
iconShortcut,
|
|
42
38
|
shortcutOnPress,
|
|
43
39
|
showBadge,
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
onPressHelpCenter,
|
|
41
|
+
onClose,
|
|
46
42
|
} = useToolkitActions({
|
|
47
43
|
preventClose,
|
|
48
44
|
useSystemTools,
|
|
@@ -60,14 +56,14 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
const
|
|
59
|
+
const useHelpCenter = context.appId !== 'vn.momo.helpcenter';
|
|
64
60
|
const closeIcon = useCloseIcon ? CLOSE_ICON : HOME_ICON;
|
|
65
61
|
let toolkitWidthStyle: ViewStyle = styles.toolkitNarrow;
|
|
66
|
-
if (
|
|
62
|
+
if (useHelpCenter) {
|
|
67
63
|
toolkitWidthStyle = styles.toolkitWide;
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
const groupCount =
|
|
66
|
+
const groupCount = useHelpCenter ? 2 : 1;
|
|
71
67
|
let capsuleHeight = DuoMetrics.controlSize;
|
|
72
68
|
if (groupCount > 1) {
|
|
73
69
|
capsuleHeight = groupCount * DuoMetrics.itemPitch;
|
|
@@ -116,52 +112,19 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
116
112
|
/>
|
|
117
113
|
)}
|
|
118
114
|
<SideBarGroup tintColor={tintColor}>
|
|
119
|
-
{
|
|
115
|
+
{useHelpCenter && (
|
|
120
116
|
<SideBarGroupItem
|
|
121
117
|
accessibilityLabel={'btn_navigation_help_center'}
|
|
122
118
|
icon={'help_center'}
|
|
123
119
|
tintColor={tintColor}
|
|
124
|
-
onPress={
|
|
120
|
+
onPress={onPressHelpCenter}
|
|
125
121
|
/>
|
|
126
122
|
)}
|
|
127
123
|
<SideBarGroupItem
|
|
128
124
|
accessibilityLabel={'btn_navigation_close'}
|
|
129
125
|
icon={closeIcon}
|
|
130
126
|
tintColor={tintColor}
|
|
131
|
-
onPress={
|
|
132
|
-
/>
|
|
133
|
-
</SideBarGroup>
|
|
134
|
-
</View>
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// on the status bar row the controls keep the side bar size
|
|
139
|
-
if (statusBarClearance) {
|
|
140
|
-
return (
|
|
141
|
-
<View style={styles.sideBarRow}>
|
|
142
|
-
{useShortcut && (
|
|
143
|
-
<SideBarButton
|
|
144
|
-
disabled={isLoading}
|
|
145
|
-
icon={iconShortcut}
|
|
146
|
-
onPress={shortcutOnPress}
|
|
147
|
-
tintColor={tintColor}
|
|
148
|
-
showBadge={showBadge}
|
|
149
|
-
/>
|
|
150
|
-
)}
|
|
151
|
-
<SideBarGroup tintColor={tintColor} horizontal>
|
|
152
|
-
{hasHelpCenter && (
|
|
153
|
-
<SideBarGroupItem
|
|
154
|
-
accessibilityLabel={'btn_navigation_help_center'}
|
|
155
|
-
icon={'help_center'}
|
|
156
|
-
tintColor={tintColor}
|
|
157
|
-
onPress={handlePressHelpCenter}
|
|
158
|
-
/>
|
|
159
|
-
)}
|
|
160
|
-
<SideBarGroupItem
|
|
161
|
-
accessibilityLabel={'btn_navigation_close'}
|
|
162
|
-
icon={closeIcon}
|
|
163
|
-
tintColor={tintColor}
|
|
164
|
-
onPress={handleClose}
|
|
127
|
+
onPress={onClose}
|
|
165
128
|
/>
|
|
166
129
|
</SideBarGroup>
|
|
167
130
|
</View>
|
|
@@ -180,18 +143,18 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
180
143
|
/>
|
|
181
144
|
)}
|
|
182
145
|
<View style={[styles.toolkitContainer, buttonStyle, toolkitWidthStyle]}>
|
|
183
|
-
{
|
|
146
|
+
{useHelpCenter && (
|
|
184
147
|
<>
|
|
185
148
|
<TouchableOpacity
|
|
186
149
|
accessibilityLabel={'btn_navigation_help_center'}
|
|
187
150
|
style={styles.toolkitButton}
|
|
188
|
-
onPress={
|
|
189
|
-
hitSlop={
|
|
151
|
+
onPress={onPressHelpCenter}
|
|
152
|
+
hitSlop={{ top: 7, bottom: 7, left: 7, right: 0 }}
|
|
190
153
|
>
|
|
191
154
|
<Icon
|
|
192
155
|
color={tintColor}
|
|
193
156
|
source={'help_center'}
|
|
194
|
-
size={
|
|
157
|
+
size={HeaderBarMetrics.iconSize}
|
|
195
158
|
/>
|
|
196
159
|
</TouchableOpacity>
|
|
197
160
|
<View style={[styles.divider, { backgroundColor: tintColor }]} />
|
|
@@ -199,11 +162,15 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
199
162
|
)}
|
|
200
163
|
<TouchableOpacity
|
|
201
164
|
accessibilityLabel={'btn_navigation_close'}
|
|
202
|
-
onPress={
|
|
165
|
+
onPress={onClose}
|
|
203
166
|
style={styles.toolkitButton}
|
|
204
|
-
hitSlop={
|
|
167
|
+
hitSlop={{ top: 7, bottom: 7, left: 0, right: 7 }}
|
|
205
168
|
>
|
|
206
|
-
<Icon
|
|
169
|
+
<Icon
|
|
170
|
+
color={tintColor}
|
|
171
|
+
source={closeIcon}
|
|
172
|
+
size={HeaderBarMetrics.iconSize}
|
|
173
|
+
/>
|
|
207
174
|
</TouchableOpacity>
|
|
208
175
|
</View>
|
|
209
176
|
</View>
|
|
@@ -5,9 +5,12 @@ import { StyleSheet, TouchableOpacity, View, ViewStyle } from 'react-native';
|
|
|
5
5
|
import { Colors, Spacing } from '../../Consts';
|
|
6
6
|
import { Icon } from '../../Icon';
|
|
7
7
|
import { BadgeDot } from '../../Badge';
|
|
8
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
9
|
+
|
|
10
|
+
const { buttonSize, iconSize } = HeaderBarMetrics;
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
|
-
* Round
|
|
13
|
+
* Round 32pt icon button of the header (back, shortcut) with an optional badge
|
|
11
14
|
* dot; switches to a dark fill under a white tint so the icon stays readable.
|
|
12
15
|
*/
|
|
13
16
|
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
@@ -35,7 +38,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
35
38
|
<Icon
|
|
36
39
|
source={icon}
|
|
37
40
|
color={tintColor ?? theme.colors.text.default}
|
|
38
|
-
size={
|
|
41
|
+
size={iconSize}
|
|
39
42
|
/>
|
|
40
43
|
</TouchableOpacity>
|
|
41
44
|
{showBadge && <BadgeDot size={'small'} style={styles.badgeDot} />}
|
|
@@ -45,12 +48,12 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
45
48
|
|
|
46
49
|
const styles = StyleSheet.create({
|
|
47
50
|
container: {
|
|
48
|
-
width:
|
|
51
|
+
width: buttonSize,
|
|
49
52
|
},
|
|
50
53
|
navigationButton: {
|
|
51
|
-
height:
|
|
52
|
-
width:
|
|
53
|
-
borderRadius:
|
|
54
|
+
height: buttonSize,
|
|
55
|
+
width: buttonSize,
|
|
56
|
+
borderRadius: buttonSize / 2,
|
|
54
57
|
justifyContent: 'center',
|
|
55
58
|
alignItems: 'center',
|
|
56
59
|
backgroundColor: Colors.black_01 + '99',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Colors, Radius, Spacing, Styles } from '../../Consts';
|
|
2
|
-
import { InputRef, InputSearch } from '../../Input';
|
|
2
|
+
import { InputRef, InputSearch, type InputSearchProps } from '../../Input';
|
|
3
3
|
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
4
4
|
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
5
5
|
import React, { useContext } from 'react';
|
|
@@ -8,7 +8,13 @@ import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
|
8
8
|
import { Text } from '../../Text';
|
|
9
9
|
import { useNormalizedSharedValue } from '../hooks';
|
|
10
10
|
import { useScreenLayout } from '../../Layout';
|
|
11
|
-
import {
|
|
11
|
+
import { HeaderBarMetrics } from '../headerLayout';
|
|
12
|
+
|
|
13
|
+
const { buttonSize, pillWidth, sidePadding, titleGap } = HeaderBarMetrics;
|
|
14
|
+
// help center | home pill and the bar padding right of it
|
|
15
|
+
const TOOLKIT_WIDTH = pillWidth + sidePadding;
|
|
16
|
+
// the iPhone Duo side bar keeps its right header width
|
|
17
|
+
const DUO_TOOLKIT_WIDTH = 73;
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* Header search bar whose fill turns from surface to default once scrolled, with
|
|
@@ -28,15 +34,21 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
28
34
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
29
35
|
const context = useContext<any>(MiniAppContext);
|
|
30
36
|
const layout = useScreenLayout();
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
let defaultRightWidth = TOOLKIT_WIDTH;
|
|
38
|
+
let searchSize: InputSearchProps['size'] = 'header';
|
|
39
|
+
if (layout.sideBar) {
|
|
40
|
+
defaultRightWidth = DUO_TOOLKIT_WIDTH;
|
|
41
|
+
searchSize = 'default';
|
|
42
|
+
}
|
|
33
43
|
|
|
34
44
|
const sharedValue = useNormalizedSharedValue(animatedValue);
|
|
35
|
-
const
|
|
36
|
-
const
|
|
45
|
+
const defaultLeft = buttonSize + sidePadding + titleGap;
|
|
46
|
+
const leftPosition = props?.leftPosition ?? defaultLeft;
|
|
47
|
+
const headerRightWidth = props?.headerRightWidth ?? defaultRightWidth;
|
|
37
48
|
|
|
38
49
|
// iPhone Duo side bar holds back: the search shares the content width with the buttons only
|
|
39
|
-
|
|
50
|
+
const rowWidth = layout.width - leftPosition - sidePadding;
|
|
51
|
+
let searchMaxWidth = rowWidth - headerRightWidth;
|
|
40
52
|
if (layout.sideBar) {
|
|
41
53
|
searchMaxWidth = layout.contentWidth - Spacing.M * 2 - headerRightWidth;
|
|
42
54
|
}
|
|
@@ -105,6 +117,7 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
105
117
|
<InputSearch
|
|
106
118
|
ref={ref}
|
|
107
119
|
{...props}
|
|
120
|
+
size={searchSize}
|
|
108
121
|
backgroundColor={'transparent'}
|
|
109
122
|
showButtonText={false}
|
|
110
123
|
/>
|