@momo-kits/foundation 0.89.5 → 0.89.6-rc.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/BottomSheet.tsx +216 -0
- package/Application/BottomTab/BottomTabBar.tsx +278 -0
- package/Application/{BottomTab.tsx → BottomTab/index.tsx} +42 -18
- package/Application/Components.tsx +350 -86
- package/Application/Localize.ts +44 -0
- package/Application/ModalScreen.tsx +14 -185
- package/Application/Navigation.ts +5 -19
- package/Application/NavigationContainer.tsx +62 -72
- package/Application/Navigator.ts +53 -35
- package/Application/StackScreen.tsx +289 -32
- package/Application/index.ts +13 -15
- package/Application/types.ts +64 -35
- package/Application/utils.tsx +76 -30
- package/Assets/icon_bank.json +1 -1
- package/Badge/Badge.tsx +1 -1
- package/Badge/BadgeDotAnimation.tsx +95 -0
- package/Badge/index.tsx +2 -1
- package/Badge/styles.ts +50 -6
- package/Button/index.tsx +44 -26
- package/CheckBox/index.tsx +37 -26
- package/CheckBox/types.ts +5 -3
- package/Consts/colors+spacing+radius.ts +14 -0
- package/Icon/index.tsx +9 -8
- package/Icon/types.ts +2 -2
- package/IconButton/index.tsx +24 -14
- package/Image/index.tsx +23 -8
- package/Image/types.ts +2 -0
- package/Input/Input.tsx +116 -26
- package/Input/InputDropDown.tsx +66 -51
- package/Input/InputMoney.tsx +106 -15
- package/Input/InputOTP.tsx +49 -26
- package/Input/InputSearch.tsx +252 -99
- package/Input/InputTextArea.tsx +26 -6
- package/Input/TextTyping.tsx +113 -0
- package/Input/common.tsx +48 -22
- package/Input/index.tsx +112 -77
- package/Input/styles.ts +48 -11
- package/Input/utils.ts +1 -1
- package/Layout/Card.tsx +4 -3
- package/Layout/FloatingButton.tsx +168 -0
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ItemList.tsx +3 -2
- package/Layout/Screen.tsx +242 -121
- package/Layout/Section.tsx +4 -3
- package/Layout/styles.ts +11 -13
- package/Layout/types.ts +1 -1
- package/Layout/utils.ts +4 -4
- package/Loader/index.tsx +2 -0
- package/Pagination/PaginationScroll.tsx +2 -2
- package/Pagination/styles.ts +1 -1
- package/Popup/PopupNotify.tsx +56 -45
- package/Popup/PopupPromotion.tsx +5 -7
- package/Popup/types.ts +1 -7
- package/Radio/index.tsx +35 -20
- package/Radio/types.ts +5 -3
- package/Switch/index.tsx +32 -18
- package/Switch/types.ts +5 -3
- package/Tag/index.tsx +9 -2
- package/Tag/styles.ts +3 -2
- package/Tag/types.ts +12 -0
- package/Text/index.tsx +24 -5
- package/Text/styles.ts +8 -8
- package/Text/types.ts +19 -1
- package/Title/index.tsx +170 -103
- package/Title/styles.ts +36 -9
- package/Title/types.ts +16 -48
- package/code-scanner.js +125 -16
- package/index.ts +7 -0
- package/migrate_typo.js +56 -0
- package/package.json +11 -10
- package/publish.sh +16 -21
- package/tsconfig.json +1 -1
- package/verify.js +37 -40
package/Title/index.tsx
CHANGED
|
@@ -1,129 +1,196 @@
|
|
|
1
1
|
import React, {FC, useContext, useState} from 'react';
|
|
2
|
-
import {
|
|
3
|
-
LayoutChangeEvent,
|
|
4
|
-
NativeSyntheticEvent,
|
|
5
|
-
Text as RNText,
|
|
6
|
-
TextLayoutEventData,
|
|
7
|
-
TouchableOpacity,
|
|
8
|
-
View,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
import {TitleProps} from './types';
|
|
2
|
+
import {Text as RNText, TouchableOpacity, View, ViewStyle} from 'react-native';
|
|
11
3
|
import {Icon} from '../Icon';
|
|
12
|
-
import styles from './styles';
|
|
13
|
-
import {ApplicationContext} from '../Application';
|
|
14
|
-
import {Colors, Spacing} from '../Consts';
|
|
15
4
|
import {scaleSize, Text} from '../Text';
|
|
5
|
+
import {ApplicationContext} from '../Application';
|
|
6
|
+
import {Badge} from '../Badge';
|
|
7
|
+
import {Colors} from '../Consts';
|
|
8
|
+
import styles from './styles';
|
|
9
|
+
import {TitleProps} from './types';
|
|
10
|
+
import {Typography} from '../Text/types';
|
|
16
11
|
|
|
17
12
|
const Title: FC<TitleProps> = ({
|
|
18
|
-
size = 'large',
|
|
19
|
-
type = 'section',
|
|
20
|
-
onPressAction,
|
|
21
|
-
actionTitle,
|
|
22
13
|
title = 'Title',
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
type = 'section',
|
|
15
|
+
size = 'medium',
|
|
25
16
|
icon,
|
|
26
17
|
description,
|
|
27
|
-
|
|
18
|
+
iconColor = null,
|
|
19
|
+
iconAlign = 'top',
|
|
20
|
+
showRightAction = false,
|
|
21
|
+
showTrailingAction = false,
|
|
22
|
+
badgeLabel,
|
|
23
|
+
buttonTitle,
|
|
24
|
+
onPressRightAction = () => {},
|
|
25
|
+
onPressTrailingAction = () => {},
|
|
26
|
+
buttonSize = 'small',
|
|
27
|
+
textOnly = false,
|
|
28
|
+
style,
|
|
28
29
|
}) => {
|
|
29
30
|
const {theme} = useContext(ApplicationContext);
|
|
30
|
-
const [
|
|
31
|
-
const [
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
const numberOfLines =
|
|
31
|
+
const [badgeWidth, setBadgeWidth] = useState(0);
|
|
32
|
+
const [contentWidth, setContentWidth] = useState(0);
|
|
33
|
+
const styleSheet: {
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
} = styles;
|
|
36
|
+
const typography = `${type}_${size}`;
|
|
37
|
+
const isSection = type === 'section';
|
|
38
|
+
const numberOfLines = showTrailingAction || !!badgeLabel ? 1 : 2;
|
|
39
|
+
const buttonTypo: Typography =
|
|
40
|
+
buttonSize === 'small' ? 'action_xs_bold' : 'action_s_bold';
|
|
41
|
+
const flexStyle = showTrailingAction && {maxWidth: '70%'};
|
|
38
42
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/>
|
|
59
|
-
</TouchableOpacity>
|
|
43
|
+
const renderIcon = () => {
|
|
44
|
+
if (!icon) return null;
|
|
45
|
+
|
|
46
|
+
let iconStyle: ViewStyle = {
|
|
47
|
+
justifyContent: 'flex-start',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (iconAlign === 'middle') {
|
|
51
|
+
iconStyle = {justifyContent: 'center'};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (iconAlign === 'bottom') {
|
|
55
|
+
iconStyle = {justifyContent: 'flex-end'};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<View style={[styles.iconView, iconStyle]}>
|
|
60
|
+
<Icon color={iconColor} source={icon} />
|
|
61
|
+
</View>
|
|
60
62
|
);
|
|
61
63
|
};
|
|
62
64
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
+
const renderContent = () => {
|
|
66
|
+
return (
|
|
67
|
+
<View style={styles.contentView}>
|
|
68
|
+
<View
|
|
69
|
+
onLayout={e => {
|
|
70
|
+
if (e.nativeEvent.layout.width !== contentWidth) {
|
|
71
|
+
setContentWidth(e.nativeEvent.layout.width);
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
style={[styles.iconLeftView, flexStyle]}>
|
|
75
|
+
<RNText
|
|
76
|
+
numberOfLines={numberOfLines}
|
|
77
|
+
style={[
|
|
78
|
+
styleSheet[typography],
|
|
79
|
+
styles.title,
|
|
80
|
+
{
|
|
81
|
+
maxWidth:
|
|
82
|
+
contentWidth > 0 ? contentWidth - badgeWidth : undefined,
|
|
83
|
+
},
|
|
84
|
+
]}>
|
|
85
|
+
{title}
|
|
86
|
+
</RNText>
|
|
87
|
+
{badgeLabel && (
|
|
88
|
+
<View
|
|
89
|
+
onLayout={e => {
|
|
90
|
+
if (e.nativeEvent.layout.width !== badgeWidth) {
|
|
91
|
+
setBadgeWidth(e.nativeEvent.layout.width);
|
|
92
|
+
}
|
|
93
|
+
}}
|
|
94
|
+
style={{
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
}}>
|
|
97
|
+
<Badge style={styles.badge} label={badgeLabel} />
|
|
98
|
+
</View>
|
|
99
|
+
)}
|
|
100
|
+
{renderActionLeft()}
|
|
101
|
+
</View>
|
|
102
|
+
{description && (
|
|
103
|
+
<Text
|
|
104
|
+
style={styles.description}
|
|
105
|
+
color={theme.colors.text.secondary}
|
|
106
|
+
typography={'description_default_regular'}>
|
|
107
|
+
{description}
|
|
108
|
+
</Text>
|
|
109
|
+
)}
|
|
110
|
+
</View>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const renderActionLeft = () => {
|
|
65
115
|
return (
|
|
66
116
|
<TouchableOpacity
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
117
|
+
onPress={onPressTrailingAction}
|
|
118
|
+
style={styles.iconLeftView}>
|
|
119
|
+
{showTrailingAction && !showRightAction && (
|
|
120
|
+
<View
|
|
121
|
+
style={[
|
|
122
|
+
styles.iconLeft,
|
|
123
|
+
{
|
|
124
|
+
backgroundColor: isSection
|
|
125
|
+
? Colors.black_06 + '99'
|
|
126
|
+
: Colors.black_06 + '4D',
|
|
127
|
+
},
|
|
128
|
+
]}>
|
|
129
|
+
<Icon
|
|
130
|
+
source={'arrow_chevron_right_small'}
|
|
131
|
+
size={scaleSize(18)}
|
|
132
|
+
color={theme.colors.text.default}
|
|
133
|
+
/>
|
|
134
|
+
</View>
|
|
135
|
+
)}
|
|
78
136
|
</TouchableOpacity>
|
|
79
137
|
);
|
|
80
138
|
};
|
|
81
|
-
const onLayout = (e: LayoutChangeEvent) => {
|
|
82
|
-
setContainerWidth(e.nativeEvent.layout.width);
|
|
83
|
-
};
|
|
84
139
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
};
|
|
140
|
+
const renderActionRight = () => {
|
|
141
|
+
if (!showRightAction || showTrailingAction) return false;
|
|
88
142
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{
|
|
115
|
-
|
|
116
|
-
{!!description && type !== 'screen' && (
|
|
117
|
-
<Text
|
|
118
|
-
numberOfLines={1}
|
|
119
|
-
typography={'description_default_regular'}
|
|
120
|
-
color={theme.colors.text.secondary}>
|
|
121
|
-
{description}
|
|
143
|
+
const lineHeight = styleSheet[typography].lineHeight;
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<View
|
|
147
|
+
style={{
|
|
148
|
+
height: lineHeight,
|
|
149
|
+
justifyContent: 'center',
|
|
150
|
+
}}>
|
|
151
|
+
{!buttonTitle ? (
|
|
152
|
+
<TouchableOpacity
|
|
153
|
+
onPress={onPressRightAction}
|
|
154
|
+
style={[
|
|
155
|
+
styles.iconRight,
|
|
156
|
+
{
|
|
157
|
+
backgroundColor: theme.colors.primary + '0F',
|
|
158
|
+
},
|
|
159
|
+
]}>
|
|
160
|
+
<Icon
|
|
161
|
+
source={'arrow_chevron_right_small'}
|
|
162
|
+
size={scaleSize(22)}
|
|
163
|
+
color={theme.colors.primary}
|
|
164
|
+
/>
|
|
165
|
+
</TouchableOpacity>
|
|
166
|
+
) : (
|
|
167
|
+
<TouchableOpacity onPress={onPressRightAction}>
|
|
168
|
+
<Text color={theme.colors.primary} typography={buttonTypo}>
|
|
169
|
+
{buttonTitle}
|
|
122
170
|
</Text>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
171
|
+
</TouchableOpacity>
|
|
172
|
+
)}
|
|
173
|
+
</View>
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
if (textOnly) {
|
|
178
|
+
return (
|
|
179
|
+
<View style={isSection && styles.margin}>
|
|
180
|
+
<RNText
|
|
181
|
+
numberOfLines={numberOfLines}
|
|
182
|
+
style={[styleSheet[typography], styles.title]}>
|
|
183
|
+
{title}
|
|
184
|
+
</RNText>
|
|
126
185
|
</View>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<View style={[style, styles.wrapper, isSection && styles.margin]}>
|
|
191
|
+
{renderIcon()}
|
|
192
|
+
{renderContent()}
|
|
193
|
+
{renderActionRight()}
|
|
127
194
|
</View>
|
|
128
195
|
);
|
|
129
196
|
};
|
package/Title/styles.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {StyleSheet} from 'react-native';
|
|
2
2
|
import {scaleSize} from '../Text';
|
|
3
|
-
import {Radius, Spacing} from '../Consts';
|
|
3
|
+
import {Colors, Radius, Spacing} from '../Consts';
|
|
4
4
|
|
|
5
5
|
export default StyleSheet.create({
|
|
6
6
|
card_small: {
|
|
@@ -27,10 +27,6 @@ export default StyleSheet.create({
|
|
|
27
27
|
fontSize: scaleSize(24),
|
|
28
28
|
lineHeight: scaleSize(34),
|
|
29
29
|
},
|
|
30
|
-
screen: {
|
|
31
|
-
fontSize: scaleSize(36),
|
|
32
|
-
lineHeight: scaleSize(44),
|
|
33
|
-
},
|
|
34
30
|
actionIcon: {
|
|
35
31
|
borderRadius: Radius.M,
|
|
36
32
|
alignItems: 'center',
|
|
@@ -41,12 +37,43 @@ export default StyleSheet.create({
|
|
|
41
37
|
borderRadius: Radius.XS,
|
|
42
38
|
},
|
|
43
39
|
wrapper: {
|
|
44
|
-
width: '100%',
|
|
45
40
|
flexDirection: 'row',
|
|
46
|
-
alignItems: 'center',
|
|
47
41
|
},
|
|
48
|
-
|
|
42
|
+
margin: {
|
|
43
|
+
marginTop: Spacing.S,
|
|
44
|
+
},
|
|
45
|
+
iconView: {
|
|
49
46
|
marginRight: Spacing.S,
|
|
50
|
-
|
|
47
|
+
},
|
|
48
|
+
iconRight: {
|
|
49
|
+
width: 22,
|
|
50
|
+
height: 22,
|
|
51
|
+
borderRadius: Radius.M,
|
|
52
|
+
alignItems: 'center',
|
|
53
|
+
justifyContent: 'center',
|
|
54
|
+
marginLeft: Spacing.S,
|
|
55
|
+
},
|
|
56
|
+
iconLeft: {
|
|
57
|
+
width: 18,
|
|
58
|
+
height: 18,
|
|
59
|
+
borderRadius: Radius.M,
|
|
60
|
+
alignItems: 'center',
|
|
61
|
+
justifyContent: 'center',
|
|
62
|
+
marginHorizontal: Spacing.XS,
|
|
63
|
+
},
|
|
64
|
+
iconLeftView: {
|
|
65
|
+
flexDirection: 'row',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
},
|
|
68
|
+
contentView: {marginRight: Spacing.S, flex: 1},
|
|
69
|
+
title: {
|
|
70
|
+
fontWeight: 'bold',
|
|
71
|
+
color: Colors.black_17,
|
|
72
|
+
},
|
|
73
|
+
badge: {
|
|
74
|
+
marginLeft: Spacing.XS,
|
|
75
|
+
},
|
|
76
|
+
description: {
|
|
77
|
+
marginTop: Spacing.XS,
|
|
51
78
|
},
|
|
52
79
|
});
|
package/Title/types.ts
CHANGED
|
@@ -1,52 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Optional. Defines the type of Title component.
|
|
4
|
-
* 'screen' - Used for screen titles.
|
|
5
|
-
* 'section' - Used for section titles within a screen.
|
|
6
|
-
* 'card' - Used for titles within a card component.
|
|
7
|
-
*/
|
|
8
|
-
type?: 'screen' | 'section' | 'card';
|
|
1
|
+
import {ViewStyle} from 'react-native';
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
export type TitleProps = {
|
|
4
|
+
type?: 'card' | 'section';
|
|
5
|
+
size?: 'small' | 'medium' | 'large';
|
|
13
6
|
title: string;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Optional. A description or subtitle that appears below the title.
|
|
17
|
-
*/
|
|
18
|
-
description?: string;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Optional. Defines the size of the Title component.
|
|
22
|
-
* 'large' - A larger, more prominent title.
|
|
23
|
-
* 'small' - A smaller, less prominent title.
|
|
24
|
-
*/
|
|
25
|
-
size?: 'large' | 'medium' | 'small';
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Optional. Represents the name or key of the icon to be displayed alongside the title.
|
|
29
|
-
*/
|
|
30
7
|
icon?: string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* Optional. Function to be called when the action associated with the title is pressed.
|
|
44
|
-
*/
|
|
45
|
-
onPressAction?: () => void;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Optional. If `true`, an action button or icon is displayed alongside the title.
|
|
49
|
-
*/
|
|
50
|
-
showAction?: boolean;
|
|
51
|
-
usePadding?: boolean;
|
|
8
|
+
description?: string;
|
|
9
|
+
iconColor?: string;
|
|
10
|
+
iconAlign?: 'top' | 'middle' | 'bottom';
|
|
11
|
+
showRightAction?: boolean;
|
|
12
|
+
showTrailingAction?: boolean;
|
|
13
|
+
badgeLabel?: string;
|
|
14
|
+
buttonTitle?: string;
|
|
15
|
+
buttonSize?: 'small' | 'large';
|
|
16
|
+
onPressRightAction?: () => void;
|
|
17
|
+
onPressTrailingAction?: () => void;
|
|
18
|
+
textOnly?: boolean;
|
|
19
|
+
style?: ViewStyle;
|
|
52
20
|
};
|
package/code-scanner.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const scanner = require('react-scanner');
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
|
|
4
5
|
const scan = async config => {
|
|
@@ -9,43 +10,151 @@ const calcSum = array => {
|
|
|
9
10
|
return array.reduce((a, b) => a + b, 0);
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
const calculateAdoptionRate = (
|
|
13
|
+
const calculateAdoptionRate = async (
|
|
14
|
+
branchName,
|
|
15
|
+
kitJsonPath,
|
|
16
|
+
miniappJsonPath,
|
|
17
|
+
reactNativeJsonPath,
|
|
18
|
+
fsJsonPath
|
|
19
|
+
) => {
|
|
13
20
|
const kitJson = require(kitJsonPath);
|
|
14
21
|
const miniAppJson = require(miniappJsonPath);
|
|
22
|
+
const reactNativeJson = require(reactNativeJsonPath);
|
|
23
|
+
const fsJson = require(fsJsonPath);
|
|
24
|
+
|
|
15
25
|
const numOfKitComponents = calcSum(Object.values(kitJson));
|
|
16
26
|
const numOfMiniAppComponents = calcSum(Object.values(miniAppJson));
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
const numOfReactNativeComponents = calcSum(Object.values(reactNativeJson));
|
|
28
|
+
const numOfFSComponents = calcSum(Object.values(fsJson));
|
|
29
|
+
|
|
30
|
+
const adoptionRate =
|
|
31
|
+
((numOfKitComponents + numOfReactNativeComponents + numOfFSComponents) /
|
|
32
|
+
numOfMiniAppComponents) *
|
|
33
|
+
100;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
miniAppName: branchName,
|
|
37
|
+
numOfKitComponents: numOfKitComponents,
|
|
38
|
+
numOfMiniAppComponents: numOfMiniAppComponents,
|
|
39
|
+
numOfReactNativeComponents: numOfReactNativeComponents,
|
|
40
|
+
numOfFSComponents: numOfFSComponents,
|
|
41
|
+
adoptionRate: adoptionRate.toFixed(2) + '%',
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function ensureFileExists(filePath, defaultContent = {}) {
|
|
46
|
+
if (!fs.existsSync(filePath)) {
|
|
47
|
+
fs.mkdirSync(path.dirname(filePath), {recursive: true});
|
|
48
|
+
fs.writeFileSync(filePath, JSON.stringify(defaultContent, null, 2));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const sendMessage = ({
|
|
53
|
+
numOfKitComponents,
|
|
54
|
+
numOfMiniAppComponents,
|
|
55
|
+
numOfFSComponents,
|
|
56
|
+
numOfReactNativeComponents,
|
|
57
|
+
adoptionRate,
|
|
58
|
+
miniAppName = '',
|
|
59
|
+
}) => {
|
|
60
|
+
const url =
|
|
61
|
+
'https://chat.googleapis.com/v1/spaces/AAAAL9P6G8M/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=fnwfYuH_u0KicBnKTSSm9S0qV6azJH5v6URm8HR7V2g';
|
|
62
|
+
|
|
63
|
+
const data = {
|
|
64
|
+
text: `MiniApp: ${miniAppName}\nNumber of kit's components: ${numOfKitComponents}\nNumber of miniapp's components: ${numOfMiniAppComponents}\nNumber of FS's components: ${numOfFSComponents}\nNumber of React Native's components: ${numOfReactNativeComponents}\nAdoption rate: ${adoptionRate}`,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
fetch(url, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(data),
|
|
73
|
+
})
|
|
74
|
+
.then(response => response.json())
|
|
75
|
+
.then(data => {
|
|
76
|
+
console.log('Success:', data);
|
|
77
|
+
})
|
|
78
|
+
.catch(error => {
|
|
79
|
+
console.error('Error:', error);
|
|
80
|
+
});
|
|
21
81
|
};
|
|
22
82
|
|
|
23
83
|
const main = async () => {
|
|
24
|
-
const
|
|
25
|
-
|
|
84
|
+
const rootPath = `${__dirname}/../../../`;
|
|
85
|
+
const app = path.join(`${__dirname}/../../../`, 'app.json');
|
|
86
|
+
const appJson = require(app);
|
|
87
|
+
const branchName = appJson.appId;
|
|
88
|
+
|
|
89
|
+
if (!branchName || !branchName.includes('vn.momo')) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
26
92
|
|
|
27
|
-
const
|
|
28
|
-
const
|
|
93
|
+
const scanPath = path.join(rootPath, 'src');
|
|
94
|
+
const kitJsonPath = path.join(rootPath, './scan/kit.json');
|
|
95
|
+
const miniappJsonPath = path.join(rootPath, './scan/miniapp.json');
|
|
96
|
+
const reactNativeJsonPath = path.join(rootPath, './scan/RN.json');
|
|
97
|
+
const fsJsonPath = path.join(rootPath, './scan/verLib.json');
|
|
98
|
+
|
|
99
|
+
const allKitsReg = /@momo-kits/;
|
|
100
|
+
const fsReg =
|
|
101
|
+
/^(?:@fs-mobile-platform\/(components(\/.*)?|investment(\/.*)?|screens(\/.*)?|foundation(\/.*)?)|@miniapp-platform\/(components(\/.*)?|foundation(\/.*)?))$/;
|
|
102
|
+
const RNReg = /react-native|react-native-svg/;
|
|
29
103
|
|
|
30
104
|
const config1 = {
|
|
31
105
|
crawlFrom: scanPath,
|
|
32
106
|
includeSubComponents: true,
|
|
33
|
-
importedFrom:
|
|
107
|
+
importedFrom: allKitsReg,
|
|
34
108
|
processors: [['count-components', {outputTo: kitJsonPath}]],
|
|
35
|
-
rootDir:
|
|
109
|
+
rootDir: process.cwd(),
|
|
36
110
|
};
|
|
37
111
|
|
|
38
112
|
const config2 = {
|
|
39
113
|
crawlFrom: scanPath,
|
|
40
114
|
includeSubComponents: true,
|
|
41
115
|
processors: [['count-components', {outputTo: miniappJsonPath}]],
|
|
42
|
-
rootDir:
|
|
116
|
+
rootDir: process.cwd(),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const config3 = {
|
|
120
|
+
crawlFrom: scanPath,
|
|
121
|
+
includeSubComponents: true,
|
|
122
|
+
importedFrom: RNReg,
|
|
123
|
+
processors: [['count-components', {outputTo: reactNativeJsonPath}]],
|
|
124
|
+
rootDir: process.cwd(),
|
|
43
125
|
};
|
|
44
126
|
|
|
45
|
-
|
|
46
|
-
|
|
127
|
+
const config4 = {
|
|
128
|
+
crawlFrom: scanPath,
|
|
129
|
+
includeSubComponents: true,
|
|
130
|
+
importedFrom: fsReg,
|
|
131
|
+
processors: [['count-components', {outputTo: fsJsonPath}]],
|
|
132
|
+
rootDir: process.cwd(),
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
ensureFileExists(kitJsonPath, {});
|
|
137
|
+
ensureFileExists(miniappJsonPath, {});
|
|
138
|
+
ensureFileExists(reactNativeJsonPath, {});
|
|
139
|
+
ensureFileExists(fsJsonPath, {});
|
|
140
|
+
|
|
141
|
+
await scan(config1);
|
|
142
|
+
await scan(config2);
|
|
143
|
+
await scan(config3);
|
|
144
|
+
await scan(config4);
|
|
47
145
|
|
|
48
|
-
|
|
146
|
+
const result = await calculateAdoptionRate(
|
|
147
|
+
branchName,
|
|
148
|
+
kitJsonPath,
|
|
149
|
+
miniappJsonPath,
|
|
150
|
+
reactNativeJsonPath,
|
|
151
|
+
fsJsonPath
|
|
152
|
+
);
|
|
153
|
+
sendMessage(result);
|
|
154
|
+
console.log(result);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('Error during scan or calculation:', error);
|
|
157
|
+
}
|
|
49
158
|
};
|
|
50
159
|
|
|
51
|
-
main()
|
|
160
|
+
main();
|
package/index.ts
CHANGED
|
@@ -49,3 +49,10 @@ export * from './Title';
|
|
|
49
49
|
export * from './Title/types';
|
|
50
50
|
export * from './Badge';
|
|
51
51
|
export * from './Badge/types';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* export trick for keep old mini app working
|
|
55
|
+
* @deprecated
|
|
56
|
+
*/
|
|
57
|
+
export * from 'react-native-modalize';
|
|
58
|
+
export * from '@gorhom/bottom-sheet';
|
package/migrate_typo.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const {readFileSync, writeFileSync, readdirSync, statSync} = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
let rootPath = process.argv[2];
|
|
4
|
+
|
|
5
|
+
const migrateText = [
|
|
6
|
+
{typo1: 'headline_s', typo2: 'headline_default_bold'},
|
|
7
|
+
{typo1: 'header_s', typo2: 'header_s_semibold'},
|
|
8
|
+
{typo1: 'header_xs', typo2: 'header_xs_semibold'},
|
|
9
|
+
{typo1: 'description_default', typo2: 'body_default_regular'},
|
|
10
|
+
{typo1: 'description_s', typo2: 'description_default_regular'},
|
|
11
|
+
{typo1: 'description_xs', typo2: 'description_xs_regular'},
|
|
12
|
+
{typo1: 'label_default', typo2: 'label_default_medium'},
|
|
13
|
+
{typo1: 'label_s', typo2: 'label_s_medium'},
|
|
14
|
+
{typo1: 'label_xs', typo2: 'label_xs_medium'},
|
|
15
|
+
{typo1: 'action_default', typo2: 'action_default_bold'},
|
|
16
|
+
{typo1: 'action_xs', typo2: 'action_xs_bold'},
|
|
17
|
+
{typo1: 'action_xxs', typo2: 'action_xxs_bold'},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function replaceTextInFile(oldText, newText, filePath) {
|
|
21
|
+
try {
|
|
22
|
+
let content = readFileSync(filePath, {encoding: 'utf-8'});
|
|
23
|
+
const regex = new RegExp(`\\b${oldText}\\b`, 'g');
|
|
24
|
+
content = content.replace(regex, newText);
|
|
25
|
+
writeFileSync(filePath, content, 'utf8');
|
|
26
|
+
console.log(`Replaced text in: ${filePath}`);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(`Error processing file ${filePath}:`, error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function scanDirectory(directory, oldText, newText) {
|
|
33
|
+
const files = readdirSync(directory);
|
|
34
|
+
|
|
35
|
+
files.forEach(file => {
|
|
36
|
+
const filePath = path.join(directory, file);
|
|
37
|
+
const stat = statSync(filePath);
|
|
38
|
+
|
|
39
|
+
if (stat.isDirectory()) {
|
|
40
|
+
scanDirectory(filePath, oldText, newText);
|
|
41
|
+
} else if (
|
|
42
|
+
stat.isFile() &&
|
|
43
|
+
(filePath.endsWith('.tsx') || filePath.endsWith('.ts'))
|
|
44
|
+
) {
|
|
45
|
+
replaceTextInFile(oldText, newText, filePath);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function main() {
|
|
51
|
+
migrateText.forEach(({typo1, typo2}) => {
|
|
52
|
+
scanDirectory(rootPath, typo1, typo2);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main();
|