@momo-kits/foundation 0.89.6 → 0.92.1-tracking.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/BottomTab.tsx +6 -1
- package/Application/Components.tsx +17 -6
- package/Application/ModalScreen.tsx +131 -107
- package/Application/NavigationContainer.tsx +51 -47
- package/Application/StackScreen.tsx +65 -7
- package/Application/types.ts +5 -3
- package/Application/utils.tsx +59 -2
- package/Button/index.tsx +49 -16
- package/CheckBox/index.tsx +44 -21
- package/CheckBox/types.ts +4 -0
- package/IconButton/index.tsx +30 -7
- package/Image/index.tsx +3 -0
- package/Input/Input.tsx +40 -5
- package/Input/InputDropDown.tsx +30 -5
- package/Input/InputMoney.tsx +41 -5
- package/Input/InputOTP.tsx +31 -8
- package/Input/InputSearch.tsx +60 -26
- package/Input/InputTextArea.tsx +12 -2
- package/Input/index.tsx +27 -2
- package/Popup/PopupNotify.tsx +12 -0
- package/Popup/PopupPromotion.tsx +8 -2
- package/Radio/index.tsx +43 -20
- package/Radio/types.ts +5 -0
- package/Switch/index.tsx +36 -14
- package/Switch/types.ts +4 -0
- package/Text/index.tsx +1 -0
- package/Text/styles.ts +2 -2
- package/index.ts +2 -1
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@ import {NavigationContainer} from '@react-navigation/native';
|
|
|
8
8
|
import {Icon} from '../Icon';
|
|
9
9
|
import {Text} from '../Text';
|
|
10
10
|
import {ApplicationContext} from './index';
|
|
11
|
-
import {getStackOptions} from './utils';
|
|
11
|
+
import {getAccessibilityID, getStackOptions} from './utils';
|
|
12
12
|
import StackScreen from './StackScreen';
|
|
13
13
|
|
|
14
14
|
const Tab = createBottomTabNavigator();
|
|
@@ -58,8 +58,11 @@ const BottomTab: React.FC<BottomTabProps> = ({
|
|
|
58
58
|
});
|
|
59
59
|
}, []);
|
|
60
60
|
|
|
61
|
+
const accessibilityID = getAccessibilityID?.("tbr_main_bottom")
|
|
62
|
+
|
|
61
63
|
return (
|
|
62
64
|
<Tab.Navigator
|
|
65
|
+
{...accessibilityID}
|
|
63
66
|
initialRouteName={initialRouteName}
|
|
64
67
|
backBehavior={'firstRoute'}
|
|
65
68
|
tabBarOptions={{
|
|
@@ -72,8 +75,10 @@ const BottomTab: React.FC<BottomTabProps> = ({
|
|
|
72
75
|
},
|
|
73
76
|
}}>
|
|
74
77
|
{tabs.map(item => {
|
|
78
|
+
const itemAccessibilityID = getAccessibilityID?.(`btn_tabbar_${item.name}`)
|
|
75
79
|
return (
|
|
76
80
|
<Tab.Screen
|
|
81
|
+
{...itemAccessibilityID}
|
|
77
82
|
key={item.name}
|
|
78
83
|
name={item.name}
|
|
79
84
|
component={TabScreen}
|
|
@@ -29,6 +29,7 @@ import {scaleSize, Text} from '../Text';
|
|
|
29
29
|
import {Icon} from '../Icon';
|
|
30
30
|
import {PopupNotify} from '../Popup';
|
|
31
31
|
import {Badge, BadgeDot} from '../Badge';
|
|
32
|
+
import {getAccessibilityID} from './utils';
|
|
32
33
|
|
|
33
34
|
const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
34
35
|
icon,
|
|
@@ -37,6 +38,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
37
38
|
useBorder = true,
|
|
38
39
|
badgeType,
|
|
39
40
|
badgeValue,
|
|
41
|
+
accessibilityID = '',
|
|
40
42
|
}) => {
|
|
41
43
|
const {theme} = useContext(ApplicationContext);
|
|
42
44
|
let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
|
|
@@ -63,8 +65,9 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
63
65
|
}
|
|
64
66
|
}, [badgeType, badgeValue]);
|
|
65
67
|
|
|
68
|
+
const ID = getAccessibilityID?.(accessibilityID);
|
|
66
69
|
return (
|
|
67
|
-
<View style={{width: scaleSize(28)}}>
|
|
70
|
+
<View {...ID} style={{width: scaleSize(28)}}>
|
|
68
71
|
<TouchableOpacity
|
|
69
72
|
style={[styles.navigationButton, buttonStyle]}
|
|
70
73
|
onPress={onPress}>
|
|
@@ -90,6 +93,7 @@ const HeaderTitle: React.FC<any> = props => {
|
|
|
90
93
|
return (
|
|
91
94
|
<Animated.Text
|
|
92
95
|
{...props}
|
|
96
|
+
accessibilityLabel={getAccessibilityID('title_navigation_header')}
|
|
93
97
|
style={[
|
|
94
98
|
styles.title,
|
|
95
99
|
{fontFamily: `${theme.font}-Bold`, opacity, color: props.tintColor},
|
|
@@ -166,10 +170,10 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
166
170
|
}
|
|
167
171
|
return true;
|
|
168
172
|
};
|
|
169
|
-
|
|
170
173
|
return (
|
|
171
174
|
<View style={styles.headerLeft}>
|
|
172
175
|
<NavigationButton
|
|
176
|
+
accessibilityID="btn_navigation_back"
|
|
173
177
|
icon="ic_back"
|
|
174
178
|
tintColor={tintColor}
|
|
175
179
|
onPress={goBackSafe}
|
|
@@ -243,7 +247,10 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
|
|
|
243
247
|
)}
|
|
244
248
|
</View>
|
|
245
249
|
<View style={[Styles.flex, {paddingHorizontal: 8}]}>
|
|
246
|
-
<Text
|
|
250
|
+
<Text
|
|
251
|
+
{...getAccessibilityID('title_navigation_header')}
|
|
252
|
+
typography="header_default_bold"
|
|
253
|
+
color={tintColor}>
|
|
247
254
|
{title}
|
|
248
255
|
</Text>
|
|
249
256
|
<Text typography="description_default_regular" color={tintColor}>
|
|
@@ -369,6 +376,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
369
376
|
if (pinTool)
|
|
370
377
|
return (
|
|
371
378
|
<NavigationButton
|
|
379
|
+
accessibilityID="btn_navigation_pin"
|
|
372
380
|
icon={pinTool.icon as string}
|
|
373
381
|
tintColor={tintColor}
|
|
374
382
|
badgeValue={badgeValue}
|
|
@@ -386,7 +394,6 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
386
394
|
/>
|
|
387
395
|
);
|
|
388
396
|
};
|
|
389
|
-
|
|
390
397
|
if (toolConfig) {
|
|
391
398
|
return (
|
|
392
399
|
<View style={styles.headerRightButton}>
|
|
@@ -399,11 +406,15 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
399
406
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
400
407
|
},
|
|
401
408
|
]}>
|
|
402
|
-
<TouchableOpacity
|
|
409
|
+
<TouchableOpacity
|
|
410
|
+
{...getAccessibilityID?.('btn_navigation_more')}
|
|
411
|
+
onPress={onMore}>
|
|
403
412
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
404
413
|
</TouchableOpacity>
|
|
405
414
|
<View style={[styles.divider, {backgroundColor: tintColor}]} />
|
|
406
|
-
<TouchableOpacity
|
|
415
|
+
<TouchableOpacity
|
|
416
|
+
{...getAccessibilityID?.('btn_navigation_close')}
|
|
417
|
+
onPress={onClose}>
|
|
407
418
|
<Icon
|
|
408
419
|
color={tintColor}
|
|
409
420
|
source="16_navigation_close_circle"
|
|
@@ -1,21 +1,29 @@
|
|
|
1
|
-
import React, {useContext, useEffect, useRef} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Dimensions,
|
|
4
|
+
Keyboard,
|
|
3
5
|
KeyboardAvoidingView,
|
|
4
6
|
Platform,
|
|
5
7
|
Pressable,
|
|
6
8
|
StyleSheet,
|
|
7
|
-
TouchableOpacity,
|
|
8
9
|
View,
|
|
9
10
|
} from 'react-native';
|
|
10
|
-
import {Modalize} from 'react-native-modalize';
|
|
11
11
|
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
import {
|
|
13
|
+
BottomSheetBackdrop,
|
|
14
|
+
BottomSheetModal,
|
|
15
|
+
BottomSheetView,
|
|
16
|
+
} from '@gorhom/bottom-sheet';
|
|
17
17
|
import Navigation from './Navigation';
|
|
18
18
|
import {BottomSheetParams, ModalParams} from './types';
|
|
19
|
+
import {Radius, Spacing, Styles} from '../Consts';
|
|
20
|
+
import {
|
|
21
|
+
ApplicationContext,
|
|
22
|
+
HeaderRightAction,
|
|
23
|
+
NavigationButton,
|
|
24
|
+
NavigationContainer,
|
|
25
|
+
} from './index';
|
|
26
|
+
import {HeaderBackground, HeaderLeft, HeaderTitle} from './Components';
|
|
19
27
|
|
|
20
28
|
const ModalScreen: React.FC<any> = props => {
|
|
21
29
|
/**
|
|
@@ -84,88 +92,141 @@ const Modal: React.FC<ModalParams> = props => {
|
|
|
84
92
|
};
|
|
85
93
|
|
|
86
94
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
95
|
+
const insets = useSafeAreaInsets();
|
|
87
96
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
flatListProps,
|
|
93
|
-
}: BottomSheetParams = props.route.params;
|
|
94
|
-
|
|
97
|
+
const [keyboardSnap, setKeyboardSnap] = useState(0);
|
|
98
|
+
const {screen, options, snapPoint, indicatorColor}: BottomSheetParams =
|
|
99
|
+
props.route.params;
|
|
100
|
+
const Component = useRef(screen).current;
|
|
95
101
|
const navigation = new Navigation(props.navigation, theme);
|
|
96
|
-
|
|
97
102
|
const params = {
|
|
98
103
|
...props.route.params,
|
|
99
104
|
navigation,
|
|
100
105
|
};
|
|
101
106
|
|
|
102
107
|
delete params.screen;
|
|
103
|
-
|
|
108
|
+
|
|
109
|
+
const snapPoints = useMemo(() => {
|
|
110
|
+
if (snapPoint) {
|
|
111
|
+
const current = parseInt(snapPoint) + keyboardSnap * 100;
|
|
112
|
+
return [`${current}%`];
|
|
113
|
+
}
|
|
114
|
+
return ['50%', '70%', '90%'];
|
|
115
|
+
}, [keyboardSnap]);
|
|
116
|
+
|
|
117
|
+
const bottomSheetRef = useRef<any>(null);
|
|
118
|
+
const mountedRef = useRef(true);
|
|
119
|
+
|
|
120
|
+
let backgroundColor = theme.colors.background.default;
|
|
121
|
+
let bottomInset = keyboardSnap * Dimensions.get('window').height;
|
|
122
|
+
if (bottomInset > 16) {
|
|
123
|
+
bottomInset -= 16;
|
|
124
|
+
}
|
|
125
|
+
if (options?.surface) {
|
|
126
|
+
backgroundColor = theme.colors.background.surface;
|
|
127
|
+
}
|
|
104
128
|
|
|
105
129
|
useEffect(() => {
|
|
106
|
-
|
|
130
|
+
const keyboardDidShow = Keyboard.addListener('keyboardDidShow', e => {
|
|
131
|
+
setKeyboardSnap(
|
|
132
|
+
e.endCoordinates.height / Dimensions.get('window').height,
|
|
133
|
+
);
|
|
134
|
+
bottomSheetRef.current?.expand();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const keyboardDidHide = Keyboard.addListener('keyboardDidHide', () => {
|
|
138
|
+
setKeyboardSnap(0);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
bottomSheetRef.current?.present();
|
|
142
|
+
return () => {
|
|
143
|
+
mountedRef.current = false;
|
|
144
|
+
keyboardDidShow.remove();
|
|
145
|
+
keyboardDidHide.remove();
|
|
146
|
+
};
|
|
107
147
|
}, []);
|
|
108
148
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
149
|
+
const backdropComponent = (backdropProps: any) => (
|
|
150
|
+
<BottomSheetBackdrop
|
|
151
|
+
disappearsOnIndex={-1}
|
|
152
|
+
appearsOnIndex={0}
|
|
153
|
+
{...backdropProps}
|
|
154
|
+
/>
|
|
155
|
+
);
|
|
112
156
|
|
|
113
157
|
return (
|
|
114
158
|
<SafeAreaView style={Styles.flex}>
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
159
|
+
<BottomSheetModal
|
|
160
|
+
ref={bottomSheetRef}
|
|
161
|
+
snapPoints={snapPoints}
|
|
162
|
+
onDismiss={() => {
|
|
163
|
+
if (mountedRef.current) {
|
|
164
|
+
navigator?.pop();
|
|
165
|
+
}
|
|
122
166
|
}}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
167
|
+
bottomInset={Platform.OS === 'ios' ? bottomInset : 0}
|
|
168
|
+
handleComponent={null}
|
|
169
|
+
backdropComponent={backdropComponent}>
|
|
170
|
+
<BottomSheetView>
|
|
171
|
+
<View style={[styles.sheetContainer, {backgroundColor}]}>
|
|
172
|
+
<View style={styles.indicatorContainer}>
|
|
173
|
+
<View
|
|
174
|
+
style={[
|
|
175
|
+
styles.indicator,
|
|
176
|
+
{backgroundColor: theme.colors.text.disable},
|
|
177
|
+
]}
|
|
178
|
+
/>
|
|
179
|
+
</View>
|
|
180
|
+
<NavigationContainer
|
|
181
|
+
maxApi={navigator?.maxApi}
|
|
182
|
+
theme={{
|
|
183
|
+
...theme,
|
|
184
|
+
assets: {...theme.assets, headerBackground: undefined},
|
|
185
|
+
}}
|
|
186
|
+
screen={props => <Component {...props} {...params} />}
|
|
187
|
+
options={{
|
|
188
|
+
...options,
|
|
189
|
+
...{
|
|
190
|
+
headerLeft: (props: any) => {
|
|
191
|
+
if (props.canGoBack) {
|
|
192
|
+
return <HeaderLeft {...props} useBorder={false} />;
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
headerTitle: (props: any) => {
|
|
196
|
+
return <HeaderTitle {...props} />;
|
|
197
|
+
},
|
|
198
|
+
headerTintColor: theme.colors.text.default,
|
|
199
|
+
headerBackground: () => (
|
|
200
|
+
<HeaderBackground backgroundColor={backgroundColor} />
|
|
201
|
+
),
|
|
202
|
+
headerTransparent: false,
|
|
203
|
+
},
|
|
204
|
+
headerTitleAlign: 'center',
|
|
205
|
+
headerRight: props => (
|
|
206
|
+
<HeaderRightAction>
|
|
207
|
+
<NavigationButton
|
|
208
|
+
{...props}
|
|
209
|
+
icon="24_navigation_close"
|
|
210
|
+
useBorder={false}
|
|
211
|
+
onPress={() => bottomSheetRef.current?.dismiss()}
|
|
212
|
+
/>
|
|
213
|
+
</HeaderRightAction>
|
|
214
|
+
),
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
<View
|
|
218
|
+
style={{
|
|
219
|
+
height: Math.min(insets.bottom, 20),
|
|
220
|
+
backgroundColor: indicatorColor ?? backgroundColor,
|
|
221
|
+
}}
|
|
222
|
+
/>
|
|
223
|
+
</View>
|
|
224
|
+
</BottomSheetView>
|
|
225
|
+
</BottomSheetModal>
|
|
135
226
|
</SafeAreaView>
|
|
136
227
|
);
|
|
137
228
|
};
|
|
138
229
|
|
|
139
|
-
const headerDefault = (title: string, onClose: () => void) => {
|
|
140
|
-
return (
|
|
141
|
-
<View style={styles.header}>
|
|
142
|
-
<Text
|
|
143
|
-
style={styles.textOption}
|
|
144
|
-
numberOfLines={2}
|
|
145
|
-
typography="header_default_bold">
|
|
146
|
-
{title ?? ''}
|
|
147
|
-
</Text>
|
|
148
|
-
<TouchableOpacity style={styles.buttonClose} onPress={onClose}>
|
|
149
|
-
<Icon source="navigation_close" />
|
|
150
|
-
</TouchableOpacity>
|
|
151
|
-
</View>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const footerDefault = (footerComponent: React.ReactNode) => {
|
|
156
|
-
const insets = useSafeAreaInsets();
|
|
157
|
-
if (!footerComponent) return;
|
|
158
|
-
return (
|
|
159
|
-
<View
|
|
160
|
-
style={{
|
|
161
|
-
marginBottom: Math.min(insets.bottom, 21) + Spacing.S,
|
|
162
|
-
paddingHorizontal: 12,
|
|
163
|
-
}}>
|
|
164
|
-
{footerComponent}
|
|
165
|
-
</View>
|
|
166
|
-
);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
230
|
const styles = StyleSheet.create({
|
|
170
231
|
container: {flex: 1, flexDirection: 'row'},
|
|
171
232
|
modalContent: {
|
|
@@ -202,43 +263,6 @@ const styles = StyleSheet.create({
|
|
|
202
263
|
height: 4,
|
|
203
264
|
borderRadius: Radius.S,
|
|
204
265
|
},
|
|
205
|
-
bottomSheetContainer: {
|
|
206
|
-
width: '100%',
|
|
207
|
-
backgroundColor: 'white',
|
|
208
|
-
borderTopRightRadius: 16,
|
|
209
|
-
borderTopLeftRadius: 16,
|
|
210
|
-
},
|
|
211
|
-
header: {
|
|
212
|
-
height: 50,
|
|
213
|
-
width: '100%',
|
|
214
|
-
alignItems: 'center',
|
|
215
|
-
justifyContent: 'center',
|
|
216
|
-
},
|
|
217
|
-
textOption: {
|
|
218
|
-
fontSize: 16,
|
|
219
|
-
color: '#303233',
|
|
220
|
-
textAlign: 'center',
|
|
221
|
-
fontWeight: 'bold',
|
|
222
|
-
paddingHorizontal: 60,
|
|
223
|
-
},
|
|
224
|
-
imageOption: {
|
|
225
|
-
height: 1,
|
|
226
|
-
backgroundColor: '#ebebeb',
|
|
227
|
-
width: '100%',
|
|
228
|
-
position: 'absolute',
|
|
229
|
-
bottom: 1,
|
|
230
|
-
},
|
|
231
|
-
buttonClose: {
|
|
232
|
-
padding: 12,
|
|
233
|
-
position: 'absolute',
|
|
234
|
-
right: 0,
|
|
235
|
-
},
|
|
236
|
-
icon: {
|
|
237
|
-
width: 24,
|
|
238
|
-
height: 24,
|
|
239
|
-
tintColor: '#303233',
|
|
240
|
-
backgroundColor: 'red',
|
|
241
|
-
},
|
|
242
266
|
});
|
|
243
267
|
|
|
244
268
|
export default ModalScreen;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useRef, useState} from 'react';
|
|
2
|
+
import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
|
|
2
3
|
import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
3
4
|
import {
|
|
4
5
|
NavigationContainer as ReactNavigationContainer,
|
|
@@ -22,6 +23,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
22
23
|
options,
|
|
23
24
|
maxApi,
|
|
24
25
|
localization,
|
|
26
|
+
initialParams,
|
|
25
27
|
}) => {
|
|
26
28
|
const context = useContext(MiniAppContext);
|
|
27
29
|
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
@@ -67,53 +69,55 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
67
69
|
|
|
68
70
|
return (
|
|
69
71
|
<SafeAreaProvider>
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<Stack.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
72
|
+
<BottomSheetModalProvider>
|
|
73
|
+
<ApplicationContext.Provider
|
|
74
|
+
value={{
|
|
75
|
+
navigator: navigator.current,
|
|
76
|
+
config: config.current,
|
|
77
|
+
theme,
|
|
78
|
+
showGrid,
|
|
79
|
+
translate,
|
|
80
|
+
}}>
|
|
81
|
+
<ReactNavigationContainer
|
|
82
|
+
theme={{
|
|
83
|
+
...theme,
|
|
84
|
+
colors: {
|
|
85
|
+
...theme.colors,
|
|
86
|
+
background: theme.colors.background.default,
|
|
87
|
+
card: theme.colors.background.surface,
|
|
88
|
+
text: theme.colors.text.default,
|
|
89
|
+
border: theme.colors.border.default,
|
|
90
|
+
notification: theme.colors.error.primary,
|
|
91
|
+
},
|
|
92
|
+
}}
|
|
93
|
+
ref={navigator.current?.ref}
|
|
94
|
+
onReady={() => {
|
|
95
|
+
isReady.current = true;
|
|
96
|
+
}}
|
|
97
|
+
independent={true}>
|
|
98
|
+
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
99
|
+
<Stack.Screen
|
|
100
|
+
name="Stack"
|
|
101
|
+
component={StackScreen}
|
|
102
|
+
initialParams={{screen, initialParams}}
|
|
103
|
+
options={{...getStackOptions(), ...options}}
|
|
104
|
+
/>
|
|
105
|
+
<Stack.Screen
|
|
106
|
+
name="Dialog"
|
|
107
|
+
component={StackScreen}
|
|
108
|
+
options={getDialogOptions()}
|
|
109
|
+
initialParams={{screen}}
|
|
110
|
+
/>
|
|
111
|
+
<Stack.Screen
|
|
112
|
+
name="Modal"
|
|
113
|
+
component={ModalScreen}
|
|
114
|
+
options={getModalOptions()}
|
|
115
|
+
initialParams={{screen}}
|
|
116
|
+
/>
|
|
117
|
+
</Stack.Navigator>
|
|
118
|
+
</ReactNavigationContainer>
|
|
119
|
+
</ApplicationContext.Provider>
|
|
120
|
+
</BottomSheetModalProvider>
|
|
117
121
|
</SafeAreaProvider>
|
|
118
122
|
);
|
|
119
123
|
};
|
|
@@ -1,29 +1,53 @@
|
|
|
1
|
-
import React, {useContext, useEffect, useLayoutEffect} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
|
|
2
2
|
import {ScreenParams} from './types';
|
|
3
3
|
import Navigation from './Navigation';
|
|
4
4
|
import {ApplicationContext, MiniAppContext} from './index';
|
|
5
5
|
import {GridSystem} from '../Layout';
|
|
6
6
|
import {useHeaderHeight} from '@react-navigation/stack';
|
|
7
|
+
import {Alert, InteractionManager} from 'react-native';
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
ScreenContext,
|
|
11
|
+
} = require('react-native/Libraries/Components/ScreenContext');
|
|
7
12
|
|
|
8
13
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
9
14
|
const {theme, showGrid, navigator} = useContext(ApplicationContext);
|
|
15
|
+
const startTime = useRef(Date.now());
|
|
16
|
+
const endTime = useRef(Date.now());
|
|
17
|
+
const timeLoad = useRef(0);
|
|
18
|
+
const timeout = useRef<any>();
|
|
19
|
+
|
|
10
20
|
const context = useContext(MiniAppContext);
|
|
11
21
|
|
|
12
|
-
const {
|
|
22
|
+
const {
|
|
23
|
+
screen: Component,
|
|
24
|
+
options,
|
|
25
|
+
initialParams,
|
|
26
|
+
}: ScreenParams = props.route.params;
|
|
13
27
|
const navigation = new Navigation(props.navigation, theme);
|
|
14
28
|
const heightHeader = useHeaderHeight();
|
|
15
29
|
|
|
16
|
-
const
|
|
30
|
+
const data = {
|
|
17
31
|
...props.route.params,
|
|
32
|
+
...initialParams,
|
|
18
33
|
navigation,
|
|
19
34
|
};
|
|
20
35
|
|
|
21
|
-
delete
|
|
36
|
+
delete data.screen;
|
|
37
|
+
delete data.initialParams;
|
|
22
38
|
|
|
23
39
|
/**
|
|
24
40
|
* set options for screen
|
|
25
41
|
*/
|
|
26
42
|
useLayoutEffect(() => {
|
|
43
|
+
InteractionManager.runAfterInteractions(() => {
|
|
44
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
45
|
+
appId: context.appId,
|
|
46
|
+
message: `${Component.name} screen_interaction_time ${
|
|
47
|
+
Date.now() - startTime.current
|
|
48
|
+
}`,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
27
51
|
if (options) {
|
|
28
52
|
navigation.setOptions(options);
|
|
29
53
|
}
|
|
@@ -33,6 +57,15 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
33
57
|
* tracking for screen
|
|
34
58
|
*/
|
|
35
59
|
useEffect(() => {
|
|
60
|
+
if (__DEV__) {
|
|
61
|
+
if (!Component.name || Component.name === 'screen') {
|
|
62
|
+
Alert.alert(
|
|
63
|
+
'Design system',
|
|
64
|
+
`Unvalidated screen name "${Component.name}" !`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
36
69
|
const tracking = {
|
|
37
70
|
...context,
|
|
38
71
|
screen_name: Component.name,
|
|
@@ -73,10 +106,35 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
73
106
|
}, []);
|
|
74
107
|
|
|
75
108
|
return (
|
|
76
|
-
|
|
77
|
-
|
|
109
|
+
<ScreenContext.Provider
|
|
110
|
+
value={{
|
|
111
|
+
appId: context.appId,
|
|
112
|
+
code: context.code,
|
|
113
|
+
screenName: Component.name,
|
|
114
|
+
autoTracking: (data: any) => {
|
|
115
|
+
navigator?.maxApi?.dispatchFunction?.('autoTracking', data);
|
|
116
|
+
},
|
|
117
|
+
onElementLoad: () => {
|
|
118
|
+
endTime.current = Date.now();
|
|
119
|
+
clearTimeout(timeout.current);
|
|
120
|
+
timeout.current = setTimeout(() => {
|
|
121
|
+
if (timeLoad.current === 0) {
|
|
122
|
+
timeLoad.current = endTime.current - startTime.current;
|
|
123
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
124
|
+
appId: context.appId,
|
|
125
|
+
message: `${Component.name} screen_load_time ${timeLoad.current}`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}, 1000);
|
|
129
|
+
},
|
|
130
|
+
}}>
|
|
131
|
+
<Component
|
|
132
|
+
heightHeader={heightHeader}
|
|
133
|
+
{...data}
|
|
134
|
+
onScreenLoad={() => {}}
|
|
135
|
+
/>
|
|
78
136
|
{showGrid && <GridSystem />}
|
|
79
|
-
|
|
137
|
+
</ScreenContext.Provider>
|
|
80
138
|
);
|
|
81
139
|
};
|
|
82
140
|
|
package/Application/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Animated,
|
|
1
|
+
import {Animated, ViewProps} from 'react-native';
|
|
2
2
|
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import Navigator from './Navigator';
|
|
@@ -94,6 +94,7 @@ export type NavigationContainerProps = {
|
|
|
94
94
|
options?: NavigationOptions;
|
|
95
95
|
theme: Theme;
|
|
96
96
|
maxApi: any;
|
|
97
|
+
initialParams: Record<string, any>;
|
|
97
98
|
localization?: LocalizationObject;
|
|
98
99
|
};
|
|
99
100
|
|
|
@@ -118,8 +119,8 @@ export interface ModalParams extends ScreenParams {
|
|
|
118
119
|
export interface BottomSheetParams extends ScreenParams {
|
|
119
120
|
[key: string]: any;
|
|
120
121
|
onDismiss?: () => void;
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
snapPoint?: '30%' | '50%' | '70%' | '90%' | 'content';
|
|
123
|
+
indicatorColor?: string;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
export type NavigationButtonProps = {
|
|
@@ -129,6 +130,7 @@ export type NavigationButtonProps = {
|
|
|
129
130
|
onPress: () => void;
|
|
130
131
|
badgeType?: 'dot' | 'number';
|
|
131
132
|
badgeValue?: number;
|
|
133
|
+
accessibilityID?: string;
|
|
132
134
|
};
|
|
133
135
|
|
|
134
136
|
export type PinnedToolType = {
|