@momo-kits/foundation 0.81.49 → 0.81.51-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.
Files changed (73) hide show
  1. package/Application/BottomSheet.tsx +216 -0
  2. package/Application/BottomTab/BottomTabBar.tsx +278 -0
  3. package/Application/{BottomTab.tsx → BottomTab/index.tsx} +42 -18
  4. package/Application/Components.tsx +356 -91
  5. package/Application/Localize.ts +44 -0
  6. package/Application/ModalScreen.tsx +14 -185
  7. package/Application/Navigation.ts +5 -19
  8. package/Application/NavigationContainer.tsx +62 -72
  9. package/Application/Navigator.ts +154 -48
  10. package/Application/StackScreen.tsx +289 -32
  11. package/Application/constants.ts +9 -0
  12. package/Application/index.ts +13 -15
  13. package/Application/types.ts +81 -35
  14. package/Application/utils.tsx +76 -30
  15. package/Assets/icon_bank.json +1 -1
  16. package/Badge/Badge.tsx +1 -1
  17. package/Badge/BadgeDotAnimation.tsx +95 -0
  18. package/Badge/index.tsx +2 -1
  19. package/Badge/styles.ts +50 -6
  20. package/Button/index.tsx +44 -26
  21. package/CheckBox/index.tsx +37 -26
  22. package/CheckBox/types.ts +5 -3
  23. package/Consts/colors+spacing+radius.ts +14 -0
  24. package/Icon/index.tsx +9 -8
  25. package/Icon/types.ts +2 -2
  26. package/IconButton/index.tsx +24 -14
  27. package/Image/index.tsx +23 -8
  28. package/Image/types.ts +2 -0
  29. package/Input/Input.tsx +116 -26
  30. package/Input/InputDropDown.tsx +66 -51
  31. package/Input/InputMoney.tsx +106 -15
  32. package/Input/InputOTP.tsx +49 -26
  33. package/Input/InputSearch.tsx +252 -99
  34. package/Input/InputTextArea.tsx +26 -6
  35. package/Input/TextTyping.tsx +113 -0
  36. package/Input/common.tsx +48 -22
  37. package/Input/index.tsx +112 -77
  38. package/Input/styles.ts +48 -11
  39. package/Input/utils.ts +1 -1
  40. package/Layout/Card.tsx +4 -3
  41. package/Layout/FloatingButton.tsx +168 -0
  42. package/Layout/GridSystem.tsx +1 -1
  43. package/Layout/ItemList.tsx +3 -2
  44. package/Layout/Screen.tsx +242 -121
  45. package/Layout/Section.tsx +4 -3
  46. package/Layout/styles.ts +11 -13
  47. package/Layout/types.ts +1 -1
  48. package/Layout/utils.ts +4 -4
  49. package/Loader/index.tsx +2 -0
  50. package/Pagination/PaginationScroll.tsx +2 -2
  51. package/Pagination/styles.ts +1 -1
  52. package/Popup/PopupNotify.tsx +57 -46
  53. package/Popup/PopupPromotion.tsx +6 -8
  54. package/Popup/types.ts +1 -7
  55. package/Radio/index.tsx +35 -20
  56. package/Radio/types.ts +5 -3
  57. package/Switch/index.tsx +32 -18
  58. package/Switch/types.ts +5 -3
  59. package/Tag/index.tsx +9 -2
  60. package/Tag/styles.ts +3 -2
  61. package/Tag/types.ts +12 -0
  62. package/Text/index.tsx +24 -5
  63. package/Text/styles.ts +8 -8
  64. package/Text/types.ts +19 -1
  65. package/Title/index.tsx +170 -103
  66. package/Title/styles.ts +36 -9
  67. package/Title/types.ts +16 -48
  68. package/code-scanner.js +125 -16
  69. package/index.ts +7 -0
  70. package/migrate_typo.js +56 -0
  71. package/package.json +10 -9
  72. package/publish.sh +16 -21
  73. package/tsconfig.json +1 -1
@@ -1,79 +1,170 @@
1
- import {CommonActions, StackActions} from '@react-navigation/native';
1
+ import {
2
+ CommonActions,
3
+ NavigationContainerRef,
4
+ StackActions,
5
+ } from '@react-navigation/native';
2
6
  import {
3
7
  BottomSheetParams,
4
8
  HeaderToolkitProps,
5
9
  ModalParams,
10
+ NavigatorCallbackParamsType,
6
11
  ScreenParams,
7
12
  } from './types';
13
+ import React from 'react';
14
+ import {
15
+ NavigationActionCallbackErrorEnum,
16
+ NavigationActionCallbackStatusEnum,
17
+ } from './constants';
8
18
 
9
19
  class Navigator {
10
- ref?: any;
20
+ ref: React.RefObject<NavigationContainerRef>;
21
+ isReady: React.MutableRefObject<boolean>;
11
22
  toolkitConfig?: HeaderToolkitProps;
12
23
  maxApi?: any;
13
- dismissData?: any;
14
- toolkitCallback?: (item: any) => void;
24
+ dismissData?: unknown;
25
+ toolkitCallback?: (key: string) => void;
15
26
 
16
- constructor(navigation: any) {
27
+ constructor(
28
+ navigation: React.RefObject<NavigationContainerRef>,
29
+ isReady: React.MutableRefObject<boolean>
30
+ ) {
17
31
  this.ref = navigation;
32
+ this.isReady = isReady;
18
33
  }
19
34
 
35
+ private validateRefAndRunAction = (params: {
36
+ action: (navigationRef: NavigationContainerRef) => void;
37
+ callback?: (params: NavigatorCallbackParamsType) => void;
38
+ }) => {
39
+ try {
40
+ if (this.isReady.current && this.ref.current) {
41
+ params.action(this.ref.current);
42
+ params.callback?.({status: NavigationActionCallbackStatusEnum.Success});
43
+ } else {
44
+ params.callback?.({
45
+ status: NavigationActionCallbackStatusEnum.Failed,
46
+ type: NavigationActionCallbackErrorEnum.NotReady,
47
+ });
48
+ }
49
+ } catch (error) {
50
+ params.callback?.({
51
+ status: NavigationActionCallbackStatusEnum.Failed,
52
+ type: NavigationActionCallbackErrorEnum.Error,
53
+ });
54
+ }
55
+ };
56
+
20
57
  /**
21
58
  * push new stack screen
22
59
  * @param params
23
60
  */
24
- push = (params: ScreenParams) => {
25
- this.ref.current.dispatch(StackActions.push('Stack', params));
61
+ push = (
62
+ params: ScreenParams,
63
+ callback?: (params: NavigatorCallbackParamsType) => void
64
+ ) => {
65
+ this.validateRefAndRunAction({
66
+ action: navigationRef => {
67
+ navigationRef.dispatch(StackActions.push('Stack', params));
68
+ },
69
+ callback,
70
+ });
26
71
  };
27
72
 
28
73
  /**
29
74
  * replace current screen with new screen
30
75
  * @param params
31
76
  */
32
- replace = (params: ScreenParams) => {
33
- this.ref.current.dispatch(StackActions.replace('Stack', params));
77
+ replace = (
78
+ params: ScreenParams,
79
+ callback?: (params: NavigatorCallbackParamsType) => void
80
+ ) => {
81
+ this.validateRefAndRunAction({
82
+ action: navigationRef => {
83
+ navigationRef.dispatch(StackActions.replace('Stack', params));
84
+ },
85
+ callback,
86
+ });
34
87
  };
35
88
  /**
36
89
  * pop to dismiss a screen
37
90
  * @param count
38
91
  */
39
- pop = (count?: number) => {
40
- this.ref.current.dispatch(StackActions.pop(count ?? 1));
92
+ pop = (
93
+ count?: number,
94
+ callback?: (params: NavigatorCallbackParamsType) => void
95
+ ) => {
96
+ this.validateRefAndRunAction({
97
+ action: navigationRef => {
98
+ navigationRef.dispatch(StackActions.pop(count ?? 1));
99
+ },
100
+ callback,
101
+ });
41
102
  };
42
103
 
43
104
  /**
44
105
  * present a new screen, show from bottom iOS
45
106
  * @param params
46
107
  */
47
- present = (params: ScreenParams) => {
48
- this.ref.current.dispatch(StackActions.push('Dialog', params));
108
+ present = (
109
+ params: ScreenParams,
110
+ callback?: (params: NavigatorCallbackParamsType) => void
111
+ ) => {
112
+ this.validateRefAndRunAction({
113
+ action: navigationRef => {
114
+ navigationRef.dispatch(StackActions.push('Dialog', params));
115
+ },
116
+ callback,
117
+ });
49
118
  };
50
119
 
51
120
  /**
52
121
  * show a modal popup
53
122
  * @param params
54
123
  */
55
- showModal = (params: ModalParams) => {
56
- this.ref.current.dispatch(StackActions.push('Modal', params));
124
+ showModal = (
125
+ params: ModalParams,
126
+ callback?: (params: NavigatorCallbackParamsType) => void
127
+ ) => {
128
+ this.validateRefAndRunAction({
129
+ action: navigationRef => {
130
+ navigationRef.dispatch(StackActions.push('Modal', params));
131
+ },
132
+ callback,
133
+ });
57
134
  };
58
135
 
59
136
  /**
60
137
  * show a bottom sheet
61
138
  * @param params
139
+ * @param callback
62
140
  */
63
- showBottomSheet = (params: BottomSheetParams) => {
64
- this.ref.current.dispatch(
65
- StackActions.push('Modal', {
66
- ...params,
67
- isBottomSheet: true,
68
- }),
69
- );
141
+ showBottomSheet = (
142
+ params: BottomSheetParams,
143
+ callback?: (params: NavigatorCallbackParamsType) => void
144
+ ) => {
145
+ this.validateRefAndRunAction({
146
+ action: navigationRef => {
147
+ navigationRef.dispatch(
148
+ StackActions.push('Modal', {
149
+ ...params,
150
+ isBottomSheet: true,
151
+ })
152
+ );
153
+ },
154
+ callback,
155
+ });
70
156
  };
71
157
 
72
158
  /**
73
159
  * pop all screen route
74
160
  */
75
- popToTop = () => {
76
- this.ref.current.dispatch(StackActions.popToTop());
161
+ popToTop = (callback?: (params: NavigatorCallbackParamsType) => void) => {
162
+ this.validateRefAndRunAction({
163
+ action: navigationRef => {
164
+ navigationRef.dispatch(StackActions.popToTop());
165
+ },
166
+ callback,
167
+ });
77
168
  };
78
169
 
79
170
  /**
@@ -81,39 +172,56 @@ class Navigator {
81
172
  * @param name
82
173
  * @param params
83
174
  */
84
- navigate = (name: string, params: any) => {
85
- this.ref.current.dispatch(
86
- CommonActions.navigate({
87
- name,
88
- params,
89
- }),
90
- );
175
+ navigate = (
176
+ name: string,
177
+ params: any,
178
+ callback?: (params: NavigatorCallbackParamsType) => void
179
+ ) => {
180
+ this.validateRefAndRunAction({
181
+ action: navigationRef => {
182
+ navigationRef.dispatch(
183
+ CommonActions.navigate({
184
+ name,
185
+ params,
186
+ })
187
+ );
188
+ },
189
+ callback,
190
+ });
91
191
  };
92
192
 
93
193
  /**
94
194
  * reset a navigation flow with new screen
95
195
  * @param params
96
196
  */
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
- );
197
+ reset = (
198
+ params: ScreenParams,
199
+ callback?: (params: NavigatorCallbackParamsType) => void
200
+ ) => {
201
+ this.validateRefAndRunAction({
202
+ action: navigationRef => {
203
+ navigationRef.dispatch(
204
+ CommonActions.reset({
205
+ index: 0,
206
+ routes: [
207
+ {
208
+ name: 'Stack',
209
+ key: `Stack_${new Date().getTime()}`,
210
+ params,
211
+ },
212
+ ],
213
+ })
214
+ );
215
+ },
216
+ callback,
217
+ });
110
218
  };
111
219
 
112
220
  /**
113
221
  * dismiss a feature data
114
222
  * @param data
115
223
  */
116
- setDismissData = (data: any) => {
224
+ setDismissData = (data: unknown) => {
117
225
  this.dismissData = data;
118
226
  };
119
227
 
@@ -121,9 +229,7 @@ class Navigator {
121
229
  * set callback function for toolkit
122
230
  * @param callback
123
231
  */
124
- setToolkitCallback = (
125
- callback: (item: {key: string; action: string}) => void,
126
- ) => {
232
+ setToolkitCallback = (callback: (key: string) => void) => {
127
233
  this.toolkitCallback = callback;
128
234
  };
129
235
  }
@@ -1,70 +1,327 @@
1
- import React, {useContext, useEffect, useLayoutEffect} from 'react';
1
+ import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
2
+ import {useHeaderHeight} from '@react-navigation/stack';
3
+ import {Alert, InteractionManager, Linking, View} from 'react-native';
2
4
  import {ScreenParams} from './types';
3
5
  import Navigation from './Navigation';
4
- import {ApplicationContext, MiniAppContext} from './index';
6
+ import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
5
7
  import {GridSystem} from '../Layout';
6
- import {useHeaderHeight} from '@react-navigation/stack';
8
+ import {Text} from '../Text';
9
+ import {Colors, Radius, Spacing} from '../Consts';
7
10
 
11
+ /**
12
+ * container for stack screen
13
+ * @param props
14
+ * @constructor
15
+ */
8
16
  const StackScreen: React.FC<ScreenParams> = props => {
9
- const {theme, showGrid, navigator} = useContext(ApplicationContext);
10
- const context = useContext(MiniAppContext);
17
+ const {showGrid, navigator} = useContext(ApplicationContext);
18
+ const tracking = useRef<any>({
19
+ timeoutLoad: undefined,
20
+ timeoutInteraction: undefined,
21
+ timeoutTracking: undefined,
22
+ startTime: Date.now(),
23
+ endTime: Date.now(),
24
+ traceIdLoad: undefined,
25
+ traceIdInteraction: undefined,
26
+ releaseLoad: undefined,
27
+ releaseInteraction: undefined,
28
+ timeLoad: 0,
29
+ timeInteraction: 0,
30
+ });
11
31
 
12
- const {screen: Component, options}: ScreenParams = props.route.params;
13
- const navigation = new Navigation(props.navigation, theme);
32
+ const context = useContext<any>(MiniAppContext);
33
+ const {screen: Component, options, initialParams} = props.route.params;
34
+ const navigation = new Navigation(props.navigation);
14
35
  const heightHeader = useHeaderHeight();
15
36
 
16
- const params = {
37
+ const data = {
38
+ ...initialParams,
17
39
  ...props.route.params,
18
40
  navigation,
19
41
  };
20
42
 
21
- delete params.screen;
43
+ delete data.screen;
44
+ delete data.initialParams;
45
+
46
+ const screenName = Component?.name || Component?.type?.name || 'Invalid';
47
+ const routes = props.navigation.getState()?.routes || [];
22
48
 
23
49
  /**
24
50
  * set options for screen
25
51
  */
26
52
  useLayoutEffect(() => {
53
+ let defaultOptions = {
54
+ headerRight: {
55
+ type: 'toolkit',
56
+ },
57
+ };
27
58
  if (options) {
28
- navigation.setOptions(options);
59
+ defaultOptions = {
60
+ ...defaultOptions,
61
+ ...options,
62
+ };
29
63
  }
64
+ navigation.setOptions(defaultOptions);
30
65
  }, [options]);
31
66
 
32
67
  /**
33
68
  * tracking for screen
34
69
  */
35
70
  useEffect(() => {
36
- const tracking = {
37
- ...context,
38
- screen_name: Component.name,
71
+ if (['Invalid', 'screen'].includes(screenName) && context.enableAutoId) {
72
+ setTimeout(() => {
73
+ navigator?.showModal({screen: EmptyScreen});
74
+ }, 300);
75
+ }
76
+
77
+ const subscription = props.navigation?.addListener?.('focus', () => {
78
+ navigator?.maxApi?.of?.({screenName});
79
+ navigator?.maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
80
+ let preScreenName = data?.screenName;
81
+ if (routes?.length > 1) {
82
+ const screen = routes?.[routes?.length - 2]?.params?.screen;
83
+ preScreenName = screen?.name || screen?.type?.name || 'Invalid';
84
+ }
85
+ onScreenNavigated(preScreenName);
86
+ navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
87
+ });
88
+ });
89
+ navigator?.maxApi?.startTraceScreenLoad?.(screenName, (data: any) => {
90
+ tracking.current.traceIdLoad = data?.traceId;
91
+ });
92
+ navigator?.maxApi?.startTraceScreenInteraction?.(
93
+ screenName,
94
+ (data: any) => {
95
+ tracking.current.traceIdInteraction = data?.traceId;
96
+ }
97
+ );
98
+
99
+ tracking.current.timeoutTracking = setTimeout(() => {
100
+ onScreenLoad();
101
+ onScreenInteraction();
102
+ }, 5000);
103
+
104
+ return () => {
105
+ onScreenLoad();
106
+ onScreenInteraction();
107
+ clearTimeout(tracking.current.timeoutTracking);
108
+ subscription?.();
39
109
  };
110
+ }, []);
111
+
112
+ /**
113
+ * tracking for screen load
114
+ */
115
+ const onScreenLoad = () => {
116
+ if (!tracking.current?.releaseLoad) {
117
+ if (tracking.current.timeLoad === 0) {
118
+ tracking.current.timeLoad =
119
+ tracking.current.endTime - tracking.current.startTime;
120
+ }
40
121
 
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;
122
+ context.autoTracking?.({
123
+ appId: context.appId,
124
+ code: context.code,
125
+ buildNumber: context.buildNumber,
126
+ screenName,
127
+ componentName: 'Screen',
128
+ state: 'load',
129
+ duration: tracking.current.timeLoad,
130
+ });
131
+ navigator?.maxApi?.stopTrace?.(
132
+ tracking.current.traceIdLoad,
133
+ {value: tracking.current.timeLoad / 1000},
134
+ null
135
+ );
136
+ tracking.current.releaseLoad = true;
137
+
138
+ /**
139
+ * debug
140
+ */
141
+ navigator?.maxApi?.showToastDebug?.({
142
+ appId: context.appId,
143
+ message: `${screenName} screen_load_time ${tracking.current.timeLoad}`,
144
+ type: 'ERROR',
145
+ });
146
+ if (tracking.current.timeLoad <= 0 && context.enableAutoId) {
147
+ Alert.alert(screenName, "Can't get screen load time");
148
+ }
46
149
  }
150
+ };
47
151
 
48
- navigator?.maxApi?.trackEvent?.('service_frame_displayed', {
49
- ...tracking,
50
- pre_screen_name,
51
- trigger_id: '111378000000000000',
52
- });
152
+ /**
153
+ * tracking for screen load
154
+ */
155
+ const onScreenInteraction = () => {
156
+ if (!tracking.current?.releaseInteraction) {
157
+ if (tracking.current.timeLoad === 0) {
158
+ tracking.current.timeLoad =
159
+ tracking.current.endTime - tracking.current.startTime;
160
+ }
161
+ if (tracking.current.timeInteraction === 0) {
162
+ tracking.current.timeInteraction = tracking.current.timeLoad;
163
+ }
164
+
165
+ context.autoTracking?.({
166
+ appId: context.appId,
167
+ code: context.code,
168
+ buildNumber: context.buildNumber,
169
+ screenName,
170
+ componentName: 'Screen',
171
+ state: 'interaction',
172
+ duration: tracking.current.timeInteraction - tracking.current.timeLoad,
173
+ totalDuration: tracking.current.timeInteraction,
174
+ });
175
+ navigator?.maxApi?.stopTrace?.(
176
+ tracking.current.traceIdInteraction,
177
+ {value: tracking.current.timeInteraction / 1000},
178
+ null
179
+ );
180
+ tracking.current.releaseInteraction = true;
53
181
 
54
- return props.navigation.addListener('beforeRemove', () => {
55
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', {
56
- ...tracking,
57
- trigger_id: '111154000000000000',
58
- icon_name: 'back',
182
+ /**
183
+ * debug toast
184
+ */
185
+ navigator?.maxApi?.showToastDebug?.({
186
+ appId: context.appId,
187
+ message: `${screenName} screen_interaction_time ${tracking.current.timeInteraction}`,
188
+ type: 'ERROR',
59
189
  });
190
+ if (tracking.current.timeInteraction <= 0 && context.enableAutoId) {
191
+ Alert.alert(screenName, "Can't get screen interaction time");
192
+ }
193
+ }
194
+ };
195
+
196
+ /**
197
+ * tracking for screen navigated
198
+ */
199
+ const onScreenNavigated = (preScreenName: string) => {
200
+ context.autoTracking?.({
201
+ appId: context.appId,
202
+ code: context.code,
203
+ buildNumber: context.buildNumber,
204
+ preScreenName,
205
+ screenName,
206
+ componentName: 'Screen',
207
+ state: 'navigated',
60
208
  });
61
- }, []);
209
+
210
+ /**
211
+ * debug toast
212
+ */
213
+ navigator?.maxApi?.showToastDebug?.({
214
+ appId: context.appId,
215
+ message: `${screenName} screen_navigated`,
216
+ type: 'ERROR',
217
+ });
218
+ };
62
219
 
63
220
  return (
64
- <>
65
- <Component heightHeader={heightHeader} {...params} />
221
+ <ScreenContext.Provider
222
+ value={{
223
+ screenName,
224
+ onElementLoad: () => {
225
+ clearTimeout(tracking.current.timeoutLoad);
226
+ tracking.current.endTime = Date.now();
227
+ tracking.current.timeoutInteraction?.cancel?.();
228
+ tracking.current.timeoutInteraction =
229
+ InteractionManager.runAfterInteractions(() => {
230
+ tracking.current.timeInteraction =
231
+ Date.now() - tracking.current.startTime;
232
+ });
233
+ tracking.current.timeoutLoad = setTimeout(() => {
234
+ if (tracking.current.timeLoad === 0) {
235
+ tracking.current.timeLoad =
236
+ tracking.current.endTime - tracking.current.startTime;
237
+ }
238
+ onScreenLoad();
239
+ onScreenInteraction();
240
+ }, 2000);
241
+ },
242
+ }}>
243
+ <Component
244
+ heightHeader={heightHeader}
245
+ {...data}
246
+ onScreenLoad={onScreenLoad}
247
+ onScreenInteraction={onScreenInteraction}
248
+ />
66
249
  {showGrid && <GridSystem />}
67
- </>
250
+ </ScreenContext.Provider>
251
+ );
252
+ };
253
+
254
+ /**
255
+ * Empty screen for unvalidated screen name
256
+ * @constructor
257
+ */
258
+ const EmptyScreen: React.FC = () => {
259
+ return (
260
+ <View
261
+ style={{
262
+ backgroundColor: Colors.black_01,
263
+ padding: Spacing.M,
264
+ borderRadius: Radius.M,
265
+ }}>
266
+ <Text typography={'header_m_bold'}>Unvalidated screen name</Text>
267
+ <Text
268
+ typography={'description_default_regular'}
269
+ style={{paddingVertical: Spacing.S}}>
270
+ Your screen has not been rendered because Platform has not detected the
271
+ screen name. Please migrate to support this feature.
272
+ </Text>
273
+ <Text typography={'header_default'} style={{width: '100%'}}>
274
+ Possible fixes:
275
+ </Text>
276
+ <View style={{marginLeft: Spacing.S}}>
277
+ <Text typography={'body_default_regular'}>1. Off webpack config</Text>
278
+ <Text typography={'body_default_regular'}>
279
+ 2. Screen name refactoring
280
+ </Text>
281
+ <View style={{marginLeft: Spacing.S}}>
282
+ <Text
283
+ typography={'description_default_regular'}
284
+ style={{marginBottom: Spacing.S}}>
285
+ - Với các screen push/import dạng arrow function ={'>'} đổi thành
286
+ named function
287
+ </Text>
288
+ <Text
289
+ typography={'description_default_regular'}
290
+ style={{marginBottom: Spacing.S}}>
291
+ - Với các screen import dạng High Order Component ={'>'} rename
292
+ generic function thành named function
293
+ </Text>
294
+ <Text
295
+ typography={'description_default_regular'}
296
+ style={{marginBottom: Spacing.S}}>
297
+ - Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
298
+ Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
299
+ khảo theo docs
300
+ </Text>
301
+ </View>
302
+ </View>
303
+ <Text typography={'header_s_semibold'}>More information: </Text>
304
+ <Text
305
+ typography={'body_default_regular'}
306
+ color={Colors.blue_01}
307
+ onPress={() => {
308
+ Linking.openURL(
309
+ 'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
310
+ );
311
+ }}>
312
+ Mini App: vn.momo.uikits/dev
313
+ </Text>
314
+ <Text
315
+ typography={'body_default_regular'}
316
+ color={Colors.blue_01}
317
+ onPress={() => {
318
+ Linking.openURL(
319
+ 'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
320
+ );
321
+ }}>
322
+ https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
323
+ </Text>
324
+ </View>
68
325
  );
69
326
  };
70
327
 
@@ -0,0 +1,9 @@
1
+ export enum NavigationActionCallbackStatusEnum {
2
+ Success = 'success',
3
+ Failed = 'failed',
4
+ }
5
+
6
+ export enum NavigationActionCallbackErrorEnum {
7
+ NotReady = 'not_ready',
8
+ Error = 'error',
9
+ }