@momo-kits/foundation 0.109.1 → 0.110.1-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/BottomTab/BottomTabBar.tsx +13 -2
- package/Application/BottomTab/index.tsx +2 -2
- package/Application/Components/BottomSheetHelpCenter.tsx +2 -0
- package/Application/Components/HeaderBackground.tsx +14 -4
- package/Application/Components/HeaderExtendHeader.tsx +13 -4
- package/Application/Components/HeaderRight.tsx +14 -19
- package/Application/Components/HeaderTitle.tsx +6 -3
- package/Application/Components/SearchHeader.tsx +17 -4
- package/Application/Localize.ts +1 -1
- package/Application/Navigation.ts +3 -1
- package/Application/StackScreen.tsx +1 -1
- package/Application/types.ts +3 -2
- package/Input/Input.tsx +19 -10
- package/Input/InputMoney.tsx +10 -7
- package/Input/InputSearch.tsx +7 -1
- package/Input/index.tsx +18 -3
- package/Layout/Screen.tsx +3 -8
- package/Radio/index.tsx +2 -2
- package/Radio/styles.ts +4 -1
- package/Text/index.tsx +100 -36
- package/Title/index.tsx +1 -1
- package/code-scanner.js +1 -1
- package/package.json +1 -1
- package/verify.js +1 -1
- package/tsconfig.json +0 -24
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
View,
|
|
17
17
|
} from 'react-native';
|
|
18
18
|
import {EdgeInsets, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
19
|
-
import {Radius} from '../../Consts';
|
|
19
|
+
import {Colors, Radius} from '../../Consts';
|
|
20
20
|
import {Icon} from '../../Icon';
|
|
21
21
|
import {Text} from '../../Text';
|
|
22
22
|
import {FloatingButtonProps} from '../types';
|
|
@@ -207,7 +207,7 @@ export default function BottomTabBar({
|
|
|
207
207
|
return (
|
|
208
208
|
<Animated.View
|
|
209
209
|
style={[
|
|
210
|
-
styles.tabBar,
|
|
210
|
+
floatingButton ? styles.tabBarFloatingButton : styles.tabBar,
|
|
211
211
|
{
|
|
212
212
|
backgroundColor: theme.colors.background.surface,
|
|
213
213
|
borderTopColor: theme.colors.border.default,
|
|
@@ -253,6 +253,17 @@ const styles = StyleSheet.create({
|
|
|
253
253
|
borderTopWidth: StyleSheet.hairlineWidth,
|
|
254
254
|
elevation: 8,
|
|
255
255
|
},
|
|
256
|
+
tabBarFloatingButton: {
|
|
257
|
+
left: 0,
|
|
258
|
+
right: 0,
|
|
259
|
+
bottom: 0,
|
|
260
|
+
zIndex: 1,
|
|
261
|
+
shadowColor: Colors.black_20,
|
|
262
|
+
shadowOffset: {width: 0, height: -2},
|
|
263
|
+
shadowOpacity: 0.05,
|
|
264
|
+
shadowRadius: 3,
|
|
265
|
+
elevation: 8,
|
|
266
|
+
},
|
|
256
267
|
floatingContainer: {
|
|
257
268
|
position: 'absolute',
|
|
258
269
|
alignItems: 'center',
|
|
@@ -7,7 +7,7 @@ import {EventArg} from '@react-navigation/core';
|
|
|
7
7
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
8
8
|
import {Colors} from '../../Consts';
|
|
9
9
|
import {Icon} from '../../Icon';
|
|
10
|
-
import {Text} from '../../Text';
|
|
10
|
+
import {exportFontFamily, Text} from '../../Text';
|
|
11
11
|
import {ApplicationContext} from '../index';
|
|
12
12
|
import StackScreen from '../StackScreen';
|
|
13
13
|
import {BottomTabProps, NavigationScreenProps} from '../types';
|
|
@@ -146,7 +146,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
|
|
|
146
146
|
lineHeight: Platform.OS === 'android' ? 17 : 14,
|
|
147
147
|
fontWeight: 'bold',
|
|
148
148
|
alignSelf: 'center',
|
|
149
|
-
fontFamily:
|
|
149
|
+
fontFamily: exportFontFamily('bold'),
|
|
150
150
|
left: isDot ? 8 : 4,
|
|
151
151
|
top: isDot ? -2 : -6,
|
|
152
152
|
backgroundColor: isNum ? Colors.red_03 : Colors.orange_03,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import LinearGradient from 'react-native-linear-gradient';
|
|
2
2
|
import {Animated, Platform, StyleSheet, View} from 'react-native';
|
|
3
|
-
import React, {useContext} from 'react';
|
|
3
|
+
import React, {useContext, useEffect, useState} from 'react';
|
|
4
4
|
import {HeaderBackgroundProps} from '../types';
|
|
5
5
|
import {ApplicationContext} from '../index';
|
|
6
6
|
import {Colors, Styles} from '../../Consts';
|
|
@@ -13,13 +13,23 @@ const LinearGradientAnimated = Animated.createAnimatedComponent(LinearGradient);
|
|
|
13
13
|
*/
|
|
14
14
|
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
15
15
|
image,
|
|
16
|
-
animatedValue,
|
|
16
|
+
animatedValue = new Animated.Value(0),
|
|
17
17
|
useGradient = true,
|
|
18
18
|
useShadowHeader = true,
|
|
19
19
|
gradientColor,
|
|
20
20
|
headerBackground,
|
|
21
21
|
}) => {
|
|
22
|
-
const {theme} = useContext(ApplicationContext);
|
|
22
|
+
const {theme, navigator} = useContext(ApplicationContext);
|
|
23
|
+
const [configHeader, setConfigHeader] = useState(null);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
navigator?.maxApi?.getFeatureById('platform_config', (config: any) => {
|
|
27
|
+
const header = config?.navigationBar?.headerBar;
|
|
28
|
+
if (header) {
|
|
29
|
+
setConfigHeader(header);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}, []);
|
|
23
33
|
|
|
24
34
|
const linearGradientColor = gradientColor ?? theme.colors.gradient;
|
|
25
35
|
|
|
@@ -59,7 +69,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
59
69
|
{!!headerImage && (
|
|
60
70
|
<Image
|
|
61
71
|
style={styles.headerBackground}
|
|
62
|
-
source={{uri: headerImage}}
|
|
72
|
+
source={{uri: configHeader || headerImage}}
|
|
63
73
|
loading={false}
|
|
64
74
|
/>
|
|
65
75
|
)}
|
|
@@ -34,7 +34,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
34
34
|
headerType = 'default',
|
|
35
35
|
animatedValue,
|
|
36
36
|
heightHeader,
|
|
37
|
-
headerRightWidth =
|
|
37
|
+
headerRightWidth = 73,
|
|
38
38
|
inputSearchProps,
|
|
39
39
|
inputSearchRef,
|
|
40
40
|
useShadowHeader = true,
|
|
@@ -46,6 +46,7 @@ const HeaderExtendHeader: React.FC<{
|
|
|
46
46
|
const gradientColor = customGradientColor ?? theme.colors.gradient;
|
|
47
47
|
const headerBackground = customBackground ?? theme.assets?.headerBackground;
|
|
48
48
|
const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20;
|
|
49
|
+
const isIos = Platform.OS === 'ios';
|
|
49
50
|
|
|
50
51
|
const opacityBackground = animatedValue?.interpolate({
|
|
51
52
|
inputRange: [0, 52],
|
|
@@ -94,7 +95,9 @@ const HeaderExtendHeader: React.FC<{
|
|
|
94
95
|
<Animated.View style={{height: height}} />
|
|
95
96
|
<Animated.View
|
|
96
97
|
style={[
|
|
97
|
-
|
|
98
|
+
isIos && useShadowHeader
|
|
99
|
+
? styles.shadowHeader
|
|
100
|
+
: styles.dividerHeader,
|
|
98
101
|
{
|
|
99
102
|
backgroundColor: theme.colors.background.surface,
|
|
100
103
|
opacity: opacityBackground,
|
|
@@ -244,8 +247,14 @@ const styles = StyleSheet.create({
|
|
|
244
247
|
shadowRadius: 10,
|
|
245
248
|
},
|
|
246
249
|
android: {
|
|
247
|
-
|
|
248
|
-
|
|
250
|
+
shadowColor: Colors.black_17,
|
|
251
|
+
shadowOffset: {
|
|
252
|
+
width: 3,
|
|
253
|
+
height: 3,
|
|
254
|
+
},
|
|
255
|
+
shadowOpacity: 0.12,
|
|
256
|
+
shadowRadius: 10,
|
|
257
|
+
elevation: 10,
|
|
249
258
|
},
|
|
250
259
|
}),
|
|
251
260
|
},
|
|
@@ -15,25 +15,15 @@ import {scaleSize, Text} from '../../Text';
|
|
|
15
15
|
import {BottomSheetHelpCenter} from './BottomSheetHelpCenter';
|
|
16
16
|
import {Image} from '../../Image';
|
|
17
17
|
|
|
18
|
-
const WHITE_LIST = [
|
|
19
|
-
'vn.momo.appx',
|
|
20
|
-
'vn.momo.transactionhistory',
|
|
21
|
-
'vn.momo.promotionhub',
|
|
22
|
-
];
|
|
23
|
-
|
|
24
18
|
/**
|
|
25
19
|
* main component for header right
|
|
26
20
|
*/
|
|
27
21
|
const HeaderRight: React.FC<any> = props => {
|
|
28
22
|
const {headerRight = {}} = props;
|
|
29
23
|
const {useOnBoarding = false, buttonOnBoarding, onPress} = headerRight;
|
|
30
|
-
const context = useContext<any>(MiniAppContext);
|
|
31
24
|
const {translate} = useContext(ApplicationContext);
|
|
32
25
|
|
|
33
|
-
if (
|
|
34
|
-
WHITE_LIST.includes(context?.appId) &&
|
|
35
|
-
typeof props.headerRight === 'function'
|
|
36
|
-
) {
|
|
26
|
+
if (typeof props.headerRight === 'function') {
|
|
37
27
|
return props.headerRight(props);
|
|
38
28
|
}
|
|
39
29
|
|
|
@@ -61,7 +51,7 @@ const HeaderRight: React.FC<any> = props => {
|
|
|
61
51
|
const HeaderToolkitAction: React.FC<any> = ({
|
|
62
52
|
tintColor,
|
|
63
53
|
preventClose,
|
|
64
|
-
useShortcut =
|
|
54
|
+
useShortcut = false,
|
|
65
55
|
useMore = false,
|
|
66
56
|
tools = [],
|
|
67
57
|
}) => {
|
|
@@ -75,7 +65,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
75
65
|
if (useShortcut) {
|
|
76
66
|
checkAppIsFavorite();
|
|
77
67
|
}
|
|
78
|
-
}, []);
|
|
68
|
+
}, [useShortcut, useMore, tools]);
|
|
79
69
|
|
|
80
70
|
let buttonStyle: ViewStyle = {};
|
|
81
71
|
if (tintColor === Colors.black_01) {
|
|
@@ -157,6 +147,9 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
157
147
|
const onPressHelpCenter = () => {
|
|
158
148
|
const appName = translate?.(context?.name);
|
|
159
149
|
const appDescription = translate?.(context?.description);
|
|
150
|
+
const isShowDescription =
|
|
151
|
+
context?.description && Object.keys(context?.description).length > 0;
|
|
152
|
+
|
|
160
153
|
navigator?.showBottomSheet({
|
|
161
154
|
options: {
|
|
162
155
|
header: (
|
|
@@ -167,11 +160,13 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
167
160
|
/>
|
|
168
161
|
<View>
|
|
169
162
|
<Text typography={'label_default_medium'}>{appName}</Text>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
163
|
+
{isShowDescription && (
|
|
164
|
+
<Text
|
|
165
|
+
typography={'description_default_regular'}
|
|
166
|
+
color={Colors.black_12}>
|
|
167
|
+
{appDescription}
|
|
168
|
+
</Text>
|
|
169
|
+
)}
|
|
175
170
|
</View>
|
|
176
171
|
</View>
|
|
177
172
|
),
|
|
@@ -207,7 +202,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
207
202
|
const showIconMore = tools && totalTools > 1;
|
|
208
203
|
const isHaveOneTool = tools && totalTools === 1;
|
|
209
204
|
|
|
210
|
-
if (showIconMore ||
|
|
205
|
+
if (showIconMore || useMore) {
|
|
211
206
|
iconShortcut = 'navigation_more_icon';
|
|
212
207
|
shortcutOnPress = onPressIconMore;
|
|
213
208
|
} else if (isHaveOneTool) {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
View,
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
import {ApplicationContext, MiniAppContext} from '../index';
|
|
10
|
-
import {scaleSize, Text} from '../../Text';
|
|
10
|
+
import {exportFontFamily, scaleSize, Text} from '../../Text';
|
|
11
11
|
import {Colors, Spacing, Styles} from '../../Consts';
|
|
12
12
|
import {TitleJourneyProps, TitleLocationProps, TitleUserProps} from '../types';
|
|
13
13
|
import {Image} from '../../Image';
|
|
@@ -17,7 +17,6 @@ import {Icon} from '../../Icon';
|
|
|
17
17
|
* default header title used for nav
|
|
18
18
|
*/
|
|
19
19
|
const HeaderTitle: React.FC<any> = props => {
|
|
20
|
-
const {theme} = useContext(ApplicationContext);
|
|
21
20
|
const opacity = props.animatedValue?.interpolate(
|
|
22
21
|
props.interpolate ?? {
|
|
23
22
|
inputRange: [0, 200],
|
|
@@ -33,7 +32,11 @@ const HeaderTitle: React.FC<any> = props => {
|
|
|
33
32
|
accessibilityLabel={'title_navigation_header'}
|
|
34
33
|
style={[
|
|
35
34
|
styles.title,
|
|
36
|
-
{
|
|
35
|
+
{
|
|
36
|
+
fontFamily: exportFontFamily('bold', 'action_xs_bold'),
|
|
37
|
+
opacity,
|
|
38
|
+
color: props.tintColor,
|
|
39
|
+
},
|
|
37
40
|
]}
|
|
38
41
|
numberOfLines={1}
|
|
39
42
|
/>
|
|
@@ -7,7 +7,16 @@ import {ApplicationContext, MiniAppContext} from '../index';
|
|
|
7
7
|
import {Text} from '../../Text';
|
|
8
8
|
|
|
9
9
|
const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
10
|
-
(
|
|
10
|
+
(
|
|
11
|
+
{
|
|
12
|
+
animatedValue,
|
|
13
|
+
buttonText = 'Huỷ',
|
|
14
|
+
onPressButtonText,
|
|
15
|
+
renderButtons,
|
|
16
|
+
...props
|
|
17
|
+
},
|
|
18
|
+
ref
|
|
19
|
+
) => {
|
|
11
20
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
12
21
|
const context = useContext<any>(MiniAppContext);
|
|
13
22
|
|
|
@@ -75,9 +84,13 @@ const SearchHeader = React.forwardRef<InputRef, SearchHeaderProps>(
|
|
|
75
84
|
/>
|
|
76
85
|
</Animated.View>
|
|
77
86
|
</View>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
{renderButtons && typeof renderButtons === 'function' ? (
|
|
88
|
+
renderButtons()
|
|
89
|
+
) : (
|
|
90
|
+
<TouchableOpacity onPress={goBackSafe} style={styles.searchAction}>
|
|
91
|
+
<Text typography={'action_default_bold'}>{buttonText}</Text>
|
|
92
|
+
</TouchableOpacity>
|
|
93
|
+
)}
|
|
81
94
|
</View>
|
|
82
95
|
);
|
|
83
96
|
}
|
package/Application/Localize.ts
CHANGED
|
@@ -30,7 +30,7 @@ class Localize {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
translateData(data: {vi: string; en: string}) {
|
|
33
|
-
return data[this.currentLanguage]
|
|
33
|
+
return data[this.currentLanguage] ?? JSON.stringify(data);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
addTranslations(translations: LocalizationObject) {
|
|
@@ -3,10 +3,12 @@ import {NavigationOptions} from './types';
|
|
|
3
3
|
import {getOptions} from './utils';
|
|
4
4
|
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
5
5
|
|
|
6
|
-
const WHITE_LIST = [
|
|
6
|
+
export const WHITE_LIST = [
|
|
7
7
|
'vn.momo.appx',
|
|
8
8
|
'vn.momo.transactionhistory',
|
|
9
9
|
'vn.momo.promotionhub',
|
|
10
|
+
'vn.momo.payment',
|
|
11
|
+
'vn.momo.ekyc',
|
|
10
12
|
];
|
|
11
13
|
|
|
12
14
|
class Navigation {
|
|
@@ -138,7 +138,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
138
138
|
type: 'ERROR',
|
|
139
139
|
});
|
|
140
140
|
if (
|
|
141
|
-
|
|
141
|
+
context.debugLastElement &&
|
|
142
142
|
lastElement.current?.children?.current?.length > 0
|
|
143
143
|
) {
|
|
144
144
|
Alert.alert(
|
package/Application/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {EventArg} from '@react-navigation/core';
|
|
2
2
|
import {StackNavigationOptions} from '@react-navigation/stack';
|
|
3
|
-
import React from 'react';
|
|
3
|
+
import React, {ReactNode} from 'react';
|
|
4
4
|
import {Animated, ViewProps} from 'react-native';
|
|
5
5
|
import {PopupNotifyProps} from '../Popup/types';
|
|
6
6
|
import Localize from './Localize';
|
|
@@ -99,7 +99,7 @@ export type Tool = {
|
|
|
99
99
|
export type NavigationContainerProps = {
|
|
100
100
|
screen: Screen;
|
|
101
101
|
options?: NavigationOptions;
|
|
102
|
-
theme
|
|
102
|
+
theme?: Theme;
|
|
103
103
|
maxApi: any;
|
|
104
104
|
initialParams?: any;
|
|
105
105
|
localize: Localize;
|
|
@@ -271,4 +271,5 @@ export interface SearchHeaderProps extends InputSearchProps {
|
|
|
271
271
|
animatedValue?: Animated.Value;
|
|
272
272
|
headerRightWidth?: 0 | 74 | 110 | number;
|
|
273
273
|
leftPosition?: 12 | 48 | number;
|
|
274
|
+
renderButtons?: () => ReactNode;
|
|
274
275
|
}
|
package/Input/Input.tsx
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
18
18
|
import {Icon} from '../Icon';
|
|
19
19
|
import {Loader} from '../Loader';
|
|
20
|
-
import {Text} from '../Text';
|
|
20
|
+
import {exportFontFamily, Text} from '../Text';
|
|
21
21
|
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
22
22
|
import {InputProps} from './index';
|
|
23
23
|
import styles from './styles';
|
|
@@ -51,7 +51,7 @@ const Input = forwardRef(
|
|
|
51
51
|
loading = false,
|
|
52
52
|
leadingIcon,
|
|
53
53
|
leadingIconColor,
|
|
54
|
-
fontWeight
|
|
54
|
+
fontWeight,
|
|
55
55
|
secureTextEntry,
|
|
56
56
|
keyboardType,
|
|
57
57
|
style,
|
|
@@ -60,6 +60,8 @@ const Input = forwardRef(
|
|
|
60
60
|
accessibilityLabel,
|
|
61
61
|
editable = true,
|
|
62
62
|
onPressFloatingIcon,
|
|
63
|
+
onPressLeadingIcon,
|
|
64
|
+
showClearIcon = true,
|
|
63
65
|
...props
|
|
64
66
|
}: InputProps,
|
|
65
67
|
ref
|
|
@@ -91,12 +93,17 @@ const Input = forwardRef(
|
|
|
91
93
|
onBlur?.(e);
|
|
92
94
|
};
|
|
93
95
|
|
|
96
|
+
const _setText = (text: string) => {
|
|
97
|
+
inputRef?.current?.setNativeProps({text});
|
|
98
|
+
_onChangeText(text);
|
|
99
|
+
};
|
|
100
|
+
|
|
94
101
|
useImperativeHandle(ref, () => {
|
|
95
102
|
return {
|
|
96
103
|
clear: onClearText,
|
|
97
104
|
focus: () => inputRef.current?.focus(),
|
|
98
105
|
blur: () => inputRef.current?.blur(),
|
|
99
|
-
setText:
|
|
106
|
+
setText: _setText,
|
|
100
107
|
};
|
|
101
108
|
});
|
|
102
109
|
|
|
@@ -196,11 +203,13 @@ const Input = forwardRef(
|
|
|
196
203
|
<View style={styles.inputView}>
|
|
197
204
|
{!!leadingIcon && (
|
|
198
205
|
<View style={styles.leadingIconContainer}>
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
<TouchableOpacity onPress={onPressLeadingIcon}>
|
|
207
|
+
<Icon
|
|
208
|
+
color={leadingIconColor}
|
|
209
|
+
source={leadingIcon}
|
|
210
|
+
size={size === 'small' ? 24 : 32}
|
|
211
|
+
/>
|
|
212
|
+
</TouchableOpacity>
|
|
204
213
|
</View>
|
|
205
214
|
)}
|
|
206
215
|
<TextInput
|
|
@@ -214,7 +223,7 @@ const Input = forwardRef(
|
|
|
214
223
|
styles.input,
|
|
215
224
|
{
|
|
216
225
|
color: textColor,
|
|
217
|
-
fontFamily:
|
|
226
|
+
fontFamily: exportFontFamily(fontWeight ?? 'regular'),
|
|
218
227
|
},
|
|
219
228
|
secure && haveValue && {fontSize: size === 'small' ? 18 : 22},
|
|
220
229
|
]}
|
|
@@ -230,7 +239,7 @@ const Input = forwardRef(
|
|
|
230
239
|
/>
|
|
231
240
|
</View>
|
|
232
241
|
<View style={styles.iconView}>
|
|
233
|
-
{focused && haveValue && (
|
|
242
|
+
{showClearIcon && focused && haveValue && (
|
|
234
243
|
<TouchableOpacity
|
|
235
244
|
style={styles.iconWrapper}
|
|
236
245
|
onPress={onClearText}>
|
package/Input/InputMoney.tsx
CHANGED
|
@@ -54,6 +54,9 @@ const InputMoney = forwardRef(
|
|
|
54
54
|
hintText,
|
|
55
55
|
value: _value,
|
|
56
56
|
onPressFloatingIcon,
|
|
57
|
+
placeholder = '0đ',
|
|
58
|
+
currency = 'đ',
|
|
59
|
+
showClearIcon = true,
|
|
57
60
|
...props
|
|
58
61
|
}: InputMoneyProps,
|
|
59
62
|
ref
|
|
@@ -67,13 +70,13 @@ const InputMoney = forwardRef(
|
|
|
67
70
|
useEffect(() => {
|
|
68
71
|
if (_value) {
|
|
69
72
|
setValue(validateText(_value));
|
|
70
|
-
onChangeText?.(formatMoneyToNumber(_value,
|
|
73
|
+
onChangeText?.(formatMoneyToNumber(_value, currency).toString());
|
|
71
74
|
}
|
|
72
75
|
}, [_value]);
|
|
73
76
|
|
|
74
77
|
const validateText = (text: string) => {
|
|
75
|
-
const valueFormat = formatMoneyToNumber(text,
|
|
76
|
-
return formatNumberToMoney(valueFormat,
|
|
78
|
+
const valueFormat = formatMoneyToNumber(text, currency);
|
|
79
|
+
return formatNumberToMoney(valueFormat, currency);
|
|
77
80
|
};
|
|
78
81
|
|
|
79
82
|
const [value, setValue] = useState(
|
|
@@ -88,10 +91,10 @@ const InputMoney = forwardRef(
|
|
|
88
91
|
|
|
89
92
|
const _onChangeText = (text: string) => {
|
|
90
93
|
if (text.length < value.length && value.indexOf(text) === 0) {
|
|
91
|
-
text = value.slice(0, -2) +
|
|
94
|
+
text = value.slice(0, -2) + currency;
|
|
92
95
|
}
|
|
93
96
|
setValue(validateText(text));
|
|
94
|
-
onChangeText?.(formatMoneyToNumber(text,
|
|
97
|
+
onChangeText?.(formatMoneyToNumber(text, currency).toString());
|
|
95
98
|
};
|
|
96
99
|
|
|
97
100
|
useImperativeHandle(ref, () => {
|
|
@@ -160,11 +163,11 @@ const InputMoney = forwardRef(
|
|
|
160
163
|
onBlur={_onBlur}
|
|
161
164
|
selectionColor={theme.colors.primary}
|
|
162
165
|
placeholderTextColor={placeholderColor}
|
|
163
|
-
placeholder={
|
|
166
|
+
placeholder={placeholder}
|
|
164
167
|
/>
|
|
165
168
|
</View>
|
|
166
169
|
<View style={styles.iconView}>
|
|
167
|
-
{focused && (
|
|
170
|
+
{showClearIcon && focused && (
|
|
168
171
|
<TouchableOpacity
|
|
169
172
|
style={styles.iconWrapper}
|
|
170
173
|
onPress={onClearText}>
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -165,12 +165,17 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
|
|
|
165
165
|
onChangeText?.(text);
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
const _setText = (text: string) => {
|
|
169
|
+
inputRef?.current?.setNativeProps({text});
|
|
170
|
+
_onChangeText(text);
|
|
171
|
+
};
|
|
172
|
+
|
|
168
173
|
useImperativeHandle(ref, () => {
|
|
169
174
|
return {
|
|
170
175
|
clear: onClearText,
|
|
171
176
|
focus: () => inputRef.current?.focus(),
|
|
172
177
|
blur: () => inputRef.current?.blur(),
|
|
173
|
-
setText:
|
|
178
|
+
setText: _setText,
|
|
174
179
|
};
|
|
175
180
|
});
|
|
176
181
|
|
|
@@ -208,6 +213,7 @@ const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
|
|
|
208
213
|
]}
|
|
209
214
|
value={value}
|
|
210
215
|
onChangeText={_onChangeText}
|
|
216
|
+
defaultValue={defaultValue}
|
|
211
217
|
onFocus={_onFocus}
|
|
212
218
|
onBlur={_onBlur}
|
|
213
219
|
placeholder={placeholder}
|
package/Input/index.tsx
CHANGED
|
@@ -97,6 +97,11 @@ export interface InputProps extends TextInputProps {
|
|
|
97
97
|
*/
|
|
98
98
|
leadingIcon?: string;
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Optional. callback function to be called when the leading icon is pressed.
|
|
102
|
+
*/
|
|
103
|
+
onPressLeadingIcon?: () => void;
|
|
104
|
+
|
|
100
105
|
/**
|
|
101
106
|
* Optional. Represents the color of the leading icon in the Input component.
|
|
102
107
|
*/
|
|
@@ -105,7 +110,7 @@ export interface InputProps extends TextInputProps {
|
|
|
105
110
|
/**
|
|
106
111
|
* Optional. Represents the font weight of the text in the Input component.
|
|
107
112
|
*/
|
|
108
|
-
fontWeight?:
|
|
113
|
+
fontWeight?: string;
|
|
109
114
|
|
|
110
115
|
/**
|
|
111
116
|
* Optional. params for element tracking.
|
|
@@ -117,7 +122,15 @@ export interface InputProps extends TextInputProps {
|
|
|
117
122
|
*/
|
|
118
123
|
hintText?: string;
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Optional. Represents the style of the Input component.
|
|
127
|
+
*/
|
|
128
|
+
onPressFloatingIcon?: () => void;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Optional. Represents the style of the Input component.
|
|
132
|
+
*/
|
|
133
|
+
showClearIcon?: boolean;
|
|
121
134
|
}
|
|
122
135
|
|
|
123
136
|
export interface InputTextAreaProps extends Omit<InputProps, 'size'> {
|
|
@@ -200,7 +213,9 @@ export interface InputSearchProps extends TextInputProps {
|
|
|
200
213
|
onPress?: (e: GestureResponderEvent) => void;
|
|
201
214
|
}
|
|
202
215
|
|
|
203
|
-
export interface InputMoneyProps extends
|
|
216
|
+
export interface InputMoneyProps extends InputProps {
|
|
217
|
+
currency?: string;
|
|
218
|
+
}
|
|
204
219
|
|
|
205
220
|
export interface InputOTPProps
|
|
206
221
|
extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
|
package/Layout/Screen.tsx
CHANGED
|
@@ -162,7 +162,7 @@ const Screen = forwardRef(
|
|
|
162
162
|
headerComponent: Header,
|
|
163
163
|
footerComponent: Footer,
|
|
164
164
|
layoutOffset = -56,
|
|
165
|
-
headerRightWidth =
|
|
165
|
+
headerRightWidth = 73,
|
|
166
166
|
backgroundColor,
|
|
167
167
|
headerType = 'default',
|
|
168
168
|
floatingButtonProps,
|
|
@@ -344,13 +344,8 @@ const Screen = forwardRef(
|
|
|
344
344
|
const setSearchHeader = (params: SearchHeaderProps) => {
|
|
345
345
|
const options: StackNavigationOptions = {
|
|
346
346
|
headerRight: undefined,
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
<SearchHeader
|
|
350
|
-
{...props}
|
|
351
|
-
{...params}
|
|
352
|
-
animatedValue={animatedValue.current}
|
|
353
|
-
/>
|
|
347
|
+
headerTitle: () => (
|
|
348
|
+
<SearchHeader {...params} animatedValue={animatedValue.current} />
|
|
354
349
|
),
|
|
355
350
|
};
|
|
356
351
|
|
package/Radio/index.tsx
CHANGED
|
@@ -64,10 +64,10 @@ const Radio: FC<RadioProps> = ({
|
|
|
64
64
|
styles.radio,
|
|
65
65
|
checkBoxStyle,
|
|
66
66
|
disabledStyle,
|
|
67
|
-
{marginRight: label ? Spacing.
|
|
67
|
+
{marginRight: label ? Spacing.S : 0},
|
|
68
68
|
]}
|
|
69
69
|
/>
|
|
70
|
-
{!!label && <Text typography={'body_default_regular'}>{label}</Text>}
|
|
70
|
+
{!!label && <Text typography={'body_default_regular'} style={styles.radioText}>{label}</Text>}
|
|
71
71
|
</TouchableOpacity>
|
|
72
72
|
</ComponentContext.Provider>
|
|
73
73
|
);
|
package/Radio/styles.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {StyleSheet} from 'react-native';
|
|
2
|
-
import {Radius} from '../Consts';
|
|
2
|
+
import {Radius, Spacing} from '../Consts';
|
|
3
3
|
|
|
4
4
|
export default StyleSheet.create({
|
|
5
5
|
radio: {
|
|
@@ -8,4 +8,7 @@ export default StyleSheet.create({
|
|
|
8
8
|
borderRadius: Radius.M,
|
|
9
9
|
},
|
|
10
10
|
container: {flex: 1},
|
|
11
|
+
radioText: {
|
|
12
|
+
marginRight: Spacing.M,
|
|
13
|
+
}
|
|
11
14
|
});
|
package/Text/index.tsx
CHANGED
|
@@ -33,6 +33,20 @@ const AlegreyaSans: TypographyWeight = {
|
|
|
33
33
|
bold: 'Bold',
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
const MomoTrustSans: TypographyWeight = {
|
|
37
|
+
100: 'Light',
|
|
38
|
+
200: 'Light',
|
|
39
|
+
300: 'Light',
|
|
40
|
+
400: 'Regular',
|
|
41
|
+
500: 'Medium',
|
|
42
|
+
600: 'Medium',
|
|
43
|
+
700: 'Medium',
|
|
44
|
+
800: 'Medium',
|
|
45
|
+
900: 'Medium',
|
|
46
|
+
normal: 'Regular',
|
|
47
|
+
bold: 'Medium',
|
|
48
|
+
};
|
|
49
|
+
|
|
36
50
|
const FontStyle: {[key: string]: string} = {
|
|
37
51
|
italic: 'Italic',
|
|
38
52
|
normal: '',
|
|
@@ -50,6 +64,12 @@ export interface TextProps extends RNTextProps {
|
|
|
50
64
|
* It can be any valid color string (e.g., hex, rgb, rgba, etc.).
|
|
51
65
|
*/
|
|
52
66
|
color?: string;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Optional. Represents the font-family of the text in the Text component.
|
|
70
|
+
* Ex: MomoSignature, MomoTrustDisplay
|
|
71
|
+
*/
|
|
72
|
+
fontFamily?: string;
|
|
53
73
|
}
|
|
54
74
|
|
|
55
75
|
const deprecatedValues: Typography[] = [
|
|
@@ -67,49 +87,61 @@ const deprecatedValues: Typography[] = [
|
|
|
67
87
|
'action_s',
|
|
68
88
|
];
|
|
69
89
|
|
|
90
|
+
const getTypoStyle = (typo: Typography, newFontFamily?: string) => {
|
|
91
|
+
const {theme} = useContext(ApplicationContext);
|
|
92
|
+
const styleSheet: {
|
|
93
|
+
[key: string]: any;
|
|
94
|
+
} = styles;
|
|
95
|
+
const typoStyle = styleSheet[typo] ?? styleSheet.paragraph_default;
|
|
96
|
+
const {fontWeight, fontSize, fontStyle, lineHeight} = typoStyle;
|
|
97
|
+
const style = FontStyle[fontStyle ?? 'normal'];
|
|
98
|
+
const font = newFontFamily ?? theme.font;
|
|
99
|
+
let fontFamily: string;
|
|
100
|
+
|
|
101
|
+
switch (font) {
|
|
102
|
+
case 'SFProText': {
|
|
103
|
+
fontFamily = `${font}-${SFProText[fontWeight]}${style}`;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case 'AlegreyaSans': {
|
|
107
|
+
fontFamily = `${font}-${AlegreyaSans[fontWeight]}${style}`;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case 'MomoTrustSans': {
|
|
111
|
+
fontFamily = `${font}-${MomoTrustSans[fontWeight]}${style}`;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case 'MomoTrustDisplay':
|
|
115
|
+
case 'MomoSignature': {
|
|
116
|
+
fontFamily = font;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
default: {
|
|
120
|
+
fontFamily = `SFProText-${SFProText[fontWeight]}${style}`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
...typoStyle,
|
|
126
|
+
fontFamily,
|
|
127
|
+
fontSize: scaleSize(fontSize),
|
|
128
|
+
lineHeight: scaleSize(lineHeight),
|
|
129
|
+
fontStyle,
|
|
130
|
+
fontWeight,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
70
134
|
const Text: React.FC<TextProps> = ({
|
|
71
135
|
typography = 'body_default_regular',
|
|
72
136
|
color,
|
|
73
137
|
children,
|
|
74
138
|
style,
|
|
139
|
+
fontFamily,
|
|
75
140
|
...rest
|
|
76
141
|
}) => {
|
|
77
142
|
const {theme} = useContext(ApplicationContext);
|
|
78
143
|
|
|
79
|
-
const
|
|
80
|
-
const styleSheet: {
|
|
81
|
-
[key: string]: any;
|
|
82
|
-
} = styles;
|
|
83
|
-
const typoStyle = styleSheet[typo] ?? styleSheet.paragraph_default;
|
|
84
|
-
const {fontWeight, fontSize, fontStyle, lineHeight} = typoStyle;
|
|
85
|
-
const style = FontStyle[fontStyle ?? 'normal'];
|
|
86
|
-
let fontFamily: string;
|
|
87
|
-
|
|
88
|
-
switch (theme.font) {
|
|
89
|
-
case 'SFProText': {
|
|
90
|
-
fontFamily = `${theme.font}-${SFProText[fontWeight]}${style}`;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
case 'AlegreyaSans': {
|
|
94
|
-
fontFamily = `${theme.font}-${AlegreyaSans[fontWeight]}${style}`;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
default: {
|
|
98
|
-
fontFamily = `SFProText-${SFProText[fontWeight]}${style}`;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
...typoStyle,
|
|
104
|
-
fontFamily,
|
|
105
|
-
fontSize: scaleSize(fontSize),
|
|
106
|
-
lineHeight: scaleSize(lineHeight),
|
|
107
|
-
fontStyle,
|
|
108
|
-
fontWeight,
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const textStyle = getTypoStyle(typography);
|
|
144
|
+
const textStyle = getTypoStyle(typography, fontFamily);
|
|
113
145
|
|
|
114
146
|
if (deprecatedValues.includes(typography)) {
|
|
115
147
|
console.warn(
|
|
@@ -121,10 +153,42 @@ const Text: React.FC<TextProps> = ({
|
|
|
121
153
|
<RNText
|
|
122
154
|
{...rest}
|
|
123
155
|
{...getAccessibilityID(rest.accessibilityLabel)}
|
|
124
|
-
style={[
|
|
156
|
+
style={[
|
|
157
|
+
style,
|
|
158
|
+
textStyle,
|
|
159
|
+
{
|
|
160
|
+
color: color ?? theme.colors.text.default,
|
|
161
|
+
},
|
|
162
|
+
]}>
|
|
125
163
|
{children ?? ''}
|
|
126
164
|
</RNText>
|
|
127
165
|
);
|
|
128
166
|
};
|
|
129
167
|
|
|
130
|
-
|
|
168
|
+
const exportFontFamily = (
|
|
169
|
+
fontWeight: string,
|
|
170
|
+
typography?: Typography,
|
|
171
|
+
fontFamily?: string
|
|
172
|
+
): string => {
|
|
173
|
+
let newFontFamily;
|
|
174
|
+
|
|
175
|
+
switch (fontWeight) {
|
|
176
|
+
case 'bold': {
|
|
177
|
+
typography = 'action_xs_bold';
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case 'regular': {
|
|
181
|
+
typography = 'body_default_regular';
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
default: {
|
|
185
|
+
typography = 'body_default_regular';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
newFontFamily = getTypoStyle(typography, fontFamily).fontFamily;
|
|
190
|
+
|
|
191
|
+
return newFontFamily;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export {Text, scaleSize, exportFontFamily, getTypoStyle};
|
package/Title/index.tsx
CHANGED
|
@@ -38,7 +38,7 @@ const Title: FC<TitleProps> = ({
|
|
|
38
38
|
const numberOfLines = showTrailingAction || !!badgeLabel ? 1 : 2;
|
|
39
39
|
const buttonTypo: Typography =
|
|
40
40
|
buttonSize === 'small' ? 'action_xs_bold' : 'action_s_bold';
|
|
41
|
-
const flexStyle = showTrailingAction && {maxWidth: '
|
|
41
|
+
const flexStyle = showTrailingAction && {maxWidth: '95%'};
|
|
42
42
|
|
|
43
43
|
const renderIcon = () => {
|
|
44
44
|
if (!icon) return null;
|
package/code-scanner.js
CHANGED
package/package.json
CHANGED
package/verify.js
CHANGED
|
@@ -27,7 +27,7 @@ if (
|
|
|
27
27
|
|
|
28
28
|
if (packageVersion > iOSAppTarget || packageVersion > androidAppTarget) {
|
|
29
29
|
throw new Error(
|
|
30
|
-
`\x1b[41m Package ${packageInfo.name} version
|
|
30
|
+
`\x1b[41m Package ${packageInfo.name} version:${packageInfo.version} require deploymentTarget ${packageVersion}`
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
|
package/tsconfig.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"rootDir": ".",
|
|
4
|
-
"allowUnreachableCode": false,
|
|
5
|
-
"allowUnusedLabels": false,
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"forceConsistentCasingInFileNames": true,
|
|
8
|
-
"jsx": "react",
|
|
9
|
-
"lib": ["esnext"],
|
|
10
|
-
"module": "esnext",
|
|
11
|
-
"moduleResolution": "node",
|
|
12
|
-
"noFallthroughCasesInSwitch": true,
|
|
13
|
-
"noImplicitReturns": false,
|
|
14
|
-
"noImplicitUseStrict": false,
|
|
15
|
-
"noStrictGenericChecks": false,
|
|
16
|
-
"noUncheckedIndexedAccess": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"resolveJsonModule": true,
|
|
20
|
-
"skipLibCheck": true,
|
|
21
|
-
"strict": true,
|
|
22
|
-
"target": "esnext"
|
|
23
|
-
}
|
|
24
|
-
}
|