@momo-kits/foundation 0.81.5 → 0.81.7-beta.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/Components.tsx +52 -14
- package/Application/ModalScreen.tsx +44 -3
- package/Application/Navigation.ts +8 -0
- package/Application/NavigationContainer.tsx +16 -1
- package/Application/Navigator.ts +39 -26
- package/Application/StackScreen.tsx +26 -2
- package/Application/types.ts +11 -3
- package/Application/utils.tsx +12 -0
- package/Input/InputOTP.tsx +1 -1
- package/Layout/Card.tsx +1 -0
- package/Layout/Item.tsx +1 -1
- package/Layout/ItemList.tsx +27 -25
- package/Layout/ItemSectionList.tsx +45 -0
- package/Layout/Section.tsx +11 -13
- package/Layout/styles.ts +0 -12
- package/package.json +3 -2
- package/tsconfig.json +0 -1
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import React, {Fragment, useContext, useEffect, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
|
+
BackHandler,
|
|
4
5
|
DeviceEventEmitter,
|
|
5
|
-
Platform,
|
|
6
6
|
StatusBar,
|
|
7
7
|
StyleSheet,
|
|
8
8
|
TouchableOpacity,
|
|
9
9
|
View,
|
|
10
10
|
} from 'react-native';
|
|
11
|
-
import {TouchableOpacity as TouchableGesture} from 'react-native-gesture-handler';
|
|
12
11
|
import {ApplicationContext} from './index';
|
|
13
12
|
import {Colors, Radius, Spacing, Styles} from '../Consts';
|
|
14
13
|
import {Image} from '../Image';
|
|
@@ -24,9 +23,6 @@ import {scaleSize, Text} from '../Text';
|
|
|
24
23
|
import {Icon} from '../Icon';
|
|
25
24
|
import {PopupNotify} from '../Popup';
|
|
26
25
|
|
|
27
|
-
const Touchable =
|
|
28
|
-
Platform.OS === 'android' ? TouchableGesture : TouchableOpacity;
|
|
29
|
-
|
|
30
26
|
const styles = StyleSheet.create({
|
|
31
27
|
navigationButton: {
|
|
32
28
|
height: 28,
|
|
@@ -106,7 +102,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
106
102
|
}
|
|
107
103
|
|
|
108
104
|
return (
|
|
109
|
-
<
|
|
105
|
+
<TouchableOpacity
|
|
110
106
|
accessibilityLabel={`NavigationButton/${accessibilityLabel}`}
|
|
111
107
|
style={[
|
|
112
108
|
styles.navigationButton,
|
|
@@ -121,7 +117,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
121
117
|
color={tintColor ?? theme.colors.text.default}
|
|
122
118
|
size={20}
|
|
123
119
|
/>
|
|
124
|
-
</
|
|
120
|
+
</TouchableOpacity>
|
|
125
121
|
);
|
|
126
122
|
};
|
|
127
123
|
|
|
@@ -154,8 +150,29 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
154
150
|
accessibilityLabel = '',
|
|
155
151
|
}) => {
|
|
156
152
|
const {navigator} = useContext(ApplicationContext);
|
|
153
|
+
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
const backHandler = BackHandler.addEventListener(
|
|
156
|
+
'hardwareBackPress',
|
|
157
|
+
goBack,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return () => backHandler.remove();
|
|
161
|
+
}, []);
|
|
162
|
+
|
|
157
163
|
const goBack = () => {
|
|
158
164
|
const canGoBack = navigator?.ref.current?.canGoBack();
|
|
165
|
+
const currentRoute = navigator?.ref?.current.getCurrentRoute();
|
|
166
|
+
|
|
167
|
+
if (navigator?.trackingInfo) {
|
|
168
|
+
navigator?.maxApi?.trackEvent('service_icon_clicked', {
|
|
169
|
+
...navigator?.trackingInfo,
|
|
170
|
+
screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
|
|
171
|
+
trigger_id: '111154000000000000',
|
|
172
|
+
icon_name: 'back',
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
159
176
|
if (canGoBack) {
|
|
160
177
|
if (preventBack) {
|
|
161
178
|
navigator?.showModal({
|
|
@@ -181,6 +198,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
181
198
|
DeviceEventEmitter.emit('dismiss', {requestId});
|
|
182
199
|
}
|
|
183
200
|
onPressLeftHeader?.();
|
|
201
|
+
return true;
|
|
184
202
|
};
|
|
185
203
|
|
|
186
204
|
return (
|
|
@@ -313,9 +331,25 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
313
331
|
}
|
|
314
332
|
|
|
315
333
|
useEffect(() => {
|
|
316
|
-
navigator?.
|
|
317
|
-
setToolConfig(
|
|
318
|
-
}
|
|
334
|
+
if (navigator?.toolkitConfig) {
|
|
335
|
+
setToolConfig(navigator?.toolkitConfig);
|
|
336
|
+
} else {
|
|
337
|
+
navigator?.requestApi('getToolkit', [undefined], (result: boolean) => {
|
|
338
|
+
if (result) {
|
|
339
|
+
navigator?.requestApi(
|
|
340
|
+
'getToolkitConfig',
|
|
341
|
+
[undefined],
|
|
342
|
+
(config: any) => {
|
|
343
|
+
navigator.toolkitConfig = {
|
|
344
|
+
...config?.utilityToolConfig,
|
|
345
|
+
appCode: config?.appCode,
|
|
346
|
+
};
|
|
347
|
+
setToolConfig(navigator?.toolkitConfig);
|
|
348
|
+
},
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
319
353
|
}, []);
|
|
320
354
|
|
|
321
355
|
useEffect(() => {
|
|
@@ -397,17 +431,21 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
397
431
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
398
432
|
},
|
|
399
433
|
]}>
|
|
400
|
-
<
|
|
434
|
+
<TouchableOpacity
|
|
435
|
+
accessibilityLabel={'Toolkit/More'}
|
|
436
|
+
onPress={onMore}>
|
|
401
437
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
402
|
-
</
|
|
438
|
+
</TouchableOpacity>
|
|
403
439
|
<View style={[styles.divider, {backgroundColor: tintColor}]} />
|
|
404
|
-
<
|
|
440
|
+
<TouchableOpacity
|
|
441
|
+
accessibilityLabel={`Toolkit/Close`}
|
|
442
|
+
onPress={onClose}>
|
|
405
443
|
<Icon
|
|
406
444
|
color={tintColor}
|
|
407
445
|
source="16_navigation_close_circle"
|
|
408
446
|
size={20}
|
|
409
447
|
/>
|
|
410
|
-
</
|
|
448
|
+
</TouchableOpacity>
|
|
411
449
|
</View>
|
|
412
450
|
</View>
|
|
413
451
|
);
|
|
@@ -26,6 +26,9 @@ import {
|
|
|
26
26
|
import {HeaderBackground, HeaderLeft, HeaderTitle} from './Components';
|
|
27
27
|
|
|
28
28
|
const ModalScreen: React.FC<any> = props => {
|
|
29
|
+
/**
|
|
30
|
+
* dismiss callback when modal | bottom sheet dismissed
|
|
31
|
+
*/
|
|
29
32
|
useEffect(() => {
|
|
30
33
|
return () => {
|
|
31
34
|
props.route.params?.onDismiss?.();
|
|
@@ -40,7 +43,7 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
40
43
|
|
|
41
44
|
const Modal: React.FC<ModalParams> = props => {
|
|
42
45
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
43
|
-
const {screen, barrierDismissible}
|
|
46
|
+
const {screen, barrierDismissible, modalName} = props.route.params;
|
|
44
47
|
const Component = useRef(screen).current;
|
|
45
48
|
const navigation = new Navigation(props.navigation, theme);
|
|
46
49
|
const params = {
|
|
@@ -50,6 +53,42 @@ const Modal: React.FC<ModalParams> = props => {
|
|
|
50
53
|
|
|
51
54
|
delete params.screen;
|
|
52
55
|
|
|
56
|
+
/**
|
|
57
|
+
* tracking
|
|
58
|
+
*/
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (navigator?.trackingInfo) {
|
|
61
|
+
const TRIGGER_ID = '111012100000000000';
|
|
62
|
+
const navigationRoutes = props.navigation.getState()?.routes || [];
|
|
63
|
+
const routesLength = navigationRoutes.length;
|
|
64
|
+
let screen_name = navigationRoutes?.[0]?.params?.screen?.name;
|
|
65
|
+
if (routesLength > 1) {
|
|
66
|
+
screen_name = navigationRoutes[routesLength - 2]?.params?.screen?.name;
|
|
67
|
+
}
|
|
68
|
+
const error_code = (screen as Function)?.()?.props?.information;
|
|
69
|
+
navigator?.maxApi?.trackEvent('service_component_displayed', {
|
|
70
|
+
...navigator?.trackingInfo,
|
|
71
|
+
screen_name,
|
|
72
|
+
trigger_id: '111012100000000000',
|
|
73
|
+
component_type: 'popup',
|
|
74
|
+
component_name: modalName,
|
|
75
|
+
error_code,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return () => {
|
|
79
|
+
navigator?.maxApi?.trackEvent('service_icon_clicked', {
|
|
80
|
+
...navigator?.trackingInfo,
|
|
81
|
+
screen_name,
|
|
82
|
+
trigger_id: '111154100000000001',
|
|
83
|
+
component_type: 'popup',
|
|
84
|
+
component_name: modalName,
|
|
85
|
+
error_code,
|
|
86
|
+
icon_name: 'close',
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
53
92
|
const onDismiss = () => {
|
|
54
93
|
if (barrierDismissible) {
|
|
55
94
|
return;
|
|
@@ -160,7 +199,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
160
199
|
navigator?.pop();
|
|
161
200
|
}
|
|
162
201
|
}}
|
|
163
|
-
bottomInset={bottomInset}
|
|
202
|
+
bottomInset={Platform.OS === 'ios' ? bottomInset : 0}
|
|
164
203
|
handleComponent={null}
|
|
165
204
|
backdropComponent={backdropComponent}>
|
|
166
205
|
<BottomSheetView accessibilityLabel={'BottomSheet'}>
|
|
@@ -181,6 +220,8 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
181
220
|
/>
|
|
182
221
|
</View>
|
|
183
222
|
<NavigationContainer
|
|
223
|
+
trackingInfo={navigator?.trackingInfo}
|
|
224
|
+
maxApi={navigator?.maxApi}
|
|
184
225
|
theme={{
|
|
185
226
|
...theme,
|
|
186
227
|
assets: {...theme.assets, headerBackground: undefined},
|
|
@@ -223,7 +264,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
223
264
|
icon="24_navigation_close"
|
|
224
265
|
backgroundColor="transparent"
|
|
225
266
|
useBorder={false}
|
|
226
|
-
onPress={bottomSheetRef.current?.dismiss}
|
|
267
|
+
onPress={() => bottomSheetRef.current?.dismiss()}
|
|
227
268
|
accessibilityLabel={'BottomSheet/Close'}
|
|
228
269
|
/>
|
|
229
270
|
</HeaderRightAction>
|
|
@@ -14,6 +14,10 @@ class Navigation {
|
|
|
14
14
|
this.theme = theme;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* navigation options will be remove if used
|
|
19
|
+
* @param params
|
|
20
|
+
*/
|
|
17
21
|
private filterParams = (params: NavigationOptions) => {
|
|
18
22
|
if (params.headerRight) {
|
|
19
23
|
const headerRight = params.headerRight?.({}) as React.ReactElement;
|
|
@@ -27,6 +31,10 @@ class Navigation {
|
|
|
27
31
|
return params;
|
|
28
32
|
};
|
|
29
33
|
|
|
34
|
+
/**
|
|
35
|
+
* navigation setOptions support props NavigationOptions base on react-navigation options
|
|
36
|
+
* @param params
|
|
37
|
+
*/
|
|
30
38
|
setOptions = (params: NavigationOptions) => {
|
|
31
39
|
if (__DEV__) {
|
|
32
40
|
params = this.filterParams(params);
|
|
@@ -23,12 +23,16 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
23
23
|
options,
|
|
24
24
|
maxApi,
|
|
25
25
|
localization,
|
|
26
|
+
trackingInfo,
|
|
26
27
|
}) => {
|
|
27
28
|
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
|
28
29
|
const navigator = useRef(new Navigator(navigationRef));
|
|
29
30
|
const [showGrid, setShowGrid] = useState(false);
|
|
30
31
|
const [language, setLanguage] = useState<'vi' | 'en'>('vi');
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* engine only shake to enable grid view
|
|
35
|
+
*/
|
|
32
36
|
useEffect(() => {
|
|
33
37
|
const subscription = DeviceEventEmitter.addListener(
|
|
34
38
|
'onChangeGrid',
|
|
@@ -37,10 +41,13 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
37
41
|
},
|
|
38
42
|
);
|
|
39
43
|
return () => {
|
|
40
|
-
subscription
|
|
44
|
+
subscription?.remove?.();
|
|
41
45
|
};
|
|
42
46
|
}, []);
|
|
43
47
|
|
|
48
|
+
/**
|
|
49
|
+
* handle mini language & listen change
|
|
50
|
+
*/
|
|
44
51
|
useEffect(() => {
|
|
45
52
|
maxApi?.getLanguage?.((lang: 'vi' | 'en') => {
|
|
46
53
|
setLanguage(lang);
|
|
@@ -53,8 +60,16 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
53
60
|
};
|
|
54
61
|
}, []);
|
|
55
62
|
|
|
63
|
+
/**
|
|
64
|
+
* inject data for navigator
|
|
65
|
+
*/
|
|
56
66
|
navigator.current.maxApi = maxApi;
|
|
67
|
+
navigator.current.trackingInfo = trackingInfo;
|
|
57
68
|
|
|
69
|
+
/**
|
|
70
|
+
* translate
|
|
71
|
+
* @param key
|
|
72
|
+
*/
|
|
58
73
|
const translate = (key: string) => {
|
|
59
74
|
const mergedLocalization: LocalizationObject = {
|
|
60
75
|
vi: {...localization?.vi, ...kitLocalization.vi},
|
package/Application/Navigator.ts
CHANGED
|
@@ -4,37 +4,62 @@ import {
|
|
|
4
4
|
HeaderToolkitProps,
|
|
5
5
|
ModalParams,
|
|
6
6
|
ScreenParams,
|
|
7
|
+
TrackingInfo,
|
|
7
8
|
} from './types';
|
|
8
9
|
|
|
9
10
|
class Navigator {
|
|
10
11
|
ref?: any;
|
|
11
12
|
toolkitConfig?: HeaderToolkitProps;
|
|
12
13
|
maxApi?: any;
|
|
14
|
+
trackingInfo?: TrackingInfo;
|
|
13
15
|
|
|
14
16
|
constructor(navigation: any) {
|
|
15
17
|
this.ref = navigation;
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
/**
|
|
21
|
+
* push new stack screen
|
|
22
|
+
* @param params
|
|
23
|
+
*/
|
|
18
24
|
push = (params: ScreenParams) => {
|
|
19
25
|
this.ref.current.dispatch(StackActions.push('Stack', params));
|
|
20
26
|
};
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* replace current screen with new screen
|
|
30
|
+
* @param params
|
|
31
|
+
*/
|
|
22
32
|
replace = (params: ScreenParams) => {
|
|
23
33
|
this.ref.current.dispatch(StackActions.replace('Stack', params));
|
|
24
34
|
};
|
|
25
|
-
|
|
35
|
+
/**
|
|
36
|
+
* pop to dismiss a screen
|
|
37
|
+
* @param count
|
|
38
|
+
*/
|
|
26
39
|
pop = (count?: number) => {
|
|
27
40
|
this.ref.current.dispatch(StackActions.pop(count ?? 1));
|
|
28
41
|
};
|
|
29
42
|
|
|
43
|
+
/**
|
|
44
|
+
* present a new screen, show from bottom iOS
|
|
45
|
+
* @param params
|
|
46
|
+
*/
|
|
30
47
|
present = (params: ScreenParams) => {
|
|
31
48
|
this.ref.current.dispatch(StackActions.push('Dialog', params));
|
|
32
49
|
};
|
|
33
50
|
|
|
51
|
+
/**
|
|
52
|
+
* show a modal popup
|
|
53
|
+
* @param params
|
|
54
|
+
*/
|
|
34
55
|
showModal = (params: ModalParams) => {
|
|
35
56
|
this.ref.current.dispatch(StackActions.push('Modal', params));
|
|
36
57
|
};
|
|
37
58
|
|
|
59
|
+
/**
|
|
60
|
+
* show a bottom sheet
|
|
61
|
+
* @param params
|
|
62
|
+
*/
|
|
38
63
|
showBottomSheet = (params: BottomSheetParams) => {
|
|
39
64
|
this.ref.current.dispatch(
|
|
40
65
|
StackActions.push('Modal', {
|
|
@@ -44,10 +69,17 @@ class Navigator {
|
|
|
44
69
|
);
|
|
45
70
|
};
|
|
46
71
|
|
|
72
|
+
/**
|
|
73
|
+
* pop all screen route
|
|
74
|
+
*/
|
|
47
75
|
popToTop = () => {
|
|
48
76
|
this.ref.current.dispatch(StackActions.popToTop());
|
|
49
77
|
};
|
|
50
78
|
|
|
79
|
+
/**
|
|
80
|
+
* reset a navigation flow with new screen
|
|
81
|
+
* @param params
|
|
82
|
+
*/
|
|
51
83
|
reset = (params: ScreenParams) => {
|
|
52
84
|
this.ref.current.dispatch(
|
|
53
85
|
CommonActions.reset({
|
|
@@ -63,36 +95,17 @@ class Navigator {
|
|
|
63
95
|
);
|
|
64
96
|
};
|
|
65
97
|
|
|
98
|
+
/**
|
|
99
|
+
* request max api for mini app
|
|
100
|
+
* @param func
|
|
101
|
+
* @param args
|
|
102
|
+
* @param callback
|
|
103
|
+
*/
|
|
66
104
|
requestApi = (func: any, args: any = [], callback: any) => {
|
|
67
105
|
if (this.maxApi) {
|
|
68
106
|
this.maxApi[func]?.(...args, callback);
|
|
69
|
-
} else {
|
|
70
|
-
const instance: any = global;
|
|
71
|
-
instance?.miniAppApi?.dispatch?.(func, ...args, callback);
|
|
72
107
|
}
|
|
73
108
|
};
|
|
74
|
-
|
|
75
|
-
getToolkit = async (): Promise<HeaderToolkitProps | undefined> => {
|
|
76
|
-
return new Promise(resolve => {
|
|
77
|
-
if (this.toolkitConfig) {
|
|
78
|
-
resolve(this.toolkitConfig);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
this.requestApi('getToolkit', [undefined], (result: boolean) => {
|
|
82
|
-
if (result) {
|
|
83
|
-
this.requestApi('getToolkitConfig', [undefined], (config: any) => {
|
|
84
|
-
this.toolkitConfig = {
|
|
85
|
-
...config?.utilityToolConfig,
|
|
86
|
-
appCode: config?.appCode,
|
|
87
|
-
};
|
|
88
|
-
resolve(this.toolkitConfig);
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
resolve(undefined);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
export default Navigator;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useContext, useLayoutEffect} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useLayoutEffect} from 'react';
|
|
2
2
|
import {ScreenParams} from './types';
|
|
3
3
|
import Navigation from './Navigation';
|
|
4
4
|
import {ApplicationContext} from './index';
|
|
@@ -6,7 +6,7 @@ import {GridSystem} from '../Layout';
|
|
|
6
6
|
|
|
7
7
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
8
8
|
const {screen: Component, options}: ScreenParams = props.route.params;
|
|
9
|
-
const {theme, showGrid} = useContext(ApplicationContext);
|
|
9
|
+
const {theme, showGrid, navigator} = useContext(ApplicationContext);
|
|
10
10
|
const navigation = new Navigation(props.navigation, theme);
|
|
11
11
|
|
|
12
12
|
const params = {
|
|
@@ -16,12 +16,36 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
16
16
|
|
|
17
17
|
delete params.screen;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* set options for screen
|
|
21
|
+
*/
|
|
19
22
|
useLayoutEffect(() => {
|
|
20
23
|
if (options) {
|
|
21
24
|
navigation.setOptions(options);
|
|
22
25
|
}
|
|
23
26
|
}, [options]);
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* tracking for screen
|
|
30
|
+
*/
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (navigator?.trackingInfo) {
|
|
33
|
+
const navigationRoutes = props.navigation.getState()?.routes || [];
|
|
34
|
+
const routesLength = navigationRoutes.length;
|
|
35
|
+
let pre_screen_name = navigationRoutes?.[0]?.params?.screen?.name;
|
|
36
|
+
if (routesLength > 1) {
|
|
37
|
+
pre_screen_name =
|
|
38
|
+
navigationRoutes[routesLength - 2]?.params?.screen?.name;
|
|
39
|
+
}
|
|
40
|
+
navigator?.maxApi?.trackEvent('service_frame_displayed', {
|
|
41
|
+
...navigator?.trackingInfo,
|
|
42
|
+
screen_name: Component.name,
|
|
43
|
+
pre_screen_name,
|
|
44
|
+
trigger_id: '111378000000000000',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
25
49
|
return (
|
|
26
50
|
<>
|
|
27
51
|
<Component {...params} />
|
package/Application/types.ts
CHANGED
|
@@ -79,12 +79,20 @@ export type LocalizationObject = {
|
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
export type TrackingInfo = {
|
|
83
|
+
[key: string]: any;
|
|
84
|
+
feature_code: string;
|
|
85
|
+
app_id: string;
|
|
86
|
+
miniapp_version: number;
|
|
87
|
+
};
|
|
88
|
+
|
|
82
89
|
export type NavigationContainerProps = {
|
|
83
90
|
screen: Screen;
|
|
84
91
|
options?: NavigationOptions;
|
|
85
92
|
theme: Theme;
|
|
86
|
-
maxApi
|
|
93
|
+
maxApi: any;
|
|
87
94
|
localization?: LocalizationObject;
|
|
95
|
+
trackingInfo?: TrackingInfo;
|
|
88
96
|
};
|
|
89
97
|
|
|
90
98
|
export type NavigationScreenProps = {
|
|
@@ -97,10 +105,12 @@ export type ScreenParams = {
|
|
|
97
105
|
[key: string]: any;
|
|
98
106
|
screen: Screen;
|
|
99
107
|
options?: NavigationOptions;
|
|
108
|
+
tracking?: any;
|
|
100
109
|
};
|
|
101
110
|
|
|
102
111
|
export interface ModalParams extends ScreenParams {
|
|
103
112
|
[key: string]: any;
|
|
113
|
+
modalName?: string;
|
|
104
114
|
onDismiss?: () => void;
|
|
105
115
|
barrierDismissible?: boolean;
|
|
106
116
|
}
|
|
@@ -125,9 +135,7 @@ export interface NavigationOptions extends StackNavigationOptions {
|
|
|
125
135
|
onPressLeftHeader?: () => void;
|
|
126
136
|
surface?: boolean;
|
|
127
137
|
hiddenBack?: boolean;
|
|
128
|
-
headerTitleAlign?: 'left' | 'center';
|
|
129
138
|
customTitle?: TitleCustomProps;
|
|
130
|
-
animatedValue?: Animated.Value;
|
|
131
139
|
}
|
|
132
140
|
|
|
133
141
|
export interface HeaderBackProps extends NavigationButtonProps {
|
package/Application/utils.tsx
CHANGED
|
@@ -13,6 +13,9 @@ import {
|
|
|
13
13
|
import {NavigationOptions, Theme} from './types';
|
|
14
14
|
import {Colors} from '../Consts';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* default options for stack screen
|
|
18
|
+
*/
|
|
16
19
|
const getStackOptions = (): StackNavigationOptions => {
|
|
17
20
|
return {
|
|
18
21
|
headerTitleAlign: 'left',
|
|
@@ -24,6 +27,9 @@ const getStackOptions = (): StackNavigationOptions => {
|
|
|
24
27
|
};
|
|
25
28
|
};
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* default options for dialog screen
|
|
32
|
+
*/
|
|
27
33
|
const getDialogOptions = (): StackNavigationOptions => {
|
|
28
34
|
return {
|
|
29
35
|
headerTitleAlign: 'left',
|
|
@@ -35,6 +41,9 @@ const getDialogOptions = (): StackNavigationOptions => {
|
|
|
35
41
|
};
|
|
36
42
|
};
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* default options for modal screen
|
|
46
|
+
*/
|
|
38
47
|
const getModalOptions = (): StackNavigationOptions => {
|
|
39
48
|
return {
|
|
40
49
|
headerShown: false,
|
|
@@ -60,6 +69,9 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
60
69
|
};
|
|
61
70
|
};
|
|
62
71
|
|
|
72
|
+
/**
|
|
73
|
+
* build react-navigation options
|
|
74
|
+
*/
|
|
63
75
|
const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
64
76
|
let options = {};
|
|
65
77
|
|
package/Input/InputOTP.tsx
CHANGED
package/Layout/Card.tsx
CHANGED
package/Layout/Item.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import {GridContext} from './index';
|
|
|
5
5
|
import {ApplicationContext} from '../Application';
|
|
6
6
|
import styles from './styles';
|
|
7
7
|
|
|
8
|
-
type SpanNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
8
|
+
export type SpanNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
9
9
|
|
|
10
10
|
export interface ItemProps extends ViewProps {
|
|
11
11
|
/**
|
package/Layout/ItemList.tsx
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
import React, {FC,
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
2
|
import {FlatList, FlatListProps, View} from 'react-native';
|
|
3
|
-
import Item from './Item';
|
|
3
|
+
import Item, {SpanNumber} from './Item';
|
|
4
4
|
import {GridContext} from './index';
|
|
5
5
|
import styles from './styles';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export interface ItemListProps extends FlatListProps<any> {
|
|
8
|
+
/**
|
|
9
|
+
* Require key support number columns change grid system
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
key: string;
|
|
13
|
+
/**
|
|
14
|
+
* Represents the width of the Card component in terms of span numbers (1-12).
|
|
15
|
+
*/
|
|
16
|
+
widthSpan?: SpanNumber;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ItemList: FC<ItemListProps> = ({
|
|
20
|
+
key,
|
|
8
21
|
renderItem,
|
|
9
|
-
|
|
22
|
+
widthSpan,
|
|
10
23
|
style,
|
|
11
24
|
contentContainerStyle,
|
|
12
25
|
...props
|
|
13
26
|
}) => {
|
|
14
|
-
const {gutterSize} = useContext(GridContext);
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
item
|
|
21
|
-
index,
|
|
22
|
-
separators,
|
|
23
|
-
}) as ReactElement;
|
|
24
|
-
|
|
25
|
-
if (children?.type !== Item) {
|
|
26
|
-
console.warn('Wrong children type for this component, expected are Item');
|
|
27
|
+
const {gutterSize, numberOfColumns} = useContext(GridContext);
|
|
28
|
+
const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
|
|
29
|
+
const numColumns = Math.floor(numberOfColumns / widthItem);
|
|
30
|
+
const indexBegin = props?.data?.map((_i, index) => index * numColumns);
|
|
31
|
+
const _renderItem = (item: any) => {
|
|
32
|
+
if (indexBegin?.includes(item?.index)) {
|
|
33
|
+
return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
|
|
27
34
|
}
|
|
28
|
-
|
|
29
35
|
return (
|
|
30
|
-
<View
|
|
31
|
-
|
|
32
|
-
numColumns > 1 && {
|
|
33
|
-
marginRight: gutterSize,
|
|
34
|
-
}
|
|
35
|
-
}>
|
|
36
|
-
{children}
|
|
36
|
+
<View style={{paddingLeft: gutterSize}}>
|
|
37
|
+
<Item widthSpan={widthItem}>{renderItem?.(item)}</Item>
|
|
37
38
|
</View>
|
|
38
39
|
);
|
|
39
40
|
};
|
|
@@ -41,6 +42,7 @@ const ItemList: FC<FlatListProps<any>> = ({
|
|
|
41
42
|
return (
|
|
42
43
|
<FlatList
|
|
43
44
|
{...props}
|
|
45
|
+
key={`${key ?? 'ItemList'}${numColumns}}`}
|
|
44
46
|
numColumns={numColumns}
|
|
45
47
|
renderItem={_renderItem}
|
|
46
48
|
horizontal={false}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {SectionList, SectionListProps, View} from 'react-native';
|
|
3
|
+
import Item, {SpanNumber} from './Item';
|
|
4
|
+
import {GridContext} from './index';
|
|
5
|
+
import styles from './styles';
|
|
6
|
+
|
|
7
|
+
export interface ItemSectionListProps extends SectionListProps<any> {
|
|
8
|
+
/**
|
|
9
|
+
* Require key support number columns change grid system
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
key: string;
|
|
13
|
+
/**
|
|
14
|
+
* Represents the width of the Card component in terms of span numbers (1-12).
|
|
15
|
+
*/
|
|
16
|
+
widthSpan?: SpanNumber;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ItemSectionList: FC<ItemSectionListProps> = ({
|
|
20
|
+
key,
|
|
21
|
+
renderItem,
|
|
22
|
+
widthSpan,
|
|
23
|
+
style,
|
|
24
|
+
contentContainerStyle,
|
|
25
|
+
...props
|
|
26
|
+
}) => {
|
|
27
|
+
const {gutterSize, numberOfColumns} = useContext(GridContext);
|
|
28
|
+
const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
|
|
29
|
+
const _renderItem = (item: any) => {
|
|
30
|
+
return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SectionList
|
|
35
|
+
{...props}
|
|
36
|
+
renderItem={_renderItem}
|
|
37
|
+
horizontal={false}
|
|
38
|
+
ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
|
|
39
|
+
style={[style, styles.protectedStyle]}
|
|
40
|
+
contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default ItemSectionList;
|
package/Layout/Section.tsx
CHANGED
|
@@ -22,11 +22,6 @@ export interface SectionProps extends ViewProps {
|
|
|
22
22
|
*/
|
|
23
23
|
useMargin?: boolean;
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* Optional. Background color for the Section component.
|
|
27
|
-
*/
|
|
28
|
-
backgroundColor?: string;
|
|
29
|
-
|
|
30
25
|
/**
|
|
31
26
|
* Optional. Background image for the Section component.
|
|
32
27
|
*/
|
|
@@ -36,8 +31,8 @@ export interface SectionProps extends ViewProps {
|
|
|
36
31
|
const Section: React.FC<SectionProps> = ({
|
|
37
32
|
children,
|
|
38
33
|
useMargin = true,
|
|
39
|
-
backgroundColor,
|
|
40
34
|
backgroundImage,
|
|
35
|
+
style,
|
|
41
36
|
}) => {
|
|
42
37
|
const {showGrid} = useContext(ApplicationContext);
|
|
43
38
|
const {numberOfColumns} = useGridSystem();
|
|
@@ -156,13 +151,16 @@ const Section: React.FC<SectionProps> = ({
|
|
|
156
151
|
}}>
|
|
157
152
|
<View
|
|
158
153
|
accessibilityLabel={`Section`}
|
|
159
|
-
style={
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
154
|
+
style={[
|
|
155
|
+
style,
|
|
156
|
+
styles.protectedStyle,
|
|
157
|
+
{
|
|
158
|
+
width: widthSection,
|
|
159
|
+
marginHorizontal: gridContext.margin,
|
|
160
|
+
flexDirection: 'row',
|
|
161
|
+
flexWrap: 'wrap',
|
|
162
|
+
},
|
|
163
|
+
]}>
|
|
166
164
|
{!!backgroundImage && (
|
|
167
165
|
<Image
|
|
168
166
|
source={{uri: backgroundImage}}
|
package/Layout/styles.ts
CHANGED
|
@@ -45,19 +45,7 @@ export default StyleSheet.create({
|
|
|
45
45
|
flexDirection: 'row',
|
|
46
46
|
flexWrap: 'wrap',
|
|
47
47
|
borderRadius: Radius.M,
|
|
48
|
-
paddingTop: undefined,
|
|
49
|
-
paddingBottom: undefined,
|
|
50
|
-
paddingLeft: undefined,
|
|
51
|
-
paddingRight: undefined,
|
|
52
|
-
paddingVertical: undefined,
|
|
53
|
-
paddingHorizontal: undefined,
|
|
54
48
|
padding: 12,
|
|
55
|
-
margin: undefined,
|
|
56
|
-
marginTop: undefined,
|
|
57
|
-
marginBottom: undefined,
|
|
58
|
-
marginLeft: undefined,
|
|
59
|
-
marginRight: undefined,
|
|
60
|
-
marginVertical: undefined,
|
|
61
49
|
},
|
|
62
50
|
item: {
|
|
63
51
|
overflow: 'hidden',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/foundation",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.7-beta.1",
|
|
4
4
|
"description": "React Native Component Kits",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"@momo-kits/foundation"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@gorhom/bottom-sheet": "
|
|
13
|
+
"@gorhom/bottom-sheet": "git+https://gitlab.com/dung.huynh1/bottom-sheet.git#main",
|
|
14
14
|
"react-native-safe-area-context": "3.1.4",
|
|
15
15
|
"react-native-linear-gradient": "2.5.6",
|
|
16
16
|
"react-native-gesture-handler": "1.10.3",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"metro-react-native-babel-preset": "^0.64.0",
|
|
39
39
|
"react-test-renderer": "17.0.1",
|
|
40
40
|
"typescript": "^4.0.3",
|
|
41
|
+
"@momo-platform/versions": "4.1.11",
|
|
41
42
|
"react-scanner": "^1.1.0"
|
|
42
43
|
},
|
|
43
44
|
"author": "@momo-kits/foundation",
|