@momo-kits/foundation 1.0.12 → 1.0.13
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/Icon/index.tsx +1 -0
- package/Image/index.tsx +6 -2
- package/Input/InputSearch.tsx +22 -14
- package/Input/index.tsx +6 -2
- package/Input/styles.ts +0 -2
- package/Layout/ScreenContainer.tsx +12 -2
- package/Navigation/BottomTab.tsx +1 -2
- package/Navigation/Components.tsx +25 -14
- package/Navigation/NavigationButton.tsx +1 -1
- package/Navigation/StackScreen.tsx +2 -1
- package/Navigation/types.ts +6 -3
- package/Navigation/utils.tsx +32 -17
- package/Popup/PopupPromotion.tsx +2 -3
- package/package.json +1 -1
package/Icon/index.tsx
CHANGED
package/Image/index.tsx
CHANGED
|
@@ -10,11 +10,12 @@ import {FastImagePropsWithoutStyle} from './types';
|
|
|
10
10
|
|
|
11
11
|
export interface ImageProps extends FastImagePropsWithoutStyle {
|
|
12
12
|
style?: StyleProp<ViewStyle>;
|
|
13
|
+
loading?: boolean;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
16
17
|
const {theme} = useContext(ApplicationContext);
|
|
17
|
-
const [loading, setLoading] = useState(
|
|
18
|
+
const [loading, setLoading] = useState(rest.loading);
|
|
18
19
|
const [fail, setFail] = useState(false);
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -54,7 +55,7 @@ const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
|
54
55
|
style={styles.image}
|
|
55
56
|
onLoad={() => {
|
|
56
57
|
setFail(false);
|
|
57
|
-
setLoading(
|
|
58
|
+
setLoading(rest.loading);
|
|
58
59
|
}}
|
|
59
60
|
onLoadEnd={() => setLoading(false)}
|
|
60
61
|
onError={() => setFail(true)}
|
|
@@ -64,4 +65,7 @@ const Image: React.FC<ImageProps> = ({style, source, ...rest}) => {
|
|
|
64
65
|
);
|
|
65
66
|
};
|
|
66
67
|
|
|
68
|
+
Image.defaultProps = {
|
|
69
|
+
loading: true,
|
|
70
|
+
};
|
|
67
71
|
export {Image};
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -7,16 +7,12 @@ import {
|
|
|
7
7
|
View,
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
import {InputSearchProps} from './index';
|
|
10
|
-
import {getBorderColor} from './common';
|
|
11
10
|
import {ApplicationContext} from '../Navigation';
|
|
12
11
|
import styles from './styles';
|
|
13
12
|
import {Icon} from '../Icon';
|
|
14
|
-
import {Image} from '../Image';
|
|
15
13
|
import {Text} from '../Text';
|
|
16
14
|
|
|
17
15
|
const InputSearch: FC<InputSearchProps> = ({
|
|
18
|
-
errorMessage,
|
|
19
|
-
disabled,
|
|
20
16
|
placeholder,
|
|
21
17
|
onFocus,
|
|
22
18
|
onBlur,
|
|
@@ -27,6 +23,7 @@ const InputSearch: FC<InputSearchProps> = ({
|
|
|
27
23
|
buttonText = 'Hủy',
|
|
28
24
|
showButtonText = true,
|
|
29
25
|
showIcon = true,
|
|
26
|
+
showBorder = true,
|
|
30
27
|
style,
|
|
31
28
|
...props
|
|
32
29
|
}) => {
|
|
@@ -54,20 +51,25 @@ const InputSearch: FC<InputSearchProps> = ({
|
|
|
54
51
|
onChangeText?.(text);
|
|
55
52
|
};
|
|
56
53
|
|
|
54
|
+
const getBorderColor = () => {
|
|
55
|
+
let borderColor = showBorder
|
|
56
|
+
? theme.colors.border.default
|
|
57
|
+
: theme.colors.background.surface;
|
|
58
|
+
|
|
59
|
+
if (focused) {
|
|
60
|
+
borderColor = theme.colors.primary;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {borderColor};
|
|
64
|
+
};
|
|
65
|
+
|
|
57
66
|
const renderInputView = () => {
|
|
58
|
-
const disabledColor = theme.colors.text.disable;
|
|
59
67
|
let textColor = theme.colors.text.default;
|
|
60
68
|
let placeholderColor = theme.colors.text.hint;
|
|
61
69
|
|
|
62
|
-
if (disabled) {
|
|
63
|
-
textColor = disabledColor;
|
|
64
|
-
placeholderColor = disabledColor;
|
|
65
|
-
iconTintColor = disabledColor;
|
|
66
|
-
}
|
|
67
70
|
return (
|
|
68
71
|
<TextInput
|
|
69
72
|
{...props}
|
|
70
|
-
editable={!disabled}
|
|
71
73
|
textAlignVertical="top"
|
|
72
74
|
ref={inputRef}
|
|
73
75
|
style={[
|
|
@@ -112,7 +114,11 @@ const InputSearch: FC<InputSearchProps> = ({
|
|
|
112
114
|
},
|
|
113
115
|
]}
|
|
114
116
|
/>
|
|
115
|
-
<Icon
|
|
117
|
+
<Icon
|
|
118
|
+
color={iconTintColor}
|
|
119
|
+
source={icon}
|
|
120
|
+
style={styles.iconSearchInput}
|
|
121
|
+
/>
|
|
116
122
|
</View>
|
|
117
123
|
)}
|
|
118
124
|
</View>
|
|
@@ -122,9 +128,11 @@ const InputSearch: FC<InputSearchProps> = ({
|
|
|
122
128
|
<View style={[style, styles.searchInputContainer]}>
|
|
123
129
|
<View
|
|
124
130
|
style={[
|
|
125
|
-
getBorderColor(
|
|
131
|
+
getBorderColor(),
|
|
126
132
|
styles.searchInputWrapper,
|
|
127
|
-
{
|
|
133
|
+
{
|
|
134
|
+
backgroundColor: theme.colors.background.surface,
|
|
135
|
+
},
|
|
128
136
|
]}>
|
|
129
137
|
<Icon
|
|
130
138
|
source={'navigation_search'}
|
package/Input/index.tsx
CHANGED
|
@@ -20,17 +20,21 @@ type InputPropsWithoutSizeAndIcon = Omit<
|
|
|
20
20
|
InputProps,
|
|
21
21
|
'size' | 'icon' | 'iconColor'
|
|
22
22
|
>;
|
|
23
|
-
type
|
|
23
|
+
type InputPropsOmitForSearch = Omit<
|
|
24
|
+
InputProps,
|
|
25
|
+
'required' | 'size' | 'errorMessage' | 'disabled'
|
|
26
|
+
>;
|
|
24
27
|
type InputPropsWithoutPlaceholder = Omit<InputProps, 'placeholder'>;
|
|
25
28
|
|
|
26
29
|
export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
|
|
27
30
|
height?: number;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
export interface InputSearchProps extends
|
|
33
|
+
export interface InputSearchProps extends InputPropsOmitForSearch {
|
|
31
34
|
buttonText?: string;
|
|
32
35
|
showButtonText?: boolean;
|
|
33
36
|
showIcon?: boolean;
|
|
37
|
+
showBorder?: boolean;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
|
package/Input/styles.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {KeyboardAvoidingView, Platform,
|
|
1
|
+
import {Animated, KeyboardAvoidingView, Platform, View} from 'react-native';
|
|
2
2
|
import {useHeaderHeight} from '@react-navigation/stack';
|
|
3
3
|
import {SafeAreaView} from 'react-native-safe-area-context';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import {ScreenContainerProps} from '../Navigation/types';
|
|
6
6
|
import {Spacing, Styles} from '../Consts';
|
|
7
7
|
import {ScreenSection, validateChildren} from './index';
|
|
8
|
+
import {Image} from '../Image';
|
|
8
9
|
|
|
9
10
|
const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
10
11
|
children,
|
|
@@ -12,11 +13,12 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
12
13
|
enableKeyboardAvoidingView,
|
|
13
14
|
scrollable,
|
|
14
15
|
scrollViewProps,
|
|
16
|
+
headerImage,
|
|
15
17
|
}) => {
|
|
16
18
|
let Component: any = View;
|
|
17
19
|
const headerHeight = useHeaderHeight();
|
|
18
20
|
if (scrollable) {
|
|
19
|
-
Component = ScrollView;
|
|
21
|
+
Component = Animated.ScrollView;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -52,6 +54,14 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
|
|
|
52
54
|
android: undefined,
|
|
53
55
|
})}>
|
|
54
56
|
<Component {...scrollViewProps} style={Styles.flex}>
|
|
57
|
+
{headerImage && (
|
|
58
|
+
<Image
|
|
59
|
+
source={{
|
|
60
|
+
uri: headerImage,
|
|
61
|
+
}}
|
|
62
|
+
style={{width: '100%', height: 300}}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
55
65
|
{renderContent()}
|
|
56
66
|
</Component>
|
|
57
67
|
</KeyboardAvoidingView>
|
package/Navigation/BottomTab.tsx
CHANGED
|
@@ -10,11 +10,10 @@ const BottomTab: FC<BottomTabProps> = ({tabs}) => {
|
|
|
10
10
|
<Tab.Navigator>
|
|
11
11
|
{tabs.map((item, index) => {
|
|
12
12
|
return (
|
|
13
|
-
// @ts-ignore
|
|
14
13
|
<Tab.Screen
|
|
15
14
|
key={`${item.label}-${index}`}
|
|
16
15
|
name={item.label}
|
|
17
|
-
component={item.
|
|
16
|
+
component={item.screen}
|
|
18
17
|
options={{
|
|
19
18
|
tabBarLabel: item.label,
|
|
20
19
|
tabBarBadge: item?.badgeLabel,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Animated,
|
|
3
4
|
DeviceEventEmitter,
|
|
4
5
|
StatusBar,
|
|
5
6
|
StyleSheet,
|
|
@@ -47,7 +48,6 @@ const styles = StyleSheet.create({
|
|
|
47
48
|
marginLeft: Spacing.S,
|
|
48
49
|
padding: Spacing.XS,
|
|
49
50
|
height: 28,
|
|
50
|
-
borderWidth: 0.5,
|
|
51
51
|
borderRadius: 14,
|
|
52
52
|
borderColor: '#00000066',
|
|
53
53
|
justifyContent: 'center',
|
|
@@ -62,15 +62,19 @@ const styles = StyleSheet.create({
|
|
|
62
62
|
headerLeft: {
|
|
63
63
|
marginLeft: 12,
|
|
64
64
|
},
|
|
65
|
+
title: {fontSize: 15, lineHeight: 22, fontWeight: '600'},
|
|
65
66
|
});
|
|
66
67
|
|
|
67
|
-
const HeaderTitle =
|
|
68
|
+
const HeaderTitle: React.FC<any> = props => {
|
|
69
|
+
const opacity = props.animatedValue?.interpolate({
|
|
70
|
+
inputRange: [0, 200],
|
|
71
|
+
outputRange: [0, 1],
|
|
72
|
+
extrapolate: 'clamp',
|
|
73
|
+
});
|
|
68
74
|
return (
|
|
69
|
-
<Text
|
|
75
|
+
<Animated.Text
|
|
70
76
|
{...props}
|
|
71
|
-
|
|
72
|
-
weight="bold"
|
|
73
|
-
color={props.tintColor}
|
|
77
|
+
style={[styles.title, {opacity, color: props.tintColor}]}
|
|
74
78
|
/>
|
|
75
79
|
);
|
|
76
80
|
};
|
|
@@ -98,19 +102,28 @@ const HeaderLeft: React.FC<any> = ({tintColor}) => {
|
|
|
98
102
|
const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
99
103
|
image,
|
|
100
104
|
backgroundColor,
|
|
105
|
+
animatedValue,
|
|
101
106
|
}) => {
|
|
102
107
|
const {theme} = useContext(ApplicationContext);
|
|
103
108
|
let headerImage = theme.assets?.headerBackground;
|
|
104
109
|
if (image === null) {
|
|
105
110
|
headerImage = undefined;
|
|
106
111
|
}
|
|
112
|
+
const opacity = animatedValue?.interpolate({
|
|
113
|
+
inputRange: [0, 200],
|
|
114
|
+
outputRange: [0, 1],
|
|
115
|
+
extrapolate: 'clamp',
|
|
116
|
+
});
|
|
107
117
|
return (
|
|
108
|
-
<View
|
|
118
|
+
<Animated.View
|
|
109
119
|
style={[
|
|
110
120
|
Styles.flex,
|
|
111
121
|
{
|
|
112
122
|
backgroundColor: backgroundColor ?? theme.colors.background.default,
|
|
113
123
|
overflow: 'hidden',
|
|
124
|
+
borderBottomWidth: headerImage ? 0 : 1,
|
|
125
|
+
borderColor: theme.colors.border.default,
|
|
126
|
+
opacity,
|
|
114
127
|
},
|
|
115
128
|
]}>
|
|
116
129
|
<StatusBar
|
|
@@ -119,7 +132,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
|
|
|
119
132
|
{headerImage && (
|
|
120
133
|
<Image style={styles.headerBackground} source={{uri: headerImage}} />
|
|
121
134
|
)}
|
|
122
|
-
</View>
|
|
135
|
+
</Animated.View>
|
|
123
136
|
);
|
|
124
137
|
};
|
|
125
138
|
|
|
@@ -193,15 +206,13 @@ const HeaderToolkitAction: React.FC<any> = ({tintColor}) => {
|
|
|
193
206
|
|
|
194
207
|
return (
|
|
195
208
|
<View style={styles.headerRightButton}>
|
|
196
|
-
<NavigationButton
|
|
197
|
-
icon="addFavorite"
|
|
198
|
-
tintColor={tintColor}
|
|
199
|
-
onPress={() => {}}
|
|
200
|
-
/>
|
|
201
209
|
<View
|
|
202
210
|
style={[
|
|
203
211
|
styles.toolkitContainer,
|
|
204
|
-
{
|
|
212
|
+
{
|
|
213
|
+
backgroundColor: backgroundColor ?? '#00000066',
|
|
214
|
+
borderWidth: backgroundColor ? 0.5 : 0,
|
|
215
|
+
},
|
|
205
216
|
]}>
|
|
206
217
|
<TouchableOpacity>
|
|
207
218
|
<Icon color={tintColor} source="navigation_more_horiz" size={20} />
|
|
@@ -23,7 +23,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
|
|
|
23
23
|
styles.container,
|
|
24
24
|
{
|
|
25
25
|
backgroundColor: backgroundColor ?? '#00000066',
|
|
26
|
-
borderWidth: useBorder ? 0.5 : 0,
|
|
26
|
+
borderWidth: useBorder && backgroundColor ? 0.5 : 0,
|
|
27
27
|
},
|
|
28
28
|
]}
|
|
29
29
|
onPress={onPress}>
|
package/Navigation/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {ScrollViewProps, ViewProps} from 'react-native';
|
|
2
|
-
import React
|
|
1
|
+
import {Animated, ScrollViewProps, ViewProps} from 'react-native';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import Navigator from './Navigator';
|
|
4
4
|
|
|
5
5
|
export type Theme = {
|
|
@@ -73,6 +73,7 @@ export interface ScreenContainerProps extends ViewProps {
|
|
|
73
73
|
enableKeyboardAvoidingView?: boolean;
|
|
74
74
|
scrollable: boolean;
|
|
75
75
|
scrollViewProps?: ScrollViewProps;
|
|
76
|
+
headerImage?: string;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export type ScreenParams = {
|
|
@@ -107,11 +108,13 @@ export type NavigationOptions = {
|
|
|
107
108
|
headerTitleAlign?: 'left' | 'center';
|
|
108
109
|
customTitle?: TitleCustomProps;
|
|
109
110
|
headerRight?: (props?: any) => React.ReactElement;
|
|
111
|
+
animatedValue?: Animated.Value;
|
|
110
112
|
};
|
|
111
113
|
|
|
112
114
|
export type HeaderBackgroundProps = {
|
|
113
115
|
image?: string | null;
|
|
114
116
|
backgroundColor?: string | null;
|
|
117
|
+
animatedValue?: Animated.Value;
|
|
115
118
|
};
|
|
116
119
|
|
|
117
120
|
export type TitleCustomProps = {
|
|
@@ -128,7 +131,7 @@ export type BottomTabItemProps = {
|
|
|
128
131
|
icon: string;
|
|
129
132
|
showDot?: boolean;
|
|
130
133
|
badgeLabel?: string;
|
|
131
|
-
|
|
134
|
+
screen: React.ComponentType<any>;
|
|
132
135
|
};
|
|
133
136
|
|
|
134
137
|
export type BottomTabProps = {
|
package/Navigation/utils.tsx
CHANGED
|
@@ -73,43 +73,58 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
76
|
-
let
|
|
77
|
-
let
|
|
76
|
+
let backgroundProps = {};
|
|
77
|
+
let titleProps = {};
|
|
78
|
+
let options = {};
|
|
78
79
|
|
|
79
80
|
if (params.surface == true) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<HeaderBackground
|
|
83
|
-
image={null}
|
|
84
|
-
backgroundColor={theme.colors.background.surface}
|
|
85
|
-
/>
|
|
86
|
-
),
|
|
81
|
+
options = {
|
|
82
|
+
...options,
|
|
87
83
|
...getTintColor({
|
|
88
84
|
...theme,
|
|
89
85
|
assets: {...theme.assets, headerBackground: undefined},
|
|
90
86
|
}),
|
|
91
87
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
backgroundProps = {
|
|
89
|
+
...backgroundProps,
|
|
90
|
+
image: null,
|
|
91
|
+
backgroundColor: theme.colors.background.surface,
|
|
96
92
|
};
|
|
93
|
+
} else {
|
|
94
|
+
backgroundProps = {};
|
|
95
|
+
options = {...options, ...getTintColor(theme)};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (params.animatedValue) {
|
|
99
|
+
backgroundProps = {...backgroundProps, animatedValue: params.animatedValue};
|
|
100
|
+
titleProps = {...titleProps, animatedValue: params.animatedValue};
|
|
101
|
+
options = {...options, headerTransparent: true};
|
|
102
|
+
} else {
|
|
103
|
+
options = {...options, headerTransparent: false};
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
if (params.customTitle) {
|
|
100
|
-
|
|
107
|
+
options = {
|
|
108
|
+
...options,
|
|
101
109
|
headerTitleAlign: 'left',
|
|
102
110
|
headerTitle: (props: any) => {
|
|
103
111
|
return <HeaderCustom {...params.customTitle} {...props} />;
|
|
104
112
|
},
|
|
105
113
|
};
|
|
106
114
|
} else {
|
|
107
|
-
|
|
108
|
-
|
|
115
|
+
options = {
|
|
116
|
+
...options,
|
|
117
|
+
headerTitle: (props: any) => {
|
|
118
|
+
return <HeaderTitle {...titleProps} {...props} />;
|
|
119
|
+
},
|
|
109
120
|
};
|
|
110
121
|
}
|
|
111
122
|
|
|
112
|
-
return {
|
|
123
|
+
return {
|
|
124
|
+
...params,
|
|
125
|
+
...options,
|
|
126
|
+
headerBackground: () => <HeaderBackground {...backgroundProps} />,
|
|
127
|
+
};
|
|
113
128
|
};
|
|
114
129
|
|
|
115
130
|
export {getStackOptions, getDialogOptions, getModalOptions, getOptions};
|
package/Popup/PopupPromotion.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native';
|
|
|
3
3
|
import {PopupPromotionProps} from './types';
|
|
4
4
|
import {ApplicationContext} from '../Navigation';
|
|
5
5
|
import {Image} from '../Image';
|
|
6
|
-
import {Radius} from '../Consts';
|
|
6
|
+
import {Radius, Spacing} from '../Consts';
|
|
7
7
|
import {Icon} from '../Icon';
|
|
8
8
|
|
|
9
9
|
const PopupPromotion: React.FC<PopupPromotionProps> = ({image, onClose}) => {
|
|
@@ -55,11 +55,10 @@ const styles = StyleSheet.create({
|
|
|
55
55
|
aspectRatio: 0.72,
|
|
56
56
|
},
|
|
57
57
|
iconCloseContainer: {
|
|
58
|
-
position: 'absolute',
|
|
59
58
|
width: '100%',
|
|
60
59
|
flexDirection: 'row',
|
|
61
60
|
justifyContent: 'center',
|
|
62
|
-
|
|
61
|
+
marginTop: Spacing.L,
|
|
63
62
|
},
|
|
64
63
|
iconClose: {
|
|
65
64
|
width: 20,
|