@momo-kits/foundation 0.167.1-beta.7 → 0.167.1-duo.12
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 +155 -134
- package/Application/Components/DuoGlassBackground.tsx +179 -0
- package/Application/Components/DuoQuickReturnHeader.tsx +42 -0
- package/Application/Components/HeaderExtendHeader.tsx +65 -28
- package/Application/Components/HeaderLeft.tsx +23 -0
- package/Application/Components/HeaderRight.tsx +104 -9
- package/Application/Components/HeaderTitle.tsx +47 -21
- package/Application/Components/OptionalGlassView.ts +11 -0
- package/Application/Components/SearchHeader.tsx +15 -14
- package/Application/Components/SideBarButton.tsx +128 -0
- package/Application/ModalScreen.tsx +16 -2
- package/Application/NavigationContainer.tsx +36 -48
- package/Application/Navigator.ts +1 -3
- package/Application/StackScreen.tsx +2 -5
- package/Application/WidgetContainer.tsx +9 -15
- package/Application/device.ts +29 -0
- package/Application/types.ts +10 -1
- package/Application/utils.tsx +10 -3
- 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 +240 -48
- package/Layout/Section.tsx +5 -18
- package/Layout/index.ts +4 -4
- package/Layout/styles.ts +5 -0
- package/Layout/utils.ts +375 -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 { 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,25 @@ 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
|
+
const leftPosition =
|
|
55
|
+
inputSearchProps?.leftPosition ||
|
|
56
|
+
(layout.sideBar ? SCREEN_PADDING : BACK_WIDTH + 20);
|
|
57
|
+
const headerRightWidth =
|
|
58
|
+
customHeaderRightWidth ?? (layout.sideBar ? 0 : TOOLKIT_WIDTH);
|
|
59
|
+
const contentLeft = layout.insetLeft + SCREEN_PADDING;
|
|
60
|
+
const contentRight = layout.insetLeft + layout.contentWidth;
|
|
61
|
+
const collapsedLeft = layout.insetLeft + leftPosition;
|
|
62
|
+
const searchWidth = layout.contentWidth - SCREEN_PADDING * 2;
|
|
63
|
+
const collapsedSearchWidth =
|
|
64
|
+
contentRight - collapsedLeft - SCREEN_PADDING - headerRightWidth;
|
|
65
|
+
// a row taller than barHeight (iPhone Duo) centers the collapsed search on the title
|
|
66
|
+
const collapsedRaise =
|
|
67
|
+
(layout.headerHeight -
|
|
68
|
+
layout.headerStatusBarHeight -
|
|
69
|
+
HeaderMetrics.barHeight) /
|
|
70
|
+
2;
|
|
55
71
|
|
|
56
72
|
let useShadowHeader = useShadowHeaderProp;
|
|
57
73
|
if (inputSearchProps && Platform.OS === 'android') {
|
|
@@ -70,7 +86,12 @@ const HeaderExtendHeader: React.FC<{
|
|
|
70
86
|
}));
|
|
71
87
|
|
|
72
88
|
const gradientOpacityStyle = useAnimatedStyle(() => ({
|
|
73
|
-
opacity: interpolate(
|
|
89
|
+
opacity: interpolate(
|
|
90
|
+
sharedValue.value,
|
|
91
|
+
[0, 52],
|
|
92
|
+
[1, 0],
|
|
93
|
+
Extrapolation.CLAMP,
|
|
94
|
+
),
|
|
74
95
|
}));
|
|
75
96
|
|
|
76
97
|
const searchTranslateStyle = useAnimatedStyle(() => ({
|
|
@@ -79,7 +100,15 @@ const HeaderExtendHeader: React.FC<{
|
|
|
79
100
|
translateX: interpolate(
|
|
80
101
|
sharedValue.value,
|
|
81
102
|
[0, 100],
|
|
82
|
-
[
|
|
103
|
+
[contentLeft, collapsedLeft],
|
|
104
|
+
Extrapolation.CLAMP,
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
translateY: interpolate(
|
|
109
|
+
sharedValue.value,
|
|
110
|
+
[0, 100],
|
|
111
|
+
[0, -collapsedRaise],
|
|
83
112
|
Extrapolation.CLAMP,
|
|
84
113
|
),
|
|
85
114
|
},
|
|
@@ -87,19 +116,19 @@ const HeaderExtendHeader: React.FC<{
|
|
|
87
116
|
width: interpolate(
|
|
88
117
|
sharedValue.value,
|
|
89
118
|
[0, 100],
|
|
90
|
-
[
|
|
91
|
-
screenWidth - SCREEN_PADDING * 2,
|
|
92
|
-
screenWidth - leftPosition - 12 - headerRightWidth,
|
|
93
|
-
],
|
|
119
|
+
[searchWidth, collapsedSearchWidth],
|
|
94
120
|
Extrapolation.CLAMP,
|
|
95
121
|
),
|
|
96
122
|
}));
|
|
97
123
|
|
|
98
124
|
const searchBackgroundStyle = useAnimatedStyle(() => {
|
|
99
125
|
const t = Math.min(Math.max(sharedValue.value / 100, 0), 1);
|
|
100
|
-
return {
|
|
101
|
-
|
|
102
|
-
|
|
126
|
+
return {
|
|
127
|
+
backgroundColor:
|
|
128
|
+
t === 0
|
|
129
|
+
? theme.colors.background.surface
|
|
130
|
+
: theme.colors.background.default,
|
|
131
|
+
};
|
|
103
132
|
});
|
|
104
133
|
|
|
105
134
|
const extendedHeightStyle = useAnimatedStyle(() => ({
|
|
@@ -124,14 +153,17 @@ const HeaderExtendHeader: React.FC<{
|
|
|
124
153
|
<Animated.View
|
|
125
154
|
style={[
|
|
126
155
|
styles.headerBox,
|
|
127
|
-
headerType === 'extended'
|
|
128
|
-
? heightStyle
|
|
129
|
-
: { height: heightHeader },
|
|
156
|
+
headerType === 'extended' ? heightStyle : { height: heightHeader },
|
|
130
157
|
]}
|
|
131
158
|
>
|
|
132
159
|
{!!gradientColor && (
|
|
133
160
|
<Animated.View
|
|
134
|
-
style={[
|
|
161
|
+
style={[
|
|
162
|
+
styles.extendedHeader,
|
|
163
|
+
// fade out within the header box, as DuoScrollGradient does
|
|
164
|
+
!!layout.sideBar && styles.fillHeaderBox,
|
|
165
|
+
gradientOpacityStyle,
|
|
166
|
+
]}
|
|
135
167
|
>
|
|
136
168
|
<LinearGradient
|
|
137
169
|
colors={[gradientColor, gradientColor + '00']}
|
|
@@ -162,10 +194,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
162
194
|
style={[{ marginVertical: Spacing.S }, searchTranslateStyle]}
|
|
163
195
|
>
|
|
164
196
|
<Animated.View
|
|
165
|
-
style={[
|
|
166
|
-
{ borderRadius: Radius.XL },
|
|
167
|
-
searchBackgroundStyle,
|
|
168
|
-
]}
|
|
197
|
+
style={[{ borderRadius: Radius.XL }, searchBackgroundStyle]}
|
|
169
198
|
>
|
|
170
199
|
<InputSearch
|
|
171
200
|
{...inputSearchProps}
|
|
@@ -191,7 +220,11 @@ const HeaderExtendHeader: React.FC<{
|
|
|
191
220
|
/>
|
|
192
221
|
{!!gradientColor && (
|
|
193
222
|
<Animated.View
|
|
194
|
-
style={[
|
|
223
|
+
style={[
|
|
224
|
+
styles.extendedHeader,
|
|
225
|
+
gradientOpacityStyle,
|
|
226
|
+
extendedHeightStyle,
|
|
227
|
+
]}
|
|
195
228
|
>
|
|
196
229
|
<LinearGradient
|
|
197
230
|
colors={[gradientColor, gradientColor + '00']}
|
|
@@ -227,6 +260,10 @@ const styles = StyleSheet.create({
|
|
|
227
260
|
position: 'absolute',
|
|
228
261
|
width: '100%',
|
|
229
262
|
},
|
|
263
|
+
fillHeaderBox: {
|
|
264
|
+
aspectRatio: undefined,
|
|
265
|
+
height: '100%',
|
|
266
|
+
},
|
|
230
267
|
headerBox: {
|
|
231
268
|
width: '100%',
|
|
232
269
|
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 { useSideBarItemStyle } from '../../Layout/utils';
|
|
10
|
+
import { useSideBarCounterStyle } from './DuoQuickReturnHeader';
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* default header left used for nav
|
|
@@ -13,9 +17,12 @@ 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();
|
|
19
26
|
|
|
20
27
|
const goBack = useCallback(() => {
|
|
21
28
|
const canGoBack = navigator?.ref?.current?.canGoBack?.();
|
|
@@ -72,6 +79,22 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
72
79
|
return () => backHandler.remove();
|
|
73
80
|
}, [goBackSafe]);
|
|
74
81
|
|
|
82
|
+
if (floating && sideBarStyle) {
|
|
83
|
+
return (
|
|
84
|
+
<Animated.View
|
|
85
|
+
style={[sideBarStyle, counterStyle]}
|
|
86
|
+
pointerEvents={'box-none'}
|
|
87
|
+
>
|
|
88
|
+
<SideBarButton
|
|
89
|
+
accessibilityLabel="btn_navigation_back"
|
|
90
|
+
icon="arrow-back"
|
|
91
|
+
tintColor={tintColor}
|
|
92
|
+
onPress={goBackSafe}
|
|
93
|
+
/>
|
|
94
|
+
</Animated.View>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
75
98
|
return (
|
|
76
99
|
<View style={styles.headerLeft}>
|
|
77
100
|
<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 { 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,12 @@ 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();
|
|
62
88
|
|
|
63
89
|
const [isFavorite, setIsFavorite] = useState<boolean>(false);
|
|
64
90
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -260,6 +286,78 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
260
286
|
group?.items?.some?.(tool => tool?.showBadge),
|
|
261
287
|
);
|
|
262
288
|
|
|
289
|
+
const useHelpCenter = context.appId !== 'vn.momo.helpcenter';
|
|
290
|
+
const closeIcon = useCloseIcon
|
|
291
|
+
? '16_navigation_close_circle'
|
|
292
|
+
: '16_basic_home';
|
|
293
|
+
|
|
294
|
+
const groupCount = useHelpCenter ? 2 : 1;
|
|
295
|
+
// Back slot, the optional shortcut, then the help/home capsule
|
|
296
|
+
const fullToolbarHeight =
|
|
297
|
+
DuoMetrics.controlSize +
|
|
298
|
+
Spacing.M +
|
|
299
|
+
(useShortcut ? DuoMetrics.controlSize + Spacing.M : 0) +
|
|
300
|
+
(groupCount > 1
|
|
301
|
+
? groupCount * DuoMetrics.itemPitch
|
|
302
|
+
: DuoMetrics.controlSize);
|
|
303
|
+
|
|
304
|
+
useEffect(() => {
|
|
305
|
+
if (vertical) {
|
|
306
|
+
setToolbarHeight?.(fullToolbarHeight);
|
|
307
|
+
}
|
|
308
|
+
}, [vertical, fullToolbarHeight, setToolbarHeight]);
|
|
309
|
+
|
|
310
|
+
// an open tab rail takes this slot for a moment
|
|
311
|
+
if (vertical && toolbarHidden) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// HIG "Toolbar compressed": tools fold into one button; tapping it expands the
|
|
316
|
+
// toolbar and compresses the tab bar instead. Not the useMore icon, to tell them apart
|
|
317
|
+
if (vertical && toolbarCompressed) {
|
|
318
|
+
return (
|
|
319
|
+
<SideBarButton
|
|
320
|
+
accessibilityLabel={'btn_navigation_toolbar'}
|
|
321
|
+
icon={'navigation_menu'}
|
|
322
|
+
tintColor={tintColor}
|
|
323
|
+
showBadge={showBadge}
|
|
324
|
+
onPress={expandToolbar}
|
|
325
|
+
/>
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (vertical) {
|
|
330
|
+
return (
|
|
331
|
+
<View style={styles.sideBarColumn}>
|
|
332
|
+
{useShortcut && (
|
|
333
|
+
<SideBarButton
|
|
334
|
+
disabled={isLoading}
|
|
335
|
+
icon={iconShortcut}
|
|
336
|
+
onPress={shortcutOnPress}
|
|
337
|
+
tintColor={tintColor}
|
|
338
|
+
showBadge={showBadge}
|
|
339
|
+
/>
|
|
340
|
+
)}
|
|
341
|
+
<SideBarGroup tintColor={tintColor}>
|
|
342
|
+
{useHelpCenter && (
|
|
343
|
+
<SideBarGroupItem
|
|
344
|
+
accessibilityLabel={'btn_navigation_help_center'}
|
|
345
|
+
icon={'help_center'}
|
|
346
|
+
tintColor={tintColor}
|
|
347
|
+
onPress={onPressHelpCenter}
|
|
348
|
+
/>
|
|
349
|
+
)}
|
|
350
|
+
<SideBarGroupItem
|
|
351
|
+
accessibilityLabel={'btn_navigation_close'}
|
|
352
|
+
icon={closeIcon}
|
|
353
|
+
tintColor={tintColor}
|
|
354
|
+
onPress={onClose}
|
|
355
|
+
/>
|
|
356
|
+
</SideBarGroup>
|
|
357
|
+
</View>
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
263
361
|
return (
|
|
264
362
|
<View style={Styles.row}>
|
|
265
363
|
{useShortcut && (
|
|
@@ -280,7 +378,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
280
378
|
},
|
|
281
379
|
]}
|
|
282
380
|
>
|
|
283
|
-
{
|
|
381
|
+
{useHelpCenter && (
|
|
284
382
|
<>
|
|
285
383
|
<TouchableOpacity
|
|
286
384
|
accessibilityLabel={'btn_navigation_help_center'}
|
|
@@ -299,13 +397,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
299
397
|
style={styles.toolkitButton}
|
|
300
398
|
hitSlop={{ top: 7, bottom: 7, left: 0, right: 7 }}
|
|
301
399
|
>
|
|
302
|
-
<Icon
|
|
303
|
-
color={tintColor}
|
|
304
|
-
source={
|
|
305
|
-
useCloseIcon ? '16_navigation_close_circle' : '16_basic_home'
|
|
306
|
-
}
|
|
307
|
-
size={20}
|
|
308
|
-
/>
|
|
400
|
+
<Icon color={tintColor} source={closeIcon} size={20} />
|
|
309
401
|
</TouchableOpacity>
|
|
310
402
|
</View>
|
|
311
403
|
</View>
|
|
@@ -376,6 +468,9 @@ const styles = StyleSheet.create({
|
|
|
376
468
|
width: 0.5,
|
|
377
469
|
height: 12,
|
|
378
470
|
},
|
|
471
|
+
sideBarColumn: {
|
|
472
|
+
gap: Spacing.M,
|
|
473
|
+
},
|
|
379
474
|
headerLeft: {
|
|
380
475
|
marginLeft: 12,
|
|
381
476
|
},
|
|
@@ -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,33 @@ 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
|
+
* max title width, the iPhone Duo side bar takes back and toolkit out of the bar
|
|
38
|
+
*/
|
|
39
|
+
const useTitleMaxWidth = () => {
|
|
40
|
+
const { width, contentWidth, sideBar } = useScreenLayout();
|
|
41
|
+
if (sideBar) {
|
|
42
|
+
return contentWidth - Spacing.M * 2;
|
|
43
|
+
}
|
|
44
|
+
return width - HEADER_ACTIONS_WIDTH;
|
|
45
|
+
};
|
|
26
46
|
|
|
27
47
|
type HeaderTitleInterpolate = {
|
|
28
48
|
inputRange: number[];
|
|
@@ -44,6 +64,7 @@ const HeaderTitle: React.FC<
|
|
|
44
64
|
> = props => {
|
|
45
65
|
const context = useContext<any>(MiniAppContext);
|
|
46
66
|
const headerFontFamily = useHeaderFontFamily();
|
|
67
|
+
const maxWidth = useTitleMaxWidth();
|
|
47
68
|
|
|
48
69
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
49
70
|
|
|
@@ -74,7 +95,7 @@ const HeaderTitle: React.FC<
|
|
|
74
95
|
style={[
|
|
75
96
|
{
|
|
76
97
|
justifyContent: 'center',
|
|
77
|
-
maxWidth
|
|
98
|
+
maxWidth,
|
|
78
99
|
},
|
|
79
100
|
showBaseLineDebug && styles.debugBaseLine,
|
|
80
101
|
]}
|
|
@@ -138,7 +159,7 @@ const TitleUser: React.FC<TitleUserProps> = ({
|
|
|
138
159
|
}) => {
|
|
139
160
|
const { theme } = useContext(ApplicationContext);
|
|
140
161
|
const headerFontFamily = useHeaderFontFamily();
|
|
141
|
-
const maxWidth =
|
|
162
|
+
const maxWidth = useTitleMaxWidth();
|
|
142
163
|
const getShortName = (name: string) => {
|
|
143
164
|
const words = name.split(' ');
|
|
144
165
|
const lastTwoWords = words.slice(-2);
|
|
@@ -421,7 +442,7 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
421
442
|
isLoading,
|
|
422
443
|
}) => {
|
|
423
444
|
const headerFontFamily = useHeaderFontFamily();
|
|
424
|
-
const maxWidth =
|
|
445
|
+
const maxWidth = useTitleMaxWidth();
|
|
425
446
|
const renderShimmer = () => {
|
|
426
447
|
return (
|
|
427
448
|
<View style={Styles.flex}>
|
|
@@ -457,9 +478,12 @@ const TitleLocation: React.FC<TitleLocationProps> = ({
|
|
|
457
478
|
</Text>
|
|
458
479
|
)}
|
|
459
480
|
<View style={Styles.row}>
|
|
460
|
-
<Text
|
|
481
|
+
<Text
|
|
482
|
+
typography="action_xs_bold"
|
|
461
483
|
fontFamily={headerFontFamily}
|
|
462
|
-
|
|
484
|
+
color={tintColor}
|
|
485
|
+
numberOfLines={1}
|
|
486
|
+
>
|
|
463
487
|
{location}
|
|
464
488
|
</Text>
|
|
465
489
|
<Icon
|
|
@@ -487,10 +511,14 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
487
511
|
isLoading,
|
|
488
512
|
}) => {
|
|
489
513
|
const headerFontFamily = useHeaderFontFamily();
|
|
490
|
-
const
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
const
|
|
514
|
+
const maxWidth = useTitleMaxWidth();
|
|
515
|
+
const { sideBar } = useScreenLayout();
|
|
516
|
+
// journey split is tuned against the whole bar width
|
|
517
|
+
const barWidth = sideBar
|
|
518
|
+
? maxWidth + HEADER_ACTIONS_WIDTH
|
|
519
|
+
: Dimensions.get('screen').width;
|
|
520
|
+
const startWidth = barWidth * 0.25;
|
|
521
|
+
const endWidth = barWidth * 0.75 - 212;
|
|
494
522
|
const renderShimmer = () => {
|
|
495
523
|
return (
|
|
496
524
|
<View style={Styles.flex}>
|
|
@@ -522,8 +550,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
522
550
|
style={{ maxWidth: startWidth }}
|
|
523
551
|
color={tintColor}
|
|
524
552
|
numberOfLines={1}
|
|
525
|
-
|
|
526
|
-
|
|
553
|
+
fontFamily={headerFontFamily}
|
|
527
554
|
>
|
|
528
555
|
{start}
|
|
529
556
|
</Text>
|
|
@@ -539,8 +566,7 @@ const TitleJourney: React.FC<TitleJourneyProps> = ({
|
|
|
539
566
|
typography="action_xs_bold"
|
|
540
567
|
color={tintColor}
|
|
541
568
|
numberOfLines={1}
|
|
542
|
-
|
|
543
|
-
|
|
569
|
+
fontFamily={headerFontFamily}
|
|
544
570
|
>
|
|
545
571
|
{end}
|
|
546
572
|
</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 };
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { Colors, Radius, Spacing, Styles } from '../../Consts';
|
|
2
2
|
import { InputRef, InputSearch } from '../../Input';
|
|
3
|
-
import {
|
|
4
|
-
Dimensions,
|
|
5
|
-
StyleSheet,
|
|
6
|
-
TouchableOpacity,
|
|
7
|
-
View,
|
|
8
|
-
} from 'react-native';
|
|
3
|
+
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
9
4
|
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
10
5
|
import React, { useContext } from 'react';
|
|
11
6
|
import { SearchHeaderProps } from '../types';
|
|
12
7
|
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
13
8
|
import { Text } from '../../Text';
|
|
14
9
|
import { useNormalizedSharedValue } from '../utils';
|
|
10
|
+
import { useScreenLayout } from '../../Layout';
|
|
15
11
|
|
|
16
12
|
const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
17
13
|
(
|
|
@@ -27,18 +23,25 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
27
23
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
28
24
|
const context = useContext<any>(MiniAppContext);
|
|
29
25
|
const BACK_WIDTH = 28;
|
|
30
|
-
const
|
|
26
|
+
const layout = useScreenLayout();
|
|
31
27
|
|
|
32
28
|
const sharedValue = useNormalizedSharedValue(animatedValue);
|
|
33
29
|
const leftPosition = props?.leftPosition ?? BACK_WIDTH + 20;
|
|
34
30
|
const headerRightWidth = props?.headerRightWidth ?? 73;
|
|
35
31
|
|
|
32
|
+
// iPhone Duo side bar holds back: the search shares the content width with the buttons only
|
|
33
|
+
let searchMaxWidth = layout.width - leftPosition - 12 - headerRightWidth;
|
|
34
|
+
if (layout.sideBar) {
|
|
35
|
+
searchMaxWidth = layout.contentWidth - Spacing.M * 2 - headerRightWidth;
|
|
36
|
+
}
|
|
37
|
+
|
|
36
38
|
const backgroundStyle = useAnimatedStyle(() => {
|
|
37
39
|
const t = Math.min(Math.max(sharedValue.value / 100, 0), 1);
|
|
38
40
|
return {
|
|
39
|
-
backgroundColor:
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
backgroundColor:
|
|
42
|
+
t === 0
|
|
43
|
+
? theme.colors.background.surface
|
|
44
|
+
: theme.colors.background.default,
|
|
42
45
|
};
|
|
43
46
|
});
|
|
44
47
|
|
|
@@ -77,13 +80,11 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
77
80
|
style={[
|
|
78
81
|
Styles.flex,
|
|
79
82
|
renderButtons && {
|
|
80
|
-
maxWidth:
|
|
83
|
+
maxWidth: searchMaxWidth,
|
|
81
84
|
},
|
|
82
85
|
]}
|
|
83
86
|
>
|
|
84
|
-
<Animated.View
|
|
85
|
-
style={[{ borderRadius: Radius.XL }, backgroundStyle]}
|
|
86
|
-
>
|
|
87
|
+
<Animated.View style={[{ borderRadius: Radius.XL }, backgroundStyle]}>
|
|
87
88
|
<InputSearch
|
|
88
89
|
ref={ref}
|
|
89
90
|
{...props}
|