@momo-kits/foundation 0.89.5 → 0.92.1-tracking.2
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 +21 -8
- package/Application/NavigationContainer.tsx +8 -3
- package/Application/Navigator.ts +51 -31
- package/Application/StackScreen.tsx +69 -9
- package/Application/types.ts +2 -0
- package/Application/utils.tsx +61 -2
- package/Button/index.tsx +46 -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 +39 -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/index.ts +2 -1
- package/package.json +1 -1
- package/verify.js +1 -1
|
@@ -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}>
|
|
@@ -120,13 +123,19 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
120
123
|
const goBack = () => {
|
|
121
124
|
const canGoBack = navigator?.ref.current?.canGoBack();
|
|
122
125
|
if (!canGoBack) {
|
|
123
|
-
const currentRoute = navigator?.ref?.current
|
|
124
|
-
|
|
126
|
+
const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
|
|
127
|
+
const params = {
|
|
125
128
|
...context,
|
|
126
129
|
screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
|
|
127
130
|
trigger_id: '111154000000000000',
|
|
128
131
|
icon_name: 'back',
|
|
132
|
+
};
|
|
133
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
134
|
+
appId: context.appId,
|
|
135
|
+
message: 'service_icon_clicked',
|
|
136
|
+
params,
|
|
129
137
|
});
|
|
138
|
+
navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
|
|
130
139
|
}
|
|
131
140
|
if (canGoBack) {
|
|
132
141
|
navigator?.ref.current?.goBack();
|
|
@@ -160,10 +169,10 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
|
|
|
160
169
|
}
|
|
161
170
|
return true;
|
|
162
171
|
};
|
|
163
|
-
|
|
164
172
|
return (
|
|
165
|
-
<View
|
|
173
|
+
<View style={styles.headerLeft}>
|
|
166
174
|
<NavigationButton
|
|
175
|
+
accessibilityID = "btn_navigation_back"
|
|
167
176
|
icon="ic_back"
|
|
168
177
|
tintColor={tintColor}
|
|
169
178
|
onPress={goBackSafe}
|
|
@@ -363,6 +372,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
363
372
|
if (pinTool)
|
|
364
373
|
return (
|
|
365
374
|
<NavigationButton
|
|
375
|
+
accessibilityID = "btn_navigation_pin"
|
|
366
376
|
icon={pinTool.icon as string}
|
|
367
377
|
tintColor={tintColor}
|
|
368
378
|
badgeValue={badgeValue}
|
|
@@ -380,7 +390,6 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
380
390
|
/>
|
|
381
391
|
);
|
|
382
392
|
};
|
|
383
|
-
|
|
384
393
|
if (toolConfig) {
|
|
385
394
|
return (
|
|
386
395
|
<View style={styles.headerRightButton}>
|
|
@@ -393,11 +402,15 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
393
402
|
borderWidth: backgroundColor ? 0.5 : 0,
|
|
394
403
|
},
|
|
395
404
|
]}>
|
|
396
|
-
<TouchableOpacity
|
|
405
|
+
<TouchableOpacity
|
|
406
|
+
{...getAccessibilityID("btn_navigation_more")}
|
|
407
|
+
onPress={onMore}>
|
|
397
408
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
398
409
|
</TouchableOpacity>
|
|
399
410
|
<View style={[styles.divider, {backgroundColor: tintColor}]} />
|
|
400
|
-
<TouchableOpacity
|
|
411
|
+
<TouchableOpacity
|
|
412
|
+
{...getAccessibilityID("btn_navigation_close")}
|
|
413
|
+
onPress={onClose}>
|
|
401
414
|
<Icon
|
|
402
415
|
color={tintColor}
|
|
403
416
|
source="16_navigation_close_circle"
|
|
@@ -23,10 +23,12 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
23
23
|
options,
|
|
24
24
|
maxApi,
|
|
25
25
|
localization,
|
|
26
|
+
params,
|
|
26
27
|
}) => {
|
|
27
28
|
const context = useContext(MiniAppContext);
|
|
28
|
-
const navigationRef =
|
|
29
|
-
const
|
|
29
|
+
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
30
|
+
const isReady = useRef(false);
|
|
31
|
+
const navigator = useRef(new Navigator(navigationRef, isReady));
|
|
30
32
|
const [showGrid, setShowGrid] = useState(false);
|
|
31
33
|
const config = useRef<any>();
|
|
32
34
|
|
|
@@ -89,12 +91,15 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
89
91
|
},
|
|
90
92
|
}}
|
|
91
93
|
ref={navigator.current?.ref}
|
|
94
|
+
onReady={() => {
|
|
95
|
+
isReady.current = true;
|
|
96
|
+
}}
|
|
92
97
|
independent={true}>
|
|
93
98
|
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
94
99
|
<Stack.Screen
|
|
95
100
|
name="Stack"
|
|
96
101
|
component={StackScreen}
|
|
97
|
-
initialParams={{screen}}
|
|
102
|
+
initialParams={{screen, params}}
|
|
98
103
|
options={{...getStackOptions(), ...options}}
|
|
99
104
|
/>
|
|
100
105
|
<Stack.Screen
|
package/Application/Navigator.ts
CHANGED
|
@@ -8,13 +8,15 @@ import {
|
|
|
8
8
|
|
|
9
9
|
class Navigator {
|
|
10
10
|
ref?: any;
|
|
11
|
+
isReady?: any;
|
|
11
12
|
toolkitConfig?: HeaderToolkitProps;
|
|
12
13
|
maxApi?: any;
|
|
13
14
|
dismissData?: any;
|
|
14
15
|
toolkitCallback?: (item: any) => void;
|
|
15
16
|
|
|
16
|
-
constructor(navigation: any) {
|
|
17
|
+
constructor(navigation: any, isReady: any) {
|
|
17
18
|
this.ref = navigation;
|
|
19
|
+
this.isReady = isReady;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -22,7 +24,9 @@ class Navigator {
|
|
|
22
24
|
* @param params
|
|
23
25
|
*/
|
|
24
26
|
push = (params: ScreenParams) => {
|
|
25
|
-
this.
|
|
27
|
+
if (this.isReady.current) {
|
|
28
|
+
this.ref.current.dispatch(StackActions.push('Stack', params));
|
|
29
|
+
}
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
/**
|
|
@@ -30,14 +34,18 @@ class Navigator {
|
|
|
30
34
|
* @param params
|
|
31
35
|
*/
|
|
32
36
|
replace = (params: ScreenParams) => {
|
|
33
|
-
this.
|
|
37
|
+
if (this.isReady.current) {
|
|
38
|
+
this.ref.current.dispatch(StackActions.replace('Stack', params));
|
|
39
|
+
}
|
|
34
40
|
};
|
|
35
41
|
/**
|
|
36
42
|
* pop to dismiss a screen
|
|
37
43
|
* @param count
|
|
38
44
|
*/
|
|
39
45
|
pop = (count?: number) => {
|
|
40
|
-
this.
|
|
46
|
+
if (this.isReady.current) {
|
|
47
|
+
this.ref.current.dispatch(StackActions.pop(count ?? 1));
|
|
48
|
+
}
|
|
41
49
|
};
|
|
42
50
|
|
|
43
51
|
/**
|
|
@@ -45,7 +53,9 @@ class Navigator {
|
|
|
45
53
|
* @param params
|
|
46
54
|
*/
|
|
47
55
|
present = (params: ScreenParams) => {
|
|
48
|
-
this.
|
|
56
|
+
if (this.isReady.current) {
|
|
57
|
+
this.ref.current.dispatch(StackActions.push('Dialog', params));
|
|
58
|
+
}
|
|
49
59
|
};
|
|
50
60
|
|
|
51
61
|
/**
|
|
@@ -53,7 +63,9 @@ class Navigator {
|
|
|
53
63
|
* @param params
|
|
54
64
|
*/
|
|
55
65
|
showModal = (params: ModalParams) => {
|
|
56
|
-
this.
|
|
66
|
+
if (this.isReady.current) {
|
|
67
|
+
this.ref.current.dispatch(StackActions.push('Modal', params));
|
|
68
|
+
}
|
|
57
69
|
};
|
|
58
70
|
|
|
59
71
|
/**
|
|
@@ -61,19 +73,23 @@ class Navigator {
|
|
|
61
73
|
* @param params
|
|
62
74
|
*/
|
|
63
75
|
showBottomSheet = (params: BottomSheetParams) => {
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
if (this.isReady.current) {
|
|
77
|
+
this.ref.current.dispatch(
|
|
78
|
+
StackActions.push('Modal', {
|
|
79
|
+
...params,
|
|
80
|
+
isBottomSheet: true,
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
70
84
|
};
|
|
71
85
|
|
|
72
86
|
/**
|
|
73
87
|
* pop all screen route
|
|
74
88
|
*/
|
|
75
89
|
popToTop = () => {
|
|
76
|
-
this.
|
|
90
|
+
if (this.isReady.current) {
|
|
91
|
+
this.ref.current.dispatch(StackActions.popToTop());
|
|
92
|
+
}
|
|
77
93
|
};
|
|
78
94
|
|
|
79
95
|
/**
|
|
@@ -82,12 +98,14 @@ class Navigator {
|
|
|
82
98
|
* @param params
|
|
83
99
|
*/
|
|
84
100
|
navigate = (name: string, params: any) => {
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
if (this.isReady.current) {
|
|
102
|
+
this.ref.current.dispatch(
|
|
103
|
+
CommonActions.navigate({
|
|
104
|
+
name,
|
|
105
|
+
params,
|
|
106
|
+
}),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
91
109
|
};
|
|
92
110
|
|
|
93
111
|
/**
|
|
@@ -95,18 +113,20 @@ class Navigator {
|
|
|
95
113
|
* @param params
|
|
96
114
|
*/
|
|
97
115
|
reset = (params: ScreenParams) => {
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
if (this.isReady.current) {
|
|
117
|
+
this.ref.current.dispatch(
|
|
118
|
+
CommonActions.reset({
|
|
119
|
+
index: 0,
|
|
120
|
+
routes: [
|
|
121
|
+
{
|
|
122
|
+
name: 'Stack',
|
|
123
|
+
key: `Stack_${new Date().getTime()}`,
|
|
124
|
+
params,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
110
130
|
};
|
|
111
131
|
|
|
112
132
|
/**
|
|
@@ -1,29 +1,49 @@
|
|
|
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 {screen: Component, options}: ScreenParams = props.route.params;
|
|
22
|
+
const {screen: Component, options, params}: ScreenParams = props.route.params;
|
|
13
23
|
const navigation = new Navigation(props.navigation, theme);
|
|
14
24
|
const heightHeader = useHeaderHeight();
|
|
15
25
|
|
|
16
|
-
const
|
|
26
|
+
const data = {
|
|
17
27
|
...props.route.params,
|
|
28
|
+
params,
|
|
18
29
|
navigation,
|
|
19
30
|
};
|
|
20
31
|
|
|
21
|
-
delete
|
|
32
|
+
delete data.screen;
|
|
22
33
|
|
|
23
34
|
/**
|
|
24
35
|
* set options for screen
|
|
25
36
|
*/
|
|
26
37
|
useLayoutEffect(() => {
|
|
38
|
+
startTime.current = Date.now();
|
|
39
|
+
InteractionManager.runAfterInteractions(() => {
|
|
40
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
41
|
+
appId: context.appId,
|
|
42
|
+
message: `${Component.name} screen_interaction_time ${
|
|
43
|
+
Date.now() - startTime.current
|
|
44
|
+
}`,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
27
47
|
if (options) {
|
|
28
48
|
navigation.setOptions(options);
|
|
29
49
|
}
|
|
@@ -33,6 +53,15 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
33
53
|
* tracking for screen
|
|
34
54
|
*/
|
|
35
55
|
useEffect(() => {
|
|
56
|
+
if (__DEV__) {
|
|
57
|
+
if (!Component.name || Component.name === 'screen') {
|
|
58
|
+
Alert.alert(
|
|
59
|
+
'Design system',
|
|
60
|
+
`Unvalidated screen name "${Component.name}" !`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
36
65
|
const tracking = {
|
|
37
66
|
...context,
|
|
38
67
|
screen_name: Component.name,
|
|
@@ -45,26 +74,57 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
45
74
|
pre_screen_name = routes[routesLength - 2]?.params?.screen?.name;
|
|
46
75
|
}
|
|
47
76
|
|
|
48
|
-
|
|
77
|
+
const params = {
|
|
49
78
|
...tracking,
|
|
50
79
|
pre_screen_name,
|
|
51
80
|
trigger_id: '111378000000000000',
|
|
81
|
+
};
|
|
82
|
+
navigator?.maxApi?.trackEvent?.('service_frame_displayed', params);
|
|
83
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
84
|
+
appId: context.appId,
|
|
85
|
+
message: `${Component.name} service_frame_displayed`,
|
|
86
|
+
params,
|
|
52
87
|
});
|
|
53
88
|
|
|
54
89
|
return props.navigation.addListener('beforeRemove', () => {
|
|
55
|
-
|
|
90
|
+
const params = {
|
|
56
91
|
...tracking,
|
|
57
92
|
trigger_id: '111154000000000000',
|
|
58
93
|
icon_name: 'back',
|
|
94
|
+
};
|
|
95
|
+
navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
|
|
96
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
97
|
+
appId: context.appId,
|
|
98
|
+
message: `${Component.name} service_icon_clicked`,
|
|
99
|
+
params,
|
|
59
100
|
});
|
|
60
101
|
});
|
|
61
102
|
}, []);
|
|
62
103
|
|
|
63
104
|
return (
|
|
64
|
-
|
|
65
|
-
|
|
105
|
+
<ScreenContext.Provider
|
|
106
|
+
value={{
|
|
107
|
+
appId: context.appId,
|
|
108
|
+
code: context.code,
|
|
109
|
+
screenName: Component.name,
|
|
110
|
+
autoTracking: (data: any) => {
|
|
111
|
+
navigator?.maxApi?.dispatchFunction?.('autoTracking', data);
|
|
112
|
+
},
|
|
113
|
+
onElementLoad: () => {
|
|
114
|
+
endTime.current = Date.now();
|
|
115
|
+
clearTimeout(timeout.current);
|
|
116
|
+
timeout.current = setTimeout(() => {
|
|
117
|
+
timeLoad.current = endTime.current - startTime.current;
|
|
118
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
119
|
+
appId: context.appId,
|
|
120
|
+
message: `${Component.name} screen_load_time ${timeLoad.current}`,
|
|
121
|
+
});
|
|
122
|
+
}, 1000);
|
|
123
|
+
},
|
|
124
|
+
}}>
|
|
125
|
+
<Component heightHeader={heightHeader} {...data} />
|
|
66
126
|
{showGrid && <GridSystem />}
|
|
67
|
-
|
|
127
|
+
</ScreenContext.Provider>
|
|
68
128
|
);
|
|
69
129
|
};
|
|
70
130
|
|
package/Application/types.ts
CHANGED
|
@@ -94,6 +94,7 @@ export type NavigationContainerProps = {
|
|
|
94
94
|
options?: NavigationOptions;
|
|
95
95
|
theme: Theme;
|
|
96
96
|
maxApi: any;
|
|
97
|
+
params: Record<string, any>;
|
|
97
98
|
localization?: LocalizationObject;
|
|
98
99
|
};
|
|
99
100
|
|
|
@@ -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 = {
|
package/Application/utils.tsx
CHANGED
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
} from './Components';
|
|
13
13
|
import {NavigationOptions, Theme} from './types';
|
|
14
14
|
import {Colors} from '../Consts';
|
|
15
|
-
|
|
15
|
+
import {Platform} from 'react-native';
|
|
16
|
+
const isIOS = Platform.OS === 'ios';
|
|
16
17
|
/**
|
|
17
18
|
* default options for stack screen
|
|
18
19
|
*/
|
|
@@ -126,6 +127,7 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
126
127
|
};
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
if (params.toolkitParams) {
|
|
129
131
|
options = {
|
|
130
132
|
...options,
|
|
131
133
|
headerRight: (props: any) => {
|
|
@@ -139,6 +141,7 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
139
141
|
);
|
|
140
142
|
},
|
|
141
143
|
};
|
|
144
|
+
}
|
|
142
145
|
|
|
143
146
|
return {
|
|
144
147
|
...params,
|
|
@@ -146,4 +149,60 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
146
149
|
};
|
|
147
150
|
};
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
const getAccessibilityID = (key = '') => {
|
|
153
|
+
if (isIOS) {
|
|
154
|
+
return {
|
|
155
|
+
accessible: true,
|
|
156
|
+
testID: key,
|
|
157
|
+
};
|
|
158
|
+
} else {
|
|
159
|
+
return {
|
|
160
|
+
accessibilityLabel: key,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const formatComponentName = (word: string) => {
|
|
166
|
+
const accentsMap = {
|
|
167
|
+
a: 'á|à|ả|ã|ạ|â|ấ|ầ|ẩ|ẫ|ậ|ă|ắ|ằ|ẳ|ẵ|ặ',
|
|
168
|
+
A: 'Á|À|Ả|Ã|Ạ|Â|Ấ|Ầ|Ẩ|Ẫ|Ậ|Ă|Ắ|Ằ|Ẳ|Ẵ|Ặ',
|
|
169
|
+
e: 'é|è|ẻ|ẽ|ẹ|ê|ế|ề|ể|ễ|ệ',
|
|
170
|
+
E: 'É|È|Ẻ|Ẽ|Ẹ|Ê|Ế|Ề|Ể|Ễ|Ệ',
|
|
171
|
+
i: 'í|ì|ỉ|ĩ|ị',
|
|
172
|
+
I: 'Í|Ì|Ỉ|Ĩ|Ị',
|
|
173
|
+
o: 'ó|ò|ỏ|õ|ọ|ô|ố|ồ|ổ|ỗ|ộ|ơ|ớ|ờ|ở|ỡ|ợ',
|
|
174
|
+
O: 'Ó|Ò|Ỏ|Õ|Ọ|Ô|Ố|Ồ|Ổ|Ỗ|Ộ|Ơ|Ớ|Ờ|Ở|Ỡ|Ợ',
|
|
175
|
+
u: 'ú|ù|ủ|ũ|ụ|ư|ứ|ừ|ử|ữ|ự',
|
|
176
|
+
U: 'Ú|Ù|Ủ|Ũ|Ụ|Ư|Ứ|Ừ|Ử|Ữ|Ự',
|
|
177
|
+
y: 'ý|ỳ|ỷ|ỹ|ỵ',
|
|
178
|
+
Y: 'Ý|Ỳ|Ỷ|Ỹ|Ỵ',
|
|
179
|
+
d: 'đ',
|
|
180
|
+
D: 'Đ',
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
for (const [nonAccent, accentGroup] of Object.entries(accentsMap)) {
|
|
184
|
+
const accents = new RegExp(accentGroup, 'g');
|
|
185
|
+
word = word.replace(accents, nonAccent);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
word = word.replace(/\s+/g, '_').toLowerCase();
|
|
189
|
+
|
|
190
|
+
return word;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const formatNameLength = (name: string) => {
|
|
194
|
+
let formattedName = name;
|
|
195
|
+
if (formattedName.length > 100) {
|
|
196
|
+
formattedName = formattedName.substring(0, 100);
|
|
197
|
+
}
|
|
198
|
+
return formattedName;
|
|
199
|
+
};
|
|
200
|
+
export {
|
|
201
|
+
getStackOptions,
|
|
202
|
+
getDialogOptions,
|
|
203
|
+
getModalOptions,
|
|
204
|
+
getOptions,
|
|
205
|
+
formatComponentName,
|
|
206
|
+
formatNameLength,
|
|
207
|
+
getAccessibilityID,
|
|
208
|
+
};
|
package/Button/index.tsx
CHANGED
|
@@ -6,15 +6,19 @@ import {
|
|
|
6
6
|
TouchableOpacityProps,
|
|
7
7
|
View,
|
|
8
8
|
} from 'react-native';
|
|
9
|
-
|
|
10
9
|
import LinearGradient from 'react-native-linear-gradient';
|
|
11
|
-
import {ApplicationContext} from '../Application';
|
|
10
|
+
import {ApplicationContext, MiniAppContext} from '../Application';
|
|
12
11
|
import {Text} from '../Text';
|
|
13
12
|
import {Typography} from '../Text/types';
|
|
14
13
|
import {Colors, Spacing} from '../Consts';
|
|
15
14
|
import styles from './styles';
|
|
16
15
|
import {Icon} from '../Icon';
|
|
17
16
|
import {Loader} from '../Loader';
|
|
17
|
+
import {formatComponentName, getAccessibilityID} from '../Application/utils';
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
ScreenContext,
|
|
21
|
+
} = require('react-native/Libraries/Components/ScreenContext');
|
|
18
22
|
|
|
19
23
|
const AnimationLinear = Animated.createAnimatedComponent(LinearGradient);
|
|
20
24
|
|
|
@@ -70,6 +74,10 @@ export interface ButtonProps extends TouchableOpacityProps {
|
|
|
70
74
|
* A callback function that is called when the button is pressed.
|
|
71
75
|
*/
|
|
72
76
|
onPress: () => void;
|
|
77
|
+
|
|
78
|
+
params?: any;
|
|
79
|
+
|
|
80
|
+
componentId?: string;
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
const Button: FC<ButtonProps> = ({
|
|
@@ -82,9 +90,13 @@ const Button: FC<ButtonProps> = ({
|
|
|
82
90
|
loading = false,
|
|
83
91
|
title = 'Button',
|
|
84
92
|
onPress,
|
|
93
|
+
params,
|
|
94
|
+
componentId,
|
|
95
|
+
accessibilityLabel,
|
|
85
96
|
...rest
|
|
86
97
|
}) => {
|
|
87
98
|
const {theme, config} = useContext(ApplicationContext);
|
|
99
|
+
const {appId, code} = useContext(MiniAppContext)
|
|
88
100
|
const {gradient, color} = config?.navigationBar?.buttonColors ?? {};
|
|
89
101
|
let gradientPros;
|
|
90
102
|
if (gradient?.length > 0 && type == 'primary') {
|
|
@@ -94,6 +106,8 @@ const Button: FC<ButtonProps> = ({
|
|
|
94
106
|
end: {x: 0, y: 0.5},
|
|
95
107
|
};
|
|
96
108
|
}
|
|
109
|
+
|
|
110
|
+
const screenInfo = useContext<any>(ScreenContext);
|
|
97
111
|
const getSizeStyle = () => {
|
|
98
112
|
const styleSheet: {[key: string]: any} = styles;
|
|
99
113
|
return styleSheet[size ?? 'small'];
|
|
@@ -289,21 +303,37 @@ const Button: FC<ButtonProps> = ({
|
|
|
289
303
|
};
|
|
290
304
|
|
|
291
305
|
const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
|
|
292
|
-
|
|
306
|
+
const accessibilityID = getAccessibilityID(`${appId}|${screenInfo.screenName}|btn_${title}`)
|
|
293
307
|
return (
|
|
294
|
-
<
|
|
295
|
-
{
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
308
|
+
<ScreenContext.Provider
|
|
309
|
+
value={{
|
|
310
|
+
...screenInfo,
|
|
311
|
+
componentName: 'Button',
|
|
312
|
+
params,
|
|
313
|
+
state: loading
|
|
314
|
+
? 'loading'
|
|
315
|
+
: type === 'disabled'
|
|
316
|
+
? 'disabled'
|
|
317
|
+
: 'enabled',
|
|
318
|
+
componentId,
|
|
319
|
+
componentValue: formatComponentName(title),
|
|
320
|
+
action: 'click',
|
|
321
|
+
}}>
|
|
322
|
+
<TouchableOpacity
|
|
323
|
+
{...rest}
|
|
324
|
+
{...accessibilityID}
|
|
325
|
+
activeOpacity={activeOpacity}
|
|
326
|
+
onPress={onPressButton}
|
|
327
|
+
style={buttonStyle}>
|
|
328
|
+
{renderLeading()}
|
|
329
|
+
{renderTitle()}
|
|
330
|
+
{renderTrailing()}
|
|
331
|
+
{gradientPros && (
|
|
332
|
+
<AnimationLinear {...gradientPros} style={styles.gradientView} />
|
|
333
|
+
)}
|
|
334
|
+
{gradientPros && <View style={styles.strokeView} />}
|
|
335
|
+
</TouchableOpacity>
|
|
336
|
+
</ScreenContext.Provider>
|
|
307
337
|
);
|
|
308
338
|
};
|
|
309
339
|
|