@momo-kits/foundation 0.167.1-beta.5 → 0.167.1-duo-test.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.tsx +115 -14
- package/Application/BottomTab/BottomTabBar.tsx +6 -3
- package/Application/BottomTab/DuoBarCompression.tsx +135 -0
- package/Application/BottomTab/DuoTabBar.tsx +462 -0
- package/Application/BottomTab/index.tsx +150 -134
- package/Application/Components/DuoGlassBackground.tsx +179 -0
- package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
- package/Application/Components/HeaderExtendHeader.tsx +75 -28
- package/Application/Components/HeaderLeft.tsx +38 -0
- package/Application/Components/HeaderRight.tsx +142 -9
- package/Application/Components/HeaderTitle.tsx +67 -17
- package/Application/Components/OptionalGlassView.ts +11 -0
- package/Application/Components/OptionalScrollObserver.ts +12 -0
- package/Application/Components/SearchHeader.tsx +22 -15
- package/Application/Components/SideBarButton.tsx +139 -0
- package/Application/ModalScreen.tsx +16 -2
- package/Application/NavigationContainer.tsx +36 -45
- package/Application/Navigator.ts +1 -3
- package/Application/StackScreen.tsx +63 -9
- package/Application/WidgetContainer.tsx +9 -7
- package/Application/device.ts +29 -0
- package/Application/types.ts +27 -1
- package/Application/utils.tsx +255 -7
- package/Consts/index.ts +0 -1
- package/Consts/theme.ts +5 -6
- package/Input/Input.tsx +3 -4
- package/Input/InputMoney.tsx +31 -51
- package/Input/InputPhoneNumber.tsx +3 -4
- package/Input/InputSearch.tsx +3 -4
- package/Input/InputTextArea.tsx +3 -4
- package/Layout/Card.tsx +8 -26
- package/Layout/FloatingButton.tsx +3 -3
- package/Layout/Item.tsx +1 -10
- package/Layout/ReservedRegions.tsx +47 -0
- package/Layout/Screen.tsx +199 -52
- package/Layout/Section.tsx +5 -18
- package/Layout/index.ts +4 -4
- package/Layout/styles.ts +5 -0
- package/Layout/utils.ts +465 -5
- package/Popup/PopupNotify.tsx +33 -22
- package/Popup/PopupPromotion.tsx +20 -8
- package/Popup/utils.ts +32 -0
- package/Text/index.tsx +2 -11
- package/Text/utils.ts +1 -2
- package/package.json +3 -2
- package/Consts/designSystemFont.ts +0 -38
- package/Layout/GridSystem.tsx +0 -137
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { Ref, useContext } from 'react';
|
|
2
2
|
import LinearGradient from 'react-native-linear-gradient';
|
|
3
|
-
import {
|
|
3
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
4
4
|
import Animated, {
|
|
5
5
|
Extrapolation,
|
|
6
6
|
interpolate,
|
|
@@ -14,21 +14,19 @@ import { Colors, Radius, Spacing } from '../../Consts';
|
|
|
14
14
|
import { Image } from '../../Image';
|
|
15
15
|
import { SearchHeaderProps } from '../types';
|
|
16
16
|
import BackgroundImageView from './BackgroundImageView';
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '../utils';
|
|
17
|
+
import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
|
|
18
|
+
import { useScreenLayout } from '../../Layout';
|
|
19
|
+
import { DuoMetrics, HeaderMetrics } from '../../Layout/utils';
|
|
21
20
|
|
|
22
21
|
const SCREEN_PADDING = 12;
|
|
23
22
|
const BACK_WIDTH = 28;
|
|
24
|
-
|
|
25
|
-
const { width: screenWidth } = Dimensions.get('window');
|
|
23
|
+
const TOOLKIT_WIDTH = 73;
|
|
26
24
|
|
|
27
25
|
const HeaderExtendHeader: React.FC<{
|
|
28
26
|
headerType?: HeaderType;
|
|
29
27
|
animatedValue: AnimatedCompatValue;
|
|
30
28
|
heightHeader: number;
|
|
31
|
-
headerRightWidth
|
|
29
|
+
headerRightWidth?: number;
|
|
32
30
|
inputSearchProps?: SearchHeaderProps;
|
|
33
31
|
inputSearchRef?: Ref<InputRef>;
|
|
34
32
|
navigation?: Navigation;
|
|
@@ -39,7 +37,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
39
37
|
headerType = 'default',
|
|
40
38
|
animatedValue,
|
|
41
39
|
heightHeader,
|
|
42
|
-
headerRightWidth
|
|
40
|
+
headerRightWidth: customHeaderRightWidth,
|
|
43
41
|
inputSearchProps,
|
|
44
42
|
inputSearchRef,
|
|
45
43
|
useShadowHeader: useShadowHeaderProp = true,
|
|
@@ -51,7 +49,35 @@ const HeaderExtendHeader: React.FC<{
|
|
|
51
49
|
const sharedValue = useNormalizedSharedValue(animatedValue);
|
|
52
50
|
const gradientColor = customGradientColor ?? theme.colors.gradient;
|
|
53
51
|
const headerBackground = customBackground ?? theme.assets?.headerBackground;
|
|
54
|
-
const
|
|
52
|
+
const layout = useScreenLayout();
|
|
53
|
+
|
|
54
|
+
// the iPhone Duo status bar row keeps side bar sized back and toolkit
|
|
55
|
+
const backWidth = layout.statusBarClearance
|
|
56
|
+
? DuoMetrics.controlSize
|
|
57
|
+
: BACK_WIDTH;
|
|
58
|
+
const toolkitWidth = layout.statusBarClearance
|
|
59
|
+
? DuoMetrics.itemPitch * 2 + SCREEN_PADDING
|
|
60
|
+
: TOOLKIT_WIDTH;
|
|
61
|
+
const leftPosition =
|
|
62
|
+
inputSearchProps?.leftPosition ||
|
|
63
|
+
(layout.sideBar ? SCREEN_PADDING : backWidth + 20);
|
|
64
|
+
const headerRightWidth =
|
|
65
|
+
customHeaderRightWidth ?? (layout.sideBar ? 0 : toolkitWidth);
|
|
66
|
+
const contentLeft = layout.insetLeft + SCREEN_PADDING;
|
|
67
|
+
const contentRight = layout.insetLeft + layout.contentWidth;
|
|
68
|
+
// collapsed on the status bar row, the search stays between its clusters
|
|
69
|
+
const collapsedLeft =
|
|
70
|
+
layout.insetLeft + leftPosition + (layout.statusBarClearance?.left ?? 0);
|
|
71
|
+
const collapsedRight = contentRight - (layout.statusBarClearance?.right ?? 0);
|
|
72
|
+
const searchWidth = layout.contentWidth - SCREEN_PADDING * 2;
|
|
73
|
+
const collapsedSearchWidth =
|
|
74
|
+
collapsedRight - collapsedLeft - SCREEN_PADDING - headerRightWidth;
|
|
75
|
+
// a row taller than barHeight (iPhone Duo) centers the collapsed search on the title
|
|
76
|
+
const collapsedRaise =
|
|
77
|
+
(layout.headerHeight -
|
|
78
|
+
layout.headerStatusBarHeight -
|
|
79
|
+
HeaderMetrics.barHeight) /
|
|
80
|
+
2;
|
|
55
81
|
|
|
56
82
|
let useShadowHeader = useShadowHeaderProp;
|
|
57
83
|
if (inputSearchProps && Platform.OS === 'android') {
|
|
@@ -70,7 +96,12 @@ const HeaderExtendHeader: React.FC<{
|
|
|
70
96
|
}));
|
|
71
97
|
|
|
72
98
|
const gradientOpacityStyle = useAnimatedStyle(() => ({
|
|
73
|
-
opacity: interpolate(
|
|
99
|
+
opacity: interpolate(
|
|
100
|
+
sharedValue.value,
|
|
101
|
+
[0, 52],
|
|
102
|
+
[1, 0],
|
|
103
|
+
Extrapolation.CLAMP,
|
|
104
|
+
),
|
|
74
105
|
}));
|
|
75
106
|
|
|
76
107
|
const searchTranslateStyle = useAnimatedStyle(() => ({
|
|
@@ -79,7 +110,15 @@ const HeaderExtendHeader: React.FC<{
|
|
|
79
110
|
translateX: interpolate(
|
|
80
111
|
sharedValue.value,
|
|
81
112
|
[0, 100],
|
|
82
|
-
[
|
|
113
|
+
[contentLeft, collapsedLeft],
|
|
114
|
+
Extrapolation.CLAMP,
|
|
115
|
+
),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
translateY: interpolate(
|
|
119
|
+
sharedValue.value,
|
|
120
|
+
[0, 100],
|
|
121
|
+
[0, -collapsedRaise],
|
|
83
122
|
Extrapolation.CLAMP,
|
|
84
123
|
),
|
|
85
124
|
},
|
|
@@ -87,19 +126,19 @@ const HeaderExtendHeader: React.FC<{
|
|
|
87
126
|
width: interpolate(
|
|
88
127
|
sharedValue.value,
|
|
89
128
|
[0, 100],
|
|
90
|
-
[
|
|
91
|
-
screenWidth - SCREEN_PADDING * 2,
|
|
92
|
-
screenWidth - leftPosition - 12 - headerRightWidth,
|
|
93
|
-
],
|
|
129
|
+
[searchWidth, collapsedSearchWidth],
|
|
94
130
|
Extrapolation.CLAMP,
|
|
95
131
|
),
|
|
96
132
|
}));
|
|
97
133
|
|
|
98
134
|
const searchBackgroundStyle = useAnimatedStyle(() => {
|
|
99
135
|
const t = Math.min(Math.max(sharedValue.value / 100, 0), 1);
|
|
100
|
-
return {
|
|
101
|
-
|
|
102
|
-
|
|
136
|
+
return {
|
|
137
|
+
backgroundColor:
|
|
138
|
+
t === 0
|
|
139
|
+
? theme.colors.background.surface
|
|
140
|
+
: theme.colors.background.default,
|
|
141
|
+
};
|
|
103
142
|
});
|
|
104
143
|
|
|
105
144
|
const extendedHeightStyle = useAnimatedStyle(() => ({
|
|
@@ -124,14 +163,17 @@ const HeaderExtendHeader: React.FC<{
|
|
|
124
163
|
<Animated.View
|
|
125
164
|
style={[
|
|
126
165
|
styles.headerBox,
|
|
127
|
-
headerType === 'extended'
|
|
128
|
-
? heightStyle
|
|
129
|
-
: { height: heightHeader },
|
|
166
|
+
headerType === 'extended' ? heightStyle : { height: heightHeader },
|
|
130
167
|
]}
|
|
131
168
|
>
|
|
132
169
|
{!!gradientColor && (
|
|
133
170
|
<Animated.View
|
|
134
|
-
style={[
|
|
171
|
+
style={[
|
|
172
|
+
styles.extendedHeader,
|
|
173
|
+
// fade out within the header box, as DuoScrollGradient does
|
|
174
|
+
!!layout.sideBar && styles.fillHeaderBox,
|
|
175
|
+
gradientOpacityStyle,
|
|
176
|
+
]}
|
|
135
177
|
>
|
|
136
178
|
<LinearGradient
|
|
137
179
|
colors={[gradientColor, gradientColor + '00']}
|
|
@@ -162,10 +204,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
162
204
|
style={[{ marginVertical: Spacing.S }, searchTranslateStyle]}
|
|
163
205
|
>
|
|
164
206
|
<Animated.View
|
|
165
|
-
style={[
|
|
166
|
-
{ borderRadius: Radius.XL },
|
|
167
|
-
searchBackgroundStyle,
|
|
168
|
-
]}
|
|
207
|
+
style={[{ borderRadius: Radius.XL }, searchBackgroundStyle]}
|
|
169
208
|
>
|
|
170
209
|
<InputSearch
|
|
171
210
|
{...inputSearchProps}
|
|
@@ -191,7 +230,11 @@ const HeaderExtendHeader: React.FC<{
|
|
|
191
230
|
/>
|
|
192
231
|
{!!gradientColor && (
|
|
193
232
|
<Animated.View
|
|
194
|
-
style={[
|
|
233
|
+
style={[
|
|
234
|
+
styles.extendedHeader,
|
|
235
|
+
gradientOpacityStyle,
|
|
236
|
+
extendedHeightStyle,
|
|
237
|
+
]}
|
|
195
238
|
>
|
|
196
239
|
<LinearGradient
|
|
197
240
|
colors={[gradientColor, gradientColor + '00']}
|
|
@@ -227,6 +270,10 @@ const styles = StyleSheet.create({
|
|
|
227
270
|
position: 'absolute',
|
|
228
271
|
width: '100%',
|
|
229
272
|
},
|
|
273
|
+
fillHeaderBox: {
|
|
274
|
+
aspectRatio: undefined,
|
|
275
|
+
height: '100%',
|
|
276
|
+
},
|
|
230
277
|
headerBox: {
|
|
231
278
|
width: '100%',
|
|
232
279
|
position: 'absolute',
|
|
@@ -4,6 +4,10 @@ import React, { useCallback, useContext, useEffect } from 'react';
|
|
|
4
4
|
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
5
5
|
import { PopupNotify } from '../../Popup';
|
|
6
6
|
import { NavigationButton } from './NavigationButton';
|
|
7
|
+
import { SideBarButton } from './SideBarButton';
|
|
8
|
+
import Animated from 'react-native-reanimated';
|
|
9
|
+
import { useScreenLayout, useSideBarItemStyle } from '../../Layout/utils';
|
|
10
|
+
import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* default header left used for nav
|
|
@@ -13,9 +17,13 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
13
17
|
preventBack,
|
|
14
18
|
onPressLeftHeader,
|
|
15
19
|
onBackHandler,
|
|
20
|
+
floating = false,
|
|
16
21
|
}) => {
|
|
17
22
|
const context = useContext<any>(MiniAppContext);
|
|
18
23
|
const { navigator } = useContext(ApplicationContext);
|
|
24
|
+
const sideBarStyle = useSideBarItemStyle('left', 0);
|
|
25
|
+
const counterStyle = useSideBarCounterStyle();
|
|
26
|
+
const { statusBarClearance } = useScreenLayout();
|
|
19
27
|
|
|
20
28
|
const goBack = useCallback(() => {
|
|
21
29
|
const canGoBack = navigator?.ref?.current?.canGoBack?.();
|
|
@@ -72,6 +80,36 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
72
80
|
return () => backHandler.remove();
|
|
73
81
|
}, [goBackSafe]);
|
|
74
82
|
|
|
83
|
+
if (floating && sideBarStyle) {
|
|
84
|
+
return (
|
|
85
|
+
<Animated.View
|
|
86
|
+
style={[sideBarStyle, counterStyle]}
|
|
87
|
+
pointerEvents={'box-none'}
|
|
88
|
+
>
|
|
89
|
+
<SideBarButton
|
|
90
|
+
accessibilityLabel="btn_navigation_back"
|
|
91
|
+
icon="arrow-back"
|
|
92
|
+
tintColor={tintColor}
|
|
93
|
+
onPress={goBackSafe}
|
|
94
|
+
/>
|
|
95
|
+
</Animated.View>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// on the status bar row the controls keep the side bar size
|
|
100
|
+
if (statusBarClearance) {
|
|
101
|
+
return (
|
|
102
|
+
<View style={styles.headerLeft}>
|
|
103
|
+
<SideBarButton
|
|
104
|
+
accessibilityLabel="btn_navigation_back"
|
|
105
|
+
icon="arrow-back"
|
|
106
|
+
tintColor={tintColor}
|
|
107
|
+
onPress={goBackSafe}
|
|
108
|
+
/>
|
|
109
|
+
</View>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
75
113
|
return (
|
|
76
114
|
<View style={styles.headerLeft}>
|
|
77
115
|
<NavigationButton
|
|
@@ -13,6 +13,12 @@ import { PopupNotify } from '../../Popup';
|
|
|
13
13
|
import { Tool, ToolGroup } from '../types';
|
|
14
14
|
import { Icon } from '../../Icon';
|
|
15
15
|
import { Text } from '../../Text';
|
|
16
|
+
import Animated from 'react-native-reanimated';
|
|
17
|
+
import { useScreenLayout, useSideBarItemStyle } from '../../Layout/utils';
|
|
18
|
+
import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
|
|
19
|
+
import { SideBarButton, SideBarGroup, SideBarGroupItem } from './SideBarButton';
|
|
20
|
+
import { useDuoBarCompression } from '../BottomTab/DuoBarCompression';
|
|
21
|
+
import { DuoMetrics } from '../../Layout/utils';
|
|
16
22
|
|
|
17
23
|
const DID_SYNC_NEW_HOME = 'did_sync_new_home';
|
|
18
24
|
|
|
@@ -21,8 +27,10 @@ const DID_SYNC_NEW_HOME = 'did_sync_new_home';
|
|
|
21
27
|
*/
|
|
22
28
|
const HeaderRight: React.FC<any> = props => {
|
|
23
29
|
const { translate } = useContext(ApplicationContext);
|
|
24
|
-
const { headerRight = {} } = props;
|
|
30
|
+
const { headerRight = {}, floating = false } = props;
|
|
25
31
|
const { useOnBoarding = false, buttonOnBoarding, onPress } = headerRight;
|
|
32
|
+
const sideBarStyle = useSideBarItemStyle('right', 1);
|
|
33
|
+
const counterStyle = useSideBarCounterStyle();
|
|
26
34
|
|
|
27
35
|
if (typeof props.headerRight === 'function') {
|
|
28
36
|
return props.headerRight(props);
|
|
@@ -38,6 +46,21 @@ const HeaderRight: React.FC<any> = props => {
|
|
|
38
46
|
);
|
|
39
47
|
}
|
|
40
48
|
|
|
49
|
+
if (floating && sideBarStyle) {
|
|
50
|
+
return (
|
|
51
|
+
<Animated.View
|
|
52
|
+
style={[sideBarStyle, counterStyle]}
|
|
53
|
+
pointerEvents={'box-none'}
|
|
54
|
+
>
|
|
55
|
+
<HeaderToolkitAction
|
|
56
|
+
{...props.headerRight}
|
|
57
|
+
tintColor={props.tintColor}
|
|
58
|
+
vertical
|
|
59
|
+
/>
|
|
60
|
+
</Animated.View>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
41
64
|
return (
|
|
42
65
|
<View style={styles.headerRightButton}>
|
|
43
66
|
<HeaderToolkitAction {...props.headerRight} tintColor={props.tintColor} />
|
|
@@ -56,9 +79,13 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
56
79
|
useMore = false,
|
|
57
80
|
tools = [],
|
|
58
81
|
useCloseIcon = false,
|
|
82
|
+
vertical = false,
|
|
59
83
|
}) => {
|
|
60
84
|
const { navigator } = useContext(ApplicationContext);
|
|
61
85
|
const context = useContext<any>(MiniAppContext);
|
|
86
|
+
const { toolbarCompressed, toolbarHidden, expandToolbar, setToolbarHeight } =
|
|
87
|
+
useDuoBarCompression();
|
|
88
|
+
const { statusBarClearance } = useScreenLayout();
|
|
62
89
|
|
|
63
90
|
const [isFavorite, setIsFavorite] = useState<boolean>(false);
|
|
64
91
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -260,6 +287,111 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
260
287
|
group?.items?.some?.(tool => tool?.showBadge),
|
|
261
288
|
);
|
|
262
289
|
|
|
290
|
+
const useHelpCenter = context.appId !== 'vn.momo.helpcenter';
|
|
291
|
+
const closeIcon = useCloseIcon
|
|
292
|
+
? '16_navigation_close_circle'
|
|
293
|
+
: '16_basic_home';
|
|
294
|
+
|
|
295
|
+
const groupCount = useHelpCenter ? 2 : 1;
|
|
296
|
+
// Back slot, the optional shortcut, then the help/home capsule
|
|
297
|
+
const fullToolbarHeight =
|
|
298
|
+
DuoMetrics.controlSize +
|
|
299
|
+
Spacing.M +
|
|
300
|
+
(useShortcut ? DuoMetrics.controlSize + Spacing.M : 0) +
|
|
301
|
+
(groupCount > 1
|
|
302
|
+
? groupCount * DuoMetrics.itemPitch
|
|
303
|
+
: DuoMetrics.controlSize);
|
|
304
|
+
|
|
305
|
+
useEffect(() => {
|
|
306
|
+
if (vertical) {
|
|
307
|
+
setToolbarHeight?.(fullToolbarHeight);
|
|
308
|
+
}
|
|
309
|
+
}, [vertical, fullToolbarHeight, setToolbarHeight]);
|
|
310
|
+
|
|
311
|
+
// an open tab rail takes this slot for a moment
|
|
312
|
+
if (vertical && toolbarHidden) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// HIG "Toolbar compressed": tools fold into one button; tapping it expands the
|
|
317
|
+
// toolbar and compresses the tab bar instead. Not the useMore icon, to tell them apart
|
|
318
|
+
if (vertical && toolbarCompressed) {
|
|
319
|
+
return (
|
|
320
|
+
<SideBarButton
|
|
321
|
+
accessibilityLabel={'btn_navigation_toolbar'}
|
|
322
|
+
icon={'navigation_menu'}
|
|
323
|
+
tintColor={tintColor}
|
|
324
|
+
showBadge={showBadge}
|
|
325
|
+
onPress={expandToolbar}
|
|
326
|
+
/>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (vertical) {
|
|
331
|
+
return (
|
|
332
|
+
<View style={styles.sideBarColumn}>
|
|
333
|
+
{useShortcut && (
|
|
334
|
+
<SideBarButton
|
|
335
|
+
disabled={isLoading}
|
|
336
|
+
icon={iconShortcut}
|
|
337
|
+
onPress={shortcutOnPress}
|
|
338
|
+
tintColor={tintColor}
|
|
339
|
+
showBadge={showBadge}
|
|
340
|
+
/>
|
|
341
|
+
)}
|
|
342
|
+
<SideBarGroup tintColor={tintColor}>
|
|
343
|
+
{useHelpCenter && (
|
|
344
|
+
<SideBarGroupItem
|
|
345
|
+
accessibilityLabel={'btn_navigation_help_center'}
|
|
346
|
+
icon={'help_center'}
|
|
347
|
+
tintColor={tintColor}
|
|
348
|
+
onPress={onPressHelpCenter}
|
|
349
|
+
/>
|
|
350
|
+
)}
|
|
351
|
+
<SideBarGroupItem
|
|
352
|
+
accessibilityLabel={'btn_navigation_close'}
|
|
353
|
+
icon={closeIcon}
|
|
354
|
+
tintColor={tintColor}
|
|
355
|
+
onPress={onClose}
|
|
356
|
+
/>
|
|
357
|
+
</SideBarGroup>
|
|
358
|
+
</View>
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// on the status bar row the controls keep the side bar size
|
|
363
|
+
if (statusBarClearance) {
|
|
364
|
+
return (
|
|
365
|
+
<View style={styles.sideBarRow}>
|
|
366
|
+
{useShortcut && (
|
|
367
|
+
<SideBarButton
|
|
368
|
+
disabled={isLoading}
|
|
369
|
+
icon={iconShortcut}
|
|
370
|
+
onPress={shortcutOnPress}
|
|
371
|
+
tintColor={tintColor}
|
|
372
|
+
showBadge={showBadge}
|
|
373
|
+
/>
|
|
374
|
+
)}
|
|
375
|
+
<SideBarGroup tintColor={tintColor} horizontal>
|
|
376
|
+
{useHelpCenter && (
|
|
377
|
+
<SideBarGroupItem
|
|
378
|
+
accessibilityLabel={'btn_navigation_help_center'}
|
|
379
|
+
icon={'help_center'}
|
|
380
|
+
tintColor={tintColor}
|
|
381
|
+
onPress={onPressHelpCenter}
|
|
382
|
+
/>
|
|
383
|
+
)}
|
|
384
|
+
<SideBarGroupItem
|
|
385
|
+
accessibilityLabel={'btn_navigation_close'}
|
|
386
|
+
icon={closeIcon}
|
|
387
|
+
tintColor={tintColor}
|
|
388
|
+
onPress={onClose}
|
|
389
|
+
/>
|
|
390
|
+
</SideBarGroup>
|
|
391
|
+
</View>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
263
395
|
return (
|
|
264
396
|
<View style={Styles.row}>
|
|
265
397
|
{useShortcut && (
|
|
@@ -280,7 +412,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
280
412
|
},
|
|
281
413
|
]}
|
|
282
414
|
>
|
|
283
|
-
{
|
|
415
|
+
{useHelpCenter && (
|
|
284
416
|
<>
|
|
285
417
|
<TouchableOpacity
|
|
286
418
|
accessibilityLabel={'btn_navigation_help_center'}
|
|
@@ -299,13 +431,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
299
431
|
style={styles.toolkitButton}
|
|
300
432
|
hitSlop={{ top: 7, bottom: 7, left: 0, right: 7 }}
|
|
301
433
|
>
|
|
302
|
-
<Icon
|
|
303
|
-
color={tintColor}
|
|
304
|
-
source={
|
|
305
|
-
useCloseIcon ? '16_navigation_close_circle' : '16_basic_home'
|
|
306
|
-
}
|
|
307
|
-
size={20}
|
|
308
|
-
/>
|
|
434
|
+
<Icon color={tintColor} source={closeIcon} size={20} />
|
|
309
435
|
</TouchableOpacity>
|
|
310
436
|
</View>
|
|
311
437
|
</View>
|
|
@@ -376,6 +502,13 @@ const styles = StyleSheet.create({
|
|
|
376
502
|
width: 0.5,
|
|
377
503
|
height: 12,
|
|
378
504
|
},
|
|
505
|
+
sideBarColumn: {
|
|
506
|
+
gap: Spacing.M,
|
|
507
|
+
},
|
|
508
|
+
sideBarRow: {
|
|
509
|
+
flexDirection: 'row',
|
|
510
|
+
gap: Spacing.M,
|
|
511
|
+
},
|
|
379
512
|
headerLeft: {
|
|
380
513
|
marginLeft: 12,
|
|
381
514
|
},
|
|
@@ -16,7 +16,47 @@ import {
|
|
|
16
16
|
import { Image } from '../../Image';
|
|
17
17
|
import { Icon } from '../../Icon';
|
|
18
18
|
import { Skeleton } from '../../Skeleton';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
AnimatedCompatValue,
|
|
21
|
+
isWhiteListDesignSystem,
|
|
22
|
+
useNormalizedSharedValue,
|
|
23
|
+
} from '../utils';
|
|
24
|
+
import { useScreenLayout } from '../../Layout';
|
|
25
|
+
|
|
26
|
+
const useHeaderFontFamily = (): string => {
|
|
27
|
+
const context = useContext<any>(MiniAppContext);
|
|
28
|
+
return isWhiteListDesignSystem(context) ? 'MoMoTrustDisplay' : 'SFProText';
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* back button and toolkit sharing the navigation bar with the title
|
|
33
|
+
*/
|
|
34
|
+
const HEADER_ACTIONS_WIDTH = 172;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* extra width the 48pt back and toolkit take on the iPhone Duo status bar row
|
|
38
|
+
*/
|
|
39
|
+
const STATUS_BAR_ROW_ACTIONS_EXTRA = 55;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* max title width, the iPhone Duo side bar takes back and toolkit out of the bar
|
|
43
|
+
*/
|
|
44
|
+
const useTitleMaxWidth = () => {
|
|
45
|
+
const { width, contentWidth, sideBar, statusBarClearance } =
|
|
46
|
+
useScreenLayout();
|
|
47
|
+
const clearance = statusBarClearance
|
|
48
|
+
? statusBarClearance.left + statusBarClearance.right
|
|
49
|
+
: 0;
|
|
50
|
+
if (sideBar) {
|
|
51
|
+
return contentWidth - Spacing.M * 2 - clearance;
|
|
52
|
+
}
|
|
53
|
+
return (
|
|
54
|
+
width -
|
|
55
|
+
HEADER_ACTIONS_WIDTH -
|
|
56
|
+
(statusBarClearance ? STATUS_BAR_ROW_ACTIONS_EXTRA : 0) -
|
|
57
|
+
clearance
|
|
58
|
+
);
|
|
59
|
+
};
|
|
20
60
|
|
|
21
61
|
type HeaderTitleInterpolate = {
|
|
22
62
|
inputRange: number[];
|
|
@@ -37,6 +77,8 @@ const HeaderTitle: React.FC<
|
|
|
37
77
|
HeaderTitleExtraProps & { [key: string]: any }
|
|
38
78
|
> = props => {
|
|
39
79
|
const context = useContext<any>(MiniAppContext);
|
|
80
|
+
const headerFontFamily = useHeaderFontFamily();
|
|
81
|
+
const maxWidth = useTitleMaxWidth();
|
|
40
82
|
|
|
41
83
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
42
84
|
|
|
@@ -67,7 +109,7 @@ const HeaderTitle: React.FC<
|
|
|
67
109
|
style={[
|
|
68
110
|
{
|
|
69
111
|
justifyContent: 'center',
|
|
70
|
-
maxWidth
|
|
112
|
+
maxWidth,
|
|
71
113
|
},
|
|
72
114
|
showBaseLineDebug && styles.debugBaseLine,
|
|
73
115
|
]}
|
|
@@ -85,7 +127,7 @@ const HeaderTitle: React.FC<
|
|
|
85
127
|
fontFamily: exportFontFamily(
|
|
86
128
|
'bold',
|
|
87
129
|
'action_xs_bold',
|
|
88
|
-
|
|
130
|
+
headerFontFamily,
|
|
89
131
|
),
|
|
90
132
|
color: props.tintColor,
|
|
91
133
|
},
|
|
@@ -130,7 +172,8 @@ const TitleUser: React.FC<TitleUserProps> = ({
|
|
|
130
172
|
isLoading,
|
|
131
173
|
}) => {
|
|
132
174
|
const { theme } = useContext(ApplicationContext);
|
|
133
|
-
const
|
|
175
|
+
const headerFontFamily = useHeaderFontFamily();
|
|
176
|
+
const maxWidth = useTitleMaxWidth();
|
|
134
177
|
const getShortName = (name: string) => {
|
|
135
178
|
const words = name.split(' ');
|
|
136
179
|
const lastTwoWords = words.slice(-2);
|
|
@@ -378,7 +421,7 @@ const TitleUser: React.FC<TitleUserProps> = ({
|
|
|
378
421
|
<View style={Styles.row}>
|
|
379
422
|
<Text
|
|
380
423
|
typography="action_xs_bold"
|
|
381
|
-
fontFamily=
|
|
424
|
+
fontFamily={headerFontFamily}
|
|
382
425
|
color={tintColor}
|
|
383
426
|
numberOfLines={1}
|
|
384
427
|
>
|
|
@@ -412,7 +455,8 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
412
455
|
onPress,
|
|
413
456
|
isLoading,
|
|
414
457
|
}) => {
|
|
415
|
-
const
|
|
458
|
+
const headerFontFamily = useHeaderFontFamily();
|
|
459
|
+
const maxWidth = useTitleMaxWidth();
|
|
416
460
|
const renderShimmer = () => {
|
|
417
461
|
return (
|
|
418
462
|
<View style={Styles.flex}>
|
|
@@ -448,9 +492,12 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
448
492
|
</Text>
|
|
449
493
|
)}
|
|
450
494
|
<View style={Styles.row}>
|
|
451
|
-
<Text
|
|
452
|
-
|
|
453
|
-
|
|
495
|
+
<Text
|
|
496
|
+
typography="action_xs_bold"
|
|
497
|
+
fontFamily={headerFontFamily}
|
|
498
|
+
color={tintColor}
|
|
499
|
+
numberOfLines={1}
|
|
500
|
+
>
|
|
454
501
|
{location}
|
|
455
502
|
</Text>
|
|
456
503
|
<Icon
|
|
@@ -477,10 +524,15 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
477
524
|
onPress,
|
|
478
525
|
isLoading,
|
|
479
526
|
}) => {
|
|
480
|
-
const
|
|
481
|
-
const maxWidth =
|
|
482
|
-
const
|
|
483
|
-
|
|
527
|
+
const headerFontFamily = useHeaderFontFamily();
|
|
528
|
+
const maxWidth = useTitleMaxWidth();
|
|
529
|
+
const { sideBar } = useScreenLayout();
|
|
530
|
+
// journey split is tuned against the whole bar width
|
|
531
|
+
const barWidth = sideBar
|
|
532
|
+
? maxWidth + HEADER_ACTIONS_WIDTH
|
|
533
|
+
: Dimensions.get('screen').width;
|
|
534
|
+
const startWidth = barWidth * 0.25;
|
|
535
|
+
const endWidth = barWidth * 0.75 - 212;
|
|
484
536
|
const renderShimmer = () => {
|
|
485
537
|
return (
|
|
486
538
|
<View style={Styles.flex}>
|
|
@@ -512,8 +564,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
512
564
|
style={{ maxWidth: startWidth }}
|
|
513
565
|
color={tintColor}
|
|
514
566
|
numberOfLines={1}
|
|
515
|
-
|
|
516
|
-
|
|
567
|
+
fontFamily={headerFontFamily}
|
|
517
568
|
>
|
|
518
569
|
{start}
|
|
519
570
|
</Text>
|
|
@@ -529,8 +580,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
529
580
|
typography="action_xs_bold"
|
|
530
581
|
color={tintColor}
|
|
531
582
|
numberOfLines={1}
|
|
532
|
-
|
|
533
|
-
|
|
583
|
+
fontFamily={headerFontFamily}
|
|
534
584
|
>
|
|
535
585
|
{end}
|
|
536
586
|
</Text>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
// native glass is optional so apps without @momo-kits/glass-view still bundle
|
|
4
|
+
let GlassView: React.ComponentType<any> | undefined;
|
|
5
|
+
try {
|
|
6
|
+
GlassView = require('@momo-kits/glass-view').GlassView;
|
|
7
|
+
} catch {
|
|
8
|
+
GlassView = undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { GlassView };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
// native observer is optional so apps without it in @momo-kits/reserved-regions still bundle
|
|
4
|
+
let ScrollObserverView: React.ComponentType<any> | undefined;
|
|
5
|
+
try {
|
|
6
|
+
ScrollObserverView =
|
|
7
|
+
require('@momo-kits/reserved-regions').ScrollObserverView;
|
|
8
|
+
} catch {
|
|
9
|
+
ScrollObserverView = undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { ScrollObserverView };
|