@momo-kits/foundation 0.74.2-react-native.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/BottomTab.tsx +120 -0
- package/Application/Components.tsx +534 -0
- package/Application/ModalScreen.tsx +268 -0
- package/Application/Navigation.ts +50 -0
- package/Application/NavigationContainer.tsx +120 -0
- package/Application/Navigator.ts +131 -0
- package/Application/StackScreen.tsx +71 -0
- package/Application/index.ts +41 -0
- package/Application/types.ts +216 -0
- package/Application/utils.tsx +151 -0
- package/Assets/DotAnimation.json +256 -0
- package/Assets/SpinnerAnimation.json +1027 -0
- package/Assets/icon.json +4031 -0
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +202 -0
- 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 +310 -0
- package/Button/styles.ts +60 -0
- package/CheckBox/index.tsx +65 -0
- package/CheckBox/styles.ts +15 -0
- package/CheckBox/types.ts +38 -0
- package/Consts/colors+spacing+radius.ts +218 -0
- package/Consts/index.ts +4 -0
- package/Consts/styles.ts +52 -0
- package/Consts/theme.ts +125 -0
- package/Divider/index.tsx +21 -0
- package/Icon/index.tsx +41 -0
- package/Icon/types.ts +27 -0
- package/IconButton/index.tsx +139 -0
- package/IconButton/styles.ts +19 -0
- package/Image/index.tsx +83 -0
- package/Image/styles.ts +5 -0
- package/Image/types.ts +5 -0
- package/Input/Input.tsx +192 -0
- package/Input/InputDropDown.tsx +114 -0
- package/Input/InputMoney.tsx +163 -0
- package/Input/InputOTP.tsx +235 -0
- package/Input/InputSearch.tsx +151 -0
- package/Input/InputTextArea.tsx +159 -0
- package/Input/common.tsx +129 -0
- package/Input/index.tsx +251 -0
- package/Input/styles.ts +160 -0
- package/Input/utils.ts +69 -0
- package/Layout/Card.tsx +180 -0
- package/Layout/GridSystem.tsx +136 -0
- package/Layout/Item.tsx +56 -0
- package/Layout/ItemList.tsx +55 -0
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +355 -0
- package/Layout/Section.tsx +179 -0
- package/Layout/index.ts +29 -0
- package/Layout/styles.ts +97 -0
- package/Layout/types.ts +23 -0
- package/Layout/utils.ts +55 -0
- package/Loader/DotLoader.tsx +37 -0
- package/Loader/Loader.tsx +13 -0
- package/Loader/ProgressBar.tsx +44 -0
- package/Loader/Spinner.tsx +28 -0
- package/Loader/index.tsx +4 -0
- package/Loader/styles.ts +10 -0
- package/Loader/types.ts +35 -0
- package/Loader/utils.ts +25 -0
- package/Pagination/Dot.tsx +16 -0
- package/Pagination/PaginationDot.tsx +38 -0
- package/Pagination/PaginationNumber.tsx +24 -0
- package/Pagination/PaginationScroll.tsx +88 -0
- package/Pagination/PaginationWhiteDot.tsx +35 -0
- package/Pagination/index.tsx +25 -0
- package/Pagination/styles.ts +50 -0
- package/Pagination/types.ts +40 -0
- package/Popup/PopupNotify.tsx +266 -0
- package/Popup/PopupPromotion.tsx +120 -0
- package/Popup/index.tsx +4 -0
- package/Popup/types.ts +87 -0
- package/Radio/index.tsx +64 -0
- package/Radio/styles.ts +11 -0
- package/Radio/types.ts +38 -0
- package/Skeleton/index.tsx +72 -0
- package/Skeleton/styles.ts +5 -0
- package/Skeleton/types.ts +6 -0
- package/Switch/index.tsx +37 -0
- package/Switch/styles.ts +23 -0
- package/Switch/types.ts +26 -0
- package/Tag/index.tsx +79 -0
- package/Tag/styles.ts +24 -0
- package/Tag/types.ts +36 -0
- package/Text/index.tsx +110 -0
- package/Text/styles.ts +73 -0
- package/Text/types.ts +34 -0
- package/Text/utils.ts +14 -0
- package/Title/index.tsx +132 -0
- package/Title/styles.ts +52 -0
- package/Title/types.ts +52 -0
- package/code-scanner.js +51 -0
- package/index.ts +51 -0
- package/package.json +36 -0
- package/publish.sh +23 -0
- package/tsconfig.json +24 -0
- package/verify.js +44 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Dimensions,
|
|
4
|
+
Keyboard,
|
|
5
|
+
KeyboardAvoidingView,
|
|
6
|
+
Platform,
|
|
7
|
+
Pressable,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
View,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
12
|
+
import {
|
|
13
|
+
BottomSheetBackdrop,
|
|
14
|
+
BottomSheetModal,
|
|
15
|
+
BottomSheetView,
|
|
16
|
+
} from '@gorhom/bottom-sheet';
|
|
17
|
+
import Navigation from './Navigation';
|
|
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';
|
|
27
|
+
|
|
28
|
+
const ModalScreen: React.FC<any> = props => {
|
|
29
|
+
/**
|
|
30
|
+
* dismiss callback when modal | bottom sheet dismissed
|
|
31
|
+
*/
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
return () => {
|
|
34
|
+
props.route.params?.onDismiss?.();
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
if (props.route?.params?.isBottomSheet) {
|
|
39
|
+
return <BottomSheet {...props} />;
|
|
40
|
+
}
|
|
41
|
+
return <Modal {...props} />;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const Modal: React.FC<ModalParams> = props => {
|
|
45
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
46
|
+
const {screen, barrierDismissible} = props.route.params;
|
|
47
|
+
const Component = useRef(screen).current;
|
|
48
|
+
const navigation = new Navigation(props.navigation, theme);
|
|
49
|
+
const params = {
|
|
50
|
+
...props.route.params,
|
|
51
|
+
navigation,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
delete params.screen;
|
|
55
|
+
|
|
56
|
+
const onDismiss = () => {
|
|
57
|
+
if (barrierDismissible) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
navigator?.pop();
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<KeyboardAvoidingView
|
|
65
|
+
style={Styles.flex}
|
|
66
|
+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
|
67
|
+
<View style={styles.container}>
|
|
68
|
+
<Pressable
|
|
69
|
+
style={styles.modalSpaceHorizontal}
|
|
70
|
+
onPress={() => onDismiss()}
|
|
71
|
+
/>
|
|
72
|
+
<View style={styles.modalCenterStage}>
|
|
73
|
+
<Pressable
|
|
74
|
+
style={styles.modalSpaceVertical}
|
|
75
|
+
onPress={() => onDismiss()}
|
|
76
|
+
/>
|
|
77
|
+
<View style={styles.modalContent}>
|
|
78
|
+
<Component {...params} />
|
|
79
|
+
</View>
|
|
80
|
+
<Pressable
|
|
81
|
+
style={styles.modalSpaceVertical}
|
|
82
|
+
onPress={() => onDismiss()}
|
|
83
|
+
/>
|
|
84
|
+
</View>
|
|
85
|
+
<Pressable
|
|
86
|
+
style={styles.modalSpaceHorizontal}
|
|
87
|
+
onPress={() => onDismiss()}
|
|
88
|
+
/>
|
|
89
|
+
</View>
|
|
90
|
+
</KeyboardAvoidingView>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
95
|
+
const insets = useSafeAreaInsets();
|
|
96
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
97
|
+
const [keyboardSnap, setKeyboardSnap] = useState(0);
|
|
98
|
+
const {screen, options, snapPoint, indicatorColor}: BottomSheetParams =
|
|
99
|
+
props.route.params;
|
|
100
|
+
const Component = useRef(screen).current;
|
|
101
|
+
const navigation = new Navigation(props.navigation, theme);
|
|
102
|
+
const params = {
|
|
103
|
+
...props.route.params,
|
|
104
|
+
navigation,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
delete params.screen;
|
|
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
|
+
}
|
|
128
|
+
|
|
129
|
+
useEffect(() => {
|
|
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
|
+
};
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
const backdropComponent = (backdropProps: any) => (
|
|
150
|
+
<BottomSheetBackdrop
|
|
151
|
+
disappearsOnIndex={-1}
|
|
152
|
+
appearsOnIndex={0}
|
|
153
|
+
{...backdropProps}
|
|
154
|
+
/>
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<SafeAreaView style={Styles.flex}>
|
|
159
|
+
<BottomSheetModal
|
|
160
|
+
ref={bottomSheetRef}
|
|
161
|
+
snapPoints={snapPoints}
|
|
162
|
+
onDismiss={() => {
|
|
163
|
+
if (mountedRef.current) {
|
|
164
|
+
navigator?.pop();
|
|
165
|
+
}
|
|
166
|
+
}}
|
|
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>
|
|
226
|
+
</SafeAreaView>
|
|
227
|
+
);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const styles = StyleSheet.create({
|
|
231
|
+
container: {flex: 1, flexDirection: 'row'},
|
|
232
|
+
modalContent: {
|
|
233
|
+
maxWidth: '100%',
|
|
234
|
+
maxHeight: '80%',
|
|
235
|
+
},
|
|
236
|
+
modalCenterStage: {
|
|
237
|
+
maxWidth: '90%',
|
|
238
|
+
},
|
|
239
|
+
modalSpaceHorizontal: {
|
|
240
|
+
flex: 1,
|
|
241
|
+
minWidth: '5%',
|
|
242
|
+
},
|
|
243
|
+
modalSpaceVertical: {
|
|
244
|
+
flex: 1,
|
|
245
|
+
minHeight: '10%',
|
|
246
|
+
},
|
|
247
|
+
sheetContainer: {
|
|
248
|
+
height: '100%',
|
|
249
|
+
width: '100%',
|
|
250
|
+
borderTopLeftRadius: Radius.M,
|
|
251
|
+
borderTopRightRadius: Radius.M,
|
|
252
|
+
overflow: 'hidden',
|
|
253
|
+
},
|
|
254
|
+
indicatorContainer: {
|
|
255
|
+
width: '100%',
|
|
256
|
+
paddingTop: Spacing.S,
|
|
257
|
+
paddingBottom: Spacing.XS,
|
|
258
|
+
alignItems: 'center',
|
|
259
|
+
justifyContent: 'center',
|
|
260
|
+
},
|
|
261
|
+
indicator: {
|
|
262
|
+
width: 40,
|
|
263
|
+
height: 4,
|
|
264
|
+
borderRadius: Radius.S,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
export default ModalScreen;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {NavigationProp} from '@react-navigation/native';
|
|
3
|
+
import {NavigationOptions, Theme} from './types';
|
|
4
|
+
import {HeaderRightAction} from './index';
|
|
5
|
+
import {getOptions} from './utils';
|
|
6
|
+
import {HeaderToolkitAction} from './Components';
|
|
7
|
+
|
|
8
|
+
class Navigation {
|
|
9
|
+
private instance: NavigationProp<any>;
|
|
10
|
+
private readonly theme: Theme;
|
|
11
|
+
|
|
12
|
+
constructor(instance: any, theme: Theme) {
|
|
13
|
+
this.instance = instance;
|
|
14
|
+
this.theme = theme;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* navigation options filter by design system rule
|
|
19
|
+
* @param params
|
|
20
|
+
*/
|
|
21
|
+
private filterParams = (params: NavigationOptions) => {
|
|
22
|
+
if (params.headerRight) {
|
|
23
|
+
const headerRight = params.headerRight?.({}) as React.ReactElement;
|
|
24
|
+
const type = headerRight?.type;
|
|
25
|
+
if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
|
|
26
|
+
console.warn(
|
|
27
|
+
'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (params.headerLeft) {
|
|
33
|
+
console.warn('headerLeft not allow override render by design system!');
|
|
34
|
+
delete params.headerLeft;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return params;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* navigation setOptions support props NavigationOptions base on react-navigation options
|
|
42
|
+
* @param params
|
|
43
|
+
*/
|
|
44
|
+
setOptions = (params: NavigationOptions) => {
|
|
45
|
+
params = getOptions(this.filterParams(params), this.theme);
|
|
46
|
+
this.instance.setOptions(params);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default Navigation;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React, {useContext, useEffect, useRef, useState} from 'react';
|
|
2
|
+
import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
|
|
3
|
+
import {SafeAreaProvider} from 'react-native-safe-area-context';
|
|
4
|
+
import {
|
|
5
|
+
NavigationContainer as ReactNavigationContainer,
|
|
6
|
+
NavigationContainerRef,
|
|
7
|
+
} from '@react-navigation/native';
|
|
8
|
+
import {createStackNavigator} from '@react-navigation/stack';
|
|
9
|
+
import {DeviceEventEmitter} from 'react-native';
|
|
10
|
+
import StackScreen from './StackScreen';
|
|
11
|
+
import ModalScreen from './ModalScreen';
|
|
12
|
+
import Navigator from './Navigator';
|
|
13
|
+
import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
14
|
+
import {LocalizationObject, NavigationContainerProps} from './types';
|
|
15
|
+
import {ApplicationContext, MiniAppContext} from './index';
|
|
16
|
+
import kitLocalization from '../Assets/language.json';
|
|
17
|
+
|
|
18
|
+
const Stack = createStackNavigator();
|
|
19
|
+
|
|
20
|
+
const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
21
|
+
screen,
|
|
22
|
+
theme,
|
|
23
|
+
options,
|
|
24
|
+
maxApi,
|
|
25
|
+
localization,
|
|
26
|
+
}) => {
|
|
27
|
+
const context = useContext(MiniAppContext);
|
|
28
|
+
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
29
|
+
const navigator = useRef(new Navigator(navigationRef));
|
|
30
|
+
const [showGrid, setShowGrid] = useState(false);
|
|
31
|
+
const config = useRef<any>();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* handle mini language & listen change
|
|
35
|
+
* engine only shake to enable grid view
|
|
36
|
+
*/
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const subscription = DeviceEventEmitter.addListener(
|
|
39
|
+
'onChangeGrid',
|
|
40
|
+
enable => {
|
|
41
|
+
setShowGrid(!!enable);
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return () => {
|
|
46
|
+
subscription?.remove?.();
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* inject data for navigator
|
|
52
|
+
*/
|
|
53
|
+
navigator.current.maxApi = maxApi;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* translate
|
|
57
|
+
* @param key
|
|
58
|
+
*/
|
|
59
|
+
const translate = (key: string) => {
|
|
60
|
+
const language: 'vi' | 'en' = context?.language ?? 'vi';
|
|
61
|
+
const mergedLocalization: LocalizationObject = {
|
|
62
|
+
vi: {...localization?.vi, ...kitLocalization.vi},
|
|
63
|
+
en: {...localization?.en, ...kitLocalization.en},
|
|
64
|
+
};
|
|
65
|
+
return mergedLocalization?.[language]?.[key] || key;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<SafeAreaProvider>
|
|
70
|
+
<BottomSheetModalProvider>
|
|
71
|
+
<ApplicationContext.Provider
|
|
72
|
+
value={{
|
|
73
|
+
navigator: navigator.current,
|
|
74
|
+
config: config.current,
|
|
75
|
+
theme,
|
|
76
|
+
showGrid,
|
|
77
|
+
translate,
|
|
78
|
+
}}>
|
|
79
|
+
<ReactNavigationContainer
|
|
80
|
+
theme={{
|
|
81
|
+
...theme,
|
|
82
|
+
colors: {
|
|
83
|
+
...theme.colors,
|
|
84
|
+
background: theme.colors.background.default,
|
|
85
|
+
card: theme.colors.background.surface,
|
|
86
|
+
text: theme.colors.text.default,
|
|
87
|
+
border: theme.colors.border.default,
|
|
88
|
+
notification: theme.colors.error.primary,
|
|
89
|
+
},
|
|
90
|
+
}}
|
|
91
|
+
ref={navigator.current?.ref}
|
|
92
|
+
independent={true}>
|
|
93
|
+
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
94
|
+
<Stack.Screen
|
|
95
|
+
name="Stack"
|
|
96
|
+
component={StackScreen}
|
|
97
|
+
initialParams={{screen}}
|
|
98
|
+
options={{...getStackOptions(), ...options}}
|
|
99
|
+
/>
|
|
100
|
+
<Stack.Screen
|
|
101
|
+
name="Dialog"
|
|
102
|
+
component={StackScreen}
|
|
103
|
+
options={getDialogOptions()}
|
|
104
|
+
initialParams={{screen}}
|
|
105
|
+
/>
|
|
106
|
+
<Stack.Screen
|
|
107
|
+
name="Modal"
|
|
108
|
+
component={ModalScreen}
|
|
109
|
+
options={getModalOptions()}
|
|
110
|
+
initialParams={{screen}}
|
|
111
|
+
/>
|
|
112
|
+
</Stack.Navigator>
|
|
113
|
+
</ReactNavigationContainer>
|
|
114
|
+
</ApplicationContext.Provider>
|
|
115
|
+
</BottomSheetModalProvider>
|
|
116
|
+
</SafeAreaProvider>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export {ApplicationContext, NavigationContainer};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {CommonActions, StackActions} from '@react-navigation/native';
|
|
2
|
+
import {
|
|
3
|
+
BottomSheetParams,
|
|
4
|
+
HeaderToolkitProps,
|
|
5
|
+
ModalParams,
|
|
6
|
+
ScreenParams,
|
|
7
|
+
} from './types';
|
|
8
|
+
|
|
9
|
+
class Navigator {
|
|
10
|
+
ref?: any;
|
|
11
|
+
toolkitConfig?: HeaderToolkitProps;
|
|
12
|
+
maxApi?: any;
|
|
13
|
+
dismissData?: any;
|
|
14
|
+
toolkitCallback?: (item: any) => void;
|
|
15
|
+
|
|
16
|
+
constructor(navigation: any) {
|
|
17
|
+
this.ref = navigation;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* push new stack screen
|
|
22
|
+
* @param params
|
|
23
|
+
*/
|
|
24
|
+
push = (params: ScreenParams) => {
|
|
25
|
+
this.ref.current.dispatch(StackActions.push('Stack', params));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* replace current screen with new screen
|
|
30
|
+
* @param params
|
|
31
|
+
*/
|
|
32
|
+
replace = (params: ScreenParams) => {
|
|
33
|
+
this.ref.current.dispatch(StackActions.replace('Stack', params));
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* pop to dismiss a screen
|
|
37
|
+
* @param count
|
|
38
|
+
*/
|
|
39
|
+
pop = (count?: number) => {
|
|
40
|
+
this.ref.current.dispatch(StackActions.pop(count ?? 1));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* present a new screen, show from bottom iOS
|
|
45
|
+
* @param params
|
|
46
|
+
*/
|
|
47
|
+
present = (params: ScreenParams) => {
|
|
48
|
+
this.ref.current.dispatch(StackActions.push('Dialog', params));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* show a modal popup
|
|
53
|
+
* @param params
|
|
54
|
+
*/
|
|
55
|
+
showModal = (params: ModalParams) => {
|
|
56
|
+
this.ref.current.dispatch(StackActions.push('Modal', params));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* show a bottom sheet
|
|
61
|
+
* @param params
|
|
62
|
+
*/
|
|
63
|
+
showBottomSheet = (params: BottomSheetParams) => {
|
|
64
|
+
this.ref.current.dispatch(
|
|
65
|
+
StackActions.push('Modal', {
|
|
66
|
+
...params,
|
|
67
|
+
isBottomSheet: true,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* pop all screen route
|
|
74
|
+
*/
|
|
75
|
+
popToTop = () => {
|
|
76
|
+
this.ref.current.dispatch(StackActions.popToTop());
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* navigate
|
|
81
|
+
* @param name
|
|
82
|
+
* @param params
|
|
83
|
+
*/
|
|
84
|
+
navigate = (name: string, params: any) => {
|
|
85
|
+
this.ref.current.dispatch(
|
|
86
|
+
CommonActions.navigate({
|
|
87
|
+
name,
|
|
88
|
+
params,
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* reset a navigation flow with new screen
|
|
95
|
+
* @param params
|
|
96
|
+
*/
|
|
97
|
+
reset = (params: ScreenParams) => {
|
|
98
|
+
this.ref.current.dispatch(
|
|
99
|
+
CommonActions.reset({
|
|
100
|
+
index: 0,
|
|
101
|
+
routes: [
|
|
102
|
+
{
|
|
103
|
+
name: 'Stack',
|
|
104
|
+
key: `Stack_${new Date().getTime()}`,
|
|
105
|
+
params,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* dismiss a feature data
|
|
114
|
+
* @param data
|
|
115
|
+
*/
|
|
116
|
+
setDismissData = (data: any) => {
|
|
117
|
+
this.dismissData = data;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* set callback function for toolkit
|
|
122
|
+
* @param callback
|
|
123
|
+
*/
|
|
124
|
+
setToolkitCallback = (
|
|
125
|
+
callback: (item: {key: string; action: string}) => void,
|
|
126
|
+
) => {
|
|
127
|
+
this.toolkitCallback = callback;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export default Navigator;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, {useContext, useEffect, useLayoutEffect} from 'react';
|
|
2
|
+
import {ScreenParams} from './types';
|
|
3
|
+
import Navigation from './Navigation';
|
|
4
|
+
import {ApplicationContext, MiniAppContext} from './index';
|
|
5
|
+
import {GridSystem} from '../Layout';
|
|
6
|
+
import {useHeaderHeight} from '@react-navigation/elements';
|
|
7
|
+
|
|
8
|
+
const StackScreen: React.FC<ScreenParams> = props => {
|
|
9
|
+
const {theme, showGrid, navigator} = useContext(ApplicationContext);
|
|
10
|
+
const context = useContext(MiniAppContext);
|
|
11
|
+
|
|
12
|
+
const {screen: Component, options}: ScreenParams = props.route.params;
|
|
13
|
+
const navigation = new Navigation(props.navigation, theme);
|
|
14
|
+
const heightHeader = useHeaderHeight();
|
|
15
|
+
|
|
16
|
+
const params = {
|
|
17
|
+
...props.route.params,
|
|
18
|
+
navigation,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
delete params.screen;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* set options for screen
|
|
25
|
+
*/
|
|
26
|
+
useLayoutEffect(() => {
|
|
27
|
+
if (options) {
|
|
28
|
+
navigation.setOptions(options);
|
|
29
|
+
}
|
|
30
|
+
}, [options]);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* tracking for screen
|
|
34
|
+
*/
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const tracking = {
|
|
37
|
+
...context,
|
|
38
|
+
screen_name: Component.name,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const routes = props.navigation.getState()?.routes || [];
|
|
42
|
+
const routesLength = routes.length;
|
|
43
|
+
let pre_screen_name = '';
|
|
44
|
+
if (routesLength > 1) {
|
|
45
|
+
pre_screen_name = routes[routesLength - 2]?.params?.screen?.name;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
navigator?.maxApi?.trackEvent?.('service_frame_displayed', {
|
|
49
|
+
...tracking,
|
|
50
|
+
pre_screen_name,
|
|
51
|
+
trigger_id: '111378000000000000',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return props.navigation.addListener('beforeRemove', () => {
|
|
55
|
+
navigator?.maxApi?.trackEvent?.('service_icon_clicked', {
|
|
56
|
+
...tracking,
|
|
57
|
+
trigger_id: '111154000000000000',
|
|
58
|
+
icon_name: 'back',
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<>
|
|
65
|
+
<Component heightHeader={heightHeader} {...params} />
|
|
66
|
+
{showGrid && <GridSystem />}
|
|
67
|
+
</>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default StackScreen;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {NavigationContainer} from './NavigationContainer';
|
|
2
|
+
import Screen from '../Layout/Screen';
|
|
3
|
+
import {
|
|
4
|
+
HeaderAnimated,
|
|
5
|
+
HeaderBackground,
|
|
6
|
+
HeaderCustom,
|
|
7
|
+
HeaderLeft,
|
|
8
|
+
HeaderRightAction,
|
|
9
|
+
HeaderTitle,
|
|
10
|
+
HeaderToolkitAction,
|
|
11
|
+
NavigationButton,
|
|
12
|
+
} from './Components';
|
|
13
|
+
import BottomTab from './BottomTab';
|
|
14
|
+
import {createContext} from 'react';
|
|
15
|
+
import {defaultContext} from '../Consts';
|
|
16
|
+
import {MiniAppInfo} from './types';
|
|
17
|
+
|
|
18
|
+
const ApplicationContext = createContext(defaultContext);
|
|
19
|
+
const MiniAppContext = createContext<MiniAppInfo>({
|
|
20
|
+
appId: '',
|
|
21
|
+
buildNumber: 0,
|
|
22
|
+
code: '',
|
|
23
|
+
toolkitConfig: {},
|
|
24
|
+
fromCode: '',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
ApplicationContext,
|
|
29
|
+
MiniAppContext,
|
|
30
|
+
NavigationContainer,
|
|
31
|
+
Screen,
|
|
32
|
+
BottomTab,
|
|
33
|
+
NavigationButton,
|
|
34
|
+
HeaderTitle,
|
|
35
|
+
HeaderLeft,
|
|
36
|
+
HeaderBackground,
|
|
37
|
+
HeaderRightAction,
|
|
38
|
+
HeaderToolkitAction,
|
|
39
|
+
HeaderCustom,
|
|
40
|
+
HeaderAnimated,
|
|
41
|
+
};
|