@momo-kits/foundation 0.80.9 → 0.81.1-beta.0
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 +212 -0
- package/Application/BottomTab/BottomTabBar.tsx +278 -0
- package/Application/BottomTab/index.tsx +143 -0
- package/Application/Components.tsx +379 -209
- package/Application/ModalScreen.tsx +14 -178
- package/Application/Navigation.ts +15 -19
- package/Application/NavigationContainer.tsx +66 -63
- package/Application/Navigator.ts +106 -53
- package/Application/StackScreen.tsx +123 -9
- package/Application/index.ts +19 -6
- package/Application/types.ts +83 -26
- package/Application/utils.tsx +38 -49
- package/Assets/icon.json +83 -5
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +3 -1
- package/Badge/Badge.tsx +56 -0
- package/Badge/BadgeDot.tsx +11 -0
- package/Badge/BadgeRibbon.tsx +125 -0
- package/Badge/Shape.tsx +29 -0
- package/Badge/index.tsx +7 -0
- package/Badge/styles.ts +58 -0
- package/Badge/types.ts +63 -0
- package/Button/index.tsx +64 -28
- package/Button/styles.ts +19 -0
- package/CheckBox/index.tsx +37 -27
- package/CheckBox/types.ts +5 -3
- package/Consts/colors+spacing+radius.ts +18 -0
- package/Icon/index.tsx +14 -9
- package/Icon/types.ts +4 -3
- package/IconButton/index.tsx +24 -15
- package/Image/index.tsx +62 -47
- package/Image/styles.ts +1 -9
- package/Image/types.ts +5 -1
- package/Input/Input.tsx +104 -25
- package/Input/InputDropDown.tsx +35 -23
- package/Input/InputMoney.tsx +79 -18
- package/Input/InputOTP.tsx +190 -149
- package/Input/InputSearch.tsx +96 -44
- package/Input/InputTextArea.tsx +33 -17
- package/Input/common.tsx +26 -17
- package/Input/index.tsx +69 -24
- package/Input/styles.ts +5 -7
- package/Input/utils.ts +1 -1
- package/Layout/AnimatedInputSearch.tsx +44 -0
- package/Layout/Card.tsx +37 -13
- package/Layout/FloatingButton.tsx +168 -0
- package/Layout/GridSystem.tsx +2 -3
- package/Layout/Item.tsx +1 -2
- package/Layout/ItemList.tsx +55 -0
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +404 -181
- package/Layout/Section.tsx +22 -22
- package/Layout/TextTyping.tsx +114 -0
- package/Layout/index.ts +12 -2
- package/Layout/styles.ts +46 -13
- package/Layout/types.ts +13 -5
- package/Layout/utils.ts +7 -12
- package/Loader/index.tsx +2 -0
- package/Pagination/PaginationDot.tsx +6 -1
- package/Pagination/PaginationNumber.tsx +7 -4
- package/Pagination/PaginationScroll.tsx +0 -1
- package/Pagination/PaginationWhiteDot.tsx +6 -1
- package/Pagination/styles.ts +3 -0
- package/Pagination/types.ts +2 -0
- package/Popup/PopupNotify.tsx +108 -40
- package/Popup/PopupPromotion.tsx +45 -10
- package/Popup/types.ts +13 -10
- package/Radio/index.tsx +35 -21
- package/Radio/types.ts +7 -5
- package/Skeleton/index.tsx +1 -1
- package/Switch/index.tsx +32 -19
- package/Switch/types.ts +5 -3
- package/Tag/index.tsx +2 -4
- package/Text/index.tsx +26 -6
- package/Text/styles.ts +38 -0
- package/Text/types.ts +25 -13
- package/Title/index.tsx +177 -63
- package/Title/styles.ts +48 -15
- package/Title/types.ts +16 -47
- package/code-scanner.js +125 -16
- package/index.ts +9 -0
- package/migrate_typo.js +56 -0
- package/package.json +9 -8
- package/publish.sh +21 -16
- package/tsconfig.json +1 -2
- package/verify.js +24 -6
- package/Application/BottomTab.tsx +0 -65
|
@@ -1,144 +1,112 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
FC,
|
|
3
|
+
Fragment,
|
|
4
|
+
useCallback,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useState,
|
|
8
|
+
} from 'react';
|
|
2
9
|
import {
|
|
3
|
-
Alert,
|
|
4
10
|
Animated,
|
|
11
|
+
BackHandler,
|
|
5
12
|
DeviceEventEmitter,
|
|
6
|
-
Platform,
|
|
7
13
|
StatusBar,
|
|
8
14
|
StyleSheet,
|
|
9
|
-
TouchableOpacity
|
|
15
|
+
TouchableOpacity,
|
|
10
16
|
View,
|
|
17
|
+
ViewStyle,
|
|
11
18
|
} from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
import {ApplicationContext} from './index';
|
|
19
|
+
import {ApplicationContext, MiniAppContext} from './index';
|
|
14
20
|
import {Colors, Radius, Spacing, Styles} from '../Consts';
|
|
15
21
|
import {Image} from '../Image';
|
|
16
22
|
import {
|
|
23
|
+
HeaderAnimatedProps,
|
|
17
24
|
HeaderBackgroundProps,
|
|
18
25
|
HeaderBackProps,
|
|
19
|
-
|
|
26
|
+
IconButton,
|
|
20
27
|
NavigationButtonProps,
|
|
21
28
|
TitleCustomProps,
|
|
22
29
|
} from './types';
|
|
23
30
|
import {scaleSize, Text} from '../Text';
|
|
24
31
|
import {Icon} from '../Icon';
|
|
25
32
|
import {PopupNotify} from '../Popup';
|
|
26
|
-
|
|
27
|
-
const Touchable = Platform.OS === 'android' ? TouchableGesture : TouchableRN;
|
|
28
|
-
|
|
29
|
-
const styles = StyleSheet.create({
|
|
30
|
-
navigationButton: {
|
|
31
|
-
height: 28,
|
|
32
|
-
width: 28,
|
|
33
|
-
borderRadius: 14,
|
|
34
|
-
borderColor: '#00000066',
|
|
35
|
-
justifyContent: 'center',
|
|
36
|
-
alignItems: 'center',
|
|
37
|
-
},
|
|
38
|
-
headerBackground: {
|
|
39
|
-
width: '100%',
|
|
40
|
-
height: undefined,
|
|
41
|
-
position: 'absolute',
|
|
42
|
-
aspectRatio: 375 / 154,
|
|
43
|
-
},
|
|
44
|
-
headerTitleContainer: {
|
|
45
|
-
alignItems: 'center',
|
|
46
|
-
justifyContent: 'center',
|
|
47
|
-
width: '100%',
|
|
48
|
-
},
|
|
49
|
-
circle: {width: 36, height: 36, borderRadius: 18},
|
|
50
|
-
square: {width: 36, height: 36, borderRadius: Radius.XS},
|
|
51
|
-
dotAvatar: {
|
|
52
|
-
position: 'absolute',
|
|
53
|
-
width: 12,
|
|
54
|
-
height: 12,
|
|
55
|
-
borderRadius: 6,
|
|
56
|
-
bottom: 0,
|
|
57
|
-
right: 0,
|
|
58
|
-
borderWidth: 1,
|
|
59
|
-
borderColor: Colors.black_01,
|
|
60
|
-
},
|
|
61
|
-
headerButton: {paddingHorizontal: 4},
|
|
62
|
-
headerRightButton: {
|
|
63
|
-
flexDirection: 'row',
|
|
64
|
-
overflow: 'hidden',
|
|
65
|
-
justifyContent: 'center',
|
|
66
|
-
alignItems: 'center',
|
|
67
|
-
paddingRight: Spacing.S,
|
|
68
|
-
},
|
|
69
|
-
toolkitContainer: {
|
|
70
|
-
marginLeft: Spacing.S,
|
|
71
|
-
padding: Spacing.XS,
|
|
72
|
-
height: 28,
|
|
73
|
-
borderRadius: 14,
|
|
74
|
-
borderColor: '#00000066',
|
|
75
|
-
justifyContent: 'center',
|
|
76
|
-
alignItems: 'center',
|
|
77
|
-
flexDirection: 'row',
|
|
78
|
-
},
|
|
79
|
-
divider: {
|
|
80
|
-
width: 1,
|
|
81
|
-
height: 12,
|
|
82
|
-
marginHorizontal: 4,
|
|
83
|
-
},
|
|
84
|
-
headerLeft: {
|
|
85
|
-
marginLeft: 12,
|
|
86
|
-
},
|
|
87
|
-
title: {
|
|
88
|
-
fontSize: scaleSize(15),
|
|
89
|
-
lineHeight: scaleSize(22),
|
|
90
|
-
fontWeight: 'bold',
|
|
91
|
-
},
|
|
92
|
-
});
|
|
33
|
+
import {Badge, BadgeDot} from '../Badge';
|
|
93
34
|
|
|
94
35
|
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
95
36
|
icon,
|
|
96
37
|
tintColor,
|
|
97
38
|
onPress,
|
|
98
|
-
backgroundColor,
|
|
99
39
|
useBorder = true,
|
|
100
|
-
|
|
40
|
+
badgeType,
|
|
41
|
+
badgeValue,
|
|
42
|
+
accessibilityLabel = '',
|
|
101
43
|
}) => {
|
|
102
44
|
const {theme} = useContext(ApplicationContext);
|
|
103
|
-
|
|
104
|
-
|
|
45
|
+
let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
|
|
46
|
+
if (tintColor !== Colors.black_01) {
|
|
47
|
+
buttonStyle = {
|
|
48
|
+
backgroundColor: 'transparent',
|
|
49
|
+
borderColor: '#00000066',
|
|
50
|
+
borderWidth: useBorder ? 0.5 : 0,
|
|
51
|
+
};
|
|
105
52
|
}
|
|
106
53
|
|
|
54
|
+
const isNumber = (label: any) => {
|
|
55
|
+
const numberRegex = /^\d+$/;
|
|
56
|
+
return numberRegex.test(String(label));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const renderBadge = useCallback(() => {
|
|
60
|
+
if (badgeType === 'dot') {
|
|
61
|
+
return <BadgeDot size="small" style={styles.badgeDot} />;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (isNumber(badgeValue)) {
|
|
65
|
+
return <Badge label={badgeValue} style={styles.badge} />;
|
|
66
|
+
}
|
|
67
|
+
}, [badgeType, badgeValue]);
|
|
68
|
+
|
|
107
69
|
return (
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
styles.navigationButton,
|
|
112
|
-
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
size={20}
|
|
122
|
-
/>
|
|
123
|
-
</Touchable>
|
|
70
|
+
<View style={{width: scaleSize(28)}}>
|
|
71
|
+
<TouchableOpacity
|
|
72
|
+
accessibilityLabel={accessibilityLabel}
|
|
73
|
+
style={[styles.navigationButton, buttonStyle]}
|
|
74
|
+
onPress={onPress}>
|
|
75
|
+
<Icon
|
|
76
|
+
source={icon}
|
|
77
|
+
color={tintColor ?? theme.colors.text.default}
|
|
78
|
+
size={20}
|
|
79
|
+
/>
|
|
80
|
+
</TouchableOpacity>
|
|
81
|
+
{renderBadge()}
|
|
82
|
+
</View>
|
|
124
83
|
);
|
|
125
84
|
};
|
|
126
85
|
|
|
127
|
-
const HeaderTitle: React.FC<any> =
|
|
86
|
+
const HeaderTitle: React.FC<any> = props => {
|
|
128
87
|
const {theme} = useContext(ApplicationContext);
|
|
129
|
-
const
|
|
88
|
+
const opacityDefault = props.animatedValue?.interpolate({
|
|
130
89
|
inputRange: [0, 200],
|
|
131
90
|
outputRange: [0, 1],
|
|
132
91
|
extrapolate: 'clamp',
|
|
133
92
|
});
|
|
93
|
+
const opacitySearch = props.animatedValue?.interpolate({
|
|
94
|
+
inputRange: [0, 100],
|
|
95
|
+
outputRange: [1, 0],
|
|
96
|
+
extrapolate: 'clamp',
|
|
97
|
+
});
|
|
134
98
|
|
|
135
99
|
return (
|
|
136
100
|
<Animated.Text
|
|
137
101
|
{...props}
|
|
138
|
-
accessibilityLabel={
|
|
102
|
+
accessibilityLabel={'title_navigation_header'}
|
|
139
103
|
style={[
|
|
140
104
|
styles.title,
|
|
141
|
-
{
|
|
105
|
+
{
|
|
106
|
+
fontFamily: `${theme.font}-Bold`,
|
|
107
|
+
opacity: props.useSearchInput ? opacitySearch : opacityDefault,
|
|
108
|
+
color: props.tintColor,
|
|
109
|
+
},
|
|
142
110
|
]}
|
|
143
111
|
/>
|
|
144
112
|
);
|
|
@@ -149,48 +117,76 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
149
117
|
preventBack,
|
|
150
118
|
onPressLeftHeader,
|
|
151
119
|
useBorder,
|
|
152
|
-
backgroundColor,
|
|
153
|
-
accessibilityLabel = '',
|
|
154
120
|
}) => {
|
|
121
|
+
const context = useContext<any>(MiniAppContext);
|
|
155
122
|
const {navigator} = useContext(ApplicationContext);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
const backHandler = BackHandler.addEventListener(
|
|
126
|
+
'hardwareBackPress',
|
|
127
|
+
goBackSafe
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return () => backHandler.remove();
|
|
131
|
+
}, []);
|
|
132
|
+
|
|
133
|
+
const goBackSafe = () => {
|
|
134
|
+
const goBack = () => {
|
|
135
|
+
const canGoBack = navigator?.ref?.current?.canGoBack?.();
|
|
136
|
+
const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
|
|
137
|
+
const params = {
|
|
138
|
+
appId: context.appId,
|
|
139
|
+
code: context.code,
|
|
140
|
+
screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
|
|
141
|
+
trigger_id: '111154000000000000',
|
|
142
|
+
icon_name: 'back',
|
|
143
|
+
};
|
|
144
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
145
|
+
appId: `auto - ${context.appId}`,
|
|
146
|
+
message: 'service_icon_clicked',
|
|
147
|
+
params,
|
|
148
|
+
});
|
|
149
|
+
navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
|
|
150
|
+
if (canGoBack) {
|
|
151
|
+
navigator?.ref?.current?.goBack?.();
|
|
152
|
+
} else if (navigator?.maxApi) {
|
|
153
|
+
navigator?.maxApi?.dismiss?.(navigator?.dismissData);
|
|
174
154
|
} else {
|
|
175
|
-
|
|
155
|
+
const currentTime = new Date().getTime();
|
|
156
|
+
const requestId = `navigationBackPress#${currentTime}`;
|
|
157
|
+
DeviceEventEmitter.emit('dismiss', {requestId});
|
|
176
158
|
}
|
|
159
|
+
onPressLeftHeader?.();
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
if (preventBack) {
|
|
163
|
+
navigator?.showModal({
|
|
164
|
+
screen: () => (
|
|
165
|
+
<PopupNotify
|
|
166
|
+
{...preventBack}
|
|
167
|
+
primary={{
|
|
168
|
+
title: preventBack.primary.title,
|
|
169
|
+
onPress: () => {
|
|
170
|
+
preventBack?.primary.onPress();
|
|
171
|
+
goBack();
|
|
172
|
+
},
|
|
173
|
+
}}
|
|
174
|
+
/>
|
|
175
|
+
),
|
|
176
|
+
});
|
|
177
177
|
} else {
|
|
178
|
-
|
|
179
|
-
const requestId = `navigationBackPress#${currentTime}`;
|
|
180
|
-
DeviceEventEmitter.emit('dismiss', {requestId});
|
|
178
|
+
goBack();
|
|
181
179
|
}
|
|
182
|
-
|
|
180
|
+
return true;
|
|
183
181
|
};
|
|
184
|
-
|
|
185
182
|
return (
|
|
186
183
|
<View style={styles.headerLeft}>
|
|
187
184
|
<NavigationButton
|
|
185
|
+
accessibilityLabel="btn_navigation_back"
|
|
188
186
|
icon="ic_back"
|
|
189
187
|
tintColor={tintColor}
|
|
190
|
-
onPress={
|
|
191
|
-
accessibilityLabel={`${accessibilityLabel}Back`}
|
|
188
|
+
onPress={goBackSafe}
|
|
192
189
|
useBorder={useBorder}
|
|
193
|
-
backgroundColor={backgroundColor}
|
|
194
190
|
/>
|
|
195
191
|
</View>
|
|
196
192
|
);
|
|
@@ -198,17 +194,20 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
198
194
|
|
|
199
195
|
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
200
196
|
image,
|
|
201
|
-
backgroundColor,
|
|
202
197
|
animatedValue,
|
|
203
|
-
|
|
198
|
+
useSurface = false,
|
|
204
199
|
}) => {
|
|
205
200
|
const {theme} = useContext(ApplicationContext);
|
|
206
201
|
let headerImage = theme.assets?.headerBackground;
|
|
202
|
+
let backgroundColor;
|
|
207
203
|
if (image === null) {
|
|
208
204
|
headerImage = undefined;
|
|
209
205
|
}
|
|
206
|
+
if (useSurface) {
|
|
207
|
+
backgroundColor = theme.colors.background.surface;
|
|
208
|
+
}
|
|
210
209
|
const opacity = animatedValue?.interpolate({
|
|
211
|
-
inputRange: [0,
|
|
210
|
+
inputRange: [0, 114],
|
|
212
211
|
outputRange: [0, 1],
|
|
213
212
|
extrapolate: 'clamp',
|
|
214
213
|
});
|
|
@@ -218,15 +217,17 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
218
217
|
style={[
|
|
219
218
|
Styles.flex,
|
|
220
219
|
{
|
|
221
|
-
backgroundColor
|
|
220
|
+
backgroundColor,
|
|
222
221
|
overflow: 'hidden',
|
|
223
|
-
borderBottomWidth:
|
|
222
|
+
borderBottomWidth: useSurface ? 1 : 0,
|
|
224
223
|
borderColor: theme.colors.border.default,
|
|
225
224
|
opacity,
|
|
226
225
|
},
|
|
227
226
|
]}>
|
|
228
227
|
<StatusBar
|
|
229
228
|
barStyle={headerImage || theme.dark ? 'light-content' : 'dark-content'}
|
|
229
|
+
translucent={true}
|
|
230
|
+
backgroundColor={'transparent'}
|
|
230
231
|
/>
|
|
231
232
|
{!!headerImage && (
|
|
232
233
|
<Image
|
|
@@ -248,7 +249,7 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
248
249
|
tintColor,
|
|
249
250
|
dotColor,
|
|
250
251
|
}) => {
|
|
251
|
-
const avatarStyle = imageShape
|
|
252
|
+
const avatarStyle = imageShape === 'circle' ? styles.circle : styles.square;
|
|
252
253
|
const header = (
|
|
253
254
|
<View style={Styles.row}>
|
|
254
255
|
<View>
|
|
@@ -258,10 +259,13 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
258
259
|
)}
|
|
259
260
|
</View>
|
|
260
261
|
<View style={[Styles.flex, {paddingHorizontal: 8}]}>
|
|
261
|
-
<Text
|
|
262
|
+
<Text
|
|
263
|
+
accessibilityLabel={'title_navigation_header'}
|
|
264
|
+
typography="header_default_bold"
|
|
265
|
+
color={tintColor}>
|
|
262
266
|
{title}
|
|
263
267
|
</Text>
|
|
264
|
-
<Text typography="
|
|
268
|
+
<Text typography="description_default_regular" color={tintColor}>
|
|
265
269
|
{subTitle}
|
|
266
270
|
</Text>
|
|
267
271
|
</View>
|
|
@@ -272,11 +276,10 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
272
276
|
|
|
273
277
|
const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
274
278
|
const validateType = (child: React.ReactElement) => {
|
|
275
|
-
const valid = child?.type === NavigationButton || child?.type
|
|
279
|
+
const valid = child?.type === NavigationButton || child?.type === Fragment;
|
|
276
280
|
if (__DEV__ && !valid) {
|
|
277
|
-
|
|
278
|
-
'
|
|
279
|
-
'HeaderRightAction contains element type of NavigationButton, Please check again.',
|
|
281
|
+
console.warn(
|
|
282
|
+
'HeaderRightAction contains element type of NavigationButton, Please check again.'
|
|
280
283
|
);
|
|
281
284
|
}
|
|
282
285
|
return child;
|
|
@@ -286,7 +289,11 @@ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
|
286
289
|
if (Array.isArray(children)) {
|
|
287
290
|
return children.map((child, index) => {
|
|
288
291
|
return (
|
|
289
|
-
<View
|
|
292
|
+
<View
|
|
293
|
+
key={`HeaderRightAction ${index}`}
|
|
294
|
+
style={{
|
|
295
|
+
marginLeft: index !== 0 ? Spacing.S : 0,
|
|
296
|
+
}}>
|
|
290
297
|
{React.cloneElement(validateType(child), {...restProps})}
|
|
291
298
|
</View>
|
|
292
299
|
);
|
|
@@ -294,120 +301,169 @@ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
|
|
|
294
301
|
}
|
|
295
302
|
|
|
296
303
|
return (
|
|
297
|
-
<View
|
|
298
|
-
{React.cloneElement(validateType(children), {...restProps})}
|
|
299
|
-
</View>
|
|
304
|
+
<View>{React.cloneElement(validateType(children), {...restProps})}</View>
|
|
300
305
|
);
|
|
301
306
|
};
|
|
302
307
|
return <View style={styles.headerRightButton}>{renderAction()}</View>;
|
|
303
308
|
};
|
|
304
309
|
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
const HeaderRight: FC<any> = ({type, ...props}) => {
|
|
311
|
+
let buttons = props?.buttons || [];
|
|
312
|
+
if (!type) {
|
|
313
|
+
return <View />;
|
|
314
|
+
}
|
|
309
315
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
316
|
+
if (type === 'iconButton') {
|
|
317
|
+
if (buttons?.length > 3) {
|
|
318
|
+
buttons = buttons.slice(0, 3);
|
|
319
|
+
}
|
|
320
|
+
return (
|
|
321
|
+
<HeaderRightAction>
|
|
322
|
+
{buttons?.map?.(({icon, onPress}: IconButton) => {
|
|
323
|
+
return (
|
|
324
|
+
<NavigationButton
|
|
325
|
+
icon={icon}
|
|
326
|
+
onPress={onPress}
|
|
327
|
+
tintColor={props?.tintColor}
|
|
328
|
+
/>
|
|
329
|
+
);
|
|
330
|
+
})}
|
|
331
|
+
</HeaderRightAction>
|
|
332
|
+
);
|
|
313
333
|
}
|
|
314
334
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
335
|
+
return <HeaderToolkitAction {...props} />;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const HeaderToolkitAction: React.FC<any> = ({
|
|
339
|
+
tintColor,
|
|
340
|
+
pinnedTool,
|
|
341
|
+
runtimeTools = [],
|
|
342
|
+
preventClose,
|
|
343
|
+
}) => {
|
|
344
|
+
const {navigator} = useContext(ApplicationContext);
|
|
345
|
+
const miniContext = useContext<any>(MiniAppContext);
|
|
346
|
+
const [toolConfig, setToolConfig] = useState<any>();
|
|
347
|
+
const {onAction} = toolConfig ?? {};
|
|
348
|
+
|
|
349
|
+
let backgroundColor;
|
|
350
|
+
if (tintColor !== Colors.black_01) {
|
|
351
|
+
backgroundColor = 'transparent';
|
|
352
|
+
}
|
|
320
353
|
|
|
321
354
|
useEffect(() => {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
'observer',
|
|
329
|
-
[addSchema],
|
|
330
|
-
(data: any) => {
|
|
331
|
-
if (data?.status) {
|
|
332
|
-
setToolConfig({
|
|
333
|
-
...(toolConfig as HeaderToolkitProps),
|
|
334
|
-
hidden: true,
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
);
|
|
339
|
-
addFavorite = navigator?.requestApi(
|
|
340
|
-
'observer',
|
|
341
|
-
[removeSchema],
|
|
342
|
-
(data: any) => {
|
|
343
|
-
if (data?.status) {
|
|
344
|
-
setToolConfig({
|
|
345
|
-
...(toolConfig as HeaderToolkitProps),
|
|
346
|
-
hidden: false,
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
);
|
|
355
|
+
if (miniContext?.toolkitConfig?.hidden === false) {
|
|
356
|
+
if (navigator?.toolkitConfig) {
|
|
357
|
+
setToolConfig(navigator?.toolkitConfig);
|
|
358
|
+
} else {
|
|
359
|
+
getToolkitConfig();
|
|
360
|
+
}
|
|
351
361
|
}
|
|
362
|
+
}, []);
|
|
352
363
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
364
|
+
const getToolkitConfig = () => {
|
|
365
|
+
navigator?.maxApi?.dispatchFunction?.(
|
|
366
|
+
'getToolsConfig',
|
|
367
|
+
[undefined],
|
|
368
|
+
(config: any) => {
|
|
369
|
+
navigator.toolkitConfig = config;
|
|
370
|
+
setToolConfig(navigator?.toolkitConfig);
|
|
371
|
+
}
|
|
372
|
+
);
|
|
362
373
|
};
|
|
363
374
|
|
|
364
375
|
const onMore = () => {
|
|
365
376
|
onAction?.('onMore');
|
|
366
|
-
navigator?.
|
|
377
|
+
navigator?.maxApi?.dispatchFunction?.(
|
|
378
|
+
'showTools',
|
|
379
|
+
{runtimeTools},
|
|
380
|
+
(res: {item: {action?: string; key: string}}) => {
|
|
381
|
+
const {item} = res;
|
|
382
|
+
navigator?.toolkitCallback?.(item);
|
|
383
|
+
getToolkitConfig();
|
|
384
|
+
}
|
|
385
|
+
);
|
|
367
386
|
};
|
|
368
387
|
|
|
369
388
|
const onClose = () => {
|
|
370
|
-
|
|
371
|
-
|
|
389
|
+
if (preventClose) {
|
|
390
|
+
navigator?.showModal({
|
|
391
|
+
screen: () => (
|
|
392
|
+
<PopupNotify
|
|
393
|
+
{...preventClose}
|
|
394
|
+
primary={{
|
|
395
|
+
title: preventClose.primary.title,
|
|
396
|
+
onPress: () => {
|
|
397
|
+
preventClose?.primary.onPress();
|
|
398
|
+
navigator?.maxApi?.dispatchFunction?.(
|
|
399
|
+
'dismiss',
|
|
400
|
+
undefined,
|
|
401
|
+
undefined
|
|
402
|
+
);
|
|
403
|
+
},
|
|
404
|
+
}}
|
|
405
|
+
/>
|
|
406
|
+
),
|
|
407
|
+
});
|
|
408
|
+
} else {
|
|
409
|
+
navigator?.maxApi?.dispatchFunction?.('dismiss', undefined, undefined);
|
|
410
|
+
}
|
|
372
411
|
};
|
|
373
412
|
|
|
374
|
-
const
|
|
375
|
-
|
|
413
|
+
const renderPinnedTool = () => {
|
|
414
|
+
const pinKey = pinnedTool?.key || toolConfig?.pinnedTool?.key;
|
|
415
|
+
const pinTool = toolConfig?.tools?.find((i: any) => i.key === pinKey);
|
|
416
|
+
const {badgeValue, badgeType} = pinnedTool ?? {};
|
|
417
|
+
|
|
418
|
+
if (pinTool)
|
|
376
419
|
return (
|
|
377
420
|
<NavigationButton
|
|
378
|
-
accessibilityLabel=
|
|
379
|
-
icon={
|
|
421
|
+
accessibilityLabel="btn_navigation_pin"
|
|
422
|
+
icon={pinTool.icon as string}
|
|
380
423
|
tintColor={tintColor}
|
|
381
|
-
|
|
424
|
+
badgeValue={badgeValue}
|
|
425
|
+
badgeType={badgeType}
|
|
426
|
+
onPress={() => {
|
|
427
|
+
navigator?.maxApi?.dispatchFunction?.(
|
|
428
|
+
'onToolAction',
|
|
429
|
+
[pinTool?.key],
|
|
430
|
+
() => {
|
|
431
|
+
getToolkitConfig();
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
navigator?.toolkitCallback?.(pinTool.key);
|
|
435
|
+
}}
|
|
382
436
|
/>
|
|
383
437
|
);
|
|
384
|
-
}
|
|
385
|
-
return null;
|
|
386
438
|
};
|
|
387
|
-
|
|
388
439
|
if (toolConfig) {
|
|
389
440
|
return (
|
|
390
441
|
<View style={styles.headerRightButton}>
|
|
391
|
-
{
|
|
442
|
+
{renderPinnedTool()}
|
|
392
443
|
<View
|
|
393
444
|
style={[
|
|
394
445
|
styles.toolkitContainer,
|
|
395
446
|
{
|
|
396
447
|
backgroundColor: backgroundColor ?? '#00000066',
|
|
397
448
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
449
|
+
marginLeft: renderPinnedTool() ? Spacing.S : 0,
|
|
398
450
|
},
|
|
399
451
|
]}>
|
|
400
|
-
<
|
|
452
|
+
<TouchableOpacity
|
|
453
|
+
accessibilityLabel={'btn_navigation_more'}
|
|
454
|
+
onPress={onMore}>
|
|
401
455
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
402
|
-
</
|
|
456
|
+
</TouchableOpacity>
|
|
403
457
|
<View style={[styles.divider, {backgroundColor: tintColor}]} />
|
|
404
|
-
<
|
|
458
|
+
<TouchableOpacity
|
|
459
|
+
accessibilityLabel={'btn_navigation_close'}
|
|
460
|
+
onPress={onClose}>
|
|
405
461
|
<Icon
|
|
406
462
|
color={tintColor}
|
|
407
463
|
source="16_navigation_close_circle"
|
|
408
464
|
size={20}
|
|
409
465
|
/>
|
|
410
|
-
</
|
|
466
|
+
</TouchableOpacity>
|
|
411
467
|
</View>
|
|
412
468
|
</View>
|
|
413
469
|
);
|
|
@@ -416,6 +472,118 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
416
472
|
return <View />;
|
|
417
473
|
};
|
|
418
474
|
|
|
475
|
+
const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
|
|
476
|
+
animatedValue,
|
|
477
|
+
image,
|
|
478
|
+
children,
|
|
479
|
+
}) => {
|
|
480
|
+
const scale = animatedValue.interpolate({
|
|
481
|
+
inputRange: [-300, 0, 300],
|
|
482
|
+
outputRange: [4, 1, 1],
|
|
483
|
+
extrapolate: 'clamp',
|
|
484
|
+
});
|
|
485
|
+
const opacity = animatedValue.interpolate({
|
|
486
|
+
inputRange: [0, 150, 300],
|
|
487
|
+
outputRange: [1, 0.5, 0],
|
|
488
|
+
extrapolate: 'clamp',
|
|
489
|
+
});
|
|
490
|
+
const translateY = animatedValue.interpolate({
|
|
491
|
+
inputRange: [-300, 0],
|
|
492
|
+
outputRange: [-80, -2],
|
|
493
|
+
extrapolate: 'clamp',
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
return (
|
|
497
|
+
<Animated.View
|
|
498
|
+
style={{
|
|
499
|
+
height: 210,
|
|
500
|
+
opacity: opacity,
|
|
501
|
+
transform: [{scale}, {translateY}],
|
|
502
|
+
}}>
|
|
503
|
+
{children ?? (
|
|
504
|
+
<Image
|
|
505
|
+
source={{
|
|
506
|
+
uri: image,
|
|
507
|
+
}}
|
|
508
|
+
style={{width: '100%', height: '100%'}}
|
|
509
|
+
/>
|
|
510
|
+
)}
|
|
511
|
+
</Animated.View>
|
|
512
|
+
);
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const styles = StyleSheet.create({
|
|
516
|
+
navigationButton: {
|
|
517
|
+
height: 28,
|
|
518
|
+
width: 28,
|
|
519
|
+
borderRadius: 14,
|
|
520
|
+
justifyContent: 'center',
|
|
521
|
+
alignItems: 'center',
|
|
522
|
+
},
|
|
523
|
+
headerBackground: {
|
|
524
|
+
width: '100%',
|
|
525
|
+
height: undefined,
|
|
526
|
+
position: 'absolute',
|
|
527
|
+
aspectRatio: 375 / 154,
|
|
528
|
+
},
|
|
529
|
+
headerTitleContainer: {
|
|
530
|
+
alignItems: 'center',
|
|
531
|
+
justifyContent: 'center',
|
|
532
|
+
width: '100%',
|
|
533
|
+
},
|
|
534
|
+
circle: {width: 36, height: 36, borderRadius: 18},
|
|
535
|
+
square: {width: 36, height: 36, borderRadius: Radius.XS},
|
|
536
|
+
dotAvatar: {
|
|
537
|
+
position: 'absolute',
|
|
538
|
+
width: 12,
|
|
539
|
+
height: 12,
|
|
540
|
+
borderRadius: 6,
|
|
541
|
+
bottom: 0,
|
|
542
|
+
right: 0,
|
|
543
|
+
borderWidth: 1,
|
|
544
|
+
borderColor: Colors.black_01,
|
|
545
|
+
},
|
|
546
|
+
headerButton: {paddingHorizontal: 4},
|
|
547
|
+
headerRightButton: {
|
|
548
|
+
flexDirection: 'row',
|
|
549
|
+
justifyContent: 'center',
|
|
550
|
+
alignItems: 'center',
|
|
551
|
+
paddingRight: Spacing.M,
|
|
552
|
+
},
|
|
553
|
+
toolkitContainer: {
|
|
554
|
+
padding: Spacing.XS,
|
|
555
|
+
height: 28,
|
|
556
|
+
borderRadius: 14,
|
|
557
|
+
borderColor: '#00000066',
|
|
558
|
+
justifyContent: 'center',
|
|
559
|
+
alignItems: 'center',
|
|
560
|
+
flexDirection: 'row',
|
|
561
|
+
},
|
|
562
|
+
divider: {
|
|
563
|
+
width: 1,
|
|
564
|
+
height: 12,
|
|
565
|
+
marginHorizontal: 4,
|
|
566
|
+
},
|
|
567
|
+
headerLeft: {
|
|
568
|
+
marginLeft: 12,
|
|
569
|
+
},
|
|
570
|
+
title: {
|
|
571
|
+
fontSize: scaleSize(15),
|
|
572
|
+
lineHeight: scaleSize(22),
|
|
573
|
+
fontWeight: 'bold',
|
|
574
|
+
},
|
|
575
|
+
badge: {
|
|
576
|
+
position: 'absolute',
|
|
577
|
+
top: -Spacing.S,
|
|
578
|
+
right: -6,
|
|
579
|
+
},
|
|
580
|
+
badgeDot: {
|
|
581
|
+
position: 'absolute',
|
|
582
|
+
top: -Spacing.XS,
|
|
583
|
+
right: -Spacing.XS,
|
|
584
|
+
},
|
|
585
|
+
});
|
|
586
|
+
|
|
419
587
|
export {
|
|
420
588
|
NavigationButton,
|
|
421
589
|
HeaderTitle,
|
|
@@ -424,4 +592,6 @@ export {
|
|
|
424
592
|
HeaderRightAction,
|
|
425
593
|
HeaderToolkitAction,
|
|
426
594
|
HeaderCustom,
|
|
595
|
+
HeaderAnimated,
|
|
596
|
+
HeaderRight,
|
|
427
597
|
};
|