@momo-kits/foundation 0.167.1-beta.7 → 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 +61 -21
- 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 -50
- package/Application/Navigator.ts +1 -3
- package/Application/StackScreen.tsx +63 -9
- package/Application/WidgetContainer.tsx +9 -15
- 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 +3 -4
- 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 +5 -15
- package/Text/utils.ts +1 -2
- package/package.json +3 -2
- package/Consts/designSystemFont.ts +0 -25
- 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
|
},
|
|
@@ -7,13 +7,7 @@ import Animated, {
|
|
|
7
7
|
} from 'react-native-reanimated';
|
|
8
8
|
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
9
9
|
import { exportFontFamily, Text, useScaleSize } from '../../Text';
|
|
10
|
-
import {
|
|
11
|
-
Colors,
|
|
12
|
-
Radius,
|
|
13
|
-
Spacing,
|
|
14
|
-
Styles,
|
|
15
|
-
useHeaderFontFamily,
|
|
16
|
-
} from '../../Consts';
|
|
10
|
+
import { Colors, Radius, Spacing, Styles } from '../../Consts';
|
|
17
11
|
import {
|
|
18
12
|
TitleJourneyProps,
|
|
19
13
|
TitleLocationProps,
|
|
@@ -22,7 +16,47 @@ import {
|
|
|
22
16
|
import { Image } from '../../Image';
|
|
23
17
|
import { Icon } from '../../Icon';
|
|
24
18
|
import { Skeleton } from '../../Skeleton';
|
|
25
|
-
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
|
+
};
|
|
26
60
|
|
|
27
61
|
type HeaderTitleInterpolate = {
|
|
28
62
|
inputRange: number[];
|
|
@@ -44,6 +78,7 @@ const HeaderTitle: React.FC<
|
|
|
44
78
|
> = props => {
|
|
45
79
|
const context = useContext<any>(MiniAppContext);
|
|
46
80
|
const headerFontFamily = useHeaderFontFamily();
|
|
81
|
+
const maxWidth = useTitleMaxWidth();
|
|
47
82
|
|
|
48
83
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
49
84
|
|
|
@@ -74,7 +109,7 @@ const HeaderTitle: React.FC<
|
|
|
74
109
|
style={[
|
|
75
110
|
{
|
|
76
111
|
justifyContent: 'center',
|
|
77
|
-
maxWidth
|
|
112
|
+
maxWidth,
|
|
78
113
|
},
|
|
79
114
|
showBaseLineDebug && styles.debugBaseLine,
|
|
80
115
|
]}
|
|
@@ -138,7 +173,7 @@ const TitleUser: React.FC<TitleUserProps> = ({
|
|
|
138
173
|
}) => {
|
|
139
174
|
const { theme } = useContext(ApplicationContext);
|
|
140
175
|
const headerFontFamily = useHeaderFontFamily();
|
|
141
|
-
const maxWidth =
|
|
176
|
+
const maxWidth = useTitleMaxWidth();
|
|
142
177
|
const getShortName = (name: string) => {
|
|
143
178
|
const words = name.split(' ');
|
|
144
179
|
const lastTwoWords = words.slice(-2);
|
|
@@ -421,7 +456,7 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
421
456
|
isLoading,
|
|
422
457
|
}) => {
|
|
423
458
|
const headerFontFamily = useHeaderFontFamily();
|
|
424
|
-
const maxWidth =
|
|
459
|
+
const maxWidth = useTitleMaxWidth();
|
|
425
460
|
const renderShimmer = () => {
|
|
426
461
|
return (
|
|
427
462
|
<View style={Styles.flex}>
|
|
@@ -457,9 +492,12 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
457
492
|
</Text>
|
|
458
493
|
)}
|
|
459
494
|
<View style={Styles.row}>
|
|
460
|
-
<Text
|
|
495
|
+
<Text
|
|
496
|
+
typography="action_xs_bold"
|
|
461
497
|
fontFamily={headerFontFamily}
|
|
462
|
-
|
|
498
|
+
color={tintColor}
|
|
499
|
+
numberOfLines={1}
|
|
500
|
+
>
|
|
463
501
|
{location}
|
|
464
502
|
</Text>
|
|
465
503
|
<Icon
|
|
@@ -487,10 +525,14 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
487
525
|
isLoading,
|
|
488
526
|
}) => {
|
|
489
527
|
const headerFontFamily = useHeaderFontFamily();
|
|
490
|
-
const
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
const
|
|
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;
|
|
494
536
|
const renderShimmer = () => {
|
|
495
537
|
return (
|
|
496
538
|
<View style={Styles.flex}>
|
|
@@ -522,8 +564,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
522
564
|
style={{ maxWidth: startWidth }}
|
|
523
565
|
color={tintColor}
|
|
524
566
|
numberOfLines={1}
|
|
525
|
-
|
|
526
|
-
|
|
567
|
+
fontFamily={headerFontFamily}
|
|
527
568
|
>
|
|
528
569
|
{start}
|
|
529
570
|
</Text>
|
|
@@ -539,8 +580,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
539
580
|
typography="action_xs_bold"
|
|
540
581
|
color={tintColor}
|
|
541
582
|
numberOfLines={1}
|
|
542
|
-
|
|
543
|
-
|
|
583
|
+
fontFamily={headerFontFamily}
|
|
544
584
|
>
|
|
545
585
|
{end}
|
|
546
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 };
|